qqtfh 发表于 2014-11-3 10:53:02

stm32f103在RT-Thread上使用one-wire总线操作DS18B20求助!

本帖最后由 qqtfh 于 2014-11-3 10:58 编辑








如题,参考了http://www.amobbs.com/forum.php?mod=viewthread&tid=5482534&highlight=STM32%2BDS18B20
贴子上的STM32F407使用one-wire总线操作DS18B20的方法移植到STM32F103上来。
代码如下:
#ifndef __DS18B20_H__
#define __DS18B20_H__

#include <rtthread.h>
#include <stm32f10x.h>

#define DS18B20_GIVE_TICK_RTOS                                                 //此定义可让线程放弃时间片
#define DS18B20_OK                                                                                                 0 //操作成功
#define DS18B20_ERROR                                                                                 1 //操作失败
#define DS18B20_NO_DEVICE                                                                 2 //总线上无设备
#define DS18B20_INVALID_BUF                                                         3 //缓冲地址非法
#define DS18B20_USART                                                                                 USART2 //操作的USART
#define DS18B20_DMA_CH_RX                                                                 DMA1_Channel6
#define DS18B20_DMA_CH_TX                                                                 DMA1_Channel7
#define DS18B20_DMA_FLAG_RX                                                         DMA1_FLAG_TC6 //RX DMA完成标志
#define DS18B20_DMA_FLAG_TX                                                         DMA1_FLAG_TC7 //TX DMA完成标志
#define DS18B20_BIT_0                                                                                 0x00 //读写位为0
#define DS18B20_BIT_1                                                                                 0xff        //读写位为1

void ds18b20_uartInit(uint32_t baudRate);
void ds18b20_dmaInit(void);
void ds18b20_init(void);
uint8_t ds18b20_reset(void);
void ds18b20_toBits(uint8_t ds18b20_byte, uint8_t *ds18b20_bits);
uint8_t ds18b20_toByte(uint8_t *ds18b20_bits);
void ds18b20_busXfer(void);
void ds18b20_writeByte(uint8_t data);
void ds18b20_writeBuf(uint8_t *buf, uint8_t length);
uint8_t ds18b20_readByte(void);
void ds18b20_readBuf(uint8_t *buf, uint8_t length);
void ds18b20_id(void);
void ds18b20_get(void);


#endif



#include <rtthread.h>
#include <stm32f10x.h>

#include "ds18b20.h"

static uint8_t ds18b20_buf;        //设备私有缓冲

void ds18b20_uartInit(uint32_t baudRate)
{
        USART_InitTypeDef USART_InitStructure;
        USART_InitStructure.USART_BaudRate = baudRate;
        USART_InitStructure.USART_WordLength = USART_WordLength_8b;
        USART_InitStructure.USART_StopBits = USART_StopBits_1;
        USART_InitStructure.USART_Parity = USART_Parity_No;
        USART_InitStructure.USART_HardwareFlowControl =
        USART_HardwareFlowControl_None;
        USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
        USART_Init(DS18B20_USART, & USART_InitStructure);
}

void ds18b20_dmaInit(void)
{
        DMA_InitTypeDef DMA_InitStructure;

DMA_DeInit(DS18B20_DMA_CH_RX);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) &(DS18B20_USART->DR);
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t) ds18b20_buf;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = sizeof(ds18b20_buf);
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_Low;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DS18B20_DMA_CH_RX, &DMA_InitStructure);

DMA_DeInit(DS18B20_DMA_CH_TX);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) &(DS18B20_USART->DR);
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t) ds18b20_buf;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = sizeof(ds18b20_buf);
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize =
                        DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_Low;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DS18B20_DMA_CH_TX, &DMA_InitStructure);
}

void ds18b20_init(void)
{
        GPIO_InitTypeDef GPIO_InitStruct;

if (DS18B20_USART == USART2)
        {
                RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);

                GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2;
                GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
                GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;

                GPIO_Init(GPIOA, &GPIO_InitStruct);

                GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3;
                GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
                GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;

                GPIO_Init(GPIOA, &GPIO_InitStruct);

                RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
}
       
        ds18b20_uartInit(115200);
        USART_Cmd(DS18B20_USART, ENABLE);
        ds18b20_dmaInit();
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
}

uint8_t ds18b20_reset(void)
{
        uint8_t ds18b20_presence;
        ds18b20_uartInit(9600);
        // Send the 0xf0 at 9600
        USART_ClearFlag(DS18B20_USART, USART_FLAG_TC);
        USART_SendData(DS18B20_USART, 0xF0);
        while (USART_GetFlagStatus(DS18B20_USART, USART_FLAG_TC) == RESET)
        {
                #ifdef ds18b20_GIVE_TICK_RTOS
                rt_thread_yield();
                #else
                __NOP();
                #endif
        }
        ds18b20_presence = USART_ReceiveData(DS18B20_USART);
        ds18b20_uartInit(115200);
        return(ds18b20_presence != 0xF0)? DS18B20_OK : DS18B20_NO_DEVICE;
}

void ds18b20_toBits(uint8_t ds18b20_byte, uint8_t *ds18b20_bits)
{
        uint8_t i;
        for (i=0; i<8; i++)
        {
                *ds18b20_bits =(ds18b20_byte & 0x01)? DS18B20_BIT_1 : DS18B20_BIT_0;
                ds18b20_bits ++;
                ds18b20_byte = ds18b20_byte >> 1;
        }
}

uint8_t ds18b20_toByte(uint8_t *ds18b20_bits)
{
        uint8_t i;
        uint8_t ds18b20_byte =0;
        for (i=0; i<8; i++)
        {
                ds18b20_byte = ds18b20_byte >> 1;
                if (*ds18b20_bits == DS18B20_BIT_1)
                {
                        ds18b20_byte |= 0x80;
                }
                ds18b20_bits ++;
        }
        return ds18b20_byte;
}

void ds18b20_busXfer(void)
{
        USART_DMACmd(DS18B20_USART, USART_DMAReq_Tx | USART_DMAReq_Rx, ENABLE);
        DMA_ClearFlag(DS18B20_DMA_FLAG_RX);
        DMA_ClearFlag(DS18B20_DMA_FLAG_TX);
        USART_DMACmd(DS18B20_USART, USART_DMAReq_Tx | USART_DMAReq_Rx, ENABLE);
DMA_Cmd(DS18B20_DMA_CH_RX, ENABLE);
DMA_Cmd(DS18B20_DMA_CH_TX, ENABLE);
        while (DMA_GetFlagStatus(DS18B20_DMA_FLAG_RX) == RESET) //等待传输完成
        {
                #ifdef ds18b20_GIVE_TICK_RTOS
                rt_thread_yield();
                #else
                __NOP();
                #endif
        }
        DMA_Cmd(DS18B20_DMA_CH_RX, DISABLE); //顺序1:RX DMA
        DMA_Cmd(DS18B20_DMA_CH_TX, DISABLE); //顺序2:TX DMA
        USART_DMACmd(DS18B20_USART, USART_DMAReq_Tx | USART_DMAReq_Rx, DISABLE);
        //顺序3:UART DMAUART DMAUART DMAUART
}

void ds18b20_writeByte(uint8_t data)
{
        ds18b20_toBits(data, ds18b20_buf);
        ds18b20_busXfer();
}

void ds18b20_writeBuf(uint8_t *buf, uint8_t length)
{
        while (length> 0)
        {
                ds18b20_writeByte(*buf);
                buf ++;
                length --;
        }
}

uint8_t ds18b20_readByte(void)
{
        ds18b20_toBits(0xFF, ds18b20_buf);
        ds18b20_busXfer();
        return ds18b20_toByte(ds18b20_buf);
}

void ds18b20_readBuf(uint8_t *buf, uint8_t length)
{
        while (length> 0)
        {
                *buf = ds18b20_readByte();
                buf ++;
                length --;
        }
}

void ds18b20_id(void)
{
        uint32_t i;
        uint8_t buf;
        ds18b20_init();
        ds18b20_reset(); //总线复位
        ds18b20_writeByte(0x33); //发送命令0x33,读取ROM
        ds18b20_readBuf(buf, 8); //读取8byte(64bit)
        rt_kprintf("Type= %02X ID= ", buf); //byte:设备类别ID
        for (i=6;i>0;i--)
        rt_kprintf("%02X",buf); //byte-:设备序列号
        rt_kprintf(" CRC= %02X", buf); //bytebyte:CRC值
        rt_kprintf("\n");
}

void ds18b20_get(void)
{
        uint8_t buf;
        int16_t* buf16 = (int16_t*)&buf;
        ds18b20_init();
        while(1)
        {
                rt_kprintf("ds18b20_get");
                ds18b20_reset(); //总线复位
                ds18b20_writeBuf("\xCC\x44", 2); //发送命令XCC跳过ROM,X44转换温度
                /*max convert time = 750ms, here we set delay = 800ms*/
                rt_thread_delay((rt_tick_t)(RT_TICK_PER_SECOND *4/5)); //最高精度转换时间<=750ms<=750ms<=750ms
                ds18b20_reset(); //总线复位
                ds18b20_writeBuf("\xCC\xBE", 2); //发送命令XCC跳过ROM,X44转换温?
                ds18b20_readBuf(buf, 2); //读取RAM最开始两个字节的温度数据
                rt_kprintf("data = %d temp = %d\n", //转换工式temp=data*0.625
                (*buf16), ((int32_t)(*buf16))*125/2); //此处温度值*1000
        }
}

但是调用ds18b20_get();代码一直停在while (USART_GetFlagStatus(DS18B20_USART, USART_FLAG_TC) == RESET)。
应该是设置有问题,初学STM32,求指点。

qqtfh 发表于 2014-11-3 16:26:23

沉得好快!

qqtfh 发表于 2014-11-6 09:54:47

问题已经解决,自问自答好了。void ds18b20_busXfer(void)里关闭DMA后需要重新配置一下DMA_InitStructure.DMA_BufferSize = Size;再打开DMA,否则DMA只能传输一次。在度娘找到的答案,不明所以,望高手解答。

bbglx 发表于 2015-1-30 18:17:52

我用楼主的程序可以读温度,但是读ID函数ds18b20_id(void),要复位两次才能读到id
”ds18b20_reset(); //总线复位
ds18b20_reset(); //总线复位"
要两次才能读ID,为啥?

qqtfh 发表于 2015-1-30 20:31:06

bbglx 发表于 2015-1-30 18:17
我用楼主的程序可以读温度,但是读ID函数ds18b20_id(void),要复位两次才能读到id
”ds18b20_reset(); //总 ...

我也读DS18B20的ID作为设备的唯一ID,但木有出现这种情况。
页: [1]
查看完整版本: stm32f103在RT-Thread上使用one-wire总线操作DS18B20求助!