STM32F207V 进行DS18B20处理

时间:2023-12-15 23:27:32

1、  DS18B20接口很简单,VCC、DQ、GND三个引脚,VCC采用外部供电3.3V,DQ需上拉电阻,当时按照参考资料上外接4.7K的上拉电阻,GPIO设置的OD无上拉,始终读不到ROM中的64位序列号,后面发送的转换指令更别想了,后来GPIO改成推挽输出时,诶,就能读到数据,推挽输出无非就是增大驱动能力,仔细看手册,其中有提到,DS18B20空闲处于低功耗状态,在执行温度转换或从高速暂存器向EPPROM传送数据时,工作电流可高达1.5mA,但并有说读ROM中的64位数据时,电流需要多少,也许在读ROM中的数据电流也需要要求。知道了加大驱动能力才能读到,加上之前写I2C和FLASH擦除时,数据线都是设置OD类型,通用性较好,好移植,所以还是改成OD类型,把4.7K的电阻换小点,换成1K电阻,就可以正确的读写操作。

GPIO配置:

 void Ds18b20_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOE,ENABLE); GPIO_InitStructure.GPIO_Pin = DS18B20_DATA;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; //OD门
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOE,&GPIO_InitStructure);
}

2、操作步骤,在使用任何一条功能指令前,都必须先执行有复位、ROM指令。

(1)、复位信号就是双方握手,达成协议后才能相互通信。时序如下,一定要注意minimum和maximum,Master主机先发送低电平脉冲,低电平持续480us~960us(这里设置700us,延迟后记得释放数据线,也就是拉高),DS18B20等待15~60us后(用while语句检测低电平的到来),会发出低电平脉冲信号给Master,该低电平脉冲60~240us,Master接收到后,就说明握手成功,用while语句检测高电平结束。

STM32F207V 进行DS18B20处理

代码:

 void Ds18b20_rst(void)
{
DS18B20_DATA_H;
DS18B20_DATA_L;
Ds18b20_delay(T700US); //700us
DS18B20_DATA_H; //释放数据线
while(DS18B20_DATA_Read); //检测低电平
Ds18b20_delay(T700US);
while(!DS18B20_DATA_Read); //检测高电平
DS18B20_DATA_H;
}

(2)、发ROM指令和功能指令,就是1bit 1bit 的往外发,读也是1bit 1bit的往里读,发送顺序是先低后高。读写时有高有低,一定要按照时序严格进行操作:

  a)、写“0”  和“1”时序,先拉低15us,发送高电平持续45us,注意不低于60us,发送完1bit,释放数据线。

STM32F207V 进行DS18B20处理

代码:

 void Ds18b20_Send_0(void)
{
DS18B20_DATA_L;
Ds18b20_delay(T15US); //15us
DS18B20_DATA_L;
Ds18b20_delay(T45US); //45us
DS18B20_DATA_H; //释放总线
} void Ds18b20_Send_1(void)
{
DS18B20_DATA_L;
Ds18b20_delay(T15US); //15us
DS18B20_DATA_H;
Ds18b20_delay(T45US);
DS18B20_DATA_H; //释放总线
} void Ds18b20_send_byte(uint8_t data)
{
uint8_t i = ; while(i--)
{
if(data & 0x01) //从低位开始发送
Ds18b20_Send_1();
else
Ds18b20_Send_0(); data >>= ;
}
}

  b)、读“0”  和“1”时序,在MASTER SAMPLES就可以采样数据,但一般会大于15us后开始采集数据,读写前 和 读写完后,都要记得释放数据

STM32F207V 进行DS18B20处理

代码:

 uint8_t Ds18b20_read_byte(void)
{
uint8_t i = ;
uint8_t data_buffer = ; DS18B20_DATA_H; //释放数据线
while(i--)
{
data_buffer >>= ;
DS18B20_DATA_L;
Ds18b20_delay(T1US); //1us
DS18B20_DATA_H; //释放数据线
Ds18b20_delay(T15US);
if(DS18B20_DATA_Read) //接收低位开始
{
data_buffer |= 0x80;
}
Ds18b20_delay(T45US);
DS18B20_DATA_H;
} return data_buffer;
}

写好写字节函数 和 读字节函数,那么就可以发送ROM指令和功能指令了,具体指令参考数据手册。

一些具体操作指令代码

ds18b20.c

 #include "ds18b20.h"

 #define DS18B20_DATA                GPIO_Pin_3
#define DS18B20_DATA_H GPIOE->BSRRL = GPIO_Pin_3
#define DS18B20_DATA_L GPIOE->BSRRH = GPIO_Pin_3
#define DS18B20_DATA_Read GPIOE->IDR & GPIO_Pin_3 #define T1US 15
#define T15US 230
#define T45US 790
#define T700US 12000 void Ds18b20_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOE,ENABLE); GPIO_InitStructure.GPIO_Pin = DS18B20_DATA;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOE,&GPIO_InitStructure);
} void Ds18b20_delay(__IO uint32_t nCount)
{
while(nCount--)
{ }
} void Ds18b20_rst(void)
{
DS18B20_DATA_H;
DS18B20_DATA_L;
Ds18b20_delay(T700US); //700us
DS18B20_DATA_H; //释放数据线
while(DS18B20_DATA_Read); //检测低电平
Ds18b20_delay(T700US);
while(!DS18B20_DATA_Read); //检测高电平
DS18B20_DATA_H;
} void Ds18b20_Send_0(void)
{
DS18B20_DATA_L;
Ds18b20_delay(T15US); //15us
DS18B20_DATA_L;
Ds18b20_delay(T45US); //45us
DS18B20_DATA_H; //释放总线
} void Ds18b20_Send_1(void)
{
DS18B20_DATA_L;
Ds18b20_delay(T15US); //15us
DS18B20_DATA_H;
Ds18b20_delay(T45US);
DS18B20_DATA_H; //释放总线
} void Ds18b20_send_byte(uint8_t data)
{
uint8_t i = ; while(i--)
{
if(data & 0x01) //从低位开始发送
Ds18b20_Send_1();
else
Ds18b20_Send_0(); data >>= ;
}
} uint8_t Ds18b20_read_byte(void)
{
uint8_t i = ;
uint8_t data_buffer = ; DS18B20_DATA_H; //释放数据线
while(i--)
{
data_buffer >>= ;
DS18B20_DATA_L;
Ds18b20_delay(T1US); //1us
DS18B20_DATA_H; //释放数据线
Ds18b20_delay(T15US);
if(DS18B20_DATA_Read) //接收低位开始
{
data_buffer |= 0x80;
}
Ds18b20_delay(T45US);
DS18B20_DATA_H;
} return data_buffer;
} void Ds18b20_Read_ROM(uint8_t *pBuff)
{
uint8_t i =;
Ds18b20_rst();
Ds18b20_send_byte(0x33); //读Rom指令
for(i=; i<; i++)
{
pBuff[i] = Ds18b20_read_byte();
}
} void Ds18b20_Convert_temprature(void)
{
Ds18b20_rst();
Ds18b20_send_byte(0xcc); //忽略ROM指令
Ds18b20_send_byte(0x44); //转换指令
} void Ds18b20_Read_register(uint8_t *pBuff)
{
uint8_t i = ;
Ds18b20_Convert_temprature();
Ds18b20_rst();
Ds18b20_send_byte(0xcc); //忽略ROM指令
Ds18b20_send_byte(0xbe); //读取存储器指令
for(i=; i<; i++)
{
pBuff[i] = Ds18b20_read_byte();
}
} void Ds18b20_weite_threshold(uint8_t TH, uint8_t TL, uint8_t Resolution)
{
Ds18b20_rst();
Ds18b20_send_byte(0xcc); //忽略ROM指令
Ds18b20_send_byte(0x4e); //写暂存器指令
Ds18b20_send_byte(TH);
Ds18b20_send_byte(TL);
if(Resolution == )
{
Ds18b20_send_byte(0x1f);
}
else if(Resolution == )
{
Ds18b20_send_byte(0x3f);
}
else if(Resolution == )
{
Ds18b20_send_byte(0x5f);
}
else //if(Resolution == 12) //其他任何都默认设置12bit分辨率
{
Ds18b20_send_byte(0x7f);
}
}

主函数:

 int main(void)
{
u8 i = ;
u8 id[];
RCC_ClocksTypeDef rcc_clocks; Clock_Config();
USART_Config(); Ds18b20_GPIO_Config();
Ds18b20_Read_ROM(id);
printf("DS18B20 64bit ROM Data:\n");
for(i=; i<; i++)
{
printf("0x%02x,",id[i]);
}
printf("\n");
printf("DS18B20 Memory Data:\n"); Ds18b20_Read_register(id);
for(i=; i<; i++)
{
printf("0x%02x,",id[i]);
} printf("\n"); Ds18b20_weite_threshold(0x3b,0x36,);
Ds18b20_Read_register(id);
for(i=; i<; i++)
{
printf("0x%02x,",id[i]);
} printf("\n"); while()
{
Ds18b20_Read_register(id);
printf("temprature:%.4f\n",((id[]<<) | id[]) * 6.25 /);
Delay(0x1fffff0); /* delay 1000ms */
}
}

3、打印信息

(1)、读5个不同DS18B20中ROM数据:

    0x28,0x37,0x4f,0xca,0x06,0x00,0x00,0x03
    0x28,0x3b,0xf4,0xc9,0x06,0x00,0x00,0xc9
    0x28,0xee,0xa0,0xcc,0x06,0x00,0x00,0xed
    0x28,0xca,0x02,0xcb,0x06,0x00,0x00,0xb1
    0x28,0xf0,0xbf,0xcb,0x06,0x00,0x00,0x30

    最前面8位是单线系列编码固定28H,接着48位是唯一序列号,最后8位是CRC,有关CRC计算参考手册,这里也没有去验证CRC是否正确。

(2)、

  DS18B20 64bit ROM Data:

  0x28,0xf0,0xbf,0xcb,0x06,0x00,0x00,0x30,   //64位中的序列号

  DS18B20 Memory Data:

  0xcd,0x01,0x4b,0x46,0x7f,0xff,0x03,0x10,  //读暂存器中的默认值

  0xcd,0x01,0x3b,0x36,0x7f,0xff,0x03,0x10, //改写后,读暂存器中的数据

  temprature:28.8125            //转换温度

printf("temprature:%.4f\n",((id[]<<) | id[]) * 6.25 /);

这里只考虑了正数温度,关于*6.25/100,参考数据手册:"温度传感器的精度为用户可编程的9、10、11或12位,分别以0.5°、0.25°、0.125°和0.0625°增量递增",程序选的是12bit分辨率,单位增量即为0.0625