DS18B20是由DALLAS半导体公司推出的一种单总线接口的温度传感器,与传统的热敏电阻等测温元件相比,它是一种新型的体积小、实用电压宽、与微处理器接口简单的数字化温度传感器。
DS18B20的内部结构以下图示编程
ROM中的64位序列号是出厂前就被光刻好的,能够看作是DS18B20的地址序列号。64位光刻ROM的排列是:8位产品类型标号+48位DS18B20序列号+8位循环冗余校验码。光刻ROM 的做用是使每个DS18B20都各不相同,这样就能够实现一根总线上挂接多个DS18B20markdown
DS18B20的内部存储器(9个字节)包括一个高速暂存器RAM和一个EEPROM,EEPROM里存放高温和低温触发器和配置寄存器,存储器详细组成见下图:异步
配置寄存器是配置不一样的位数来肯定温度和数字的转化,其结构下图示:低五位都是1,TM是测试模式位(设置工做模式或测试模式,默认为0即工做模式),R1和R0用来设置精度,可设9~12位精度,对应的温度分辨率为0.5, 0.25, 0.125, 0.0625℃
全部的单总线器件都要求采样严格的信号时序,以保证设局的完整性。DS18B20的时序有:初始化时序、写(0和1)时序、读(0和1)时序。DS18B20发送全部的命令和数据都是字节的低位在前,下面介绍这几个信号的时序:ide
⏩ 初始化时序函数
内置闪存模块能够在通用地址空间直接寻址,任何32位数据的读操做都能访问闪存模块的内容并获得相应的数据。
⏩ 写时序测试
写时序包括写0和写1时序。全部写时序至少须要60us,而且在2次独立的写时序之间至少须要1us的恢复时间,两种写时序均起始于主机拉低总线。写1时序,主机输出低电平,延时2us,而后释放总线,延时60us;写0时序,主机输出低电平,延时60us,而后释放总线,延时2us。写时序图以下
⏩ 读时序ui
单总线器件仅在主机发出读时序时,才向主机传输数据,因此在主机发出读数据命令后,必须立刻产生读时序,以便从机可以传输数据。全部读时序至少须要60us,且在2次独立的读时序之间至少须要1us的恢复时间。每一个读时序都由主机发起,至少拉低总线1us,主机在读时序器件必须释放总线,而且在时序起始后的15us以内采样总线状态。典型的读时序过程为,主机输出低电平延时2us,而后主机转入输入模式延时12us,而后读取单总线当前的电平,而后延时50us
DS18B20的典型温度读取过程:复位 --> 发SKIP ROM命令(0XCC) --> 发开始转换命令(0X44) --> 延时 --> 复位 --> 发SKIP ROM命令(0XCC) --> 发读存储器命令(0XBE) --> 连续读出两个字节数据(即温度) --> 结束设计
D1指示灯用来提示系统运行状态,DS18B20温度传感器用来检测环境温度,串口1用来打印温度值3d
指示灯D1code
USART1串口
DS18B20
3.1 STM32CubeMX设置
➡️ RCC设置外接HSE,时钟设置为72M
➡️ PC0设置为GPIO推挽输出模式、上拉、高速、默认输出电平为高电平
➡️ USART1选择为异步通信方式,波特率设置为115200Bits/s,传输数据长度为8Bit,无奇偶校验,1位中止位
➡️ PG11设置为GPIO推挽输出模式、上拉、高速
➡️ 激活TIM7,预分频因子设为72-1,向上计数,自动重载值为65535;所以计数器CNT_CLK = 1MHz,计数器周期为1us
➡️输入工程名,选择路径(不要有中文),选择MDK-ARM V5;勾选Generated periphera initialization as a pair of ‘.c/.h’ files per IP ;点击GENERATE CODE,生成工程代码
3.2 MDK-ARM软件编程
➡️ 在tim.c文件下实现微秒延时(us)函数
void delay_us(uint16_t us){ uint16_t differ = 0xffff-us-5; //设定TIM7计数器起始值 __HAL_TIM_SET_COUNTER(&htim7,differ); //启动定时器 HAL_TIM_Base_Start(&htim7); while(differ < 0xffff-5){ //判断 //查询计数器的计数值 differ = __HAL_TIM_GET_COUNTER(&htim7); } HAL_TIM_Base_Stop(&htim7); }
➡️ 建立按键驱动文件ds18b20.c 和相关头文件ds18b20.h
void DS18B20_IO_IN(void){ GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.Pin = GPIO_PIN_11; GPIO_InitStructure.Mode = GPIO_MODE_INPUT; HAL_GPIO_Init(GPIOG,&GPIO_InitStructure); } void DS18B20_IO_OUT(void){ GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.Pin = GPIO_PIN_11; GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOG,&GPIO_InitStructure); } void DS18B20_Rst(void){ DS18B 20_IO_OUT(); DS18B20_DQ_OUT_LOW; delay_us(750); DS18B20_DQ_OUT_HIGH; delay_us(15); } uint8_t DS18B20_Check(void){ uint8_t retry = 0; DS18B20_IO_IN(); while(DS18B20_DQ_IN && retry < 200){ retry++; delay_us(1); } if(retry >= 200) return 1; else retry = 0; while(!DS18B20_DQ_IN && retry < 240){ retry++; delay_us(1); } if(retry >= 240) return 1; return 0; } uint8_t DS18B20_Read_Bit(void){ uint8_t data; DS18B20_IO_OUT(); DS18B20_DQ_OUT_LOW; delay_us(2); DS18B20_DQ_OUT_HIGH; DS18B20_IO_IN(); delay_us(12); if(DS18B20_DQ_IN) data = 1; else data = 0; delay_us(50); return data; } uint8_t DS18B20_Read_Byte(void){ uint8_t i,j,data; data = 0; for(i=1;i<=8;i++){ j = DS18B20_Read_Bit(); data = (j<<7)|(data>>1); } return data; } void DS18B20_Write_Byte(uint8_t data){ uint8_t j; uint8_t testb; DS18B20_IO_OUT(); for(j=1;j<=8;j++){ testb=data&0x01; data=data>>1; if(testb){ DS18B20_DQ_OUT_LOW; delay_us(2); DS18B20_DQ_OUT_HIGH; delay_us(60); }else{ DS18B20_DQ_OUT_LOW; delay_us(60); DS18B20_DQ_OUT_HIGH; delay_us(2); } } } void DS18B20_Start(void){ DS18B20_Rst(); DS18B20_Check(); DS18B20_Write_Byte(0xcc); DS18B20_Write_Byte(0x44); } uint8_t DS18B20_Init(void){ GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.Pin = GPIO_PIN_11; GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStructure.Pull = GPIO_PULLUP; GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOG,&GPIO_InitStructure); DS18B20_Rst(); return DS18B20_Check(); } short DS18B20_Get_Temperature(void){ uint8_t temp; uint8_t TL,TH; short temperature; DS18B20_Start(); DS18B20_Rst(); DS18B20_Check(); DS18B20_Write_Byte(0xcc); DS18B20_Write_Byte(0xbe); TL = DS18B20_Read_Byte(); TH = DS18B20_Read_Byte(); if(TH>7){ TH = ~TH; TL = ~TL; temp = 0; }else temp = 1; temperature = TH; temperature <<= 8; temperature += TL; temperature = (float)temperature*0.625; if(temperature) return temperature; else return -temperature; }
➡️ 在main.c文件下编写ds18b20测试代码
int main(void){ float temperature; HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_TIM7_Init(); MX_USART1_UART_Init(); /* USER CODE BEGIN 2 */ while(DS18B20_Init()){ printf("DS18B20 checked failed!!!\r\n"); HAL_Delay(500); } printf("DS18B20 checked success!!!\r\n"); /* USER CODE END 2 */ while (1){ temperature = DS18B20_Get_Temperature(); if(temperature < 0) printf("temperature = -%.2f degree\r\n",temperature/10); else printf("temperature = %.2f degree\r\n",temperature/10); HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0); HAL_Delay(200); } }
编译无误下载到开发板后,能够看到D1指示灯不断闪烁,串口不断打印出当前温度值