DS18B20是一个非常简单的温度传感器,对于像我这样单片机萌新是比较友好的。网上关于它的介绍非常多,包括原理、引脚、通信、以及51单片机、STM32的各种代码等等。本人写了一个简单的ds18b20.c库文件分享给大家,该文件内的函数可以实现单个元件的单次测温功能,温度精确到整数。这个程序在STM32F103C8上进行了实际测试,但是稍加修改就可以移植到其他类型的单片机上。
DS18B20的引脚定义、线路连接、工作时序、指令含义等,在他人写的文章中有详细阐述,在这里不再介绍。值得注意的是,经过我多次测试,发现在有VCC供电的情况下,VCC稳定在3.1V以上,才能正常测温;而如果使用数据线供电,在我单片机3.3V的VCC下没法正常测温(或许5V的VCC可以,但我没试验过)所以不推荐这种方法。
首先是头文件ds18b20.h:
#ifndef INC_DS18B20_H_
#define INC_DS18B20_H_
#define DS18_GPIO_Port GPIOB
#define DS18_Pin GPIO_PIN_0
unsigned char ds18b20_Init(void);
char readtemp(void);
void ds18b20start(void);
#endif /* INC_DS18B20_H_ */
头文件中#define 这两行是对ds18b20数据线对应管脚的定义,用户需要根据自己单片机上连接的管脚进行修改。需要注意的是,下面ds18b20_Init()中并没有包含管脚的初始化。用户需要在调用该函数之前先完成对GPIO管脚的初始化操作,将其配置成为开漏输出模式并配置上拉电阻。(我用的STM32Cube,自动生成了对GPIO管脚的初始化函数)
下面三个函数是main函数中需要调用的函数。具体调用方法如下:
-
在初始化时调用ds18b20_Init()函数。
-
每次测量温度前,都要先调用ds18b20start()函数。
-
调用完ds18b20start()后,需要等至少500ms,其测量完温度后再调用readtemp()函数进行读取(单位是摄氏度)。
接下来是这些函数的具体实现,即ds18b20.c:
/*
* ds18b20.c
*
* Created on: Dec 20, 2021
* Author: ASUS
* 使用前必读
* 需要修改的部分包括:
* 1.在DELAY_Us中,修改__NOP()的数量,CPU频率是多少MHz,就用多少个NOP.
* 2.添加或修改DS18_GPIO_Port,DS18_Pin的重定义内容,使之匹配对应的端口。
* 3.如HAL_GPIO_WritePin()和HAL_GPIO_ReadPin没有定义,则自己写一个。
* 4.在主程序中,需要对响应的GPIO端口进行初始化,设置为开漏输出和上拉电阻模式。
* 本文件只有单次测量温度的程序。调用函数的方法:
* 开机先用ds18b20_Init(void)初始化。每次测量前先用ds18b20start()开始测温,等大约0.5s后用readtemp()读取结果。
*/
#include "ds18b20.h"
#include "main.h"
void DELAY_Us(unsigned int count)
{
while(count--)
{
__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
}
}
unsigned char ds18b20_Init(void)
{
/*****初始化DS18B20*****/
unsigned char x=0;
HAL_GPIO_WritePin(DS18_GPIO_Port,DS18_Pin,1); //DQ复位
DELAY_Us(30); //稍做延时
HAL_GPIO_WritePin(DS18_GPIO_Port,DS18_Pin,0); //单片机将DQ拉低
DELAY_Us(500); //精确延时,大于480us
HAL_GPIO_WritePin(DS18_GPIO_Port,DS18_Pin,1); //拉高总线
DELAY_Us(100);
x=HAL_GPIO_ReadPin(DS18_GPIO_Port,DS18_Pin); //稍做延时后,如果x=0则初始化成功,x=1则初始化失败
DELAY_Us(500);
return x;
}
void ds18b20_Write1byte(unsigned char data)
{
unsigned char i=0;
for(i=8;i>0;i--)
{
HAL_GPIO_WritePin(DS18_GPIO_Port,DS18_Pin,0);
DELAY_Us(3);
HAL_GPIO_WritePin(DS18_GPIO_Port,DS18_Pin,data&0x01);
DELAY_Us(70);
HAL_GPIO_WritePin(DS18_GPIO_Port,DS18_Pin,1);
DELAY_Us(3);
data>>=1;
}
DELAY_Us(30);
}
unsigned char ds18b20_Read1byte(void)
{
unsigned char i,j,dat;
dat=0;
for (i=1;i<=8;i++)
{
HAL_GPIO_WritePin(DS18_GPIO_Port,DS18_Pin,0);
DELAY_Us(3);
HAL_GPIO_WritePin(DS18_GPIO_Port,DS18_Pin,1);
DELAY_Us(18);
j=HAL_GPIO_ReadPin(DS18_GPIO_Port,DS18_Pin);
DELAY_Us(50);
dat=(j<<7)|(dat>>1);
}
return dat;
}
void ds18b20start(void)
{
ds18b20_Init();
ds18b20_Write1byte(0xcc);
ds18b20_Write1byte(0x44);
}
char readtemp(void)
{
unsigned char TL=0x01,TH=0x07;
char temp;
ds18b20_Init();
ds18b20_Write1byte(0xcc);
ds18b20_Write1byte(0xbe);
TL=ds18b20_Read1byte();
DELAY_Us(1);
TH=ds18b20_Read1byte();
temp=(char)((TH<<4)|TL>>4);
return temp;
}
这里首先一个函数是微秒级延时函数DELAY_Us()。这里使用了一个简单的__NOP()做延时。这实际上对应着CPU的汇编指令,表示延时一个时钟周期,什么都不做。所以用户需要根据CPU时钟频率修改__NOP()的个数,频率是多少MHz就加多少个__NOP()。当然,不同单片机的指令名称可能有所不同,用户自行替换就行了。
用户还需要修改的一部分是对GPIO端口的读写操作函数。我这里用的STM32HAL库,所以用的是HAL_GPIO_WritePin()和HAL_GPIO_ReadPin()函数。如果大家没有此库函数,就在本文件下面写一个,重新定义一下。
用户修改完上述部分后,就可以在主程序中调用ds18b20.h中的三个函数,进行温度的测量了。测量的结果就可以根据你喜欢的方式进行输出~(不过这就不是本文件需要包含的内容了)文章来源:https://www.toymoban.com/news/detail-452494.html
如果有错误,还请在评论区指正。如果想看多点测温,欢迎在评论区留言,想看的人多我就写一写(嘿嘿文章来源地址https://www.toymoban.com/news/detail-452494.html
到了这里,关于DS18B20温度测量程序文件(简单通用)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!