基于51单片机的温度检测
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 前言
- 程序代码和调试结果
- 总结
前言
利用51单片机为核心实现温度测量,利用DS18B20温度传感器获取温度信号,将需要测量的温度信号转化为数字信号,利用单总线和单片机交换数据,最终单片机将识别的温度以数码管显示和串口返回数据的形式输出。本次程序使用的是清翔51单片机,温度测量范围为-10~+85°C,精度为+-0.5°C。
使用步骤
1.最终成果代码
代码如下:
#include <reg52.h>
#include <intrins.h>
#include <stdio.h>#define uint unsigned int
#define uchar unsigned charsbit WE = P2^7;
sbit DU = P2^6;
sbit DS = P2^2;
uint temp,a=0;uchar code SMGwei[] = {0xfe,0xfd,0xfb};//共阴数码管段选表0-9
uchar code SMGduan[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,};//数码管位选码//us延时函数,执行一次us--需6.5us,进入一次函数需11.95us
void delay_us(uchar us)
{while(us--);
}//数码管显示
void display(uchar i)
{static uchar wei;P0 = 0xfe;//清除断码WE = 1;//打开位选锁存P0 = SMGwei[wei];//WE = 0;switch(wei){case 0:DU = 1;P0 = SMGduan[i / 100]; DU = 0;break;case 1:DU = 1;P0 = SMGduan[i % 100 /10]|0x80; DU = 0;break;case 2:DU = 1;P0 = SMGduan[i % 10]; DU = 0;break;}wei++;if(wei == 3)wei = 0;
}bit ds_init()
{bit i;DS = 1;_nop_();DS = 0;delay_us(75);//拉低总线499.45us,挂接在总线上的18B20将会全部复位DS = 1;//释放总线delay_us(4);//延时37.95us等待18B20发挥存在信号i = DS;delay_us(20);//延时141.95usDS = 1;_nop_();return (i);
}//写一个字节
void write_byte(uchar dat)
{uchar i;for(i=0;i<8;i++){DS = 0;_nop_();DS = dat & 0x01;delay_us(10);DS = 1;//释放总线,准备下一次数据写入_nop_();dat >>= 1;}
}uchar read_byte()
{uchar i,j,dat;for(i=0;i<8;i++){DS = 0;_nop_();//产生读时序DS = 1;_nop_();j = DS;delay_us(10);//76.95usDS = 1;_nop_();dat = (j<<7)|(dat>>1);}return (dat);
}//定时器0初始化
void timer0Init()
{EA = 1;//打开总中断ET0 = 1;//打开定时器0中断TR0 = 1;//启动定时器0TMOD |= 0x01;//定时器工作模式,16位定时模式TH0 = 0xed;TL0 = 0xff;//定时5ms
}//串口初始化
void UARTInit()
{EA = 1;ES = 1;//打开串口中断SCON = 0x50;//串口工作方式REN = 1;//串口允许接收TR1 = 1;//启动定时器1TMOD |= 0x20;// 定时器1,工作模式2,8位自动重装TH1 |= 0xfd;//TL1 |= 0xfd;//设置比特率9600
}void main ()
{uint L,M;UARTInit();timer0Init();while(1){ EA = 0;ds_init();//初始化DS18B20write_byte(0xcc);//发送跳跃ROM指令write_byte(0x44);//发送温度转换指令ds_init();//初始化DS18B20write_byte(0xcc);//发送跳跃ROM指令write_byte(0xbe);//读取DS18B20暂存器L = read_byte();M = read_byte();temp = M;temp <<= 8;temp |= L;temp = temp*0.0625*10+0.5;EA = 1;}
}//定时器0中断函数
void timer0() interrupt 1
{a++;TH0 = 0xed;TL0 =0xff;display(temp);if(a==200){TI = 1;printf("现在的温度为%d\n",temp);while(!TI);TI = 0;a = 0;}}
2.出现的一些问题和错误
代码如下(示例):
//定时器0初始化
void timer0Init()
{EA = 1;//打开总中断ET0 = 1;//打开定时器0中断TR0 = 1;//启动定时器0TMOD |= 0x01;//定时器工作模式,16位定时模式TH0 = 0xed;TL0 = 0xff;//定时5ms
}//定时器1初始化
void timer1Init()
{EA = 1;//打开总中断ET1 = 1;//打开定时器0中断TR1 = 1;//启动定时器0TMOD |= 0x10;//定时器1工作模式,16位定时模式TH1 |= 0xed;TL1 |= 0xff;//定时5ms
}//串口初始化
void UARTInit()
{EA = 1;ES = 1;//打开串口中断SCON = 0x50;//串口工作方式REN = 1;//串口允许接收TR1 = 1;//启动定时器1TMOD |= 0x20;// 定时器1,工作模式2,8位自动重装TH1 |= 0xfd;//TL1 |= 0xfd;//设置比特率9600
}void main ()
{uint L,M;UARTInit();timer0Init();while(1){ //EA = 0;//此处应先屏蔽中断,是的18B20进行温度转换时不受干扰,因为我们的51板子是I2C单总线通信,同时进行中断会影响数据输出,数码管数据显示会被其他不知名的数字覆盖,或者显示数据错乱,起初我是没有屏蔽中断的ds_init();//初始化DS18B20write_byte(0xcc);//发送跳跃ROM指令write_byte(0x44);//发送温度转换指令ds_init();//初始化DS18B20write_byte(0xcc);//发送跳跃ROM指令write_byte(0xbe);//读取DS18B20暂存器L = read_byte();M = read_byte();temp = M;temp <<= 8;temp |= L;temp = temp*0.0625*10+0.5;//EA = 1;//打开中断,使定时器正常运行,数码管显示温度}
}//定时器0中断函数
void timer0() interrupt 1
{
// a++;LED = 0;TH0 = 0xed;TL0 =0xff;display(temp);
// if(a==200)
// {
// TI = 1;
// printf("现在的温度为%d\n",temp);
// while(!TI);
// TI = 0;
// a = 0;
// }}//定时器1中断函数
void timer1() interrupt 3
{ TH1 |= 0xed;TL1 |=0xff;LED = 0;TI = 1;printf("现在的温度为%d\n",temp);delay(10);while(!TI);TI = 0;}
起初我为了串口也能返回数据,将串口接收打印汉字程序添加到定时器0中,如下
//定时器0中断函数
void timer0() interrupt 1
{TH0 = 0xed;TL0 =0xff;display(temp);TI = 1;printf("现在的温度为%d\n",temp);delay(10);//为了避免串口打印频率过高while(!TI);TI = 0;
}
但这样即使不使用delay函数,由于其他语句占用太多时间,display函数执行次数减少,数码管动态扫描次数不够,数码管显示出现频闪
于是我将串口打印添加到定时器1中,如下
//定时器0初始化
void timer0Init()
{EA = 1;//打开总中断ET0 = 1;//打开定时器0中断TR0 = 1;//启动定时器0TMOD |= 0x01;//定时器工作模式,16位定时模式TH0 = 0xed;TL0 = 0xff;//定时5ms
}//定时器1初始化
void timer1Init()
{EA = 1;//打开总中断ET1 = 1;//打开定时器0中断TR1 = 1;//启动定时器0TMOD |= 0x10;//定时器1工作模式,16位定时模式TH1 |= 0xed;TL1 |= 0xff;//定时5ms
}//串口初始化
void UARTInit()
{EA = 1;ES = 1;//打开串口中断SCON = 0x50;//串口工作方式REN = 1;//串口允许接收TR1 = 1;//启动定时器1TMOD |= 0x20;// 定时器1,工作模式2,8位自动重装TH1 |= 0xfd;//TL1 |= 0xfd;//设置比特率9600
}void main ()
{uint L,M;UARTInit();timer0Init();timer1Init();while(1){ ds_init();//初始化DS18B20write_byte(0xcc);//发送跳跃ROM指令write_byte(0x44);//发送温度转换指令ds_init();//初始化DS18B20write_byte(0xcc);//发送跳跃ROM指令write_byte(0xbe);//读取DS18B20暂存器L = read_byte();M = read_byte();temp = M;temp <<= 8;temp |= L;temp = temp*0.0625*10+0.5;}
}//定时器0中断函数
void timer0() interrupt 1
{TH0 = 0xed;TL0 =0xff;display(temp);LED1 = 0;//添加小灯观察是否进入中断}//定时器1中断函数
void timer1() interrupt 3
{ TH1 |= 0xed;TL1 |=0xff;LED2 = 0;//添加小灯,观察是否进入中断函数TI = 1;printf("现在的温度为%d\n",temp);while(!TI);TI = 0;}
结果LED1、2均亮起,数码管显示0,串口打印一次“现在温度为0”;
究其原因,是定时器1既被用作波特率计算,又当定时器计时,会发生混乱,且定时器之间存在优先级,多个定时器设计的定时时间一样时不能同时执行中断函数,故要想达到“串口打印温度且打印频率适中”、“数码管显示温度且不频闪”的目的,在不能使用定时器1中断时,
可按如下程序的构思
//定时器0中断函数
void timer0() interrupt 1
{a++;TH0 = 0xed;TL0 =0xff;display(temp);if(a==200)//使a加加延长时间,在a加到200之前不会执行if语句,故而不影响数码管动态扫描{TI = 1;printf("现在的温度为%d\n",temp);while(!TI);TI = 0;a = 0;}}
总结
- 在一些函数中加入标志性的语句来判断该函数有没有被执行;
- 延时有多种方法,不同的延时方式产生不同效果,比如这里使用delay函数就会影响数码管动态扫描,使用定时器过多会影响18B20温度读取、数码管显示,使用if语句则能很好的达到目的;
- 多尝试,不害怕出错,及时记录调试方案总结升华
基于51单片机的温度检测相关推荐
- matlab ds18b20 单片机,基于51单片机ds18b20温度检测————设计报告.doc
基于51单片机ds18b20温度检测----设计报告 课程名称: 微机原理课程设计 题 目: 温度检测课程设计 摘要 随着时代的进步和发展,单片机技术已经普及到我们生活,工作,科研,各个领域,已经成为 ...
- 基于51单片机的温度检测报警系统
目录 具体实现功能 设计背景 硬件设计 软件设计 原理图 程序 仿真实现 全部资料 具体实现功能 系统由STC89C51单片机+液晶1602显示+DS18B20温度传感器+按键模块+报警模块构成. 具 ...
- 基于51单片机多路温度检测proteus仿真 ds18b20
本设计是基于51单片机多路温度检测proteus仿真_ds18b20(仿真+程序+原理图) 仿真图proteus 7.8 程序编译器:keil 4/keil 5 编程语言:C语言 设计编号:C0042 ...
- 单片机51测温度c语言,基于51单片机的温度检测及显示设计
2.2 软件设计 用C语言进行单片机程序设计,采用结构化程序设计思想:在总体设计中采用"自顶而下"(TOP-DOWN)的方法,在程序设计中采用模块化编程.把整体任务分成一个个子任务 ...
- 基于51单片机1602温度显示时钟
基于51单片机LCD1602温度显示时钟 要在1602上显示时间和温度先要了解1602是如何显示的.详情可以参考我之前的文章基于51单片机1602显示 :时间显示可以用时钟芯片DS1302,但是此次我 ...
- 实物设计|基于51单片机的温湿度检测报警系统
目录 具体实现功能: 设计介绍 51单片机简介 设计方案 资料内容 原理图和PCB(AD19) 仿真实现(protues8.7) 程序(Keil5) 全部资料(压缩文件) 具体实现功能: 由STC89 ...
- 综合小项目1--基于51单片机的温度检测报警系统
目录 一. 系统简介 二. 系统设计 三. 实验设备 四. 实验过程 五. 系统测试 六. 总结 一. 系统简介 该系统是基于51单片机的温度监测报警系统.由主控模块.检测模块.显示模块以及报警模 ...
- 基于51单片机的火灾检测设计(仿真+程序+原理图+论文报告)
本设计: 基于51单片机的火灾检测设计(仿真+程序+原理图+论文报告) Proteus仿真版本:proteus7.8 原理图:Altium Designer 程序编译器:keil 4 编程语言:C语言 ...
- 基于51单片机的废气检测I2Cproteus仿真
目录 文章目录 前言 二.设计步骤 1.proteus设计 2.keil5代码编程设计 总结 前言 前段时间高中同学让我帮忙给她做一个数电课设,反正也没事做就随便做了做,现在总结一下,话不多说直接上效 ...
最新文章
- 高性能Linux服务器运维实战,《高性能Linux服务器构建实战》笔记
- python yield用法
- 舍友清华博士毕业,我建议他留在高校
- BigPipe学习研究
- 去哪面试都会问的HashMap
- postgresql9.4.4中文手册笔记-9.10 支持枚举函数
- 学python后做什么工作好_学习完Python课程后可以做什么工作?
- 写时复制就这么几行代码,还是不会?
- Frequent values【线段树】
- 值转换成布尔类型的False;
- java关键字值transient
- 【转】JS判断SWF,JPG加载完毕、兼容(Activex,plugIn)所有浏览器
- ATL COM类之激活
- Android系统移植与调试之-------如何修改Android手机显示的4G信号强度的格子数
- SitePoint播客#160:坐在树上的Adobe和HTML
- php导出excel 繁体,php导出excel并解决乱码问题的方法介绍
- 基恩士PLC④--MAIN程序实例笔记
- 献计《权力的游戏》珊莎•斯塔克
- cesium分屏对比
- 怎么将两段视频合并在一起?快速操作技巧