网上18B20的资料很多,但似乎都找不到要点。官方文档很详尽,但也是通篇不分段,官方文档就不能1、2、3的给出主要注意点嘛。
这里结合自己调试过程,总结要点如下,使用stm32 72Mhz主频。
本幅图包括复位时序与写时序要点。
复位时序
1、拉低至少480us
2、拉高15-60us,读取状态,为0则通过
3、再次延迟时间,实验时过短会影响后续结果的读出,这里实验最短120us左右。
写时序
1、一次写1bit操作最少持续60us
2、低到高的操作需在15us内完成
读时序
1、一次读1bit操作需至少持续60us
2、拉低操作持续1us~15us后释放,且在60us内完成读操作
总结:
这种串行操作的器件属于慢外设,一次温度读取包括两次复位,写4字节,读2字节,这里把所有时序压缩到几乎最短,一次读取也需要4.5ms左右,时间很长,因此如果实时性要求高的话,估计得用中断方式操作。
另外,期间感觉写1时序和读时序好像一样的,器件是怎么知道是写1还是读呢?判断应该是通过写“CC”“BE”成功才启动的读过程,而在此之前都是写过程,写完成启动读时序。因此,先调试写、再调试读,是合理的调试过程。
附代码:
#include "18B20.h"
#define DQ_1_H() GPIO_SetBits(GPIOB, GPIO_Pin_4)
#define DQ_1_L() GPIO_ResetBits(GPIOB, GPIO_Pin_4)
#define RD_DQ_1() GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_4)
#define DQ_2_H() GPIO_SetBits(GPIOB, GPIO_Pin_3)
#define DQ_2_L() GPIO_ResetBits(GPIOB, GPIO_Pin_3)
#define RD_DQ_2() GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_3)
void delay_nus(u16 time)
{
u16 i=0;
while(time--)
{
i=35;
while(i--);
}
}
u8 Waitready_1(void)
{
u8 presence = 0;
DQ_1_H();
delay_nus(1) ;
DQ_1_L();
delay_nus(105) ;
DQ_1_H();
delay_nus(2) ;
presence = RD_DQ_1();
delay_nus(30) ;
DQ_1_H();
return(presence) ;
}
void Init_18B20(void) {
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
///PB4:channal 1
///PB3:channal 2
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
while(Waitready_1() != 0);
}
u8 ReadOneChar_1(void)
{
u8 i = 0 ;
u8 dat = 0 ;
for (i = 8 ; i > 0 ; i--)
{
DQ_1_L();
delay_nus(1) ;
DQ_1_H();
dat >>= 1 ;
// DQ_1_H();
delay_nus(1) ;
if(RD_DQ_1())
dat |= 0x80 ;
delay_nus(11) ;
}
return (dat) ;
}
void WriteOneChar_1(unsigned char dat)
{
u8 i = 0 ;
for (i = 8 ; i > 0 ; i--)
{
if (dat&0x01) {
DQ_1_L();
delay_nus(1) ;
DQ_1_H();
delay_nus(13) ;
}
else {
DQ_1_L();
delay_nus(13) ;
DQ_1_H();
delay_nus(1) ;
}
dat>>=1 ;
}
}
s8 Read_Temperature_1(void)
{
u8 temp_data[2];
s8 rtn = 0;
Waitready_1() ;
WriteOneChar_1(0xCC) ;
WriteOneChar_1(0x44) ;
Waitready_1() ;
WriteOneChar_1(0xCC) ;
WriteOneChar_1(0xBE) ;
temp_data[0] = ReadOneChar_1() ;
temp_data[1] = ReadOneChar_1() ;
rtn = (temp_data[1] << 4) | (temp_data[0] >> 4);
if ( rtn > 0 ) {
}
return (rtn);
}