实验09 DS18B20及LCD 1602(温度检测与显示)

这篇具有很好参考价值的文章主要介绍了实验09 DS18B20及LCD 1602(温度检测与显示)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

文末有源文件!

实验内容:单片机开机读取 ds18b20 检测到的温度,并显示在 1602 上,精确到0.1度;能显示超过100的温度和零下温度。温度值后面要加上符号:℃

提示:在lcd 1602上总共需要6位显示温度值: ???. ?℃

其中的.和℃都是固定位置的固定符号,可在程序里写好。

另外4个?号处的温度值要实时的从18b20读取。

当温度为零下时,最高位?号处显示为-号;

当温度为0及以上时,最高位不显示+号,且不为0;其中当温度值>=100,该处显示1。

实验09 DS18B20及LCD 1602(温度检测与显示)

 

1.首先是LCD1602模块,用于把读出的温度进行展示,LcdStar()用于对显示器的初始化,可以按照所需进行定制初始化。LcdWriteDat()表示向LCD写入字节类型的数据,LcdSetCursor(unsigned char x, unsigned char y)表示写入字节的位置,即屏幕坐标。LcdShowStr(unsigned char x, unsigned char y, unsigned char *str)就是对两个函数的综合。代码如下。

#include <reg52.h>
#define LCD1602_DB P0
sbit LCD1602_RS = P2^0;
sbit LCD1602_RW = P2^1;
sbit LCD1602_E = P2^2;
void InitLcd1602();
int n=0;
int i=0;
int j=0;
int l=0;
int ii=0;
void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);
void LcdWriteCmd(unsigned char cmd);
void delay(unsigned int j);

void LcdStar()
{
	unsigned char str1[] = "Welcome to aau";
	unsigned char str2[] = "No .5         ";
	unsigned char str3[] = "              ";
	unsigned char str4[] = "              ";
//	unsigned char tab[]="Temp="; 
	InitLcd1602();/* 初始化 1602 液晶 */
//	LcdShowStr(2, 0, str);
//	LcdShowStr(1, 1, tab);
	LcdShowStr(9, 1, "...");//默认初始化温度00
//	LcdShowStr(12, 1,0XDF);
	LcdShowStr(14, 1,"C");//添加C温度
//	LcdShowStr(1, 1, str2);
		 for(i=0;i<14;i++){
//	   			  for(j=i,l=0;j<14;j++,l++){
//				  		str3[l]=str1[j];
//						str4[l]=str2[j];
//				  }
//		  LcdShowStr(2, 0, str3);
//		  for(ii=0;ii<14;ii++){
//		  str3[ii]=0x00;
//		  }
//	   	   delay(100);
//		   LcdWriteCmd(0x01);
//		   LcdShowStr(1, 1, str2);	  
		 }


	LcdWriteCmd(0x01); //清屏	
		
}
  void delay(unsigned int jj){
	unsigned char i=250;
	for(;jj>0;jj--){
	while(--i);
	i=249;
	while(--i);
	i=250;
	}

}

/* 等待液晶准备好 */
void LcdWaitReady()
{
	unsigned char sta;
	LCD1602_DB = 0xFF;
	LCD1602_RS = 0;
	LCD1602_RW = 1;
	do {
		LCD1602_E = 1;
		sta = LCD1602_DB; //读取状态字
		LCD1602_E = 0;
	} while (sta & 0x80); //bit7 等于 1 表示液晶正忙,重复检测直到其等于 0 为止
}
/* 向 LCD1602 液晶写入一字节命令, cmd-待写入命令值 */
void LcdWriteCmd(unsigned char cmd)
{
	LcdWaitReady();
	LCD1602_RS = 0;
	LCD1602_RW = 0;
	LCD1602_DB = cmd;
	LCD1602_E = 1;
	LCD1602_E = 0;
}
/* 向 LCD1602 液晶写入一字节数据, dat-待写入数据值 */
void LcdWriteDat(unsigned char dat)
{
	LcdWaitReady();
	LCD1602_RS = 1;
	LCD1602_RW = 0;
	LCD1602_DB = dat;
	LCD1602_E = 1;
	LCD1602_E = 0;
}
/* 设置显示 RAM 起始地址,亦即光标位置, (x,y)-对应屏幕上的字符坐标 */
void LcdSetCursor(unsigned char x, unsigned char y)
{
	unsigned char addr;
	if (y == 0) //由输入的屏幕坐标计算显示 RAM 的地址
		addr = 0x00 + x; //第一行字符地址从 0x00 起始
	else
		addr = 0x40 + x; //第二行字符地址从 0x40 起始
	LcdWriteCmd(addr | 0x80); //设置 RAM 地址
}
/* 在液晶上显示字符串, (x,y)-对应屏幕上的起始坐标, str-字符串指针 */
void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str)
{
	LcdSetCursor(x, y); //设置起始地址
	while (*str != '\0') //连续写入字符串数据,直到检测到结束符
	{
		LcdWriteDat(*str++); //先取 str 指向的数据,然后 str 自加 1
	}
}
/* 初始化 1602 液晶 */
void InitLcd1602()
{
	LcdWriteCmd(0x38); //16*2 显示, 5*7 点阵, 8 位数据接口
	LcdWriteCmd(0x0C); //显示器开,光标关闭
	LcdWriteCmd(0x06); //文字不动,地址自动+1
	LcdWriteCmd(0x01); //清屏
}

将代码保存为LCD1602.h

2.DS18B20模块,工作原理为读出16位二进制数据,前五位代表符号位,后十一位表示数据位。并且为补码表示,如果是负数就要对后十一位数据进行取反加一进行运算,符号位不变,也不参加运算。由于分辨率默认为0.0625,所以需要将所得的数×0.0625。或者÷16,此代码中是在主函数中进行4位移位运算。得到我们需要的温度。具体代码如下:

#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int 
void delay5(uchar);
void init_ds18b20(void);
uchar readbyte(void);
void writebyte(uchar);
void retemp(int);
sbit DQ=P3^2;

void delay5(uchar n)		//函数功能:延时5μs
{
	 do
	 {
	 	_nop_();
	 	_nop_();
	 	_nop_();
	 	n--;
	 }
	 while(n);
}

void init_ds18b20(void)	//函数功能:18B20初始化
{
	 uchar x=0; 
	 DQ =0;    
	 delay5(120); 
	 DQ =1;    
	 delay5(16);
	 delay5(80);
}
uchar readbyte(void) 	{		//函数功能:读取1字节数据
	uchar dat;
	uchar mask;
	EA = 0; //禁止总中断
	for (mask=0x01; mask!=0; mask<<=1) //低位在先,依次采集 8 个 bit
	{
	DQ = 0; //产生 2us 低电平脉冲
	_nop_();
	_nop_();
	DQ = 1; //结束低电平脉冲,等待 18B20 输出数据
	_nop_(); //延时 2us
	_nop_();
	if (!DQ) //读取通信引脚上的值
		dat &= ~mask;
	else
		dat |= mask;
delay5(60); //再延时 60us
	}
	EA = 1; //重新使能总中断
	return dat;
}
void writebyte(uchar dat) {	//函数功能:写1字节
uchar i=0;
 for(i=8;i>0;i--) {
	  DQ =0;
	  DQ =dat&0x01;		//写"1" 在15μs内拉低
	  delay5(12);	   		//写"0" 拉低60μs
	  DQ = 1;	   
	  dat>>=1;
	  delay5(5);
	  }
}
void retemp(int *temp) {	    	
	uchar a,b;
	uint t;
	init_ds18b20();
	writebyte(0xCC); 
	writebyte(0x44);
	init_ds18b20();
	writebyte(0xCC); 
	writebyte(0xBE); 
	a=readbyte();
	b=readbyte();
	t=b;
	t<<=8;
	t=t|a;
//	*temp = t*0.0625;
	*temp = (((int)b << 8) + a);

}

将代码保存为DS18B20_1.h(别问为什么加了_1因为头文件写的太多了,为了方便调试,又加了一个,为了标准,可以直接去掉,但是主函数中记得改引入的头文件)。

3.主函数模块:主函数就是将两块代码进行整合,其中有一个将数字转化成字符串函数,是因为LCD1602不能输出数字。具体代码如下:

#include <reg52.h>
#include<DS18B20.h>
#include<LCD1602.h>
#include<DS18B20_1.h>
bit flag1s = 0; //1s 定时标志
unsigned char T0RH = 0; //T0 重载值的高字节
unsigned char T0RL = 0; //T0 重载值的低字节
void ConfigTimer0(unsigned int ms);
unsigned char IntToString(unsigned char *str, int dat);
extern void init_ds18b20();
extern void retemp(int *temp);
extern void InitLcd1602();
extern void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);
void main()
{

	int temp; //读取到的当前温度值
	int intT, decT; //温度值的整数和小数部分
	unsigned char len;
	unsigned char str[12];
	unsigned char tab[]="Temp=";
	EA = 1; //开总中断
	ConfigTimer0(10); //T0 定时 10ms
//	Start18B20(); //启动 DS18B20
	InitLcd1602(); //初始化液晶
	LcdStar();
	while (1)
	{
	if (flag1s) //每秒更新一次温度
	{
		flag1s = 0;
		retemp(&temp); //读取当前温度			  
			intT = temp >> 4; //分离出温度值整数部分
			decT = temp & 0xF; //分离出温度值小数部分
			len = IntToString(str, intT); //整数部分转换为字符串
			str[len++] = '.'; //添加小数点
			decT = (decT*10) / 16; //二进制的小数部分转换为 1 位十进制位
			if(	intT<0){
				
					decT=10-decT;
				
			}
			str[len++] = decT + '0'; //十进制小数位再转换为 ASCII 字符
			while (len < 6) //用空格补齐到 6 个字符长度
			{
				str[len++] = ' ';
			}
	str[len] = '\0'; //添加字符串结束符

	LcdShowStr(1, 1, tab);
	LcdShowStr(7, 1, str); //显示到液晶屏上
	LcdShowStr(12, 1,0xdf);
	LcdShowStr(14, 1,"C");//添加C温度

	}


	}
	
}
/* 整型数转换为字符串, str-字符串指针, dat-待转换数,返回值-字符串长度 */
unsigned char IntToString(unsigned char *str, int dat)
{
	signed char i = 0;
	unsigned char len = 0;
	unsigned char buf[6];
	if (dat < 0) //如果为负数,首先取绝对值,并在指针上添加负号
	{
		dat = -dat-1;
		*str++ = '-';
		len++;
	}
	do { //先转换为低位在前的十进制数组
			buf[i++] = dat % 10;
			dat /= 10;
	} while (dat > 0);
	len += i; //i 最后的值就是有效字符的个数
	while (i-- > 0) //将数组值转换为 ASCII 码反向拷贝到接收指针上
	{
		*str++ = buf[i] + '0';
		}
	*str = '\0'; //添加字符串结束符
	return len; //返回字符串长度
	}
/* 配置并启动 T0, ms-T0 定时时间 */
void ConfigTimer0(unsigned int ms)
{
	unsigned long tmp; //临时变量
	tmp = 11059200 / 12; //定时器计数频率
	tmp = (tmp * ms) / 1000; //计算所需的计数值
	tmp = 65536 - tmp; //计算定时器重载值
	tmp = tmp + 12; //补偿中断响应延时造成的误差
	T0RH = (unsigned char)(tmp>>8); //定时器重载值拆分为高低字节
	T0RL = (unsigned char)tmp;
	TMOD &= 0xF0; //清零 T0 的控制位
	TMOD |= 0x01; //配置 T0 为模式 1
	TH0 = T0RH; //加载 T0 重载值
	TL0 = T0RL;
	ET0 = 1; //使能 T0 中断
	TR0 = 1; //启动 T0
}
/* T0 中断服务函数,完成 1 秒定时 */
void InterruptTimer0() interrupt 1
{
	static unsigned char tmr1s = 0;
	TH0 = T0RH; //重新加载重载值
	TL0 = T0RL;
	tmr1s++;
	if (tmr1s >= 100) //定时 1s
	{
		tmr1s = 0;
		flag1s = 1;
	}
}

原理图以及hex文件连接如下:

链接:https://pan.baidu.com/s/1WR04LHYcTlr2i-M_9fbwnA?pwd=h4e0 
提取码:h4e0 
闫老师可以提问问题:负小数是怎么显示出来的:对读出的十一位数据位进行反码加一,转换成再十进制,代码中表示如下:实验09 DS18B20及LCD 1602(温度检测与显示)

转换成十进制后,如果小数小于零,就对其进行十减,整数部分进行取反。

整个工程如下实验09 DS18B20及LCD 1602(温度检测与显示)添加头文件操作如下:实验09 DS18B20及LCD 1602(温度检测与显示) 

添加时,头文件和主函数在同一个目录,编译后就会变成下面。 文章来源地址https://www.toymoban.com/news/detail-482026.html

到了这里,关于实验09 DS18B20及LCD 1602(温度检测与显示)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于51单片机的DS18B20温度显示

    本讲内容:       了解温度传感器DS18B20的使用,并通过一个例程展示温度传感器DS18B20测温过程。 DS18B20简介:       DS18B20 是单线数字温度传感器,即“一线器件”,其具有独特的优点:     (1)采用单总线的接口方式 与微处理器连接时 仅需要一条口线即可实现微处理器

    2024年02月12日
    浏览(38)
  • STM32读取DS18B20温度,并在OLED上显示

    部分代码来源于网络,侵权删 本文使用硬件:STM32F103C8T6最小系统板、IIC协议0.96寸OLED屏幕显示、DS18B20传感器  实现功能:在OLED上显示出DS18B20采集到的温度,精确到小数点后一位。 DS18B20.c DS18B20.h main.c 实物效果图: 工程文件百度网盘链接:链接:https://pan.baidu.com/s/17QLXeaq2

    2024年02月15日
    浏览(27)
  • 基于51单片机多路温度检测proteus仿真 ds18b20

    本设计是基于51单片机多路温度检测proteus仿真_ds18b20(仿真+程序+原理图) 仿真图proteus 7.8 程序编译器:keil 4/keil 5 编程语言:C语言 设计编号:C0042 功能说明: 通过对多路DS18B20温度传感器的数据采集,实现8路/4路温度采集并将数值显示在LCD显示屏上; 通过按键设置温度报警

    2024年02月12日
    浏览(36)
  • STM32CubeMX 读取DS18B20温度传感器数据串口打印显示

    本文要做的所有工作标题基本都包括了,读取温度传感器的温度数值,再通过串口打印到串口助手; 好多博主大神的教程我按步骤做了之后总是出现程序不报错并且检测不到传感器的情况,后来找到原因并且修改后调试正常。 我用的是普中科技的实验板,主控芯片为STM3210

    2024年02月05日
    浏览(63)
  • 通过stm32读取DS18B20并在显示屏上显示温度值(附源码)

    使用stm32f103c8t6的芯片,在OLED显示屏上显示DS18B20的温度值。 DS18B20 数字温度计提供 9 位温度读数,指示器件的温度信息经过单线接口送入 DS18B20 或从 DS18B20 送出, 因此从中央处理器到 DS18B20 仅需连接一条线。 读、写和完成温度变换所需的电源可以由数据线本身提供而不需要外

    2024年02月15日
    浏览(26)
  • DS18B20测量温度

    一般在使用DS18B20时会按照以下步骤进行温度转换并读取: 1、主机发送复位脉冲 2、DS18B20响应 3、发送0xCC命令跳过ROM命令 4、发送功能命令 5、发送功能命令0x44启动温度转换 6、判断温度转换是否完成(为读取1Bit数据为1表示完成) 7、下一个初始化序列开始读取温度 8、然后按

    2023年04月08日
    浏览(33)
  • 基于普中A2实验板,ds18b20温度传感器与ds1302时钟芯片的冲突现象的探讨

    在普中板上进行写较综合的项目时,是否会出现温度传感器经常出错的问题,明明是严格按照时序图所编写的程序就是无法读出正确的值(全为0),或许温度底层在其他工程里能正常运行,而到了某些工程中却总是出错。这些就是我经常遇到的问题。 那么问题的根源是什么

    2024年02月11日
    浏览(28)
  • 【基于STM32F103C8T6的DS18b20温度检测系统】

    库函数是ST公司针对STM32系列微控制器提供的一套API,可以方便地实现各种功能。下面是一个基于STM32F103C8T6的温度检测系统的示例,使用了STM32F10x标准库函数。 硬件部分: - STM32F103C8T6微控制器 - 电源模块 - 温度传感器模块 软件部分: - Keil C编译器 - STM32F10x_StdPeriph_Driver库文件

    2024年01月20日
    浏览(33)
  • DS18B20与单片机的通信、DS18B20采集温度、MODBUS协议、练习框架

    单总线数字温度计 异步的半双工的串行通信 测量范围从-55℃ ~ +125℃,增量值为0.5℃ 要用DS18B20采集温度,就要实现与单片机之间的通信,因此有两个问题 Bus master active low:主机执行低电平 DS1820 active low:DS18B20执行低电平 Both bus master and DS1820 active low:全都释放低电平 Resis

    2024年04月16日
    浏览(33)
  • DS18B20温度传感器工作原理

    目录 管脚描述 综述 访问DS18B20的事件序列 通信时序 VDD:电源引脚,当采用寄生电源的时候,VDD必须连接到地 DQ:单总线运用的数据输入/输出,当采用寄生电源供电时,同时向设备提供电源 GND:地 ①DS18B20片内的ROM中都存在独一无二的64位编码,在后期通信时,是用此编码进

    2024年02月09日
    浏览(26)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包