51单片机单总线控制两个DS18B20
- 格式:docx
- 大小:12.72 KB
- 文档页数:6
51单片机控制DS18B20测温的PID温控程序51单片机控制DS18B20测温的PID温控程序#include;#include;#include;#include;struct PID {unsigned int SetPoint; // 设定目标 Desired Value unsigned int Proportion; // 比例常数 Proportional Constunsigned int Integral; // 积分常数 Integral Const unsigned int Derivative; // 微分常数 Derivative Constunsigned int LastError; // Error[-1]unsigned int PrevError; // Error[-2]unsigned int SumError; // Sums of Errors};struct PID spid; // PID Control Structure unsigned int rout; // PID Response (Output) unsigned int rin; // PID Feedback (Input) sbit data1=P1^0;sbit clk=P1^1;sbit plus=P2^0;sbit subs=P2^1;sbit stop=P2^2;sbit output=P3^4;sbit DQ=P3^3;unsigned char flag,flag_1=0;unsigned char high_time,low_time,count=0;//占空比调节参数unsigned char set_temper=35;unsigned char temper;unsigned char i;unsigned char j=0;unsigned int s;void delay(unsigned char time){unsigned char m,n;for(n=0;nfor(m=0;m;>;i;temp=temp&1;write_bit(temp);}delay(7);// TR0=1;EA=1;}unsigned char read_bit(){unsigned char i,value_bit;EA=0;DQ=0;_nop_();_nop_();DQ=1;for(i=0;i;>;4;temper=i|j;}void PIDInit (struct PID *pp){memset ( pp,0,sizeof(struct PID)); //全部初始化为0 }unsigned int PIDCalc( struct PID *pp, unsigned int NextPoint ) {unsigned int dError,Error;Error = pp->;SetPoint - NextPoint; // 偏差pp->;SumError += Error; // 积分dError = pp->;LastError - pp->;PrevError; // 当前微分pp->;PrevError = pp->;LastError;pp->;LastError = Error;return (pp->;Proportion * Error // 比例项+ pp->;Integral * pp->;SumError // 积分项+ pp->;Derivative * dError); // 微分项}void compare_temper(){unsigned char i;if(set_temper>;temper) //是否设置的温度大于实际温度{if(set_temper-temper>;1) //设置的温度比实际的温度是否是大于1度{high_time=100; //如果是,则全速加热low_time=0;}else //如果是在1度范围内,则运行PID计算 {for(i=0;i;0){high_time=0;low_time=100;}else{for(i=0;i;>;1;if(m==1)data1=1;elsedata1=0;_nop_();clk=1;_nop_();}}}void display(){unsigned char codenumber[]={0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0 ,0xfe,0x f6};unsigned char disp_num[6];unsigned int k,k1;k=high_time;k=k00;k1=k/100;if(k1==0)disp_num[0]=0;elsedisp_num[0]=0x60;k=k0;disp_num[1]=number[k/10];disp_num[2]=number[k];k=temper;k=k0;disp_num[3]=number[k/10];disp_num[4]=number[k]+1;disp_num[5]=number[s/10];disp_1(disp_num);}void main(){unsigned char z;unsigned char a,b,flag_2=1,count1=0;unsigned char phil[]={2,0xce,0x6e,0x60,0x1c,2}; TMOD=0x21;TH0=0x2f;TL0=0x40;SCON=0x50;PCON=0x00;TH1=0xfd;TL1=0xfd;PS=1;EA=1;EX1=0;ET0=1;ES=1;TR0=1;TR1=1;high_time=50;low_time=50;PIDInit ( &spid ); // Initialize Structure spid.Proportion = 10; // Set PID Coefficients 比例常数 Proportional Constspid.Integral = 8; //积分常数 Integral Const spid.Derivative =6; //微分常数Derivative Const spid.SetPoint = 100; // Set PIDSetpoint 设定目标Desired Valuewhile(1){if(plus==0){EA=0;for(a=0;a;5)temper=a;elsetemper=b;a=temper;flag_2=0;if(++count1>;30){display();count1=0;}compare_temper();}TR0=0;z=1;while(1){EA=0;if(stop==0){for(a=0;a<5;a++)for(b=0;b<102;b++){} if(stop==0)disp_1(phil);// break;}EA=1; }}。
基于51单片机两路温度控制器的设计方案本文提出了基于51 单片机两路温度控制器的设计方案,该设计方案采用两个DS18B20 温度传感器,采集两个不同地方的温度,通过AT89C51 处理进行,由四位LED 数码管显示所测量温度,前两位为第一个温度传感器的温度,后两位为第二个温度传感器的温度。
采用3 个按键实现温度最高和最低的设定,采用蜂鸣器和电动机实现温度过高或过低报警。
1.引言目前,温度控制器存在的问题是如何缩减成本,减少功耗,温度测量的准确性和多路温度的同时显示。
本方案设计的实现基于C51 单片机的两路温度控制器,做到成本最低化,精确度高,两路温度的显示和控制,能在温度超出设定的最高温度时启动电风扇进行降温,在温度低于设定的最低温度时启动蜂鸣器报警,能够用户设定最高最低温。
2.系统结构温度控制器系统包括以下几个主要部分:温度传感器,报警电路,LED 显示电路,键盘控制,89C51 控制部分。
如图所示:本系统设计实现:启动温度控制器后,绿灯亮起,四位LED 数码显示器上前两位为温度传感器1 所测的环境温度,后两位为温度传感器2 所测的环境温度。
3.硬件结构3.1 温度传感器本设计采用的是DS18B20 作为温度传感器,DS18B20 与传统的热敏电阻相比具有精确度高,测量误差小,方便实现多点测温等优点,因此用DS18B20 作温度传感器。
3.2 报警电路本设计采用蜂鸣器和电风扇报警电路。
蜂鸣器报警电路由三极管和蜂鸣器组成。
当温度低于设定的最低温度时,则蜂鸣器报警。
电风扇报警电路由三极管和电风扇组成。
当温度高于设定的最高温度时,则电风扇报警。
3.3 显示电路本系统采用L E D 数码显示管显示,LED 亮度高,可视角度高。
LCD 的可视角度低,亮度较低,价格高。
考虑到此温度传感器主要用于温室大棚等亮度不太高的环境,从经济与实用的角度来看选LED 作为显示器。
3.4 键盘控制本系统采用3 个独立的按键作为键盘控制电路。
51单片机+DS18B20温控保温汇编程序;DS18B20和AT89C2051制作的热水器程序!两位数码管显示温度,设定温度时数码管成闪烁状态,延时几秒后跳转到被测温度;DS18B20的正电源就是红线接+5伏,兰线接地,黄线接P3.2,红线和黄线之间接一个4.7K的上拉电阻;这是关于DS18B20的读写程序,数据脚P3.2,晶振12MHz ;温度传感器18B20汇编程序,采用器件默认的12位转化,最大转化时间750微秒;可以将检测到的温度直接显示到AT89C2051的p1口输数码管段码到两位一体数码管上;显示温度00到99度,很准确哦~~无需校正!;p3.1驱动加热管装置,让温度保温在0-99度内;p3.0保温指示灯,p3.4是温度设定按键加1度;p3.5是温度设定按键减1度,p3.7是数码管高位位码,p3.3是数码管低位位码;程序16进制的温度值放在29h里,我用可调节0度到99度的16进制值(#08H/#0EH)与之比较;1至40度的16进制为:01H 02H 03H 04H 05H 06H 07H 08H 09H 0AH 1-10度; 0BH 0CH 0DH 0EH 0FH 10H 11H 12H 13H 14H 11-20度; 15H 16H 17H 18H 19H 1AH 1BH 1CH 1DH 1EH 21-30度; 1FH 2OH 21H 22H 23H 24H 25H 26H 27H 28H 31-40度; 29H 2AH 2BH 2CH 2DH 2EH 2FH 30H 31H 32H 41-50度; 33H 34H 35H 36H 37H 38H 39H 3AH 3BH 3CH 51-60度; 3CH 3DH 3EH 3FH 40H 41H 42H 43H 44H 45H 61-70度; 46H 47H 48H 49H 4AH 4BH 4CH 4DH 4EH 4FH 71-80度; 51H 52H 53H 54H 55H 56H 57H 58H 59H 5AH 81-90度; 5BH 5CH 5DH 5EH 5FH 60H 61H 62H 63H 64H 91-100度;================================================ =========================================;单片机内存分配申明!TEMPER_L EQU 29H ;用于保存读出温度的低8位 TEMPER_H EQU 28H ;用于保存读出温度的高8位(特别是可位寻址,程序中用的着哦)TIAO_H EQU 27H ;用于保存设定温度的数据(最低温度的设定,高温度为低温度加2度)FLAG1 EQU 38H ;是否检测到DS18B20标志位a_bit equ 20h ;数码管个位数存放内存位置b_bit equ 21h ;数码管十位数存放内存位置SL EQU 22H ;设定温度时数码管个位数存放内存位置SH EQU 23H ;设定温度时数码管十位数存放内存位置sdwd equ 24h ;设定温度压缩BCD码位DS18B20 BIT P3.2 ;定义DS18B20的数据脚为P3.2端口ORG 0000HMOV sdwd,#25H ;;;;设定初始温度37度,上电后内部设定温度MAIN:LCALL INIT_1820 ;调用复位DS18B20子程序MAIN1:LCALL GET_TEMPER ;调用读温度子程序;进行温度显示,这里我是用两位数码管来显示温度,显示范围00到99度,显示精度为1度;因为12位转化时每一位的精度为0.0625度,我们不要求显示小数所以可以抛弃29H的低4位;将28H中的低4位移入29H中的高4位,这样获得一个新字节,这个字节就是实际测量获得的温度;这个转化温度的方法可是我想出来的哦~~非常简洁无需乘于0.0625系数MOV A,29HMOV C,40H ;将28H中的最低位移入CRRC AMOV C,41HRRC AMOV C,42HRRC AMOV C,43HRRC AMOV 29H,ALCALL DISPLAY ;调用数码管显示子程序;这里是后加的,做为控制在0-99度内恒温的程序!p3.1驱动加热管装置setb p3.4setb p3.5jnb p3.4,DD1 ;按下后转加1程序jnb p3.5,DD2 ;按下后转减1程序;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;TT: CLR C ;比较转换值与设定值MOV 26H,sdwd ;把低温度设定保存到26H单元后减2度,作为低度的数据DEC 26HMOV A,29HCJNE A,26H,LOOP1 ;下限设定温度度,不相等跳LOOP1SJMP HOTTING ;与下限值相等跳HOTTING,加热LOOP1:JC HOTTING ;温度小于下限值跳HOTTING,加热MOV A,29H ;温度大于下限值,与上限值比较CLR Cmov 27h,sdwdinc 27hCJNE A,27h,LOOP2 ;上限设定温度度,不相等跳LOOP2SJMP STOPHOT ;相等跳STOPHOT,停止加热LOOP2:JNC STOPHOT ;温度大于上限值跳STOPHOT,停止加热SJMP KEEP ;温度小于上限且大于下限值跳KEEP,保温HOTTING:CLR P3.1 ;小,加热器驱动setb p3.0 ;关闭保温灯KEEP:SJMP MAIN ;返回,保持原态,保温STOPHOT:SETB P3.1 ;关闭加热器clr p3.0 ;点亮保温灯AJMP MAIN ;反回主程序;;;;;;;;;;;;;;;;;;;;;按键处理;;;;;;;;;;;; ;;;;;加限设定温度度;;;;;;;;;;DD1:LCALL displa ;调用数码管闪烁设定显示子程序mov r5,#30JNB P3.4,DD1mov a,sdwd ;把设定温度送累加器判断cjne a,#62h,ty1 ;比较设定温度是否到99度,不是则加ajmp dh2ty1: INC sdwddh2:jnb p3.4,DD1jnb p3.5,DD2 ;按下后转减1程序LCALL displa ;调用数码管闪烁设定显示子程序djnz r5,dh2LJMP TT;;;减限设定温度度;;;;;;;;;;;;DD2:LCALL displa ;调用数码管闪烁设定显示子程序mov r5,#30JNB P3.5,DD2mov a,sdwd ;把设定温度送累加器判断cjne a,#01h,ty ;比较设定温度是否到0度,不是则减ajmp dh1ty: DEC sdwddh1:jnb p3.5,DD2jnb p3.4,DD1 ;按下后转加1程序LCALL displa ;调用数码管闪烁设定显示子程序djnz r5,dh1LJMP TT;================================================ =========================================; DS18B20复位初始化程序INIT_1820:SETB DS18B20NOPCLR DS18B20MOV R0,#06BH ;主机发出延时537微秒的复位低脉冲MOV R1,#03HTSR1:DJNZ R0,TSR1MOV R0,#6BHDJNZ R1,TSR1SETB DS18B20 ;然后拉高数据线NOPNOPNOPMOV R0,#25HTSR2:JNB DS18B20,TSR3 ;等待DS18B20回应DJNZ R0,TSR2LJMP TSR4 ;延时TSR3:SETB FLAG1 ;置标志位,表示DS1820存在 LJMP TSR5TSR4:CLR FLAG1 ;清标志位,表示DS1820不存在 LJMP TSR7TSR5:MOV R0,#06BHTSR6:DJNZ R0,TSR6 ;时序要求延时一段时间TSR7:SETB DS18B20;================================================ =========================================; 读出转换后的温度值GET_TEMPER:SETB DS18B20 ;定时入口LCALL INIT_1820 ;先复位DS18B20JB FLAG1,TSS2RET ;判断DS1820是否存在?若DS18B20不存在则返回TSS2:MOV A,#0CCH ;跳过ROM匹配LCALL WRITE_1820MOV A,#44H ;发出温度转换命令LCALL WRITE_1820LCALL DISPLAY ;这里通过调用显示子程序实现延时一段时间,等待AD转换结束,12位的话750微秒. LCALL INIT_1820 ;准备读温度前先复位MOV A,#0CCH ;跳过ROM匹配LCALL WRITE_1820MOV A,#0BEH ;发出读温度命令LCALL WRITE_1820LCALL READ_18200 ;将读出的温度数据保存到35H/36H;写DS18B20的子程序(有具体的时序要求)WRITE_1820:MOV R2,#8 ;一共8位数据CLR CWR1:CLR DS18B20MOV R3,#6DJNZ R3,$RRC AMOV DS18B20,CMOV R3,#23DJNZ R3,$SETB DS18B20NOPDJNZ R2,WR1SETB DS18B20RET; 读DS18B20的程序,从DS18B20中读出两个字节的温度数据READ_18200:MOV R4,#2 ;将温度高位和低位从DS18B20中读出MOV R1,#29H ;低位存入29H(TEMPER_L),高位存入28H(TEMPER_H)RE00:MOV R2,#8RE01:CLR CSETB DS18B20NOPNOPCLR DS18B20NOPNOPNOPSETB DS18B20MOV R3,#09RE10:DJNZ R3,RE10MOV C,DS18B20MOV R3,#23RE20:DJNZ R3,RE20RRC ADJNZ R2,RE01MOV @R1,ADEC R1DJNZ R4,RE00RET;========================================================================================= ;;;;;;;;;;;;;;;显示子程序;;;;;;;;;;;;;;;;;; display:mov a,29H ;将29H中的十六进制数转换成10进制mov b,#10 ;10进制/10=10进制div abmov b_bit,a ;十位在amov a_bit,b ;个位在bmov dptr,#numtab ;指定查表启始地址mov r1,#250 ;显示250次dplop:mov a,a_bit ;取个位数MOVC A,@A+DPTR ;查个位数的7段代码mov p1,a ;送出个位的7段代码clr p3.3 ;开个位显示acall d1ms ;显示1mssetb p3.3mov a,b_bit ;取十位数MOVC A,@A+DPTR ;查十位数的7段代码mov p1,a ;送出十位的7段代码clr p3.7 ;开十位显示acall d1ms ;显示1mssetb p3.7djnz r1,dplop ;250次没完循环RET;;;============================================== =================;;;;;;;闪烁设定显示子程序===================== displa: MOV A,sdwdmov b,#10 ;10进制/10=10进制div abmov SL,a ;十位在amov SH,b ;个位在bmov r1,#250 ;显示250次dpl2: mov a,SL ;取设定温度个位数mov dptr,#numtab ;指定查表启始地址MOVC A,@A+DPTR ;查个位数的7段代码mov p1,a ;送出个位的7段代码clr p3.7 ;开个位显示acall d1ms ;显示1mssetb p3.7mov a,SH ;取设定温度十位数MOVC A,@A+DPTR ;查十位数的7段代码mov p1,a ;送出十位的7段代码clr p3.3 ;开十位显示acall d1ms ;显示1mssetb p3.3djnz r1,dpl2 ;250次没完循环acall D1s ;显示1msRET;;=============================================== ==========================================;1MS延时(按12MHZ算)D1MS:MOV R7,#80DJNZ R7,$RET;;1S延时(按12MHZ算)D1s:MOV R7,#255l1:nopnopnopnopnopnopnopnopnopnop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nopnop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nopnop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nopnop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nopnop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nopnopnopDJNZ R7,l1RET;================================================ ========================================= numtab: DB 0EEH;0DB 048H;1DB 0D6H;2DB 0DCH;3DB 078H;4DB 0BCH;5DB 0BEH;6DB 0C8H;7DB 0FEH;8DB 0FCH;9END。
DS18B20多点测温<读序列,匹配序列,51 C程序,1602显示)因为本人在前两天找DS18B20多点测温<51C程序),网上下载了很多,但是都不是很理想,后来,自己总结前人的知识,重新写了这个程序。
其中包括程序一:单个读序列号。
程序二,匹配并且读两个DS18B20,当然,读多个与读两个基本原理一样,只要加上其序列号等即可。
本程序所有显示都是用LCD160 2显示。
程序一:度序列号,并用1602显示,1602从左到右分别是低到高位。
#include<reg51.h>#define uchar unsigned char#define uint unsigned intsbit DQ=P3^7。
//ds18b20与单片机连接口sbit RS=P3^0。
sbit RW=P3^1。
sbit EN=P3^2。
unsigned char code str1[]={""}。
unsigned char code str2[]={" "}。
uchar fCode[8]。
uchar data disdata[5]。
uint tvalue。
//温度值uchar tflag。
//温度正负标志/*************************lcd1602程序**************************/void delay1ms(unsigned int ms>//延时1毫秒<不够精确的){unsigned int i,j。
for(i=0。
i<ms。
i++>for(j=0。
j<100。
j++>。
}void wr_com(unsigned char com>//写指令//{ delay1ms(1>。
RS=0。
RW=0。
EN=0。
P2=com。
delay1ms(1>。
EN=1。
delay1ms(1>。
#include<reg52.h>#include<intrins.h>#include<stdio.h>#define uchar unsigned char#define uint unsigned intuchar num;sbit lcd_en=P2^2;sbit lcd_rw=P2^3;sbit lcd_rs=P2^4;#define lcd_date P0/*****数码管端口定义*******************/sbit LEDCLK=P3^4;sbit LEDDIN=P2^3;/***************************//************************************************************** 延时函数*功能: 可随意设置延时时间,延时时间为(tt*9+16)us.晶振为12MHz***************************************************************/ void delay_us(unsigned int tt){while(tt--){;}}/*****************************************************延时函数*功能: 可随意设置延时时间,延时时间为tt ms.晶振为12MHz*****************************************************/void delay_ms(unsigned int tms){unsigned char i;while(tms--)for(i=123;i>0;i--);}void Write_com(uchar com){lcd_rs=0;lcd_date=com;delay_ms(2);lcd_en=1;delay_ms(2);lcd_en=0;}void Writ_dat(uchar dat){lcd_rs=1;lcd_date=dat;delay_ms(2);lcd_en=1;delay_ms(2);lcd_en=0;}/*------------------------------------------------写入字符函数------------------------------------------------*/void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data) {if (y == 0){Write_com(0x80 + x);}else{Write_com(0xC0 + x);}Writ_dat( Data);}/************************************************写入字符串函数**************************************************/void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s) {if (y == 0){Write_com(0x80 + x);}else{Write_com(0xC0 + x);}while (*s){Writ_dat( *s);s ++;}}void lcd_init(){lcd_rw=0;lcd_en=0;delay_ms(15);Write_com(0x38);delay_ms(5);Write_com(0x38);delay_ms(5);Write_com(0x38);//显示模式设置Write_com(0x08);//显示关闭Write_com(0X01);//清屏Write_com(0x06);//显示光标移动设置Write_com(0X0c);//显示开及光标设置}#define uint unsigned int#define uchar unsigned char#define dataa 2000uchar code str1[]={0x28,0x55,0xC5,0xB8,0x00,0x00,0x00,0xA6}; //ROM1 PROTUES中的rom 序列号要变化序号:B8C555uchar code str2[]={0x28,0x37,0xC5,0xB8,0x00,0x00,0x00,0x0B}; //ROM2 序号:B8C537 uchar code table[]={'0','1','2','3','4','5','6','7','8','9'};uchar SN[8];uint temper,temper2,Max;//温度寄存器uchar temp[16];bit flag_low,flag_low2;#define NOP3() _nop_();_nop_();_nop_()sbit DQ=P3^0;sbit Set=P2^7;sbit Up=P2^5;sbit Down=P2^6;sbit Beep=P3^1;bit flag_init;//DS18B20是否存在标志/****DS18B20初始化**************************************/void reset(){flag_init=1;DQ=1;NOP3();DQ=0;delay_us(60);//480~960usDQ=1;delay_us(5);//60usflag_init=DQ;delay_us(25);//241us}/****写一个字节函数*************************************/ void Write_Byte(uchar dat){uchar i;DQ=1;EA=0;for(i=8;i>0;i--){DQ=0;DQ=(bit)(dat&0x01);delay_us(5);//61usDQ=1;dat>>=1;}EA=1;}/*****读数据函数*****************************/uchar Read_Byte(){uchar i,date;DQ=1;EA=0;//关中断for(i=8;i>0;i--){DQ=0;date>>=1;DQ=1;NOP3();if(DQ){date|=0x80;}delay_us(5);//61us}EA=1;//开中断return(date);}/**************************//* 获得SN码**************************/void Get_SN(){uchar i;reset();delay_ms(2);Write_Byte(0x33);for(i=0;i<8;i++)SN[i] = Read_Byte();for(i=0;i<8;i++){sprintf(temp,"%2x",SN[i]);LCD_Write_String(0+i*2,1,temp);}}/**************************//* 对比SN码**************************/void Check_SN(uchar a){char j;Write_Byte(0x55);//发送匹配ROM命令if(a==1){for(j=0;j<8;j++)Write_Byte(str1[j]); //发送18B20的序列号,先发送低字节}if(a==2){for(j=0;j<8;j++)Write_Byte(str2[j]); //发送18B20的序列号,先发送低字节}}/**************************//* 获得温度值**************************/void GET2_tem(uchar z){uchar teml,temh;reset();Write_Byte(0xcc);Write_Byte(0x44);//启动温度转换delay_ms(750);//750msreset();if(z==1){Check_SN(1);}if(z==2){Check_SN(2);}Write_Byte(0xbe);//读取温度值teml=Read_Byte();temh=Read_Byte();if((temh&0xf0)==0xf0)//如果是负温度{flag_low=1;temper=(~((temh)*256+(teml))+1)*6.25;}elsetemper=(temh*256+teml)*6.25;//放大100倍}void GETall_tem(){uchar teml,temh,teml2,temh2;reset();Write_Byte(0xcc);Write_Byte(0x44);//启动温度转换delay_ms(750);//750msreset();Check_SN(1);Write_Byte(0xbe);//读取温度值teml=Read_Byte();temh=Read_Byte();if((temh&0xf0)==0xf0)//如果是负温度{flag_low=1;temper=(~((temh)*256+(teml))+1)*6.25;}elsetemper=(temh*256+teml)*6.25;//放大100倍reset();Check_SN(2);Write_Byte(0xbe);//读取温度值teml2=Read_Byte();temh2=Read_Byte();if((temh2&0xf0)==0xf0)//如果是负温度{flag_low2=1;temper2=(~((temh2)*256+(teml2))+1)*6.25;}elsetemper2=(temh2*256+teml2)*6.25;//放大100倍}init_mcu(){TMOD=0x11;TH1=(65536-dataa)/256;TL1=(65536-dataa)%256;ET1=1;TR1=1;EA=1;}/**************************//* 更新温度值**************************/void Uptemp(){GETall_tem();if(flag_low==1){flag_low=0;LCD_Write_Char(5,0,'-');}elseLCD_Write_Char(5,0,'+');LCD_Write_Char(6,0,table[temper/1000]);LCD_Write_Char(7,0,table[temper%1000/100]);LCD_Write_Char(8,0,'.');LCD_Write_Char(9,0,table[temper%100/10]);LCD_Write_Char(10,0,table[temper%10]);LCD_Write_Char(11,0,0xdf);LCD_Write_Char(12,0,'C');if(flag_low2==1){flag_low2=0;LCD_Write_Char(5,1,'-');}elseLCD_Write_Char(5,1,'+');LCD_Write_Char(6,1,table[temper2/1000]);LCD_Write_Char(7,1,table[temper2%1000/100]);LCD_Write_Char(8,1,'.');LCD_Write_Char(9,1,table[temper2%100/10]);LCD_Write_Char(10,1,table[temper2%10]);LCD_Write_Char(11,1,0xdf);LCD_Write_Char(12,1,'C');}void Upmax(){LCD_Write_Char(6,1,table[Max%100/10]);LCD_Write_Char(7,1,table[Max%10]);LCD_Write_Char(8,1,0xdf);LCD_Write_Char(9,1,'C');}void Key(){uchar i=0;Write_com(0x01);//清屏LCD_Write_String(1,0,"MAX Tempr Set");Upmax();while(i==0){if(Up==0){delay_ms(2);if(Up==0){Max++;if(Max==100) Max=0;Upmax();}while(Up==0);}if(Down==0){delay_ms(2);if(Down==0){Max--;if(Max>100)Max=99;Upmax();}while(Down==0);}if(Set==0){delay_ms(2);if(Set==0){i++;}while(Set==0);}}}main(){init_mcu();lcd_init();/*Get_SN();while(1);*/ Max=30;LCD_Write_String(2,0,"T0");LCD_Write_String(2,1,"T1");while(1){Uptemp();}}/***定时器1中断********************************/ void time1_int() interrupt 3{TH1=(65536-dataa)/256;TL1=(65536-dataa)%256;if(Set==0){delay_ms(2);if(Set==0){while(Set==0);Key();}Write_com(0x01);//清屏LCD_Write_String(2,0,"T0");LCD_Write_String(2,1,"T1");}if(temper/100+1>Max||temper2/100+1>Max)Beep=0;else Beep=1;}仿真图。
单总线控制DS18B20温度传感器一DS18B20通过单总线初始化时序如下:由上图可见,当主机要操作DS18B20时,需要把总线打底,并持续480us以960us 然后释放总线(即拉高),当时间流逝15-60us的时候,DS18B20若存在且没有坏的话,它会把总线拉低,并持续60-240us .在这段时间主机可以查看总线状态,来确定初始化完成 .二DS18B20通过单总线读写时序如下:由上图可以看出,主机要读或写DS18B20时,需要要将总线接低并持续15us,上面的两个时序是写的时序,主机在接低总线的15us后继续拉低总线,持续15-30us. 在这个时间内DS18B20采样0,完成0的写入.主机拉低总线15us后拉高总线然后持续15-30us等待DS18B20采样完成 1的写入.下面的两个图是读的时序图.主机拉低总线并持续15us后,释放总线.如果DS18B20要输出0就继续拉低总线,若要输出1 就拉高总线,并持续15-30us,等待主机查询总线状态完成 0或者1的读写.三DS18B20的ROM操作命令如下:四DS18B20的存储器操作命令如下:五DS18B20内部9个字节存储器以及E2RAM:六DS18B20内部存储温度字节格式:七DS18B20操作的C语言程序:/*************************此部分为18B20的驱动程序*************************************/#include <reg52.H>#include <intrins.h>sbit D18B20=P3^7;#define NOP() _nop_() /* 定义空指令 */#define _Nop() _nop_() /*定义空指令*/void TempDelay (unsigned char idata us);void Init18b20 (void);void WriteByte (unsigned char idata wr); //单字节写入void read_bytes (unsigned char idata j);unsigned char CRC (unsigned char j);void GemTemp (void);void Config18b20 (void);void ReadID (void);void TemperatuerResult(void);bit flag;unsigned int idata Temperature,D[10];unsigned char idata temp_buff[9]; //存储读取的字节,read scratchpad为9字节,read rom ID为8字节unsigned char idata id_buff[8];unsigned char idata *p,TIM;unsigned char idata crc_data;unsigned char code CrcTable [256]={0, 94,188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65,157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220,35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98,190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255,70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102,229, 187, 89, 7,219, 133,103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 1 96, 154,217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36,248, 166,68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 2 31, 185,140, 210,48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113, 147, 205,17, 79, 173, 243, 112, 46, 204, 146, 211, 141, 111, 49, 178, 236, 14, 80,175, 241,19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82, 176, 238,50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115,202, 148,118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 2 13, 139,87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22,233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168,116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53};///*************************************************************Function:延时处理*parameter:*Return:*Modify:*************************************************************/void TempDelay (unsigned char idata us){while(us--);}/*************************************************************Function:18B20初始化*parameter:*Return:*Modify:*************************************************************/void Init18b20 (void){_nop_();D18B20=0;TempDelay(50); //delay 530 uS//80_nop_();D18B20=1;TempDelay(10); //delay 100 uS//14_nop_();_nop_();_nop_();if(D18B20==0)flag = 1; //detect 1820 success!elseflag = 0; //detect 1820 fail!TempDelay(15); //20_nop_();_nop_();D18B20 = 1;}/************************************************************ *Function:向18B20写入一个字节*parameter:*Return:*Modify:*************************************************************/ void WriteByte (unsigned char idata wr) //单字节写入{unsigned char idata i;for (i=0;i<8;i++){D18B20 = 0;_nop_();D18B20=wr&0x01;TempDelay(3); //delay 45 uS //5_nop_();_nop_();D18B20=1;wr >>= 1;}}/************************************************************ *Function:读18B20的一个字节*parameter:*Return:*Modify:*************************************************************/ unsigned char ReadByte (void) //读取单字节{unsigned char idata i,u=0;for(i=0;i<8;i++){D18B20 = 0;u >>= 1;D18B20 = 1;if(D18B20==1)u |= 0x80;TempDelay (2);_nop_();}return(u);}/************************************************************ *Function:读18B20*parameter:*Return:*Modify:*************************************************************/ void read_bytes (unsigned char idata j){unsigned char idata i;for(i=0;i<j;i++){*p = ReadByte();p++;}}/************************************************************ *Function:CRC校验*parameter:*Return:*Modify:*************************************************************/ unsigned char CRC (unsigned char j){unsigned char idata i,crc_data=0;for(i=0;i<j;i++) //查表校验crc_data = CrcTable[crc_data^temp_buff[i]];return (crc_data);}/************************************************************ *Function:读取温度*parameter:*Return:*Modify:*************************************************************/ void GemTemp (void){read_bytes (9);if (CRC(9)==0) //校验正确{Temperature = temp_buff[1]*0x100 + temp_buff[0];// Temperature *= 0.625;Temperature /= 16;TempDelay(1);}}/************************************************************ *Function:内部配置*parameter:*Return:*Modify:*************************************************************/ void Config18b20 (void) //重新配置报警限定值和分辨率{Init18b20();WriteByte(0xcc); //skip romWriteByte(0x4e); //write scratchpadWriteByte(0x19); //上限WriteByte(0x1a); //下限WriteByte(0x7f); //set 11 bit (0.125)Init18b20();WriteByte(0xcc); //skip romWriteByte(0x48); //保存设定值Init18b20();WriteByte(0xcc); //skip romWriteByte(0xb8); //回调设定值}/************************************************************ *Function:读18B20ID*parameter:*Return:*Modify:*************************************************************/ void ReadID (void)//读取器件 id{Init18b20();WriteByte(0x33); //read romread_bytes(8);}/************************************************************ *Function:18B20ID全处理*parameter:*Return:*Modify:*************************************************************/ void TemperatuerResult(void){p = id_buff;ReadID();Config18b20();Init18b20 ();WriteByte(0xcc); //skip romWriteByte(0x44); //Temperature convertInit18b20 ();WriteByte(0xcc); //skip romWriteByte(0xbe); //read Temperaturep = temp_buff;GemTemp();}unsigned int TempTick=0;void GetTemp(){if(TIM==1){ TIM=0;TemperatuerResult();D[5]=Temperature;}}/*************************************[ t1 (0.5ms)中断] 中断中做 PWM 输出------------1000/(0.02ms*250)=200Hz*************************************/void T1zd(void) interrupt 3{TH1 = 0xfe; //11.0592TL1 = 0x33;TIM++;}。
1.1 温度传感器DS18B20与MCS-51单片机的接口数字温度传感器问世于20世纪90年代中期。
它是微电子技术、计算机技术和自动测试技术的结晶。
数字温度传感器具有价格低、精度高、封装小、温度范围宽、使用方便等优点,被广泛应用于工业控制、电子测温计、医疗仪器等各种温度控制系统中。
数字温度传感器一般内部包含温度传感器、A/D转换器、信号处理器、存储器和相应的接口电路,有的还带多路选择器、中央控制器(CPU)、随机存储器(RAM)和只读存储器(ROM)。
数字温度传感器的种类繁多,一般按总线形式可分为单总线(1-wire)接口、双总线(I2C)接口和三总线(SPI)接口。
下面主要以单总线接口数字温度传感器芯片DS18B20为例来介绍数字温度传感器的使用。
1.1.1 DS18B20简介DS18B20是DALLAS公司生产的单总线数字温度传感器芯片,具有3引脚TO-92小体积封装形式;温度测量范围为-55℃~+125℃;可编程为9~12位A/D转换精度;用户可自设定非易失性的报警上下限值;被测温度用16位补码方式串行输出;测温分辨率可达0.0625℃;其工作电源既可在远端引入,也可采用寄生电源方式产生;多个DS18B20可以并联到3根或两根线上,CPU只需一根端口线就能与诸多DS18B20通信,占用微处理器的端口较少。
可广泛用于工业、民用、军事等领域的温度测量及控制仪器、测控系统和大型设备中。
1.1.2 DS18B20的外部结构DS18B20可采用3脚TO-92小体积封装和8脚SOIC封装。
其外形和引脚图如图7.17所示。
GND DQ V DDNCNCNC VGND(a) TO-92封装(b) SOIC封装图1.1 DS18B20的外形及引脚图图中引脚定义如下。
(1) DQ:数字信号输入/输出端。
(2) GND:电源地。
(3) V DD:外接供电电源输入端(在寄生电源接线方式时接地)。
1.1.3 DS18B20的内部结构DS18B20内部主要由4部分组成:64位光刻ROM 、温度传感器、非易失性温度报警触发器TH 和TL 、配置寄存器等。
#in clude<reg52.h>#defi ne uchar un sig ned char#defi ne uint un sig ned int sbit DQ=P1A 0;sbit rs=P2A0; sbit rw=P2A1;sbit e=P2A2;uchar temp1,temp2;II 定义两个存放温度的变量 //uchar ID[8]; 〃存放DS18B20的64位序列号的数组uchar code ID_1[]={0x28,0x3a,0x24,0xc6,0x02,0x00,0x00,0xa4}; II 第一个 DS18B20 的序列号uchar code ID_2[]={0x28,0x66,0xa2,0xc1,0x02,0x00,0x00,0x26};II 第二个 DS18B20 的序列号 uchar code table[]="0123456789";uchar code table_temp[]="tempreture:";uchar code table_0[]="C :/****************************************************/ II50us 的延时函数 IILCD1602写指令 IILCD1602写数据 IILCD1602 初 始 IIds18b20初始化 IIwhile ( t--)延时函数 IIDS18B20初始化函数 IIds18b20写一个字节函数 IIds18b20读一个字节函数uchar readtempl(void); ucharreadtemp2(void); void display(void);I*void readrom(void) II 读取温度传感器的序列号子函数 {ini t_ds18b20();delay_50us(2);write_byte(0x33);ID[0]=read_byte();ID[1]=read_byte();ID[2]=read_byte();ID[3]=read_byte();ID[4]=read_byte();ID[5]=read_byte();ID[6]=read_byte();ID[7]=read_byte();/*****************************************************/*void keep_rom(uchar *p) // 存序列号函数{uchar i;void delay_50us( uint time);void write_com(uchar com); voidwrite_data(uchar dat);void in it_LCD1602(void); idini t_ds18b20(void);void delay( uint t);void ini t_ds18b20(void); voidwrite_byte(char dat); ucharread_byte(void);II 第一个ds18b20读取温度函数 //第二个ds18b20读取温度函数IILCD1602显示温度函数*******************************************for(i=0;i<8;i++){*P=ID[i];P++;}}/***************************************************** /*void display_rom(void) // 显示序列号函数{uchar i;write_com(0x80); for(i=0;i<8;i++){write_data(table[ID[i]/16]); write_data(table[ID[i]%16]);}}/****************************************************/ void mai n(void){in it_LCD1602();while(1){temp1=readtemp1();temp2=readtemp2();display();}}]**********************************************'void delay_50us( uint time){uchar j;for(;time>0;time--); for(j=19;j>0;j++);}/************************************************/void write_com(uchar com) //LCD1602 写指令{e=0;rs=0;rw=0;PO=com;delay_50us(10); e=1;delay_50us(20);e=0;}/***************************************************/void write_data(uchar dat) //LCD1602 写数据{e=0;rs=1;rw=0;PO=dat;delay_50us(10);e=1;delay_50us(20);e=0;}]***************************************************]void init_LCD1602(void) //LCD1602 初始化函数{delay_50us(300);write_com(0x38);delay_50us(100);write_com(0x38);delay_50us(100);write_com(0x38);write_com(0x38);//显示模式设置write_com(0x08);〃显示关闭write_com(0x01);〃显示清屏write_com(0x06);〃显示光标移动设置write_com(0x0c);〃显示开及光标设置}/*********************************************/ void delay( uint t){while(t--);}/*************************************************void init_ds18b20(void)〃初始化{uchar n;DQ=1; //默认为高电平delay(8);DQ=O;delay(80); 〃12MHz晶振下大约600微秒的延时DQ=1; 〃释放总线delay(8);n=DQ;delay(4);}/***************************************************/void write_byte(char dat)〃写一个字节{uchar i;for(i=0;i<8;i++){DQ=0;DQ=dat&0x01;〃从最低位开始写,0x01delay(4);DQ=1;〃拉高,传下一帧数据dat>>=1;}delay(4);}/****************************************************/ uchar read_byte(void)〃读一个字节{uchar i;uchar value;for(i=0;i<8;i++){DQ=0;value>>=1; 〃判断8次,移位七次(起延时作用)DQ=1;if(DQ) 〃采样,判断DQvalue|=0x80; //赋值,与0x80 与一下delay(4);}retur n value;}/*****************************************************/ uchar readtemp1(void){uchar a,b,i; ini//读一个高八位,一个低八位t_ds18b20(); 〃readrom();// keep_rom(IP_1);// display_rom();write_byte(0x55);for(i=0;i<8;i++){write_byte(ID_1[i]);}write_byte(0x44); // 启动温度测量delay(300);ini t_ds18b20();write_byte(0x55);for(i=0;i<8;i++){write_byte(ID_1[i]);}write_byte(0xbe); 〃读这个温度a=read_byte(); 〃低位b=read_byte(); // 高位b<<=4;b+=(a&0 xfO)>>4; // 屏蔽低四位return b;}/******************************************************/ uchar readtemp2(void){uchar a,b,i; //读一个高八位,一个低八位ini t_ds18b20();〃readrom();// keep_rom(IP_1);// display_rom();write_byte(0x55);for(i=0;i<8;i++){write_byte(ID_2[i]);}write_byte(0x44); // 启动温度测量delay(300);ini t_ds18b20();write_byte(0x55);for(i=0;i<8;i++){write_byte(ID_2[i]);}write_byte(0xbe); 〃读这个温度a=read_byte(); 〃低位b=read_byte(); // 高位b<<=4;b+=(a&0 xfO)>>4; // 屏蔽低四位return b;}[未*************************************************** void display(void){uchar i;write_com(0x80);for(i=0;i<11;i++){write_data(table_temp[i]);delay_50us(1);}write_com(0x80+0x40);write_data(table[temp1/10]); write_data(table[temp1%10]); write_data(table_O[O]);write_data(table_0[1]);write_com(0x80+0x47);write_data(table[temp2/10]); write_data(table[temp2%10]); write_data(table_O[O]);write_data(table_0[1]); // 显示tempreture//第一个温度值//显示温度十位//显示温度个位〃第二个温度值〃显示温度十位〃显示温度个位。
题目:基于89C51和DS18B20的数字温度计设计一、设计要求数字式温度计要求测温范围为-55~125°C,精度误差在0.1°C以内,LED 数码管直读显示。
二、方案论证根据系统的设计要求,选择DS18B20作为本系统的温度传感器,选择单片机AT89C51为测控系统的核心来完成数据采集、处理、显示、报警等功能。
选用数字温度传感器DS18B20,省却了采样/保持电路、运放、数/模转换电路以及进行长距离传输时的串/并转换电路,简化了电路,缩短了系统的工作时间,降低了系统的硬件成本。
该系统的总体设计思路如下:温度传感器DS18B20把所测得的温度发送到AT89C51单片机上,经过51单片机处理,将把温度在显示电路上显示,本系统显示器用4位共阳LED数码管以动态扫描法实现。
检测范围-55摄氏度到125摄氏度。
按照系统设计功能的要求,确定系统由3个模块组成:主控制器、测温电路和显示电路。
数字温度计总体电路结构框图如图1所示。
图1 数字温度计总体电路结构框图三、系统硬件电路的设计温度计电路设计原理图如图2所示,控制器使用单片机AT89C51,温度传感器使用DS18B20,用4位共阳LED数码管实现温度显示。
图2 数字温度计设计电路原理图1、主控制器AT89C51是一种带4K字节闪烁可编程可擦除只读存储器的低电压,高性能CMOS8位微处理器。
该器件采用ATMEL高密度非易失存储器制造技术制造,与工业标准的MCS-51指令集和输出管脚相兼容。
由于将多功能8位CPU和闪烁存储器组合在单个芯片中,ATMEL的AT89C51是一种高效微控制器,为很多嵌入式控制系统提供了一种灵活性高且价廉的方案。
2、显示电路显示电路采用4位共阳LED数码管,从P0口输出段码,列扫描用P3.0~P3.3口来实现,列驱动用8550三极管。
3、温度传感器工作原理DS18B20温度传感器是美国DALLAS半导体公司最新推出的一种改进型智能温度传感器,与传统的热敏电阻等测温元件相比,它能直接读出被测温度,并且可根据实际要求通过简单的编程实现9~12位的数字值读数方式。
单总线温度传感器DS18B20简介DS18B20是DALLAS公司生产的单总线式数字温度传感器,它具有微型化、低功耗、高性能、搞干扰能力强、易配处理器等优点,特别适用于构成多点温度测控系统,可直接将温度转化成串行数字信号(提供9位二进制数字)给单片机处理,且在同一总线上可以挂接多个传感器芯片。
它具有3引脚TO-92小体积封装形式,温度测量范围为-55℃~+125℃,可编程为9位~12位A/D转换精度,测温分辨率可达0.0625℃,被测温度用符号扩展的16位数字量方式串行输出,其工作电源既可在远端引入,也可采用寄生电源方式产生,多个DS18B20可以并联到3根或2根线上,CPU只需一根端口线就能与多个DS18B20通信,占用微处理器的端口较少,可节省大量的引线和逻辑电路。
以上特点使DS18B20非常适用于远距离多点温度检测系统。
DS18B20外形及引脚说明外形及引脚如图2所示:图2 管脚排列图在TO-92和SO-8的封装中引脚有所不同,具体差别请查阅PDF手册,在TO-92封装中引脚分配如下:1(GND):地2(DQ):单线运用的数据输入输出引脚3(VDD):可选的电源引脚DS18B20工作过程及时序DS18B20内部的低温度系数振荡器是一个振荡频率随温度变化很小的振荡器,为计数器1提供一频率稳定的计数脉冲。
高温度系数振荡器是一个振荡频率对温度很敏感的振荡器,为计数器2提供一个频率随温度变化的计数脉冲。
初始时,温度寄存器被预置成-55℃,每当计数器1从预置数开始减计数到0时,温度寄存器中寄存的温度值就增加1℃,这个过程重复进行,直到计数器2计数到0时便停止。
初始时,计数器1预置的是与-55℃相对应的一个预置值。
以后计数器1每一个循环的预置数都由斜率累加器提供。
为了补偿振荡器温度特性的非线性性,斜率累加器提供的预置数也随温度相应变化。
计数器1的预置数也就是在给定温度处使温度寄存器寄存值增加1℃计数器所需要的计数个数。
51单片机多路DS18B20测温显示并读取序列号/*********************************************功能:读取序列号并匹配序列号,并读温度值多功能试验板显示多路温度采集正常显示2个DS18B20温度正常读取DS18B20序列号单片机:STC12C5A60S2晶振:11.0592M作者:苏义江改编自网络时间:2016-8-25************************************************/#include <reg52.h>#include <intrins.h>#define uchar unsigned char#define uint unsigned intsbit RS=P2^7;sbit RW=P2^6;sbit EN=P2^5;sbit DQ=P3^4; //传感器引脚sbit key=P3^7;sbit d1=P1^3;//指示灯sbit d2=P1^4;bit st=1;uchar code table0[]={"DuoLuWenDuXS:U "}; uchar code table2[]={"SD: "}; //湿度uchar code table1[]={"0123456789ABCDEF"};//现有的2个DS18B20传感器的序列号ROM1,ROM2 uchar DSrom[4][8]={//4个器件每个64位序列号{0x28,0xff,0x2a,0x0A,0x22,0x04,0x00,0xf6},//ROM1 {0x28,0xFF,0x0b,0x0d,0x20,0x04,0x00,0x0a},//ROM2{0x28,0x0C,0xBA,0xBA,0x02,0x00,0x00,0x54},//ROM3 {0x28,0xff,0x91,0x14,0x22,0x04,0x00,0xe4}//ROM4 };int f[4]; //温度数组int tvalue; //温度值变量float ftvalue; //温度值变量uchar fCode[8];//序列号数组uint warnl=300; //设定温度值高uint warnh=992;//设定温度值低void ds1820wr(uchar dat);//写数据void ds1820rst();//ds1820复位uchar ds1820rd();//读数据void DispCode();//读取序列号uchar tflag;//温度正负标志//////////lcd1602程序////////////void delay1ms(uint ms)//延时1毫秒(不够精确的){uint i,j;for(i=0;i<ms;i++)for(j=0;j<620;j++);}void wr_com(uchar com)//写指令//{delay1ms(1);RS=0;RW=0;EN=0;P0=com;delay1ms(1);EN=1;delay1ms(1);EN=0;}void wr_dat(uchar dat)//写数据// {delay1ms(1);;RS=1;RW=0;EN=0;P0=dat;delay1ms(1);EN=1;delay1ms(1);EN=0;}void lcd_init()//1602初始化设置// {delay1ms(15);wr_com(0x38);delay1ms(5);wr_com(0x08);delay1ms(5);wr_com(0x01);delay1ms(5);wr_com(0x06);delay1ms(5);wr_com(0x0c);delay1ms(5);}void display(uchar *p)//显示字符串{while(*p!='\0'){wr_dat(*p);p++;delay1ms(1);}}void displayinit()//初始化显示{lcd_init();wr_com(0x80);display(table0);wr_com(0xC6);wr_dat(0xdf);wr_com(0xC7);wr_dat('C');wr_com(0xCf);wr_dat(0x25);wr_com(0XC9);display(table2);}void tmstart()//初始化ds18b20 {DQ=1;d1=1;d2=1;ds1820rst();delay1ms(1);ds1820wr(0xcc);ds1820wr(0x44);}void read_dealtemp()//读取并处理温度{uchar i,j,t;uchar a,b;for(j=0;j<5;j++) //挂载4个设备{ds1820rst(); //复位delay1ms(1);ds1820wr(0x55); //匹配EOM指令for(i=0;i<8;i++){ds1820wr(DSrom[j][i]);//发送64位序列号}ds1820wr(0xbe);//温度转换a=ds1820rd(); //读高位b=ds1820rd(); //读低位tvalue=b;tvalue<<=8;tvalue=tvalue|a;if(tvalue<0) //判断正负温度{d1=1;tvalue=~tvalue+1;wr_com(0xc0); //第二行第一列wr_dat(0x2d); //负温度符号"-"if(tvalue<warnl) //温度高于设定值warnl=300; {d2=0; //报警DQ=0;}else{d2=1;DQ=1;}}else{d2=1;wr_com(0xc0);wr_dat(' ');if(tvalue>warnh) //温度高于设定值warnh=992; {d1=0; //报警DQ=0;}else{d1=1;DQ=1;}}if(j==0){wr_com(0x8f);wr_dat('1');}if(j==1){wr_com(0x8f);wr_dat('2');}if(j==2){wr_com(0x8f);wr_dat('3');}if(j==3){wr_com(0x8f);wr_dat('4');}if(j==4){wr_com(0x8f);wr_dat('5');}ftvalue=tvalue*0.0625;tvalue=ftvalue*10+0.5;ftvalue=ftvalue+0.05; //温度补偿f[j]=tvalue;//温度扩大十倍,精确到一位小数tvalue=f[j];t=tvalue/1000;wr_com(0x80+0x41);wr_dat(table1[t]);//显示百位t=tvalue%1000/100;wr_dat(table1[t]);//显示十位t=tvalue%100/10;wr_dat(table1[t]);//显示个位wr_dat(0x2e); //显示小数点儿t=tvalue%10/1;wr_dat(table1[t]);//显示小数位delay1ms(5000);}}void keyscan()//按键{if(key==0){delay1ms(30);if(key==0){st=~st;}while(!key);}}void main(){d1=1;d2=1;DQ=1;displayinit();//初始化显示while(1){keyscan();//按住按键等4个器件循环完毕显示序列号if(st==1){wr_com(0x01);displayinit();//初始化显示tmstart();//初始化read_dealtemp();//读取温度}else{wr_com(0x01);keyscan();//按住按键等4个器件循环完毕显示序列号DispCode();//读取序列号delay1ms(1000);}}}////////DS18B20函数///////////////void delay_b20(uint n)//STC12C5A单片机定时1us {while(n--){_nop_();}}void ds1820rst()/*ds1820复位*/ {uchar x=0;DQ = 1; //DQ复位delay_b20(1); //延时DQ = 0; //DQ拉低delay_b20(500); //精确延时大于480us DQ = 1; //拉高delay_b20(80);}uchar ds1820rd()/*读数据*/{uchar i=0;uchar dat = 0;for (i=0;i<8;i++){DQ = 1; //给脉冲信号delay_b20(1);DQ = 0; //给脉冲信号delay_b20(1);dat>>=1;DQ = 1; //给脉冲信号if(DQ)dat|=0x80;delay_b20(60);}return(dat);}void ds1820wr(uchar dat)/*写数据*/ {uchar i=0;for (i=0; i<8; i++){DQ = 1;delay_b20(1);DQ = 0;DQ = dat&0x01;delay_b20(60);DQ = 1;delay_b20(60);dat>>=1;}delay_b20(1);}///////////读取序列号//////////void DispCode()//读取序列号{uchar i,temp;ds1820rst();ds1820wr(0x33);for (i=0;i<8;i++){fCode[i]=ds1820rd();}wr_com(0x80+0x40);for (i=0;i<8;i++){temp = fCode[i]>>4; //显示高四位if (temp<10)wr_dat(temp + 0x30); // 显示数字elsewr_dat(temp + 0x37); //否则大于数字9显示字母temp = fCode[i]&0x0f;//显示低四位if (temp<10)wr_dat(temp+ 0x30);elsewr_dat(temp + 0x37);}}。
基于51单片机和DS18B20的数字温度计设计说明
1.硬件设计:
-51单片机:选择合适的型号,如STC89C52或AT89C52等。
-DS18B20温度传感器:该传感器是一种数字温度传感器,具有单总线接口和高精度测量能力。
-接口电路:将51单片机和DS18B20传感器连接起来,要注意电平转换和信号线的阻抗匹配。
2.软件设计:
-初始化:在主函数中,首先对单片机进行初始化设置,包括时钟设置、串口配置等。
-DS18B20通信协议:使用单总线协议与DS18B20传感器进行通信,包括发送复位信号、读写数据等操作。
-温度测量:通过向DS18B20发送读取温度的命令,从传感器中读取温度值并保存。
-数据传输:将温度值转换为可显示的格式,如摄氏度或华氏度,并通过串口输出或LED显示。
3.程序流程:
-初始化单片机,设置时钟和串口参数。
-进入主循环,循环执行以下操作:
-发送复位信号,启动温度转换。
-等待转换完成,发送读取温度命令。
-读取温度值,并进行数据处理转换。
-输出温度值。
4.其他功能:
-可以添加LCD显示模块,将温度值显示在液晶屏上。
-可以添加按键输入模块,通过按键切换温度单位或进行其他操作。
需要注意的是,该设计只是一个简单的示例,实际应用中可能需要根据具体需求进行扩展和修改。
同时,在程序设计过程中,也要注意低功耗和数据稳定性等方面的考虑。
51单片机DS18B20温度传感器原理及实验一、引言温度传感器是一种常用的传感器器件,它的作用是将物体的温度变化转换为电信号输出,以实现温度的监测和控制。
DS18B20是一种数字温度传感器,采用数字信号输出,具有体积小、精度高、线性度好等特点,被广泛应用于各种温度控制系统中。
本文将介绍DS18B20的工作原理及实验方法。
二、DS18B20的工作原理DS18B20是一种基于一线传输协议的数字温度传感器,其工作原理如下:1.接口电路:DS18B20具有三个引脚,分别是VDD、DQ和GND。
其中,VDD是供电引脚,DQ是数据引脚,GND是地引脚。
2.传感器原理:DS18B20内部包含一个温度传感器和一个数字转换器。
温度传感器采用热敏电阻的原理,通过测量热敏电阻的电阻值来反映物体的温度变化。
数字转换器将传感器测得的电阻值转换为数字信号输出。
三、实验流程以下是使用51单片机对DS18B20温度传感器进行实验的详细流程:1.硬件准备:-将DS18B20的VDD引脚连接到单片机的VCC引脚,DQ引脚连接到单片机的任意IO引脚,GND引脚连接到单片机的GND引脚。
-确保DS18B20的供电电压和单片机的工作电压一致。
2.初始化:-在程序中定义DS18B20的DQ引脚所对应的单片机的IO引脚。
-初始化DS18B20,即发送初始化指令给DS18B20。
3.温度转换:-发送温度转换指令给DS18B20,DS18B20开始测量温度。
-等待一定的延时,确保DS18B20完成温度转换。
4.读取温度:-发送读取温度指令给DS18B20,DS18B20将温度的原始数据发送给单片机。
-单片机通过计算将原始数据转换为温度值。
-温度值可以通过串口或LCD等方式进行显示。
5.循环实验:-以上步骤需要不断重复,以便实时监测温度的变化。
四、总结DS18B20温度传感器是一种常用的数字温度传感器,具有精度高、体积小、线性度好等特点,适用于各种温度控制系统。
基于51单片机和DS18B20的数字温度计设计说明题目:基于89C51和DS18B20的数字温度计设计一、设计要求数字式温度计要求测温范围为-55~125°C,精度误差在0.1°C以内,LED数码管直读显示。
二、方案论证根据系统的设计要求,选择DS18B20作为本系统的温度传感器,选择单片机AT89C51为测控系统的核心来完成数据采集、处理、显示、报警等功能。
选用数字温度传感器DS18B20,省却了采样/保持电路、运放、数/模转换电路以及进行长距离传输时的串/并转换电路,简化了电路,缩短了系统的工作时间,降低了系统的硬件成本。
该系统的总体设计思路如下:温度传感器DS18B20把所测得的温度发送到AT89C51单片机上,经过51单片机处理,将把温度在显示电路上显示,本系统显示器用4位共阳LED数码管以动态扫描法实现。
检测范围-55摄氏度到125摄氏度。
按照系统设计功能的要求,确定系统由3个模块组成:主控制器、测温电路和显示电路。
数字温度计总体电路结构框图如图1所示。
图1 数字温度计总体电路结构框图三、系统硬件电路的设计温度计电路设计原理图如图2所示,控制器使用单片机AT89C51,温度传感器使用DS18B20,用4位共阳LED数码管实现温度显示。
图2 数字温度计设计电路原理图1、主控制器AT89C51是一种带4K字节闪烁可编程可擦除只读存储器的低电压,高性能CMOS8位微处理器。
该器件采用ATMEL高密度非易失存储器制造技术制造,与工业标准的MCS-51指令集和输出管脚相兼容。
由于将多功能8位CPU 和闪烁存储器组合在单个芯片中,ATMEL的AT89C51是一种高效微控制器,为很多嵌入式控制系统提供了一种灵活性高且价廉的方案。
2、显示电路显示电路采用4位共阳LED数码管,从P0口输出段码,列扫描用P3.0~P3.3口来实现,列驱动用8550三极管。
3、温度传感器工作原理DS18B20温度传感器是美国DALLAS半导体公司最新推出的一种改进型智能温度传感器,与传统的热敏电阻等测温元件相比,它能直接读出被测温度,并且可根据实际要求通过简单的编程实现9~12位的数字值读数方式。
基于51单片机的DS18B20温度显示本讲内容:了解温度传感器DS18B20的使用,并通过一个例程展示温度传感器DS18B20测温过程。
DS18B20简介:DS18B20 是单线数字温度传感器,即“一线器件”,其具有独特的优点:(1)采用单总线的接口方式与微处理器连接时仅需要一条口线即可实现微处理器与 DS18B20 的双向通讯。
单总线具有经济性好,抗干扰能力强,适合于恶劣环境的现场温度测量,使用方便等优点,使用户可轻松地组建传感器网络。
(2)测量温度范围宽,测量精度高。
DS18B20 的测量范围为-55 ℃ ~+ 125 ℃;在 -10~+ 85°C 范围内,精度为± 0.5°C 。
(3)多点组网功能多个 DS18B20 并联在惟一的单线上,实现多点测温。
DS18B20的存储器由一个高速暂存RAM 和一个非易失性、电可擦除(E2)RAM 组成。
配置寄存器:出场设置默认R0、R1为11。
也就是12位分辨率,也就是1位代表0.0625摄氏度。
DS18B20经转换所得的温度值以二字节补码形式存放在高速暂存存储器的第0和第1个字节。
所以当我们只想简单的读取温度值的时候,只用读取暂存器中的第0和第1个字节就可以了。
简单的读取温度值的步骤如下: 1:跳过ROM 操作 2:发送温度转换命令 3:跳过ROM 操作 4:发送读取温度命令 5:读取温度值 DS18B20接口电路图:DS18B20的初始化:主机首先发出一个480-960微秒的低电平脉冲,然后释放总线变为高电平,并在随后的480微秒时间内对总线进行检测,如果有低电平出现说明总线上有器件已做出应答。
若无低电平出现一直都是高电平说明总线上无器件应答。
做为从器件的DS18B20在一上电后就一直在检测总线上是否有480-960微秒的低电平出现,如果有,在总线转为高电平后等待15-60微秒后将总线电平拉低60-240微秒做出响应存在脉冲,告诉主机本器件已做好准备。
#in clude<reg52.h>#defi ne uchar un sig ned char#defi ne uint un sig ned int sbit DQ=P1A 0;sbit rs=P2A0; sbit rw=P2A1;sbit e=P2A2;uchar temp1,temp2;II 定义两个存放温度的变量 //uchar ID[8]; 〃存放DS18B20的64位序列号的数组uchar code ID_1[]={0x28,0x3a,0x24,0xc6,0x02,0x00,0x00,0xa4}; II 第一个 DS18B20 的序列号uchar code ID_2[]={0x28,0x66,0xa2,0xc1,0x02,0x00,0x00,0x26};II 第二个 DS18B20 的序列号 uchar code table[]="0123456789";uchar code table_temp[]="tempreture:";uchar code table_0[]="C :/****************************************************/ II50us 的延时函数 IILCD1602写指令 IILCD1602写数据 IILCD1602 初 始 IIds18b20初始化 IIwhile ( t--)延时函数 IIDS18B20初始化函数 IIds18b20写一个字节函数 IIds18b20读一个字节函数uchar readtempl(void); ucharreadtemp2(void); void display(void);I*void readrom(void) II 读取温度传感器的序列号子函数 {ini t_ds18b20();delay_50us(2);write_byte(0x33);ID[0]=read_byte();ID[1]=read_byte();ID[2]=read_byte();ID[3]=read_byte();ID[4]=read_byte();ID[5]=read_byte();ID[6]=read_byte();ID[7]=read_byte();/*****************************************************/*void keep_rom(uchar *p) // 存序列号函数{uchar i;void delay_50us( uint time);void write_com(uchar com); voidwrite_data(uchar dat);void in it_LCD1602(void); idini t_ds18b20(void);void delay( uint t);void ini t_ds18b20(void); voidwrite_byte(char dat); ucharread_byte(void);II 第一个ds18b20读取温度函数 //第二个ds18b20读取温度函数IILCD1602显示温度函数*******************************************for(i=0;i<8;i++){*P=ID[i];P++;}}/***************************************************** /*void display_rom(void) // 显示序列号函数{uchar i;write_com(0x80); for(i=0;i<8;i++){write_data(table[ID[i]/16]); write_data(table[ID[i]%16]);}}/****************************************************/ void mai n(void){in it_LCD1602();while(1){temp1=readtemp1();temp2=readtemp2();display();}}]**********************************************'void delay_50us( uint time){uchar j;for(;time>0;time--); for(j=19;j>0;j++);}/************************************************/void write_com(uchar com) //LCD1602 写指令{e=0;rs=0;rw=0;PO=com;delay_50us(10); e=1;delay_50us(20);e=0;}/***************************************************/void write_data(uchar dat) //LCD1602 写数据{e=0;rs=1;rw=0;PO=dat;delay_50us(10);e=1;delay_50us(20);e=0;}]***************************************************]void init_LCD1602(void) //LCD1602 初始化函数{delay_50us(300);write_com(0x38);delay_50us(100);write_com(0x38);delay_50us(100);write_com(0x38);write_com(0x38);//显示模式设置write_com(0x08);〃显示关闭write_com(0x01);〃显示清屏write_com(0x06);〃显示光标移动设置write_com(0x0c);〃显示开及光标设置}/*********************************************/ void delay( uint t){while(t--);}/*************************************************void init_ds18b20(void)〃初始化{uchar n;DQ=1; //默认为高电平delay(8);DQ=O;delay(80); 〃12MHz晶振下大约600微秒的延时DQ=1; 〃释放总线delay(8);n=DQ;delay(4);}/***************************************************/void write_byte(char dat)〃写一个字节{uchar i;for(i=0;i<8;i++){DQ=0;DQ=dat&0x01;〃从最低位开始写,0x01delay(4);DQ=1;〃拉高,传下一帧数据dat>>=1;}delay(4);}/****************************************************/ uchar read_byte(void)〃读一个字节{uchar i;uchar value;for(i=0;i<8;i++){DQ=0;value>>=1; 〃判断8次,移位七次(起延时作用)DQ=1;if(DQ) 〃采样,判断DQvalue|=0x80; //赋值,与0x80 与一下delay(4);}retur n value;}/*****************************************************/ uchar readtemp1(void){uchar a,b,i; ini//读一个高八位,一个低八位t_ds18b20(); 〃readrom();// keep_rom(IP_1);// display_rom();write_byte(0x55);for(i=0;i<8;i++){write_byte(ID_1[i]);}write_byte(0x44); // 启动温度测量delay(300);ini t_ds18b20();write_byte(0x55);for(i=0;i<8;i++){write_byte(ID_1[i]);}write_byte(0xbe); 〃读这个温度a=read_byte(); 〃低位b=read_byte(); // 高位b<<=4;b+=(a&0 xfO)>>4; // 屏蔽低四位return b;}/******************************************************/ uchar readtemp2(void){uchar a,b,i; //读一个高八位,一个低八位ini t_ds18b20();〃readrom();// keep_rom(IP_1);// display_rom();write_byte(0x55);for(i=0;i<8;i++){write_byte(ID_2[i]);}write_byte(0x44); // 启动温度测量delay(300);ini t_ds18b20();write_byte(0x55);for(i=0;i<8;i++){write_byte(ID_2[i]);}write_byte(0xbe); 〃读这个温度a=read_byte(); 〃低位b=read_byte(); // 高位b<<=4;b+=(a&0 xfO)>>4; // 屏蔽低四位return b;}[未*************************************************** void display(void){uchar i;write_com(0x80);for(i=0;i<11;i++){write_data(table_temp[i]);delay_50us(1);}write_com(0x80+0x40);write_data(table[temp1/10]); write_data(table[temp1%10]); write_data(table_O[O]);write_data(table_0[1]);write_com(0x80+0x47);write_data(table[temp2/10]); write_data(table[temp2%10]); write_data(table_O[O]);write_data(table_0[1]); // 显示tempreture//第一个温度值//显示温度十位//显示温度个位〃第二个温度值〃显示温度十位〃显示温度个位。