完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
实验摘要
本文主要关于如何用STM32系列单片机驱动DS18B20温度传感器实现温度的串口打印显示,本实验中STM32基于HAL库开发。本文全程记录实验过程,手把手教大家基于STM32的DS18B20温度采集实验。 DS18B20简述 首先,我们拿到DS18B20之后进行观察。 该器件只有3个引脚,分别为电源端VCC,地GND和数据线DQ。只有一条数据线,说明该器件是单总线器件。单总线器件好处是只占用一个单片机的一个I/O口。 DS18B20通信协议通过查阅DS18B20中文资料获得,该部分将在驱动文件编写部分详细讲解。 STMCubeMX引脚配置 本文使用STMCubeMX软件进行引脚和时钟的配置 芯片选型 本文选择STM32L431RC系列,根据自己的芯片选择。 引脚和时钟配置 引脚主要配置外部时钟输入输出口,串口通信USART1用于打印温度数据,传感器数据DQ接口(此处使用PA5)。 将HCLK配置为80MHz。 工程管理,设置项目名称和保存路径,选择MDK-ARM V5。 Code Generator中建议勾选Generate peripheral initialization as a pair of ‘.c/.h’ files per peripheral,为每个外设生成独立的.c文件。 生成ARM-MDK工程 点击GENERATE CODE生成ARM-MDK工程。 编写DS18B20驱动文件 新建工程项目组 单击红圈出现 这里可以自行添加文件管理项目结构,清晰明了。这里我们可以在Group新建一个文件夹Hardware用于存放DS18B20的驱动文件。(DS18B20.C和DS18B20.h) 接着在文件夹Hardware中添加DS18B20.C和DS18B20.h 编写DS18B20.c /**************************************************************************** 函数名:delay_us 功能:微秒级延时 输入:延时数据 输出:无 返回值:无 备注: ****************************************************************************/ void delay_us(uint32_t time) { time *= 10; while(time) time--; } 主机首先发出一个480-960微秒的低电平脉冲,然后释放总线变为高电平,并在随后的480微秒时间内对总线进行检测,如果有低电平出现说明总线上有器件已做出应答。若无低电平出现一直都是高电平说明总线上无器件应答。 做为从器件的DS18B20在一上电后就一直在检测总线上是否有480-960微秒的低电平出现,如果有,在总线转为高电平后等待15-60微秒后将总线电平拉低60-240微秒做出响应存在脉冲,告诉主机本器件已做好准备。若没有检测到就一直在检测等待。我们需要配置引脚为输入或输出模式,需要两个函数。 发送复位信号和检测存在脉冲两个函数。 引脚输入输出配置函数参考gpio.c中的void MX_GPIO_Init(void)函数编写。 /**************************************************************************** 函数名:DS18B20_IO_IN 功能:使DS18B20_DQ引脚变为输入模式 输入:无 输出:无 返回值:无 备注:DQ引脚为PA5 ****************************************************************************/ void DS18B20_IO_IN(void){ GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.Pin = GPIO_PIN_5; GPIO_InitStructure.Mode = GPIO_MODE_INPUT; HAL_GPIO_Init(GPIOA,&GPIO_InitStructure); } /**************************************************************************** 函数名:DS18B20_IO_OUT 功能:使DS18B20_DQ引脚变为推挽输出模式 输入:无 输出:无 返回值:无 备注:DQ引脚为PA5 ****************************************************************************/ void DS18B20_IO_OUT(void){ GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.Pin = GPIO_PIN_5; GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOA,&GPIO_InitStructure); } /*************************************************************************** 函数名:DS18B20_Rst 功 能:发送复位信号 输 入: 无 输 出:无 返回值:无 备 注: ***************************************************************************/ void DS18B20_Rst(void){ DS18B20_IO_OUT();//引脚输出模式 //拉低总线并延时750us DS18B20_DQ_OUT_LOW; delay_us(750); //释放总线为高电平并延时等待15~60us DS18B20_DQ_OUT_HIGH; delay_us(15); } /*************************************************************************** 函数名:DS18B20_Check 功 能:检测DS18B20返回的存在脉冲 输 入: 无 输 出:无 返回值:0:成功 1:失败 2:释放总线失败 备 注: ***************************************************************************/ 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; //判断DS18B20是否释放总线 while(!DS18B20_DQ_IN && retry < 240){ retry++; delay_us(1); } if(retry >= 240) return 2; return 0; } 写时序 写周期最少为60微秒,最长不超过120微秒。写周期一开始做为主机先把总线拉低1微秒表示写周期开始。随后若主机想写0,则继续拉低电平最少60微秒直至写周期结束,然后释放总线为高电平。若主机想写1,在一开始拉低总线电平1微秒后就释放总线为高电平,一直到写周期结束。而做为从机的DS18B20则在检测到总线被拉底后等待15微秒然后从15us到45us开始对总线采样,在采样期内总线为高电平则为1,若采样期内总线为低电平则为0。 /*************************************************************************** 函数名:DS18B20_Write_Byte 功 能:向DS18B20写一个字节 输 入: 要写入的字节 输 出:无 返回值:无 备 注: ***************************************************************************/ void DS18B20_Write_Byte(uint8_t data){ uint8_t j; uint8_t databit; DS18B20_IO_OUT(); for(j=1;j<=8;j++){ databit=data&0x01;//取数据最低位 data=data>>1; //右移一位 if(databit){ //当前位写1 DS18B20_DQ_OUT_LOW; delay_us(2); DS18B20_DQ_OUT_HIGH; delay_us(60); }else{ //当前位写0 DS18B20_DQ_OUT_LOW; delay_us(60); DS18B20_DQ_OUT_HIGH; delay_us(2); } } } 读时序 /*************************************************************************** 函数名:DS18B20_Read_Bit 功 能:向DS18B20读一个位 输 入: 无 输 出:无 返回值:读入数据 备 注: ***************************************************************************/ 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; } /*************************************************************************** 函数名:DS18B20_Read_Byte 功 能:向DS18B20读一个字节 输 入: 无 输 出:无 返回值:读入数据 备 注: ***************************************************************************/ 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); /*j=0或1,j<<7=0x00或0x80,和data右移一位相或,即把1/0写入最高位,下次再往右移位*/ } return data; } 读取温度 基本时序操作已经完成,再根据资料中的ROM命令编写DS18B20的启动函数。由于我们只使用一个DS18B20,所以可以直接跳过ROM。 DS18B20的ROM指令集 存储器指令 用到的指令 [tr]指令名称指令代码[/tr]
/*************************************************************************** 函数名:DS18B20_Start 功 能:DS18B20开启 输 入: 无 输 出:无 返回值:无 备 注: ***************************************************************************/ void DS18B20_Start(void){ DS18B20_Rst(); DS18B20_Check(); DS18B20_Write_Byte(0xcc);//跳过ROM DS18B20_Write_Byte(0x44);//温度变换命令 } /*************************************************************************** 函数名:DS18B20_Init 功 能:DS18B20初始化 输 入: 无 输 出:无 返回值:无 备 注: ***************************************************************************/ uint8_t DS18B20_Init(void){ //引脚初始化 GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.Pin = GPIO_PIN_5; GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStructure.Pull = GPIO_PULLUP; GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOA,&GPIO_InitStructure); DS18B20_Rst(); return DS18B20_Check(); } /*************************************************************************** 函数名:DS18B20_Read_Temperature 功 能:读取一次温度 输 入: 无 输 出:无 返回值:读取到的温度数据 备 注:适用于总线上只有一个DS18B20的情况 ***************************************************************************/ short DS18B20_Get_Temperature(uint8_t a){ uint8_t temp; uint8_t TL,TH; short temperature; DS18B20_Start(); DS18B20_Rst(); DS18B20_Check(); DS18B20_Write_Byte(0xcc);//跳过ROM DS18B20_Write_Byte(0xbe);//读暂存器 TL = DS18B20_Read_Byte();//低八位 TH = DS18B20_Read_Byte();//高八位 //判断温度值是否为负数 if(TH>0x70){ 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; } 定义三个引脚操作函数。 主程序实现功能 用户包含 /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "DS18B20.h" /* USER CODE END Includes */ 函数声明 /* USER CODE BEGIN PFP */ uint8_t DS18B20_Init(void); short DS18B20_Get_Temperature(void); /* USER CODE END PFP */ /* USER CODE BEGIN 1 */ float temperature; /* USER CODE END 1 */ /* USER CODE BEGIN 2 */ while(DS18B20_Init()){ printf("DS18B20 checked failed!!!rn"); HAL_Delay(500); } printf("DS18B20 checked success!!!rn"); /* USER CODE END 2 */ /* USER CODE BEGIN 3 */ temperature = DS18B20_Get_Temperature(); if(temperature < 0) printf("temperature = -%.2f degreern",temperature/10); else printf("temperature = %.2f degreern",temperature/10); HAL_Delay(200);} /* USER CODE END 3 */ 重定向printf函数 在usart.c中添加printf重定向函数,该函数在不同信号芯片可能有不同。 #if 1 #include int fputc(int ch, FILE *stream) { /* 堵塞判断串口是否发送完成 */ while((USART1->ISR & 0X40) == 0); /* 串口发送完成,将该字符发送 */ USART1->TDR = (uint8_t) ch; return ch; } #endif 包含头文件路径 单击魔法棒图标 选择C/C++,在include path中添加文件路径。 …>>New(Insert)>> 选择DS18B20.c和DS18B20.h的路径。 编译项目并下载到硬件中 连接硬件线路 三条线路,连接之后DS18B20模块电源指示灯亮起。 检验结果 烧录程序,并打开串口助手,这里推荐win10应用市场的串口调试助手,可以免费下载。 我们看到温度数据可以被读取出来,可以用手捂一下传感器看温度是否有变化。实验完成! 总结 该实验完成了对DS18B20温度传感器的使用,主要重点是对单总线器件通信时序的学习,掌握了单总线器件时序的原理可以帮助我们使用其他的器件。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1090 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1107 浏览 1 评论
545 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
412 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
990 浏览 2 评论
1593浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
262浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
274浏览 3评论
245浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
238浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-8-16 08:05 , Processed in 0.853159 second(s), Total 78, Slave 62 queries .
Powered by 电子发烧友网
© 2015 www.ws-dc.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号