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,求指点。 沉得好快! 问题已经解决,自问自答好了。void ds18b20_busXfer(void)里关闭DMA后需要重新配置一下DMA_InitStructure.DMA_BufferSize = Size;再打开DMA,否则DMA只能传输一次。在度娘找到的答案,不明所以,望高手解答。 我用楼主的程序可以读温度,但是读ID函数ds18b20_id(void),要复位两次才能读到id
”ds18b20_reset(); //总线复位
ds18b20_reset(); //总线复位"
要两次才能读ID,为啥? bbglx 发表于 2015-1-30 18:17
我用楼主的程序可以读温度,但是读ID函数ds18b20_id(void),要复位两次才能读到id
”ds18b20_reset(); //总 ...
我也读DS18B20的ID作为设备的唯一ID,但木有出现这种情况。
页:
[1]