DS18B20温度传感器和数码管显示例程
- 格式:doc
- 大小:44.50 KB
- 文档页数:7
18b20测温数码管显示实验--精确到小数点后4位//滑国虎于09.9.20完成////DS18B20的读写程序,数据脚P1.5 ////温度传感器18B20程序,采用器件默认的12位转化 ////最大转化时间750微秒,显示温度-55到+125度,显示精度 // //为0.1度,显示采用4位LED共阳显示测温值 ////P0口为段码输入,P27~P21为位选 ///***************************************************/#include "reg51.h"#include "intrins.h" //_nop_();延时函数用 #define Disdata P0 //段码输出口 #define discan P2 //扫描口 #define uchar unsigned char #define uint unsigned intsbit DQ=P1^5; //温度输入口 sbit DIN=P0^7; //LED小数点控制 uint h;uint temp;//uchar codedis_7[12]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0x bf};//共阳LED段码表 "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "不亮""-"uchar code scan_con[7]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd}; //列扫描控制字uchar data temp_data[2]={0x00,0x00}; //读出温度暂放 uchar data display[7]={0x00,0x00,0x00,0x00,0x00,0x00,0x00}; //显示单元数据,共4个数据和一个运算暂用/*****************11us延时函数*************************///void delay(uint t) //11us{for (;t>0;t--);}///****************DS18B20复位函数************************/ow_reset(void){char presence=1;while(presence){while(presence){DQ=1;_nop_();_nop_();//从高拉倒低DQ=0;delay(50); //550 usDQ=1;delay(6); //66 uspresence=DQ; //presence=0 复位成功,继续下一步}delay(45); //延时500 uspresence=~DQ;}DQ=1; //拉高电平 }/****************DS18B20写命令函数************************/ //向1-WIRE 总线上写1个字节void write_byte(uchar val){uchar i;for(i=8;i>0;i--){DQ=1;_nop_();_nop_(); //从高拉倒低DQ=0;_nop_();_nop_();_nop_();_nop_(); //5 usDQ=val&0x01; //最低位移出delay(6); //66 usval=val/2; //右移1位}DQ=1;delay(1);}/****************DS18B20读1字节函数************************/ //从总线上取1个字节uchar read_byte(void){uchar i;uchar value=0;for(i=8;i>0;i--){DQ=1;_nop_();_nop_();value>>=1;DQ=0;_nop_();_nop_();_nop_();_nop_(); //4 usDQ=1;_nop_();_nop_();_nop_();_nop_(); //4 usif(DQ)value|=0x80;delay(6); //66 us}DQ=1;return(value);}/****************显示扫描函数***************************/ scan(){char k;for(k=0;k<7;k++) //4位LED扫描控制{Disdata=dis_7[display[k]]; //数据显示 P0if (k==2){DIN=0;} //小数点显示 P0.7discan=scan_con[k]; //位选 P2delay(150);discan=0xff;}}/****************读出温度函数************************/ //read_temp(){ow_reset(); //总线复位delay(200);write_byte(0xcc); //发命令write_byte(0x44); //发转换命令ow_reset();delay(1);write_byte(0xcc); //发命令write_byte(0xbe);temp_data[0]=read_byte(); //读温度值的低字节temp_data[1]=read_byte(); //读温度值的高字节temp=temp_data[1];temp=temp&0x0f; //去掉符号位temp=temp<<8; //temp为16位temp=temp|temp_data[0]; // 两字节合成一个整型变量。
最近天气热了,想要是做个能显示温度的小设备就好了,于是想到DIY个电子温度计,网上找了很多资料,结合自己的材料,设计了这个用单片机控制的实时电子温度计。
作为单片机小虾的我做这个用了2天时间,当然是下班后,做工不行见谅了。
主要元件用到了单片机STC89C54RD+,DB18B20温度传感器,4为共阳数码管,PNPS8550三极管等。
先上原理图:洞洞板布局图:然后就是实物图了:附上源程序:程序是别人写的,我只是自己修改了下,先谢谢原程序者的无私奉献。
#include"reg52.h"#define uchar unsigned char#define uint unsigned intsbit DQ=P3^4; //温度数据口sbit wx1=P2^0; //位选1sbit wx2=P2^1; //位选2sbit wx3=P2^2; //位选3sbit wx4=P2^3; //位选4unsigned int temp, temp1,temp2, xs;uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99, //共阳数码管0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6};/******延时程序*******/void delay1(unsigned int m){unsigned int i,j;for(i=m;i>0;i--)for(j=110;j>0;j--);}void delay(unsigned int m) //温度延时程序{while(m--);}void Init_DS18B20(){unsigned char x=0;DQ = 1; //DQ复位ds18b20通信端口delay(8); //稍做延时DQ = 0; //单片机将DQ拉低delay(80); //精确延时大于480usDQ = 1; //拉高总线delay(4);x=DQ; //稍做延时后如果x=0那么初始化成功x=1那么初始化失败delay(20);}/***********ds18b20读一个字节**************/uchar ReadOneChar(){unsigned char i=0;unsigned char dat = 0;for (i=8;i>0;i--){DQ = 0; // 高电平拉成低电平时读周期开始dat>>=1;DQ = 1; // 给脉冲信号if(DQ)dat|=0x80; //delay(4);}return(dat);}/*************ds18b20写一个字节****************/void WriteOneChar(unsigned char dat){unsigned char i=0;for (i=8; i>0; i--){DQ = 0; //从高电平拉至低电平时,写周期的开始DQ = dat&0x01; //数据的最低位先写入delay(5); //60us到120us延时DQ = 1;dat>>=1; //从最低位到最高位传入}}/**************读取ds18b20当前温度************/void ReadTemperature(){unsigned char a=0;unsigned b=0;unsigned t=0;Init_DS18B20();WriteOneChar(0xCC); // 跳过读序号列号的操作/WriteOneChar(0x44); // 启动温度转换delay(5); // this message is wery importantInit_DS18B20();WriteOneChar(0xCC); //跳过读序号列号的操作WriteOneChar(0xBE); //读取温度存放器等〔共可读9个存放器〕前两个就是温度/ delay(5);a=ReadOneChar(); //读取温度值低位/b=ReadOneChar(); //读取温度值高位/temp1=b<<4; //高8位中后三位数的值temp1+=(a&0xf0)>>4; //低8位中的高4位值加上高8位中后三位数的值temp1室温整数值temp2=a&0x0f; //小数的值temp=((b*256+a)>>4); //当前采集温度值除16得实际温度值zhenshuxs=temp2*0.0625*10; //小数位,假设为0.5那么算为5来显示xs小数xiaoshu }void wenduxianshi(){wx1=0;P0=table[temp/10]; //显示百位delay1(5);wx1=1;wx2=0;P0=table[temp%10]+0x80; //显示十位加上0x80就显示小数点了。
这个是我自己制作的51单片机板上的DS18B20温度采集和显示程序,你如果有现成的51板稍微修改一下可以用,在我这里是可以用没问题的。
环境是KEIL。
我这个51板也完全符合你的要求。
#pragma db code#include<AT89X52.H>//#include "reg52.h"#include "INTRINS.H"// 此实验是使用18B20检测温度,然后在数码管上显示#define uchar unsigned char#define uint unsigned int#define BUSY1 (DQ1==0)sbit LED_0=P1^0;sbit LED_1=P1^1;sbit LED_2=P1^2;sbit LED_3=P1^3;sbit DQ1=P1^6;//void delay(uint x);void display(unsigned char d1,unsigned char d2,unsigned char d3,unsigned char d4);void ds_reset_1(void);void wr_ds18_1(char dat);void time_delay(unsigned char time);int get_temp_1(void);void delay(unsigned int x);void read_ROM(void);int get_temp_d(void);/*=====0-9=====A-G=====*/uchar a[16]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0x86,0x8e,0x82}; unsigned char ResultSignal;int ResultTemperatureLH,ResultT emperatureLL,ResultTemperatureH; unsigned char ROM[8];unsigned char idata TMP;unsigned char idata TMP_d;unsigned char f;unsigned char rd_ds18_1();unsigned int TemH,TemL;void main(){unsigned int TemH,TemL,k=0;ds_reset_1();ds_reset_1(); //resetwr_ds18_1(0xcc); //skip rom_nop_();wr_ds18_1(0x7f);ds_reset_1();wr_ds18_1(0xcc);_nop_();wr_ds18_1(0x44);for(k=0;k<11000;k++)time_delay(255);ds_reset_1();while(1){wr_ds18_1(0xcc);wr_ds18_1(0xbe);TemH=get_temp_1();TemL=get_temp_d();TemH&=0x00ff;TemL&=0x00ff;display((TemH/10),(T emH%10),(TemL/10),(TemL%10));}}/***************延时程序,单位us,大于10us*************/ void time_delay(unsigned char time){time=time-10;time=time/6;while(time!=0)time--;}/*****************************************************//* reset ds18b20 */ /*****************************************************/void ds_reset_1(void){unsigned char idata count=0;DQ1=0;time_delay(240);time_delay(240);DQ1=1;return;}void check_pre_1(void){while(DQ1);while(~DQ1);time_delay(30);}void read_ROM(void){int n;check_pre_1();wr_ds18_1(0x33);for(n=0;n<8;n++){ROM[n]=rd_ds18_1();}}/*****************************************************//* Read a bit from 1820 位读取*/ /*****************************************************/bit tmrbit_1(void){idata char i=0;bit dat;DQ1=0;_nop_();DQ1=1;_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();dat = DQ1;time_delay(50);return dat;}/*****************************************************//* read a bety from ds18b20 字节读取*/ /*****************************************************/unsigned char rd_ds18_1(){unsigned char idata i,j,dat=0;for(i=1;i<=8;i++){j=tmrbit_1();dat=(j<<(i-1))|dat;}return dat;}/*****************************************************//* write a bety from ds18b20 写字节*/ /****************************************************/void wr_ds18_1(char dat){signed char idata i=0;unsigned char idata j;bit testb;for(j=1;j<=8;j++){testb=dat & 0x01;dat = dat>>1;if(testb){DQ1=0;_nop_();_nop_();DQ1=1;time_delay(60);}else{DQ1=0;time_delay(50);DQ1=1;_nop_();_nop_();}}}int get_temp_1(void){unsigned char idata a=0,b=0; unsigned char idata i;EA=0;ds_reset_1();check_pre_1();wr_ds18_1(0xcc);wr_ds18_1(0x44);while(BUSY1);ds_reset_1();check_pre_1();wr_ds18_1(0xcc);wr_ds18_1(0xbe);a=rd_ds18_1();b=rd_ds18_1();i=b; /*若b为1则为负温*/ i=(i>>4);if(i==0){f=0;TMP=((a>>4)|(b<<4));a=(a&0x0f);if (a>8){TMP=(TMP+1);}}else{f=1;a=a>>4;b=b<<4;TMP=(a|b);TMP=~TMP;TMP=(TMP+1);}EA=1;return(TMP);}int get_temp_d(void){unsigned char idata a=0,b=0; unsigned char idata i,m;EA=0;ds_reset_1();//复位check_pre_1();wr_ds18_1(0xcc);wr_ds18_1(0x44);while(BUSY1);ds_reset_1();check_pre_1();wr_ds18_1(0xcc);wr_ds18_1(0xbe);a=rd_ds18_1();b=rd_ds18_1();i=b; /*若b为1则为负温*/ i=(i>>4);if(i==0){f=0;TMP=((a>>4)|(b<<4)); a=(a&0x0f);TMP_d=a;}else{f=1;a=~a;a=(a+1);b=~b;b=(b+1);m=a;a=a>>4;b=b<<4;TMP=(a|b);m=(m&0x0f);TMP_d=m;}EA=1;return(TMP_d);}void delay(unsigned int x) {unsigned int i;for(i=0;i<x;i++);}void display(unsigned char d1,unsigned char d2,unsigned char d3,unsigned char d4) {P2=a[d1];LED_0=0;delay(100);LED_0=1;P2=a[d2];LED_1=0;delay(100);LED_1=1;P2=a[d3];LED_2=0;delay(100);LED_2=1;P2=a[d4];LED_3=0;delay(100);LED_3=1;}。
以下是原理图:以下是原理图的程序设计:#include <reg52.h>#include<math.h>#define uchar unsigned charsbit DQ=P1^6;unsigned char tempL=0;unsigned char tempH=0;unsigned int tempa;uchar display_data[4]={0};uchar flag_fu=0; //温度正负值标志位float temperature; //温度值void DS18_delay(int useconds)//延时函数{int s;for (s=0; s<useconds;s++);}unsigned char Init_DS18B20(void){unsigned char x=0;DQ=0; //发送复位脉冲DS18_delay(29); //延时(>480ms)DQ=1; //拉高数据线DS18_delay(3); //等待(15~60ms) 等待存在脉冲x=DQ; //获得存在信号(用于判断是否有器件)DS18_delay(25); // 等待时间隙结束return(x); //返回存在信号,0 = 器件存在, 1 = 无器件}ReadOneChar(void)//读一个字节{unsigned char i=0;unsigned char dat=0;for (i=8;i>0;i--){DQ=1;DS18_delay(1);DQ=0;dat>>=1;//复合赋值运算,等效dat=dat>>1(dat=dat右移一位后的值) DQ=1;if(DQ)dat|=0x80;DS18_delay(4);}return(dat);}WriteOneChar(unsigned char dat){unsigned char i=0;for(i=8;i>0;i--){DQ=0;DQ=dat&0x01;DS18_delay(5);DQ=1;dat>>=1;}DS18_delay(4);}unsigned int ReadTemperature(void){Init_DS18B20();WriteOneChar(0xcc);WriteOneChar(0x44);DS18_delay(125);Init_DS18B20();WriteOneChar(0xcc);WriteOneChar(0xbe);tempL=ReadOneChar();tempH=ReadOneChar();tempa=((tempH*256)+tempL);if(tempa&0x8000){tempa=~tempa;tempa+=1;flag_fu=1;}else{flag_fu=0;}//温度转换,把高低位做相应的运算转化为实际温度temperature=tempa*0.625*8;DS18_delay(200);return temperature ;}void display(){unsigned char code dis[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0x7f,0xff};P3=0x01;P2=dis[display_data[0]];DS18_delay(10);P3=0x02;P2=dis[display_data[1]];DS18_delay(10);P3=0x04;P2=dis[display_data[2]]+0x80;DS18_delay(10);P3=0x08;P2=dis[display_data[3]];DS18_delay(10);}void main(){unsigned int temp;uchar i;while(1){temp=ReadTemperature();if(flag_fu==0){ if(temp>=1000){display_data[0]=temp/1000;display_data[1]=(temp/100)%10;display_data[2]=(temp/10)%10;display_data[3]=temp%10;}else if(temp>=100){display_data[0]=12;display_data[1]=temp/100;display_data[2]=(temp%100)/10;display_data[3]=temp%10;}else{ display_data[0]=12;display_data[1]=12;display_data[2]=temp/10;display_data[3]=temp%10;}}else{ if(abs(temp)>100){display_data[0]=10;display_data[1]=abs(temp)/100;display_data[2]=(abs(temp)%100)/10;display_data[3]=abs(temp)%10;}else{display_data[0]=12;display_data[1]=10;display_data[2]=abs(temp)/10;display_data[3]=abs(temp)%10;}}for(i=0;i<250;i++)display();}}。
ME300实例-DS18B20温度控制实验(汇编语言源程序)程序说明:DS18B20的管脚定义:1、GND2、DQ3、VCCDQ → P3.3K1 → P1.4K2 → P1.5K3 → P1.6K4 → P1.7JP2 用跳线帽短接1和2,选用LCD。
温度显示用四位,当温度>=100度时,第四位才显示。
检测 DS18B20 状态:DS18B20正常显示:DS18B20 OKTEMP: 25.8℃←显示实际温度DS18B20不正常显示:DS18B20 ERRORTEMP: ----℃←显示----这时你要检查DS18B20是否连接好、接对,否则要更换一个新的 DS18B20 芯片。
一、查看温度报警值:K1 →进入查看温度报警值状态。
LCD 1602 显示:LOOK ALERT CODETH:028℃ TL:18℃TH:028 高位报警值TL:18 低位报警值K3 →退出查看温度报警值状态。
二、设定温度报警值:K2 →进入设定温度报警值状态。
LCD 1602 显示:RESET ALERT CODETH:028℃ TL:18℃K1 : 设定值加(UP)、减(DOWN)方式选择键(默认为减少)K2 : TH值设定键K3 : TL值设定键K4 : 确定键(退出设定状态)K2 或 K3 以减(DOWN)方式设定,当设定数值减到“0”时自动转换为加(UP)方式。
K2 或 K3 以加(UP)方式设定,当设定数值 TH=120、TL=99 时,设定数值均变为“0”。
K4 →确定并退出设定温度报警值状态。
将设定的温度报警值自动存入 DS18B20 的 EEROM 中,可永久保存。
每次开机时自动从 DS18B20 的 EEROM 读出温度报警值。
三、报警状态的显示:1、当实际温度大于 TH 的设定值时,LCD1602 显示:DS18B20 OKTEMP: 88.8℃ > H关闭继电器,蜂鸣器响,表示超温。
#include<reg52.h>#include<intrins.h>#define uchar unsigned char#define uint unsigned intsbit w1=P2^4;sbit w2=P2^5;sbit w3=P2^6;sbit w4=P2^7;sbit DQ=P3^7;uint temp;float f_temp; //温度值variable of temperaturebit flag;uchar code table[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef };//uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,//0x4f,0x79,0x24,0x70,0x19,0x12,0x02,0x78,0x00,0x10};void delay(uint z){uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}void Init_Ds18b20(void) //DS18B20初始化send reset and initialization command {uint i;DQ = 0; //单片机拉低总线i=70;while(i>0)i--;DQ = 1; //释放总线,即拉高了总线i=4;while(i>0)i--;}bit Read_One_bit() //读取一个字节的数据read a byte date//读数据时,数据以字节的最低有效位先从总线移出{uint i;bit dat;DQ=0;i++;DQ=1;i++;i++;dat=DQ;i=3;while(i>0)i--;return (dat);}uchar Read_One_Byte(void){uchar i,j,dat;dat=0;for(i=1;i<=8;i++){j=Read_One_bit();dat=(j<<7)|(dat>>1);}return (dat);}void Write_One_Byte(uchar dat){uint i;uchar j;bit testb;for(j=1;j<=8;j++){testb=dat&0x01;dat=dat>>1;if(testb){DQ=0;i++;i++;DQ=1;i=5;while(i>0)i--;}else{DQ=0;i=5;while(i>0)i--;DQ=1;i++;i++;}}}void tmpchange(void){uchar f;Init_Ds18b20();f=70;while(f>0)f--;delay(1);Write_One_Byte(0xcc); //忽略ROM指令Write_One_Byte(0x44); //温度转换指令}uint Get_Tmp() //获取温度get the temperature{uchar a,b,f;Init_Ds18b20(); //初始化f=70;while(f>0)f--;Write_One_Byte(0xcc); //忽略ROM指令Write_One_Byte(0xbe); //温度转换指令a = Read_One_Byte(); //读取到的第一个字节为温度LSBb = Read_One_Byte(); //读取到的第一个字节为温度MSBtemp = b; //先把高八位有效数据赋于temptemp <<= 8; //把以上8位数据从temp低八位移到高八位temp = temp|a; //两字节合成一个整型变量f_temp = temp*0.0625; //temp = f_temp*10+0.5; //放大十倍f_temp=f_temp+0.5; // //同时进行一个四舍五入操作。
DS18B20和数码管的使用1温度传感器DS18B20的使用:DS1820 是这样测温的:用一个高温度系数的振荡器确定一个门周期,内部计数器在这个门周期内对一个低温度系数的振荡器的脉冲进行计数来得到温度值。
计数器被预置到对应于-55℃的一个值。
如果计数器在门周期结束前到达0,则温度寄存器(同样被预置到-55℃)的值增加,表明所测温度大于-55℃。
同时,计数器被复位到一个值,这个值由斜坡式累加器电路确定,斜坡式累加器电路用来补偿感温振荡器的抛物线特性。
然后计数器又开始计数直到 0,如果门周期仍未结束,将重复这一过程。
斜坡式累加器用来补偿感温振荡器的非线性,以期在测温时获得比较高的分辨力。
这是通过改变计数器对温度每增加一度所需计数的的值来实现的。
因此,要想获得所需的分辨力,必须同时知道在给定温度下计数器的值和每一度的计数值。
DS1820 内部对此计算的结果可提供 0.5℃的分辨力。
温度以 16bit 带符号位扩展的二进制补码形式读出,表 1 给出了温度值和输出数据的关系。
数据通过单线接口以串行方式传输。
DS1820 测温范围-55℃~+125℃,以 0.5℃递增。
如用于华氏温度,必须要用一个转换因子查找表。
注意 DS1820 内温度表示值为1/2℃LSB,如下所示 9bit 格式:最高有效(符号)位被复制充满存储器中两字节温度寄存器的高 MSB 位,由这种“符号位扩展”产生出了示于表 1 的 16bit 温度读数。
可用下述方法获得更高的分辨力。
首先,读取温度值,将 0.5℃位(LSB)从读取的值中截去,这个值叫做 TEMP_READ。
然后读取计数器中剩余的值,这个值是门周期结束后保留下来的值(COUNT_REMAIN)。
最后,我们用到在这个温度下每度的计数值(COUNT_PER_C)。
用户可以用下面的公式计算实际温度值:1 Ds1820 用 9 位存贮温值度最高位为符号位下图为 18b20 的温度存储方式负温度S=1 正温度 S=0 如 00AAH为+85 ,0032H为 25 FF92H为 552 Ds18b20用 12 位存贮温值度最高位为符号位下图为 18b20 的温度存储方式负温度S=1 正温度 S=0 如0550H为+85 0191H为 25.0625 ,FC90H为-55在我们编写的程序中,由于数码管只有四位能够显示,因此我们决定保留一位小数位,而以12位贮藏温度值的最小分度值为0.0625,即2-4。
;DS18B20温度传感器和7个LED数码显示程序(原创程序,请支持)ORG 0000H;LED数码管采用动态,P0口接八个数据口,P2.0-P2.2采用3-8译码器控制七个LED TX BIT P2.3 ;DS18B20数据口接P2.3FLAG BIT 10HTEMH EQU 50H ;整数部分TEML EQU 51H ;小数部分MOV SP,#60HCLR EAAJMP MAINORG 0200HMAIN:;MOV R0,#10LCALL TMP;温度传感器设置LCALL CHANG;温度转换为十进制STR:LCALL DISPLAY;温度显示;DJNZ R0,STRAJMP MAIN;//////////////////////////TMP:;温度传感器DS18B20LCALL RESERTMOV A,#0CCHLCALL WRITEMOV A,#44HLCALL WRITE;LCALL DELAY750;延时750MsLCALL RESERTMOV A,#0CCHLCALL WRITEMOV A,#0BEHLCALL WRITELCALL READMOV 30H,ALCALL READMOV 31H,ARETDELAY750:;750USDELAYSETB RS0MOV R0,#20MS2:MOV R1,#20MS1:MOV R2,#20DJNZ R2,$DJNZ R1,MS1DJNZ R0,MS2CLR RS0RET;////////////////////////////CHANG:;温度转换为十进制PUSH APUSH BMOV A,31HANL A,#07HSWAP AMOV B,AMOV A,30HANL A,#0F0HSWAP AADD A,BMOV TEMH,AMOV A,30HANL A,#0FHMOV TEML,AMOV A,31HJNB ACC.3,POSI;区分正负温度;//////////////负温度转化MOV A,TEMLSWAP ACPL AANL A,#0F0HADD A,#10HSWAP AMOV 1FH,CMOV TEML,AMOV A,TEMHCPL ASUBB A,#80HMOV C,1FHADDC A,#0MOV 70H,#20AJMP NEGPOSI:MOV A,TEMHMOV B,#100DIV ABMOV 70H,AMOV A,BNEG:MOV B,#10DIV ABMOV 71H,AMOV A,BADD A,#10MOV 72H,A;整数部分分离MOV A,TEMLMOV B,#5MUL ABMOV B,#10DIV ABMOV 76H,BMOV 75H,AMOV A,TEMLMOV B,#2MUL ABADD A,75HMOV B,#10DIV ABMOV 75H,BMOV 74H,AMOV A,TEMLMOV B,#6MUL ABADDC A,74HMOV B,#10DIV ABMOV 74H,BMOV 73H,A;小数部分分离POP BPOP ARET;//////////////////////DISPLAY:;温度显示70H---76H XXX.XXXX;采用默认的12位,精度0.0625,-55~~+125 SETB RS0MOV R0,#70HMOV R1,#7MOV R2,#0MOV DPTR,#TABLE DIS:MOV A,@R0MOVC A,@A+DPTR MOV P2,R2MOV P0,AINC R2INC R0LCALL DELAY1MS DJNZ R1,DISCLR RS0RET;/////////////////////////DELAY1MS:SETB RS1MOV R0,#100MS:MOV R1,#20DJNZ R1,$DJNZ R0,MSCLR RS1RET;//////////////////// RESERT:;DS18B20初始化;SETB RS0SETB TXNOPCLR TXMOV R0,#240;RST:CLR TXDJNZ R0,$;DELAY480US SETB TXMOV R1,#30;DELAY 60US DJNZ R1,$JNB TX,RE1CLR FLAGSETB TXRETRE1:SETB FLAGMOV R2,#200DJNZ R2,$ ;DELAY 400us SETB TXRET;///////////WRITE:;DS18B20写字节;SETB RS0CLR CMOV R0,#8WW:MOV R1,#6MOV R2,#23RRC ACLR TXDJNZ R1,$;DELAY 12USMOV TX,CDJNZ R2,$;DELAY 46USSETB TXNOPDJNZ R0,WWSETB TX;CLR RS0RET;///////////READ:;DS18B20读字节;SETB RS0CLR CMOV R0,#8;八位RE:SETB TXMOV R1,#10;延时20usMOV R2,#15 ;延时30usCLR TXNOPSETB TX;此句最重要,读取数据的时候一定要释放总线,否则读不出暂存器数据DJNZ R1,$MOV C,TXDJNZ R2,$RRC ADJNZ R0,RESETB TX;CLR RS0RET;//////////////TABLE:DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH;0-9 需要加点应用ADD 80H即可DB 0BFH,86H,0DBH,0CFH,0E6H,0EDH,0FDH,87H,0FFH,0EFH;0.-9.DB 40H ;-END。
//DS18B20温度传感器和数码管显示//编程时间:2010.4.7-2010.4.9//////**********************************************************//连线表: CPU=stc89C52 SysClock=12MHz// LEDLE=P1.0 控制位高电平有效LEDSEG=P2 KEYBOARD=P3 LEDWEI=P0.5-0,LED高到底//**********************************************************//DS18B20//**********************************************************//连线表: CPU=stc89C52 SysClock=12MHz * //单总线:TMDAT=P1.1////**********************************************************#include <reg52.h>#define uchar unsigned char#define uint unsigned intuchar discount=0;//显示扫描位计数uchar last=0;//最终温度值uchar itcount=0x13;//定时器延时计数uchar seg[4];//数码管显示暂存uchar tem[2];//读取温度暂存uchar flag=0;//温度正负标志位/********************LED引脚定义********************/sfr LEDSEG=0x80;//P2sfr LEDWEI=0xA0;//P3/********************DS18B20引脚定义********************/sbit TMDAT=P1^0; //温度传感器数据位/********************DS18B20函数定义*******************/void dmsec(uint count);//延时(count)毫秒void tmreset(void); //产生复位信号void tmpre(void); //检测器件应答信号bit tmrbit(void); //从总线读一个bituchar tmrbyte(void); //从总线读一个字节void mwbyte(uchar dat);//向总线写一个字节void tmstart(void); //启动一次温度转换uchar tmrtemp(void); //读取温度数据/********************LED函数定义*******************/uchar * uchartodectoseg(uchar unm);//字符转换为十进制然后转换为数码管段表void disp(uchar *seg);//显示函数void delay_ms(uint t); //延时函数/************************************************/uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0xc6};/*************数码表*******0 1 2 3 4 5 6 7 8 9 无显示C**************/ /************************************************/uchar * uchartodectoseg(uchar unm){uchar x00,xx,x0,x,n;x00=unm/100;//取百位xx=unm%100;//取余x0=xx/10;//取十位x=xx%10;//取余即取个位n=0;seg[n]=table[x00];n++;seg[n]=table[x0];n++;seg[n]=table[x];n++;seg[n]=table[11];//最后一位显示摄氏度符号Cif(flag==1)seg[0]=0x40;//显示负号‘-’if(seg[0]==table[0])seg[0]=table[10]; //如果百位为零则不显示if((seg[0]==table[0])&(seg[1]==table[0]))seg[1]=table[10];//如果百位为零且十位为零则十位不显示return seg;}/***************************************************//******DELAY***************************/void delay_ms(uint t){uint m,n;for(m=0;m<t;m++){for(n=0;n<950;n++);}}/******************************************//*********************显示LEDSEG*****************************/void disp(uchar *seg){uchar wei[]={0x08,0x04,0x02,0x01};//位扫描码//LEDSEG=seg[10];LEDWEI =wei[discount];LEDSEG = seg[discount];delay_ms(1);discount++;if(discount==4){ delay_ms(1);discount=0;//LEDSEG=seg[10];LEDWEI=wei[discount];LEDSEG=seg[discount];}//检测是否扫描完,扫描完的话则重新置初值}/*********************************************************//*****************DS18B20函数体定义****************/void dmsec(uint count){uint i;while(count--){for(i=0;i<125;i++){}}}void tmreset(void){uint i;TMDA T=0;i=103;while(i>0) i--;TMDA T=1;i=4;while(i>0) i--;}void tmpre(void){uint i;while(TMDAT);while(~TMDAT);i=4;while(i>0) i--;}bit tmrbit(void){uint i;bit dat;TMDA T=0;i++;TMDA T=1;i++;i++;dat=TMDAT;i=8;while(i>0) i--;return(dat);}uchar tmrbyte(void){uchar i,j,dat;dat=0;for(i=1;i<=8;i++){ j=tmrbit();dat=(j<<7)|(dat>>1); }return(dat);}void tmwbyte(uchar dat) {uint i;uchar j;bit testb;for(j=1;j<=8;j++){ testb=dat & 0x01;dat=dat>>1;if(testb){ TMDAT=0;i++; i++;TMDAT=1;i=8;while(i>0) i--;}else{ TMDAT=0;i=8;while(i>0) i--;TMDAT=1;i++; i++;}}}void tmstart(void){tmreset();tmpre();dmsec(1);tmwbyte(0xcc);tmwbyte(0x44);}uchar tmrtemp(void){uchar y1,y2,y3;tmreset();tmpre();dmsec(1);tmwbyte(0xcc);tmwbyte(0xbe);tem[0]=tmrbyte();tem[1]=tmrbyte();if(tem[1]>127){tem[1]=(255-tem[1]);tem[0]=(255-tem[0]);flag=1;} //负温度求补码y1=tem[0]>>4;y2=tem[1]<<4;y3=y1|y2;return(y3);}/*********************************************************/void main(){TMOD=0X01;TL0=0XB0;TH0=0X3C;EA=1;ET0=1;TR0=1;dmsec(1);tmstart();while(1){uchartodectoseg(last);disp(seg);}}void time0() interrupt 1{TL0=0XB0;TH0=0X3C;//定时50msitcount--;if(itcount==0){last=tmrtemp();dmsec(1);tmstart();itcount=0x13;}}。