历史上的今天
今天是:2024年08月27日(星期二)
2021年08月27日 | 玩转STM32CubeMX | DS18B20温度传感器
2021-08-27 来源:eefocus
1.DS18B20简介
DS18B20是由DALLAS半导体公司推出的一种单总线接口的温度传感器,与传统的热敏电阻等测温元件相比,它是一种新型的体积小、实用电压宽、与微处理器接口简单的数字化温度传感器。
DS18B20的内部结构如下图示

ROM中的64位序列号是出厂前就被光刻好的,可以看做是DS18B20的地址序列号。64位光刻ROM的排列是:8位产品类型标号+48位DS18B20序列号+8位循环冗余校验码。光刻ROM 的作用是使每一个DS18B20都各不相同,这样就可以实现一根总线上挂接多个DS18B20
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发送所有的命令和数据都是字节的低位在前,下面介绍这几个信号的时序:
⏩ 初始化时序
内置闪存模块可以在通用地址空间直接寻址,任何32位数据的读操作都能访问闪存模块的内容并得到相应的数据。
⏩ 写时序
写时序包括写0和写1时序。所有写时序至少需要60us,并且在2次独立的写时序之间至少需要1us的恢复时间,两种写时序均起始于主机拉低总线。写1时序,主机输出低电平,延时2us,然后释放总线,延时60us;写0时序,主机输出低电平,延时60us,然后释放总线,延时2us。写时序图如下
⏩ 读时序
单总线器件仅在主机发出读时序时,才向主机传输数据,所以在主机发出读数据命令后,必须马上产生读时序,以便从机能够传输数据。所有读时序至少需要60us,且在2次独立的读时序之间至少需要1us的恢复时间。每个读时序都由主机发起,至少拉低总线1us,主机在读时序器件必须释放总线,并且在时序起始后的15us之内采样总线状态。典型的读时序过程为,主机输出低电平延时2us,然后主机转入输入模式延时12us,然后读取单总线当前的电平,然后延时50us
DS18B20的典型温度读取过程:复位 --> 发SKIP ROM命令(0XCC) --> 发开始转换命令(0X44) --> 延时 --> 复位 --> 发SKIP ROM命令(0XCC) --> 发读存储器命令(0XBE) --> 连续读出两个字节数据(即温度) --> 结束
2.硬件设计
D1指示灯用来提示系统运行状态,DS18B20温度传感器用来检测环境温度,串口1用来打印温度值
指示灯D1
USART1串口
DS18B20
TIM7(提供us延时)

3.软件设计
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!!!rn");
HAL_Delay(500);
}
printf("DS18B20 checked success!!!rn");
/* USER CODE END 2 */
while (1){
temperature = DS18B20_Get_Temperature();
if(temperature < 0)
printf("temperature = -%.2f degreern",temperature/10);
else
printf("temperature = %.2f degreern",temperature/10);
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0);
HAL_Delay(200);
}
}
4.下载验证
编译无误下载到开发板后,可以看到D1指示灯不断闪烁,串口不断打印出当前温度值

史海拾趣
|
一、概况 韩国通信开展ADSL业务的主要原因是由于激烈的市场竞争。由于电信业务完全放开,除韩国通信之外,还有不少宽带业务提供商也在提供电信业务。当韩国通信还在推广ISDN业务时,一些CATV公司已利用CableModem占去了不少宽带Internet接入市场。 ...… 查看全部问答> |
|
MFC requires WINVER to be #defined to 0x0400 or greater 项目建立的时候是wm5.0,后来选择别的模拟器,编译的时候出现“MFC requires WINVER to be #defined to 0x0400 or greater”,应该如何解决?… 查看全部问答> |
|
条码手持终端开发工程师 1. 2名,大专以上学历; 2. 了解制造业物流业务和条码/RFID技术,有仓库和生产线条码/RFID手持终端开发经验。 3. 熟悉C#语言编程 ...… 查看全部问答> |
|
热光源:利用热能激发的光源,如白炽灯在3,000-4,000K温度时热辐射发光。白炽灯有80-90%的能量转换能热能,10%左右的能量转换为光能。因此发光效率较低。我们不是根据灯具外壳的温度来定义为冷光源,还是热光源。灯具週边的温度高低,只能评判 ...… 查看全部问答> |
|
转贴自:http://www.2cto.com/os/201108/98426.html init的进程号是1(ps -aux | less),从这一点就能看出,init进程是系统所有进程的起点,Linux在完成核内引导以后,就开始运行init程序。 init程序需要读取配置文件/etc/ini ...… 查看全部问答> |




