环境:
IAR 7.4
stm32cubemx 4.13.1
stm32f1 1.3.1
freertos 8.1
读ds18b20主要是时序,就是一个微秒级的delay。
先看电路:
这里使用上拉电阻,DQ设为OD模式,在读取和输出时,也做了PIN的方向改变,不做改变,则只能读取到0值。
不想使用上拉电阻,则可以把DQ设为PP模式,Mbed开发板使用这个可以成功读出。
没有电路的代码,是不完整的,不容易让人理解。
delay的实现,是使用timer,也可以使用nop指令。这里使用Timer3 定时器提供滴答。
GPIO和TIMER的配置使用stm32cubemx,这里不列出,有问题可以在forum里提出。
/*
* 微秒延迟
*/
void therm_delay(uint16_t nCount)
{
__IO uint16_t TIMCounter = nCount;
uint16_t start = TIM_MST->CNT;
uint16_t end = start + TIMCounter;
__IO uint16_t read;
while (1) {
read = TIM_MST->CNT;
if(read < start)
read = 0xffff - start + read;
if (read >= end)
break;
}
}
频繁调用的改变方向和读取,改到寄存器操作,减少函数调用的开销。
根据需要对端口和Pin进行修改。
//PB8: IO方向设置
#define THERM_INPUT_MODE() { GPIOB->CRH &= 0xFFFFFFF0; GPIOB->CRH |= 0x4; }
#define THERM_OUTPUT_MODE() { GPIOB->CRH &= 0xFFFFFFF0; GPIOB->CRH |= 0x5; }
#define DQ_READ() ((GPIOB->IDR & GPIO_PIN_8) >> 8)
把对ds18b20的读取放在一个对实时要求不高的task里,它会延误task几个毫秒的执行。
代码里有crc验证,如果中断或其他任务干扰读取时序,则取用值时将其扔掉。因此可以放心的把它集成到自己的项目中去。
调用:
// 读取结果
typedef struct {
int8_t value;
int8_t error;
} ThermValue;
.
.
.
__IO ThermValue v_ds18b20;
/* ds18b20 */
if (start_conversion) {
v_ds18b20 = therm_read_temperature();
start_conversion = false;
}
else {
therm_start_conversion();
start_conversion = true;
}
if (v_ds18b20.error == 0)
cv = v_ds18b20.value;
操作ds18b20的代码和例子非常多,实际上也很简单,但是有的代码别人正常,而自己就是不正常。
原因就是硬件和软件的不一致,而且发生问题无处可问。