51单片机单总线控制两个DS18B20
51单片机控制温度传感器DS18B20测量温度

DS18B20的初步了解
TO-92封装的18B20样式非常小巧,有三只脚,分别为: 1脚GND,2脚数据,3脚电压,外形和直插式的三极管一模一 样,接口电路如图所示。
DS18B20的初步了解
18B20通过编程可以实现最高12位的温度转换,同时可 识别温度正负。温度数据寄存器格式如表所示:
温度值被存在一个16位寄存器中,前面五位“S”为符
接下来看“配置寄存器”,之所以说它是配置寄存器, 是因为它能控制温度转换的精度:到底是9位、10位、11位 还是12位。它是一个8bit的寄存器,格式如表所示:
R1与R0值由用户设置,其余6bit为固定值。R1与R0的值 与转换精度对应的关系如表12.9所示:
bit7 bit6 bit5
0
R1 R0
10、B8H-读取EEPROM。执行该指令,会把EEPROM中的TH、 TL、配置寄存器的值,分别存入暂存器中相应的位置。
11、B4H-读取供电模式。DS18B20有两种供电模式:外 部电源供电与寄生电源供电。执行该指令后,寄生电源供电 的DS18B20会把总线拉低,外部电源供电的DS18B20会把总线 拉高。
数字输出(十六进制) 07D0h 0550h 0191h 00A2h 0008h 0000h FFF8h FF5Eh FE6Fh FC90h
DS18B20的初步了解
以12位分辨率为例,二进制数最低位增加1,表示温度 增加0.0625°C。0.5°C的二进制数换算成10进制后为 8,0.0625×8结果刚好为0.5。
7、4EH-写暂存器。DS18B20内部有9个字节的暂存器, 暂存器地址从0至8。执行该指令后,需向DS18B20写入三个 字节的数据:第一个字节写入温度上限寄存器TH(第三个暂 存器),设置报警温度的上限;第二个字节写入温度下限寄 存器TL(第四个暂存器),设置报警温度的下限;第三个字 节写入配置寄存器(第五个暂存器),设置转换精度。写指 令时,由于是串行传输,写入顺序为先写低位,后写高位。
51单片机控制DS18B20测温的PID温控程序

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单片机两路温度控制器的设计方案本文提出了基于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温控保温汇编程序

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程序)

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>。
C51单总线控制2个18b20测温程序

#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通过单总线初始化时序如下:由上图可见,当主机要操作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++;}。
单总线两个DS18B20的LCD液晶显示

调试的软件的时候
• 1、先看懂LCD显示程序,以及程序里如 何体现与硬件连? • 2、看懂LCD显示程序后,请看懂 单个 DS18B20的温度显示,读懂每一个子程 序的用处。 • 3、然后读懂 两个DS18B20的温度显示 程序。
软硬件调试
• 1、先进行任意一个ds18b20的调试 • 2、一根总线上同时放上两个DS18B20的情况: 需要先读到这两个DS18B20的ROMID(序列 号),通过调用下面的子程序在LCD里显示。 read_and_display_DS18B20_ROMID() • 3、访问总线上的任意一个DS18B20时,需要 先进行ROMID(序列号)匹配,把读到的 ROMID作为get_temperature()的入口参 数,就可以得到温度了。
LCD部分和最小系统调试完 的同学: 请设计一路DS18B20温度 显示系统。请用Proteus先 进行程序设计。最后进行 硬件调试。
第三次课: 一路DS18B20温度显示系统
• 硬件电路
+3--+5.5V 接其他单总线设备
DS18B20 4.7K 微处理器 接外部电源 +3--+5.5V
DS18B20温度传感器应用 Nhomakorabea考核方式
平时成绩(30%) 课堂表现、作业完成情况、
出勤情况等。
强调:吃的不准带进来,不准穿拖鞋
实验成绩(40%) 实验表现 、实验报告、成功作 品等。
重点:有成功的作品出来。 实践考核(30%) 随机抽取(个人抓阄)一个项目 进行考核。
项目一 单片机最小系统 设计
项目要求
• 1、两人一组,先进行组队,然后登记,此后就不变了。 • 2、两人分工明确: • (1)一人画原理图并写相关文档(包括说明文档,调 试文档和调试步骤,并记录调试过程中遇到的问题), 另一人元件布局进行焊接并调试各功能模块。 • (2)下一个项目可以相互轮流。 • (3)针对单片机的程序部分,两人共同解决。 • (4)一组的人成绩相同,不进行区分。若是一个人做 出来,另一个人完全不参与则无分数。只记录成功或者 失败,若有公认的完美作品,可以追加分数。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
#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//第一个温度值//显示温度十位//显示温度个位〃第二个温度值〃显示温度十位〃显示温度个位。