提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 程序代码和调试结果
  • 总结

前言

利用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;}}

总结

  1. 在一些函数中加入标志性的语句来判断该函数有没有被执行;
  2. 延时有多种方法,不同的延时方式产生不同效果,比如这里使用delay函数就会影响数码管动态扫描,使用定时器过多会影响18B20温度读取、数码管显示,使用if语句则能很好的达到目的;
  3. 多尝试,不害怕出错,及时记录调试方案总结升华

基于51单片机的温度检测相关推荐

  1. matlab ds18b20 单片机,基于51单片机ds18b20温度检测————设计报告.doc

    基于51单片机ds18b20温度检测----设计报告 课程名称: 微机原理课程设计 题 目: 温度检测课程设计 摘要 随着时代的进步和发展,单片机技术已经普及到我们生活,工作,科研,各个领域,已经成为 ...

  2. 基于51单片机的温度检测报警系统

    目录 具体实现功能 设计背景 硬件设计 软件设计 原理图 程序 仿真实现 全部资料 具体实现功能 系统由STC89C51单片机+液晶1602显示+DS18B20温度传感器+按键模块+报警模块构成. 具 ...

  3. 基于51单片机多路温度检测proteus仿真 ds18b20

    本设计是基于51单片机多路温度检测proteus仿真_ds18b20(仿真+程序+原理图) 仿真图proteus 7.8 程序编译器:keil 4/keil 5 编程语言:C语言 设计编号:C0042 ...

  4. 单片机51测温度c语言,基于51单片机的温度检测及显示设计

    2.2 软件设计 用C语言进行单片机程序设计,采用结构化程序设计思想:在总体设计中采用"自顶而下"(TOP-DOWN)的方法,在程序设计中采用模块化编程.把整体任务分成一个个子任务 ...

  5. 基于51单片机1602温度显示时钟

    基于51单片机LCD1602温度显示时钟 要在1602上显示时间和温度先要了解1602是如何显示的.详情可以参考我之前的文章基于51单片机1602显示 :时间显示可以用时钟芯片DS1302,但是此次我 ...

  6. 实物设计|基于51单片机的温湿度检测报警系统

    目录 具体实现功能: 设计介绍 51单片机简介 设计方案 资料内容 原理图和PCB(AD19) 仿真实现(protues8.7) 程序(Keil5) 全部资料(压缩文件) 具体实现功能: 由STC89 ...

  7. 综合小项目1--基于51单片机的温度检测报警系统

    目录 一. 系统简介 二. 系统设计 三. 实验设备 四. 实验过程 五. 系统测试 六. 总结 一. 系统简介   该系统是基于51单片机的温度监测报警系统.由主控模块.检测模块.显示模块以及报警模 ...

  8. 基于51单片机的火灾检测设计(仿真+程序+原理图+论文报告)

    本设计: 基于51单片机的火灾检测设计(仿真+程序+原理图+论文报告) Proteus仿真版本:proteus7.8 原理图:Altium Designer 程序编译器:keil 4 编程语言:C语言 ...

  9. 基于51单片机的废气检测I2Cproteus仿真

    目录 文章目录 前言 二.设计步骤 1.proteus设计 2.keil5代码编程设计 总结 前言 前段时间高中同学让我帮忙给她做一个数电课设,反正也没事做就随便做了做,现在总结一下,话不多说直接上效 ...

最新文章

  1. 高性能Linux服务器运维实战,《高性能Linux服务器构建实战》笔记
  2. python yield用法
  3. 舍友清华博士毕业,我建议他留在高校
  4. BigPipe学习研究
  5. 去哪面试都会问的HashMap
  6. postgresql9.4.4中文手册笔记-9.10 支持枚举函数
  7. 学python后做什么工作好_学习完Python课程后可以做什么工作?
  8. 写时复制就这么几行代码,还是不会?
  9. Frequent values【线段树】
  10. 值转换成布尔类型的False;
  11. java关键字值transient
  12. 【转】JS判断SWF,JPG加载完毕、兼容(Activex,plugIn)所有浏览器
  13. ATL COM类之激活
  14. Android系统移植与调试之-------如何修改Android手机显示的4G信号强度的格子数
  15. SitePoint播客#160:坐在树上的Adobe和HTML
  16. php导出excel 繁体,php导出excel并解决乱码问题的方法介绍
  17. 基恩士PLC④--MAIN程序实例笔记
  18. 献计《权力的游戏》珊莎•斯塔克
  19. cesium分屏对比
  20. 怎么将两段视频合并在一起?快速操作技巧

热门文章

  1. js如何将最大值和最小值之间的数划分为五个添加进新数组
  2. Bean与@Bean注解
  3. matlab的simplify
  4. 嵌入式开发要求的一些专业技能总结
  5. 吐血整理AutoSAR Com-Stack 的配置【基于ETAS】
  6. Python Hangman猜字游戏
  7. 基于Node.js+MySQL开发的开源微信小程序B2C商城(页面高仿网易严选) 1
  8. 努比亚android最高版本,努比亚Z17用户注意了,安卓9.0很快就要升级了
  9. ROS与navigation教程——ACML参数配置
  10. 使用STM32F103C8T6驱动NRF24L01具体步骤