你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

基于STM32F103——DS18B20温度采集+串口打印

[复制链接]
STMCU小助手 发布时间:2022-8-22 17:27
DS18B20相关介绍
DS18B20特性
1.独特的单总线接口,就需一条线则可实现双向通信(测温)
2.测温范围:-55℃~+125℃,可通过编程设定9—12位分辨率,对应分辨温度分别为0.5、0.25、0.125、0.0625℃。
3.支持多点组网(可连接多个DS18B20温度传感器),多个DS18B20可以并联(3或2线)实现多个组网测温,但注意超过8个要解决好供电问题,否则电压过低会导致传输不稳定,从而数据不准确。
4.工作电压:3.0~5.5V (寄生电源方式下可由数据线供电)
5.在使用过程中不需要外围电路,全部传感元件及转换电路都在芯片内了。(上拉电阻)
6.测温结果直接是数字量输出,单总线串行传送方式,同时可传送CRC校验码(校验数据采集是否正确),具有极强的抗干扰和纠错能力。
7.在9位分辨率时最多在93.75ms内把温度转换为数字,12位分辨率时最多在750ms内把温度值转换为数字。
8.负压特性:电源极性接反时,芯片不会因发热而烧毁, 但不能正常工作。

封装形式与引脚说明

20210222200600101.png

供电方式(外部电源供电、寄生电源供电、寄生电源强上拉)


20210222200952313.png
20210222202601797.png

20210222202554322.png

内部结构
DS18B20内部结构如图所示,其中与操作有关的是:64位光刻ROM、温度传感器、9个字节的RAM存储器、EEPROM(温度报警寄存器TH和TL、配置寄存器)。

20210223004635178.png

光刻ROM中64位序列号是出厂前就光刻好的,相当地址序列号。排列是低位开始,低8位(产品类型标号),接着48位(自身序列号,)相当于身份证号、最高8位(前面56位的循环亢余校验码)。
如果一条总线挂接多个DS18B20需要MCU(微控制器)通过单总线对多个DS18B20进行寻址。

20210223005709281.png

20210223120003160.png

温度存储格式及配置寄存器(模式和分辨率)

DS18B20温度传感器进行测温,测温是以16位的二进制形式提供。
存放格式:

20210223010612427.png

16位中 低4位是温度的小数部分、最高5位是温度的正负(全为0为正,全为1为负),中间的7位则是温度的整数部分。小数部分十进制等于16进制乘0.0625。

例子:

20210223010921706.png

注意:如果是负数温度,那么得按位取反+1。
下面是数据处理例子

  1.                          温度数据的处理
  2. 比如我接收temp数据:十进制:64656  16进制:0XFC90   
  3. 二进制:                1111 1100 1001 0000

  4. 首先先看高5位 是1哦 好  那温度就是负数 (是0就是正数 不用取反+1)
  5. 我们得得取反+1  temp = ~temp + 1;
  6. 即                        1111 1100 1001 0000
  7. 取反后       0000 0011 0110 1111
  8. +1结果              0000 0011 0111 0000

  9. 此时结果为:        0000 0011 0111 0000
  10. 整数温度等于 温度整数 = temp >> 4; 把小数部分(低四位扔掉就行了)
  11. 二进制:                0011 0111
  12.                         10进制:55        16进制:         0X37        
  13. 小数温度等于 温度小数 = temp & 0x0f;        就要低四位 低四位是小数部分
  14. 二进制:                0000 0000
  15.                         10进制: 0 16进制: 0X00

  16. 所以 温度就是 -55.0°C   
复制代码
   
配置寄存器

~B9Y8G8%U4OV)`B[Y)GYK(J.png

TM:测试模式位,用于设置是在工作方式还是测试模式。在DS18B20出厂时该位设为0,用户不要改动。
R1 R0:分辨率设置

ICA~4GKU~S@`VXW}1]J`E%I.png


需要修改精度的 往下看 下面有写

DS18B20指令(ROM指令操作)

O{GBTHSEW_LS0JDCG6V4LI2.png

T[7F}157NI8GFNC[[5X55UK.png
        
指令的使用
多个DS18B20情况: 对某一个操作时,主机先逐个与DS18B20挂接-搜索ROM——(F0H),发出匹配ROM指令(55H),紧接着提供64位序列号,之后操作就是针对DS18B20的了。

单个DS18B20情况: 不需要搜索ROM指令,读ROM指令以及匹配ROM等操作,直接跳过ROM指令(CCH),温度转换(44H),读温度操作(8EH)。

注意事项

一、 DS18B20硬件是简单,但软件就比较复杂,特别是时序要求。
二、 连接DS18B20线长限制:部分资料显示:
采用普通信号电缆传输超50m时,测温数据不稳定。
采用带屏蔽层双绞线电缆,正常通讯距离可达到150m。
采用每米绞合次数更多的带屏蔽层双绞线电缆时,通讯距离进一步加长。
三、 距离长了测温要考虑总线分布电容和阻抗匹配问题。
在测温程序设计中,一般如果硬件没什么问题,可以采用延时来跳过检测,但是如果要检测是否有应答要注意不要进入了死循环。

时序图
查看 DS18B20 状态 函数

20210224120259849.png

  1. /******************************************************************
  2. 描述: DS18B20 查看状态 函数
  3. 返回: 0:应答        1:不应答
  4. *******************************************************************/
  5. uint8_t ds18b20_check(void)
  6. {
  7.         uint8_t ack = 0;
  8.         DS18B20_SET_OUT;        //设置输出模式
  9.         DS18B20_HIGH;                //起始拉高电平        
  10.         DS18B20_LOW;                //拉低电平
  11.         delay_us(480);                //维持480us
  12.         DS18B20_HIGH;                //释放总线
  13.         DS18B20_SET_IN;                //设置输入模式
  14.         delay_us(25);                //维持15~60us 最好是25us以上 25以下测试不够时间  
  15.         if( GPIO_ReadInputDataBit(DS18B20_PORT, DS18B20_PIN) == SET)
  16.         {
  17.                 ack = 1;        //没应答
  18.         }
  19.         DS18B20_HIGH;        //释放总线
  20.         delay_us(240);        //保证时序完整
  21.         return ack;
  22. }        
复制代码

写时序 DS18B20写一字节函数

20210224121558637.png

  1. /******************************************************************
  2. 描述: DS18B20 写一字节指令 函数
  3. 参数: cmd: 要写入的指令
  4. *******************************************************************/
  5. void ds18b20_write_cmd(uint8_t cmd)
  6. {
  7.         uint8_t i;
  8.         DS18B20_SET_OUT;//设置输出模式        
  9.         for(i=0; i<8; i++)
  10.         {
  11.                 DS18B20_LOW;        //拉低总线
  12.                 delay_us(1);        //至少1us
  13.                 if(cmd & 0x01)
  14.                 {
  15.                         DS18B20_HIGH;
  16.                 }
  17.                 else
  18.                 {
  19.                         DS18B20_LOW;
  20.                 }
  21.                 delay_us(60);        //继续维持至少60us 最多120us 电平
  22.                 DS18B20_HIGH;        //释放总线
  23.                 cmd >>= 1;                //右移一位
  24.         }
  25. }
复制代码

读时序 DS18B20读取一字节函数

20210224122616209.png

  1. /******************************************************************
  2. 描述: DS18B20 读取一字节数据 函数
  3. 返回: 返回读取到的数据
  4. *******************************************************************/
  5. uint8_t ds18b20_read_data(void)
  6. {
  7.         uint8_t i;
  8.         uint8_t data = 0;
  9.         for(i=0; i<8; i++)
  10.         {        
  11.                 DS18B20_SET_OUT;//设置输出模式
  12.                 DS18B20_LOW;        //拉低总线
  13.                 DS18B20_SET_IN; //设置输入模式
  14.                 data >>= 1;
  15.                 if( GPIO_ReadInputDataBit(DS18B20_PORT, DS18B20_PIN) == 1)
  16.                 {
  17.                         data |= 0x80;
  18.                 }
  19.                 delay_us(45);
  20.                 DS18B20_HIGH;        //释放总线
  21.         }
  22.         return data;
  23. }
复制代码

程序代码(部分)
由于代码多 我这里就不一一贴出来了 需要可以 留言
由于代码多 我这里就不一一贴出来了 需要可以 留言

每一次进行写ROM相关命令都记得初始化。
对于单个DS18B20我们可以直接跳过ROM指令 直接温度转换。读取温度

步骤:
1.初始化
2.跳过ROM指令
3.启动温度转换(转换出来需要时间)
4.延时(等待温度转换)加不加都行
5.初始化 (记得每写ROM相关命令记得需要从初始化开始)
6.读取温度

DS18B20 相关代码
DS18B20 修改精度函数

修改精度 需要用到一个指令 写暂存器 0X4E
写暂存器: 在该写暂存器指令后向DS18B20的暂存器TH.TL以及配置寄存器中写入数据。(不了解可以看看上面的结构图)
所以我们一次得写入3个参数 代码如下:

  1. /*******************************************************************************
  2. 描述: DS18B20 设置低温限值、高温限值、精度 函数
  3. 参数: temp_low:  写高速缓存器TL低温限值 temp_high:写高速缓存器TH高温限值
  4.           accuracy: 精度设置 9/10/11/12 (默认12位)
  5. ********************************************************************************/
  6. static uint8_t ds18b20_set_accuracy(uint8_t temp_low,uint8_t temp_high,uint8_t accuracy)
  7. {
  8.         if(ds18b20_check() == 1)
  9.         {
  10.                 return 1;
  11.         }               
  12.         ds18b20_write_cmd(WRITE_MEMORY);        //写暂存器指令4E        
  13.         ds18b20_write_cmd(temp_high);                //写高速缓存器TH高温限值 temp_high 度
  14.         ds18b20_write_cmd(temp_low);                //写高速缓存器TL低温限值 temp_low  度
  15.         
  16.         ds18b20_write_cmd(accuracy);                //精度设置
  17.         return 0;
  18. }
复制代码

DS18B20初始化函数

  1. #define DS18B20_SET_OUT ds18b20_set_output_mode()                                                //设置输出模式        
  2. /******************************************************************
  3. 描述: DS18B20 设置成输出模式 函数
  4. *******************************************************************/
  5. void ds18b20_set_output_mode(void)
  6. {
  7.         GPIO_InitTypeDef DS18B20_Struction;                                //定义结构体成员
  8.         RCC_APB2PeriphClockCmd(DS18B20_RCC, ENABLE);        //打开时钟
  9.         
  10.         DS18B20_Struction.GPIO_Pin  = DS18B20_PIN;                //引脚
  11.         DS18B20_Struction.GPIO_Mode = GPIO_Mode_Out_PP;        //推挽输出
  12.         DS18B20_Struction.GPIO_Speed = GPIO_Speed_50MHz;//速率        

  13.         GPIO_Init(DS18B20_PORT,&DS18B20_Struction);                //对成员进行初始化        
  14. }

  15. /******************************************************************
  16. 描述: DS18B20 配置函数
  17. 参数: accuracy: 精度
  18.         默认是 12位分辨率        转换时间750ms
  19.         9位分辨率 0x1f : 0.5   °C  转换时间需要93.75ms
  20.         10位分辨率0x3f : 0.25  °C  转换时间需要187.5ms
  21.         11位分辨率0x5f : 0.125 °C  转换时间需要375ms
  22.         12位分辨率0x7f : 0.0625°C  转换时间需要750ms        
  23. 返回: 0:成功         1:失败
  24. *******************************************************************/
  25. uint8_t ds18b20_init(uint8_t accuracy)
  26. {
  27.         uint8_t status;
  28.         DS18B20_SET_OUT;        //设置成输出模式
  29.         status = ds18b20_set_accuracy(0,70,accuracy);        //设置转换精度
  30.         return status;
  31. }
复制代码

DS18B20读取温度函数

  1. /******************************************************************
  2. 描述: DS18B20 读取温度 函数
  3. 返回: 读取成功:DS18B20_READ_SUCCESS  读取失败:DS18B20_READ_FAILURE
  4. *******************************************************************/
  5. uint8_t ds18b20_read_temperature(void)
  6. {
  7.         uint8_t low,high;
  8.         uint16_t temp = 0;        
  9.         
  10.         if(ds18b20_check() == 1)                 //DS18B20 初始化
  11.         {
  12.                 return DS18B20_READ_FAILURE;//读取失败
  13.         }
  14.         ds18b20_write_cmd(SKIP_ROM);        //跳过ROM
  15.         ds18b20_write_cmd(TEMP_SWITCH); //启动温度转换

  16.         ds18b20_check();                                        //DS18B20 初始化
  17.         ds18b20_write_cmd(SKIP_ROM);        //跳过ROM        
  18.         ds18b20_write_cmd(READ_MEMORY);        //发送读暂存存储器指令
  19.         
  20.         //D15 D14 D13 D12 D11    D10 D9 D8   D7 D6 D5 D4    D3 D2 D1 D0           16位数据 说明
  21.         //** 温度正负标志 **     **  温度整数部分 **        **小数部分**
  22.         
  23.         low  = ds18b20_read_data();        //低字节
  24.         high = ds18b20_read_data();        //高字节 高5位是正负标志 全为1 负 全为0 正
  25.         
  26.         temp = ((uint8_t)high<<8) | low;
  27.                
  28.         if(temp & 0x8000)        
  29.         {
  30.                 ds18b20_temp_symbol = 1;//负温度
  31.                 temp = ~temp + 1;
  32.         }
  33.         else
  34.         {
  35.                 ds18b20_temp_symbol = 0;//正温度
  36.         }
  37.         ds18b20_temp_integer = temp >> 4;                //整数部分
  38.         ds18b20_temp_decimal = temp & 0x0f;         //小数部分

  39.         if(ds18b20_temp_integer >= 100)
  40.         {
  41.                 ds18b20_temp_integer = 99;        //保持在2位数
  42.         }
  43.         
  44.         return DS18B20_READ_SUCCESS;//读取成功
  45. }
复制代码

串口 相关代码
如果 对 串口 不熟悉的 可以参考 我之前写的 文章STM32串口通信介绍

串口初始化 函数
  1. /* 配置串口1 函数*/
  2. void usart1_init(uint32_t baudRate)
  3. {
  4.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);        //打开GPIOA时钟
  5.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);        //打开串口1时钟
  6.         
  7.         GPIO_InitTypeDef GPIO_initStruction;
  8.         USART_InitTypeDef USART_initStruction;

  9.         /*配置GPIOA  TX */
  10.         GPIO_initStruction.GPIO_Pin = USART1_TX;                 // TX
  11.         GPIO_initStruction.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
  12.         GPIO_initStruction.GPIO_Speed = GPIO_Speed_50MHz;
  13.         GPIO_Init(GPIOA, &GPIO_initStruction);
  14.         
  15.         /*配置GPIOA RX */
  16.         GPIO_initStruction.GPIO_Pin = USART1_RX;                 // RX
  17.         GPIO_initStruction.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
  18.         GPIO_Init(GPIOA, &GPIO_initStruction);
  19.         
  20.         /*配置USART1 TX和RX */
  21.         USART_initStruction.USART_BaudRate = baudRate;        //波特率
  22.         USART_initStruction.USART_WordLength = USART_WordLength_8b; //8位有效数据位
  23.         USART_initStruction.USART_StopBits = USART_StopBits_1;        //1个停止位
  24.         USART_initStruction.USART_Parity = USART_Parity_No;                //无奇偶校验位
  25.         USART_initStruction.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //不硬件控制流
  26.         USART_initStruction.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; //发送 和 接收
  27.         USART_Init(USART1, &USART_initStruction);
  28.         
  29.         NVIC_USART1_configuration();        //串口1中断优先级配置
  30.         USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//使能接收中断
  31.         USART_Cmd(USART1, ENABLE); //使能串口1
  32. }
复制代码

串口 发送一字节 函数
  1. /*串口 发送1字节 函数*/
  2. void usart_sendByte(USART_TypeDef* USARTx,uint8_t data)
  3. {
  4.         USART_SendData(USARTx, data);
  5.         while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET); //等待发送寄存器为空 证明发送完
  6. }
复制代码

串口 发送字符串 函数
  1. /*串口 发送字符串 函数*/
  2. void usart_sendString(USART_TypeDef* USARTx,char *str)
  3. {
  4.         while(*str != '\0')
  5.         {
  6.                 usart_sendByte(USARTx,*str);
  7.                 str++;
  8.         }
  9.         while(USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET); //发送完成标志位
  10. }
复制代码

主程序 main

main.c(主函数)
  1. #include "stm32f10x.h"
  2. #include "ds18b20.h"
  3. #include "usart.h"
  4. #include "delay.h"
  5. #include "stdio.h"
  6. int  main()
  7. {
  8.         char ds18b20_str[10] = {0};               
  9.         usart1_init(9600);                                //串口1初始化 波特率9600
  10.         while(ds18b20_init(0x5f))                //DS18B20初始化 11位分辨率 0.125
  11.                 usart_sendString(USART1,"DS18B20 error!\r\n");
  12.         
  13.         usart_sendString(USART1,"DS18B20 success!\r\n");
  14.         while(1)
  15.         {
  16.                 delay_ms(500);
  17.                 if(ds18b20_read_temperature() == DS18B20_READ_SUCCESS)
  18.                 {
  19.                         //将温度转换成字符串
  20.                         sprintf(ds18b20_str,"%2u.%1u%1u%1u\r\n",(uint32_t)ds18b20_temp_integer,((uint32_t)ds18b20_temp_decimal*10/16),
  21.                                         ((uint32_t)ds18b20_temp_decimal*100/16%10),((uint32_t)ds18b20_temp_decimal*1000/16%10));
  22.                         usart_sendString(USART1,ds18b20_str);        //通过串口发送出去
  23.                 }
  24.                 else
  25.                 {
  26.                         usart_sendString(USART1,"DS18B20 error!\r\n");
  27.                 }
  28.                
  29.         }  
  30. }
复制代码

项目展示

d32c6610e2a14fe6919f1568f7f84bdd.png
————————————————
转载:皮卡丘吉尔


收藏 评论0 发布时间:2022-8-22 17:27

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版