单总线两个DS18B20的LCD液晶显示
- 格式:ppt
- 大小:3.95 MB
- 文档页数:26
;****************************************************************************** ***;****************************************************************************** **;* 描述: *;* DS18B20温度控制1602LCD显示*;**;* 使用方法参考readme.txt文档*;**;**;****************************************************************************** ***;****************************************************************************** **TEMP_ZH DATA 24H ;实时温度值存放单元TEMPL DATA 25H ;TEMPH DATA 26H ;TEMP_TH DATA 27H ;高温报警值存放单元TEMP_TL DATA 28H ;低温报警值存放单元TEMPHC DATA 29H ;TEMPLC DATA 2AHK1 EQU P1.4K2 EQU P1.5K3 EQU P1.6K4 EQU P1.7BEEP EQU P3.7RELAY EQU P1.3LCD_X EQU 2FH ;LCD 地址变量LCD_RS EQU P2.0LCD_RW EQU P2.1LCD_EN EQU P2.2flag1 equ 20H.0 ;DS18B20是否存在标记KEY_UD EQU 20H.1 ;设定KEY 的UP与DOWN 标记date_line equ p3.3;=====================================================ORG 0000HJMP MAINORG 0030HMAIN: MOV SP,#60HMOV A,#00HMOV R0,#20H ;将20H-2FH 单元清零MOV R1,#10HCLEAR: MOV @R0,AINC R0DJNZ R1,CLEARCALL SET_LCDCALL RE_18B20start: CALL RESET ;18B20复位子程序JNB FLAG1,START1 ;DS1820不存在CALL MENU_OKCALL READ_E2CALL TEMP_BJ ;显示温度标记JMP START2START1: CALL MENU_ERRORCALL TEMP_BJ ;显示温度标记JMP $START2:CALL RESETJNB FLAG1,START1 ;DS1820不存在MOV A,#0CCH ; 跳过ROM匹配CALL WRITEMOV A,#44H ; 发出温度转换命令CALL WRITECALL RESETMOV A,#0CCH ; 跳过ROM匹配CALL WRITEMOV A,#0BEH ; 发出读温度命令CALL WRITECALL READcall CONVTEMPCall DISPBCDCALL CONVCALL TEMP_COMPCALL PROC_KEY ; 键扫描SJMP START2;-----------------------------------------------------PROC_KEY:JB K1,PROC_K1 ; 按键K1处理CALL BEEP_BLJNB K1,$MOV DPTR,#M_ALAX1MOV A,#1CALL LCD_PRINTCALL LOOK_ALARMJB K3,$CALL BEEP_BLJMP PROC_K2PROC_K1: ; 按键K2处理JB K2,PROC_ENDCALL BEEP_BLJNB K2,$MOV DPTR,#RESET_A1MOV A,#1CALL LCD_PRINTCALL SET_ALARMCALL RE_18B20 ;将设定的TH,TL值写入DS18B20内CALL WRITE_E2PROC_K2:CALL MENU_OKCALL TEMP_BJPROC_END:RET;============================================;设定报警值TH、TL;============================================SET_ALARM:;CALL RESET_ALARMCALL LOOK_ALARMAS0:JB K1,AS00CALL BEEP_BLJNB K1,$CPL 20H.1 ;UP/DOWN 标记AS00: JB 20H.1,ASZ01 ;20H.1=1,UPJMP ASJ01 ;20H.1=0,DOWNASZ01: JB K2,ASZ02 ;TH值调整(增加)CALL BEEP_BLINC TEMP_THMOV A,TEMP_THCJNE A,#120,ASZ011MOV TEMP_TH,#0ASZ011: CALL LOOK_ALARMMOV R5,#10CALL DELAYJMP ASZ01ASZ02: JB K3,ASZ03 ;TL值调整(增加)CALL BEEP_BLINC TEMP_TLMOV A,TEMP_TLCJNE A,#99,ASZ021MOV TEMP_TL,#00HASZ021: CALL LOOK_ALARM ;MOV R5,#10CALL DELAYJMP ASZ02ASZ03: JB K4,AS0 ;确定调整OKCALL BEEP_BLJNB K4,$RETASJ01:JB K2,ASJ02 ;TH值调整(减少)CALL BEEP_BLDEC TEMP_THMOV A,TEMP_THCJNE A,#0FFH,ASJ011JMP ASJ022ASJ011: CALL LOOK_ALARMMOV R5,#10CALL DELAYJMP AS0ASJ02: JB K3,ASJ03 ;TL值调整(减少)CALL BEEP_BLDEC TEMP_TLMOV A,TEMP_TLCJNE A,#0FFH,ASJ021JMP ASJ022ASJ021: CALL LOOK_ALARM ;MOV R5,#10CALL DELAYJMP AS0ASJ022: CPL 20H.1JMP ASZ01ASJ03: JMP ASZ03RETRESET_ALARM:MOV DPTR,#RESET_A1 ;指针指到显示信息区MOV A,#1 ;显示在第一行CALL LCD_PRINTRETRESET_A1:DB "RESET ALERT CODE";==================================================== ;实际温度值与标记温度值比较子程序;==================================================== TEMP_COMP:MOV A,TEMP_THSUBB A,TEMP_ZH ;减数>被减数,则JC CHULI1 ;借位标志位C=1,转MOV A,TEMP_ZHSUBB A,TEMP_TL ;减数>被减数,则JC CHULI2 ;借位标志位C=1,转MOV DPTR,#BJ5CALL TEMP_BJ3CLR RELAY ;继电器吸合RETCHULI1:MOV DPTR,#BJ3CALL TEMP_BJ3SETB RELAY ;继电器关闭CALL BEEP_BLRETCHULI2:MOV DPTR,#BJ4CALL TEMP_BJ3CALL BEEP_BLRET;-----------------------------------------TEMP_BJ3:MOV A,#0CEHCALL WCOMMOV R1,#0MOV R0,#2BBJJ3: MOV A,R1MOVC A,@A+DPTRCALL WDATAINC R1DJNZ R0,BBJJ3RETBJ3:DB ">H"BJ4:DB "<L"BJ5:DB " !";================================================== ;显示温度标记子程序;================================================== TEMP_BJ:MOV A,#0CBHCALL WCOMMOV DPTR,#BJ1 ;指针指到显示消息MOV R1,#0MOV R0,#2BBJJ1: MOV A,R1MOVC A,@A+DPTRCALL WDATAINC R1DJNZ R0,BBJJ1RETBJ1:DB 00H,"C";================================================= MENU_OK:MOV DPTR,#M_OK1 ;指针指到显示消息MOV A,#1 ;显示在第一行CALL LCD_PRINTMOV DPTR,#M_OK2 ;指针指到显示消息MOV A,#2 ;显示在第一行CALL LCD_PRINTRETM_OK1:DB " DS18B20 OK ",0M_OK2:DB " TEMP: ",0;-----------------------------------------------MENU_ERROR:MOV DPTR,#M_ERROR1 ;指针指到显示消息1MOV A,#1 ;显示在第一行CALL LCD_PRINTMOV DPTR,#M_ERROR2 ;指针指到显示消息1MOV A,#2 ;显示在第一行CALL LCD_PRINTRETM_ERROR1:DB " DS18B20 ERROR ",0M_ERROR2:DB " TEMP: ---- ",0;==================================================== reset: setb date_linenopclr date_linemov r0,#6bh ;主机发出延时复位低脉冲mov r1,#04htsr1: djnz r0,$mov r0,#6bhdjnz r1,tsr1setb date_line ;然后拉高数据线nopnopnopmov r0,#32htsr2: jnb date_line,tsr3 ;等待DS18B20回应djnz r0,tsr2jmp tsr4 ; 延时tsr3: setb flag1 ; 置标志位,表示DS1820存在jmp tsr5tsr4: clr flag1 ; 清标志位,表示DS1820不存在jmp tsr7tsr5: mov r0,#06bhtsr6: djnz r0,$ ; 时序要求延时一段时间tsr7: setb date_lineret;=======================================================RE_18B20:JB FLAG1,RE_18B20ARETRE_18B20A:CALL RESETMOV A,#0CCH ;跳过ROM匹配LCALL WRITEMOV A,#4EH ;写暂存寄存器LCALL WRITEMOV A,TEMP_TH ;TH(报警上限)LCALL WRITEMOV A,TEMP_TL ;TL(报警下限)LCALL WRITEMOV A,#7FH ;12位精确度LCALL WRITERET;------------------------------------------------------------WRITE_E2:CALL RESETMOV A,#0CCH ;跳过ROM匹配LCALL WRITEMOV A,#48H ;把暂存器里的温度报警值拷贝到EEROMLCALL WRITERET;--------------------------------------------------------------READ_E2:CALL RESETMOV A,#0CCH ;跳过ROM匹配LCALL WRITEMOV A,#0B8H ;把EEROM里的温度报警值拷贝回暂存器CALL WRITERET;--------------------------------------------------------------;将自定义字符写入LCD1602的CGRAM中;--------------------------------------------------------------STORE_DATA:MOV A,#40HCALL WCOMMOV R2,#08HMOV DPTR,#D_DATAMOV R3,#00HS_DATA:MOV A,R3MOVC A,@A+DPTRCALL WDATA ;写入数据INC R3DJNZ R2,S_DATARETD_DATA:DB 0CH,12H,12H,0CH,00H,00H,00H,00H;============================================================== write: mov r2,#8 ;一共8位数据CLR Cwr1:clr date_line ;开始写入DS18B20总线要处于复位(低)状态mov r3,#07djnz r3,$ ;总线复位保持16微妙以上rrc a ;把一个字节DATA 分成8个BIT环移给Cmov date_line,c ;写入一个BITmov r3,#3CHdjnz r3,$ ;等待100微妙setb date_line ;重新释放总线nopdjnz r2,wr1 ;写入下一个BITsetb date_lineret;--------------------------------------------------------------------read: mov r4,#4 ; 将温度低位、高位、TH、TL从DS18B20中读出mov r1,#TEMPL ; 存入25H、26H、27H、28Hre00: mov r2,#8re01: clr cysetb date_linenopnopclr date_line ;读前总线保持为低nopnopnopsetb date_line ;开始读总线释放mov r3,#09 ;延时18微妙djnz r3,$mov c,date_line ;从DS18B20总线读得一个BITmov r3,#3CHdjnz r3,$ ;等待100微妙rrc a ;把读得的位值环移给Adjnz r2,re01 ;读下一个BITmov @r1,ainc r1djnz r4,re00ret;*****************************************************; 处理温度BCD 码子程序;**************************************************** CONVTEMP: MOV A,TEMPH ;判温度是否零下ANL A,#80HJZ TEMPC1 ;温度零上转CLR CMOV A,TEMPL ;二进制数求补(双字节)CPL A ;取反加1ADD A,#01HMOV TEMPL,AMOV A,TEMPHCPL AADDC A,#00HMOV TEMPH,ASJMP TEMPC11TEMPC1: MOV TEMPHC,#0AH ;+TEMPC11: MOV A,TEMPHCSWAP AMOV TEMPHC,AMOV A,TEMPLANL A,#0FH ;乘0.0625MOV DPTR,#TEMPDOTTABMOVC A,@A+DPTRMOV TEMPLC,A ;TEMPLC LOW=小数部分BCDMOV A,TEMPL ;整数部分ANL A,#0F0H ;取出高四位SWAP AMOV TEMPL,AMOV A,TEMPH ;取出低四位ANL A,#0FHSWAP AORL A,TEMPL ;重新组合MOV TEMP_ZH,ALCALL HEX2BCD1MOV TEMPL,AANL A,#0F0HSWAP AORL A,TEMPHC ;TEMPHC LOW = 十位数BCDMOV TEMPHC,AMOV A,TEMPLANL A,#0FHSWAP A ;TEMPLC HI = 个位数BCDORL A,TEMPLCMOV TEMPLC,AMOV A,R4JZ TEMPC12ANL A,#0FHSWAP AMOV R4,AMOV A,TEMPHC ;TEMPHC HI = 百位数BCDANL A,#0FHORL A,R4MOV TEMPHC,ATEMPC12: RET;---------------------------------------------------------------HEX2BCD1:MOV B,#064H ;十六进制-> BCDDIV AB ;B= A % 100MOV R4,A ;R7 = 百位数MOV A,#0AHXCH A,BDIV AB ;B = A % BSWAP AORL A,BRET;-------------------------------------------------------------; 小数部分码表;------------------------------------------------------------- TEMPDOTTAB:DB 00H,00H,01H,01H,02H,03H,03H,04HDB 05H,05H,06H,06H,07H,08H,08H,09H;===================================================== LOOK_ALARM:MOV DPTR,#M_ALAX2 ;指针指到显示信息区MOV A,#2 ;显示在第二行CALL LCD_PRINTMOV A,#0C6HCALL TEMP_BJ1MOV A,TEMP_TH ;加载TH数据MOV LCD_X,#3 ;设置位置CALL SHOW_DIG2H ;显示数据MOV A,#0CEHCALL TEMP_BJ1MOV A,TEMP_TL ;加载TL数据MOV LCD_X,#12 ;设置位置CALL SHOW_DIG2L ;显示数据RET;--------------------------------------------M_ALAX1:DB " LOOK ALERT CODE",0M_ALAX2:DB "TH: TL: ",0;--------------------------------------------TEMP_BJ1:CALL WCOMMOV DPTR,#BJ2 ;指针指到显示信息区MOV R1,#0MOV R0,#2BBJJ2: MOV A,R1MOVC A,@A+DPTRCALL WDATAINC R1DJNZ R0,BBJJ2RETBJ2:DB 00H,"C";---------------------------------------------------SHOW_DIG2H: ;在LCD 的第二行显示数字MOV B,#100DIV ABADD A,#30HPUSH BMOV B,LCD_XCALL LCDP2POP BMOV A,#0AHXCH A,BDIV ABADD A,#30HINC LCD_XPUSH BMOV B,LCD_XCALL LCDP2POP BINC LCD_XMOV A,BMOV B,LCD_XADD A,#30HCALL LCDP2RETSHOW_DIG2L: ;在LCD 的第二行显示数字MOV B,#100DIV ABMOV A,#0AHXCH A,BDIV ABADD A,#30HPUSH BMOV B,LCD_XCALL LCDP2POP BINC LCD_XMOV A,BMOV B,LCD_XADD A,#30HCALL LCDP2RET;-------------------------------------------------------------;显示区BCD 码温度值刷新子程序;-------------------------------------------------------------DISPBCD:MOV A,TEMPLCANL A,#0FHMOV 70H,A ;小数位MOV A,TEMPLCSWAP AANL A,#0FHMOV 71H,A ;个位MOV A,TEMPHCANL A,#0FHMOV 72H,A ;十位MOV A,TEMPHCSWAP AANL A,#0FHMOV 73H,A ;百位MOV A,TEMPHCANL A,#0F0HCJNE A,#010H,DISPBCD0SJMP DISPBCD2DISPBCD0: MOV A,TEMPHCANL A,#0FHJNZ DISPBCD2 ;十位数是0MOV A,TEMPHCSWAP AANL A,#0FHMOV 73H,#0AH ;符号位不显示MOV 72H,A ;十位数显示符号DISPBCD2: RET;========================================================== ; LCD 1602 显示子程序;========================================================== CONV:MOV A,73H ;加载百位数据MOV LCD_X,#6 ;设置位置CJNE A,#1,CONV1JMP CONV2CONV1: MOV A,#" "MOV B,LCD_XCALL LCDP2JMP CONV3CONV2: CALL SHOW_DIG2 ;显示数据CONV3: INC LCD_X ;mov a,72h ;十位CALL SHOW_DIG2inc LCD_Xmov a,71h ;个位CALL SHOW_DIG2inc LCD_XMOV A,#'.'MOV B,LCD_XCALL LCDP2MOV A,70h ;加载小数点位INC LCD_X ;设置位置CALL SHOW_DIG2 ;显示数据RET;-------------------------------------------------------SHOW_DIG2: ;在LCD 的第二行显示数字ADD A,#30HMOV B,LCD_XCALL LCDP2RET;---------------------------------------------------------LCDP2: ;在LCD的第二行显示字符PUSH ACC ;MOV A,B ;设置显示地址ADD A,#0C0H ;设置LCD的第二行地址CALL WCOM ;写入命令POP ACC ;由堆栈取出ACALL WDATA ;写入数据RET;---------------------------------------------------------SET_LCD: ;对LCD 做初始化设置及测试CLR LCD_ENCALL INIT_LCD ;初始化LCDCALL STORE_DATA ;将自定义字符存入LCD的CGRAMRETINIT_LCD: ;8位I/O控制LCD 接口初始化MOV A,#38H ;双列显示,字形5*7点阵CALL WCOMcall delay1MOV A,#38HCALL WCOMcall delay1MOV A,#38HCALL WCOMcall delay1MOV A,#0CH ;开显示,显示光标,光标不闪烁CALL WCOMcall delay1MOV A,#01H ;清除LCD 显示屏CALL WCOMcall delay1RET;==================================================CLR_LINE1: ;清除LCD的第一行字符MOV A,#80H ;设置LCD 的第一行地址CALL WCOM ;MOV R0,#24 ;设置计数值C1: MOV A,#' ' ;载入空格符至LCDCALL WDATA ;输出字符至LCDDJNZ R0,C1 ;计数结束RET;==================================================LCD_PRINT: ;在LCD的第一行或第二行显示字符CJNE A,#1,LINE2 ;判断是否为第一行LINE1: MOV A,#80H ;设置LCD 的第一行地址CALL WCOM ;写入命令CALL CLR_LINE ;清除该行字符数据MOV A,#80H ;设置LCD 的第一行地址CALL WCOM ;写入命令JMP FILLLINE2: MOV A,#0C0H ;设置LCD 的第二行地址CALL WCOM ;写入命令CALL CLR_LINE ;清除该行字符数据MOV A,#0C0H ;设置LCD 的第二行地址CALL WCOMFILL: CLR A ;填入字符MOVC A,@A+DPTR ;由消息区取出字符CJNE A,#0,LC1 ;判断是否为结束码RETLC1: CALL WDATA ;写入数据INC DPTR ;指针加1JMP FILL ;继续填入字符RET;=========================================CLR_LINE: ;清除该行LCD 的字符MOV R0,#24CL1: MOV A,#' 'CALL WDATADJNZ R0,CL1RETDE: MOV R7,#250DJNZ R7,$RET;============================================WCOM: ;以8位控制方式将命令写至LCD MOV P0,A ;写入命令CLR LCD_RS ;RS=L,RW=L,D0-D7=指令码,E=高脉冲CLR LCD_RWSETB LCD_ENACALL DELAY1CLR LCD_ENRET;=============================================WDATA: ;以8位控制方式将数据写至LCD MOV P0,A ;写入数据SETB LCD_RSCLR LCD_RWSETB LCD_ENCALL DECLR LCD_ENCALL DERET;=============================================;PRINT A CHAR ON LINE 1;A=ASC DATA, B=LINE X POS;==============================================LCDP1: ;在LCD的第一行显示字符PUSH ACC ;MOV A,B ;设置显示地址ADD A,#80H ;设置LCD的第一行地址CALL WCOM ;写入命令POP ACC ;由堆栈取出ACALL WDATA ;写入数据RET;============================================== BEEP_BL:MOV R6,#100BL2: CALL DEX1CPL BEEPDJNZ R6,BL2MOV R5,#10CALL DELAYRETDEX1: MOV R7,#180DE2: NOPDJNZ R7,DE2RETDELAY: ;(R5)*延时10MSMOV R6,#50DL1: MOV R7,#100DJNZ R7,$DJNZ R6,DL1DJNZ R5,DELAYRETDELAY1: ;延时5MSMOV R6,#25DL2: MOV R7,#100DJNZ R7,$DJNZ R6,DL2RET;================================================ END。
DS1302时钟+DS18B20用LCD1602显示(系统很简单)看仔细点啊貌似很多这样的图但可不一样喔最小系统是用AT89s52搭建的!记得回去自己用prot ues和Keil仿真一下,这样有利于进一步了解!故未将仿真好的代码上传,如果真的需要的话可以和我联系!程序代码:#include <>#include <>据端口8A8C0F0F0F0F0F0F0F2007/07/228c07/07/25期: 3. 时间: 23:59:55Write1302(0x88,0x07);Write1302(0x86,0x25);Write1302(0x8a,0x07);Write1302(0x84,0x23);Write1302(0x82,0x59);Write1302(0x80,0x55);Write1302(0x8e,0x80); {;}}}void outkey() //跳出调整模式,返回默认显示{ uchar Second;if(out==0||wireless_1==1){ mdelay(8);count=0;hide_sec=0,hide_min=0,hide_hour=0,hide_day=0,hide_week=0,hide_month=0,hide_year=0;Second=Read1302(DS1302_SECOND);Write1302(0x8e,0x00); //写入允许Write1302(0x80,Second&0x7f);Write1302(0x8E,0x80); //禁止写入done=0;while(out==0);while(wireless_1==1);}}////////////////////////////////////////////////////////////////////////////////////////// //////////////////void Upkey()//升序按键{Up=1;if(Up==0||wireless_2==1){mdelay(8);switch(count){case 1:temp="Read1302"(DS1302_ SECOND); //读取秒数temp="temp"+1; //秒数加1up_flag=1; //数据调整后更新标志if((temp&0x7f)>0x59) //超过59秒,清零temp="0";break;case 2:temp="Read1302"(DS1302_ MINUTE); //读取分数temp="temp"+1; //分数加1up_flag=1;if(temp>0x59) //超过59分,清零temp="0";break;case 3:temp="Read1302"(DS1302_ HOUR); //读取小时数temp="temp"+1; //小时数加1up_flag=1;if(temp>0x23) //超过23小时,清零temp="0";break;case 4:temp="Read1302"(DS1302_ WEEK); //读取星期数temp="temp"+1; //星期数加1up_flag=1;if(temp>0x7)temp="1";break;case 5:temp="Read1302"(DS1302_ DAY); //读取日数temp="temp"+1; //日数加1up_flag=1;if(temp>0x31)temp="1";break;case 6:temp="Read1302"(DS1302_ MONTH); //读取月数temp="temp"+1; //月数加1up_flag=1;if(temp>0x12)temp="1";break;case 7:temp="Read1302"(DS1302_ YEAR); //读取年数temp="temp"+1; //年数加1up_flag=1;if(temp>0x85)temp="0";break;default:break;}while(Up==0);while(wireless_2==1);}}////////////////////////////////////////////////////////////////////////////////////////// //////////////////void Downkey()//降序按键{Down=1;if(Down==0||wireless_3==1){mdelay(8);switch(count){case 1:temp="Read1302"(DS1302_ SECOND); //读取秒数temp="temp-1"; //秒数减1down_flag=1; //数据调整后更新标志if(temp==0x7f) //小于0秒,返回59秒temp="0x59";break;case 2:temp="Read1302"(DS1302_ MINUTE); //读取分数temp="temp-1"; //分数减1down_flag=1;if(temp==-1)temp="0x59"; //小于0秒,返回59秒break;case 3:temp="Read1302"(DS1302_ HOUR); //读取小时数temp="temp-1"; //小时数减1down_flag=1;if(temp==-1)temp="0x23";break;case 4:temp="Read1302"(DS1302_ WEEK); //读取星期数temp="temp-1"; //星期数减1down_flag=1;if(temp==0)temp="0x7";;break;case 5:temp="Read1302"(DS1302_ DAY); //读取日数temp="temp-1"; //日数减1down_flag=1;if(temp==0)temp="31";break;case 6:temp="Read1302"(DS1302_ MONTH); //读取月数temp="temp-1"; //月数减1down_flag=1;if(temp==0)temp="12";break;case 7:temp="Read1302"(DS1302_ YEAR); //读取年数temp="temp-1"; //年数减1down_flag=1;if(temp==-1)temp="0x85";break;default:break;}while(Down==0);while(wireless_3==1);}}void Setkey()//模式选择按键{Set=1;if(Set==0||wireless_4==1){mdelay(8);count="count"+1; //Setkey按一次,count就加1 done="1"; //进入调整模式while(Set==0);while(wireless_4==1);}}void keydone()//按键功能执行{ uchar Second;if(flag==0) //关闭时钟,停止计时{ Write1302(0x8e,0x00); //写入允许temp="Read1302"(0x80);Write1302(0x80,temp|0x80);Write1302(0x8e,0x80); //禁止写入flag="1";}Setkey(); //扫描模式切换按键 switch(count){case 1:do //count=1,调整秒{outkey(); //扫描跳出按钮 Upkey(); //扫描加按钮Downkey(); //扫描减按钮if(up_flag==1||down_flag==1) //数据更新,重新写入新的数据{Write1302(0x8e,0x00); //写入允许Write1302(0x80,temp|0x80); //写入新的秒数Write1302(0x8e,0x80); //禁止写入up_flag=0;down_flag=0;}hide_sec++; //位闪计数if(hide_sec>3)hide_sec=0;show_time(); //液晶显示数据 }while(count==2);break;case 2:do //count=2,调整分{hide_sec=0;outkey();Upkey();Downkey();if(temp>0x60)temp="0";if(up_flag==1||down_flag==1){Write1302(0x8e,0x00); //写入允许Write1302(0x82,temp); //写入新的分数Write1302(0x8e,0x80); //禁止写入up_flag=0;down_flag=0;}hide_min++;if(hide_min>3)hide_min=0;show_time();}while(count==3);break;case 3:do //count=3,调整小时{hide_min=0;outkey();Upkey();Downkey();if(up_flag==1||down_flag==1){Write1302(0x8e,0x00); //写入允许Write1302(0x84,temp); //写入新的小时数Write1302(0x8e,0x80); //禁止写入up_flag=0;down_flag=0;}hide_hour++;if(hide_hour>3)hide_hour=0;show_time();}while(count==4);break;case 4:do //count=4,调整星期{hide_hour=0;outkey();Upkey();Downkey();if(up_flag==1||down_flag==1){Write1302(0x8e,0x00); //写入允许Write1302(0x8a,temp); //写入新的星期数Write1302(0x8e,0x80); //禁止写入up_flag=0;down_flag=0;}hide_week++;if(hide_week>3)hide_week=0;show_time();}while(count==5);break;case 5:do //count=5,调整日{hide_week=0;outkey();Upkey();Downkey();if(up_flag==1||down_flag==1){Write1302(0x8e,0x00); //写入允许Write1302(0x86,temp); //写入新的日数Write1302(0x8e,0x80); //禁止写入up_flag=0;down_flag=0;}hide_day++;if(hide_day>3)hide_day=0;show_time();}while(count==6);break;case 6:do //count=6,调整月{hide_day=0;outkey();Upkey();Downkey();if(up_flag==1||down_flag==1){Write1302(0x8e,0x00); //写入允许Write1302(0x88,temp); //写入新的月数Write1302(0x8e,0x80); //禁止写入up_flag=0;down_flag=0;}hide_month++;if(hide_month>3)hide_month=0;show_time();}while(count==7);break;case 7:do //count=7,调整年{hide_month=0;outkey();Upkey();Downkey();if(up_flag==1||down_flag==1){Write1302(0x8e,0x00); //写入允许Write1302(0x8c,temp); //写入新的年数Write1302(0x8e,0x80); //禁止写入up_flag=0;down_flag=0;}hide_year++;if(hide_year>3)hide_year=0;show_time();}while(count==8);break;case 8: count="0";hide_year=0; //count8, 跳出调整模式,返回默认显示状态Second="Read1302"(DS1302_SECOND);Write1302(0x8e,0x00); //写入允许Write1302(0x80,Second&0x7f);Write1302(0x8E,0x80); //禁止写入 done="0";break; //count=7,开启中断,标志位置0并退出default:break;}}void show_time() //液晶显示程序{DS1302_GetTime(&CurrentTime); //获取时钟芯片的时间数据TimeToStr(&CurrentTime); //时间数据转换液晶字符DateToStr(&CurrentTime); //日期数据转换液晶字符ReadTemp(); //开启温度采集程序temp_to_str(); //温度数据转换成液晶字符GotoXY(12,1); //液晶字符显示位置Print(TempBuffer); //显示温度GotoXY(0,1);Print; //显示时间GotoXY(0,0);Print; //显示日期GotoXY(15,0);Print(week_value); //显示星期GotoXY(11,0);Print("Week"); //在液晶上显示字母 weekDelay1ms(400); //扫描延时}main(){flag="1";//时钟停止标志LCD_Initial(); //液晶初始化Init_DS18B20( ) ; / /DS18B20初始化Initial_DS1302(); //时钟芯片初始化up_flag=0;down_flag=0;done=0; / /进入默认液晶显示wireless_1=0;wireless_2=0;wireless_3=0;wireless_4=0;while(1){while(done==1)keydone();//进入调整模式while(done==0){show_tim e(); //液晶显示数据flag="0" ;Setkey();//扫描各功能键}}}。
/*本程序为基于51单片机的DS18b20与lcd1602显示温度程序,1602数据线友P0口提供*/程序已通过硬件测试直接使用作者:liuzqiang1016#include<reg51.h>#define uchar unsigned char#define uint unsigned intsbit DQ=P2^0;//ds18b20sbit lcd_rw=P2^5;sbit lcd_rs=P2^6;sbit lcd_en=P2^7;unsigned char code str1[]={"temperature: "};unsigned char code str2[16]={" "};uchar data disdata[5];uint value;//温度值uchar flag;//正负标志/*************************lcd1602程序**************************/void delay1ms(unsigned int ms)//延时1毫秒(不够精确的){unsigned int i,j;for(i=0;i<ms;i++)for(j=0;j<100;j++);}void write_com(unsigned char com)//写指令//{ delay1ms(1);lcd_rs=0;lcd_rw=0;lcd_en=0;P0=com;delay1ms(1);lcd_en=1;delay1ms(1);lcd_en=0;}void write_dat(unsigned char dat)//写数据//{ delay1ms(1);;lcd_rs=1;lcd_rw=0;lcd_en=0;P0=dat;delay1ms(1);lcd_en=1;delay1ms(1);lcd_en=0;}void lcd_init()//初始化设置//{write_com(0x38);delay1ms(5);write_com(0x08);delay1ms(5);write_com(0x01);delay1ms(5);write_com(0x06);delay1ms(5);write_com(0x0c);delay1ms(5);}void display(unsigned char *p)//显示//{while(*p!='\0'){write_dat(*p);p++;delay1ms(1);}}init_play()//初始化显示{ lcd_init();write_com(0x80);display(str1);write_com(0xc0);display(str2);}void delay_18B20(unsigned int i)//延时1微秒{while(i--);}void ds1820rst()/*ds1820复位*/{unsigned char x=0;DQ = 1; //DQ复位delay_18B20(4); //延时DQ = 0; //DQ拉低delay_18B20(100); //精确延时大于480usDQ = 1; //拉高delay_18B20(40);}uchar ds1820rd()/*读数据*/{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_18B20(10);}return(dat);}void ds1820wr(uchar wdata)/*写数据*/ {unsigned char i=0;for (i=8; i>0; i--){ DQ = 0;DQ = wdata&0x01;delay_18B20(10);DQ = 1;wdata>>=1;}}read_temp()/*读取温度值并转换*/{uchar a,b;ds1820rst();ds1820wr(0xcc);//*跳过读序列号*/ds1820wr(0x44);//*启动温度转换*/ds1820rst();ds1820wr(0xcc);//*跳过读序列号*/ds1820wr(0xbe);//*读取温度*/a=ds1820rd();b=ds1820rd();value=b;value<<=8;value=value|a;if(value<0x0fff)flag=0;else{value=~value+1;flag=1;}value=value*(0.625);//温度值扩大10倍,精确到1位小数return(value);}/*******************************************************************/ void ds1820disp()//温度值显示{ uchar flagdat;disdata[0]=value/1000+0x30;//百位数disdata[1]=value%1000/100+0x30;//十位数disdata[2]=value%100/10+0x30;//个位数disdata[3]=value%10+0x30;//小数位if(flag==0)flagdat=0x20;//正温度不显示符号elseflagdat=0x2d;//负温度显示负号:-if(disdata[0]==0x30){disdata[0]=0x20;//如果百位为0,不显示if(disdata[1]==0x30){disdata[1]=0x20;//如果百位为0,十位为0也不显示}}write_com(0xc0);write_dat(flagdat);//显示符号位write_com(0xc1);write_dat(disdata[0]);//显示百位write_com(0xc2);write_dat(disdata[1]);//显示十位write_com(0xc3);write_dat(disdata[2]);//显示个位write_com(0xc4);write_dat(0x2e);//显示小数点write_com(0xc5);write_dat(disdata[3]);//显示小数位}/********************主程序***********************************/ void main(){ init_play();//初始化显示while(1){read_temp();//读取温度ds1820disp();//显示}}。
目录1引言 (1)2系统描述 (2)2.1系统功能 (2)2.2系统设计指标 (2)3系统的主要元件 (3)3.1单片机 (3)3.2温度传感元件 (4)3.3LCD显示屏 (6)4硬件电路 (7)4.1系统整体原理图 (7)4.2单片机晶振电路 (7)4.3温度传感器连接电路 (8)4.4LCD电路 (9)4.5报警和外部中断电路 (10)5结论 (11)温度监测系统硬件设计摘要:利用DS18B20为代表的新型单总线数字式温度传感器实现温度的监测,可以简化硬件电路,也可以实现单线的多点分布式温度监测,而不会浪费单片机接口,提供了单片机接口的利用率。
同时提高了系统能够的抗干扰性,使系统更灵活、方便。
本系统主要实现温度的检测、显示以及高低温的报警。
也可以通过单总线挂载多个DS18B20实现多点温度的分布式监测。
关键词: DS18B20,单总线,温度,单片机1引言在科技广泛发展的今天,计算机的发展已经越来越快,它的应用已经越来越广泛。
而单片机的发展和应用是其中的重要一方面。
单片机在工业生产(机电、化工、轻纺、自控等等)和民用家电各方面有广泛的应用。
其中,单片机在工业生产中的应用尤其广泛。
单片机具有集成度高,处理能力强,可靠性高,系统结构简单,价格低廉的优点,因此被广泛应用。
在工业生产中,电流、电压、温度、压力、流量、流速和开关量都是常用的主要测量参数。
例如:在冶金工业、化工工业、电力工程、机械制造和食品加工等许多领域中,人们都需要对各类加热炉、热处理炉、反映炉和锅炉,尤其是热学试验(如:物体的比热容、汽化热、热功当量、压强温度系数等教学实验)中的温度进行测量,并经常会对其进行控制。
传统的方式是采用热电偶或热电阻,但是由于模拟温度传感器输出为模拟信号,必须经过A/D 转换环节获得数字信号后才能够被单片机等微处理器接收处理,使得硬件电路结构复杂,制作成本较高。
近年来,美国DALLAS公司生产的DS18B20为代表的新型单总线数字式温度传感器以其突出优点广泛使用于仓储管理、工农业生产制造、气象观测、科学研究以及日常生活中。
单总线数字温度传感器DS18B20一DS18B20特点DS18B20 是单线数字温度传感器,即“一线器件”。
单总线即只有一根数据线,系统中的数据交换,控制都由这根线完成。
单总线通常要求外接一个约为4.7K—10K 的上拉电阻,这样,当总线闲置时其状态为高电平。
DS18B20具有独特的优点:( 1 )采用单总线的接口方式与微处理器连接时仅需要一条口线即可实现微处理器与DS18B20 的双向通讯。
单总线具有经济性好,抗干扰能力强,适合于恶劣环境的现场温度测量,使用方便等优点,使用户可轻松地组建传感器网络,为测量系统的构建引入全新概念。
( 2 )测量温度范围宽,测量精度高DS18B20 的测量范围为-55 ℃~+ 125 ℃;在-10~+ 85°C 范围内,精度为±0.5°C 。
(3 )在使用中不需要任何外围元件。
(4 )持多点组网功能多个DS18B20 可以并联在惟一的单线上,实现多点测温。
(5 )供电方式灵活DS18B20 可以通过内部寄生电路从数据线上获取电源。
因此,当数据线上的时序满足一定的要求时,可以不接外部电源,从而使系统结构更趋简单,可靠性更高。
(6 )测量参数可配置DS18B20 的测量分辨率可通过程序设定9~12 位。
(7 )负压特性电源极性接反时,温度计不会因发热而烧毁,但不能正常工作。
(8 )掉电保护功能DS18B20 内部含有EEPROM ,在系统掉电以后,它仍可保存分辨率及报警温度的设定值。
(9 )DS18B20 具有体积更小、适用电压更宽、更经济、可选更小的封装方式,更宽的电压适用范围,适合于构建自己的经济的测温系统,因此也就被设计者们所青睐。
二DS18B20芯片结构1 DS18B20的外部结构DS18B20可采用3脚TO-92小体积封装和8脚SOIC封装。
其外形和引脚图如下:2 DS18B20内部结构如图所示主要由4部分组成:64 位ROM、温度传感器、非挥发的温度报警触发器TH 和TL、配置寄存器。
单总线温度传感器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℃计数器所需要的计数个数。
电子综合实践设计报告专业班级:学生姓名:指导教师:设计时间:物理与通信电子学院摘要DS18B20数字温度计是DALLAS公司生产的1-Wire,即单总线器件,具有线路简单、体积小、低功耗、高精度、抗干扰能力强等特点的数字温度传感器。
本设计采用多点测温方法,在一个IO口上挂接多个DS18B20测温,在远距离工作时,为了防止信号的衰减,DS18B20用屏蔽双绞线包裹,远端接地的方法工作,并把所测得的温度在LCD上显示出来。
文中简要的介绍了DS18B20的基本特点、引脚功能、测温原理及时序的控制。
给出了DS18B20的使用电路、使用中的注意事项、硬件及软件设计方法。
经过测试,该系统的测量精度及速度等指标均能满足设计要求。
关键词:DS18B20 测温系统数字温度传感器多点测温目录摘要 (2)1 引言 (4)2 设计要求 (4)3 方案设计与原理 (4)3.1 DS18B20 简介 (4)3.1.1 DS18B20特性 (4)3.1.2说明: (5)3.1.3 DS18B20测温原理: (5)3.1.4 DS18B20测温原理图: (6)3.1.5 64位激光刻ROM (7)3.1.6 CRC发生器 (7)3.1.7 单总线系统 (7)3.2 DS18B20指令控制 (7)3.2.1 ROM时序指令控制 (8)3.2.2DS18B20功能指令控制 (8)3.3 18B20时序详解 (9)3.3.1初始化时序 (9)3.3.2读/写时序 (9)3.4二叉树遍历 (11)4 设计程序流程图: (16)5 设计硬件原理图 (17)6 DS18B20使用中应注意事项 (18)7测试中出现的问题及解决办法和说明: (18)8 结束语 (19)9 参考文献: (20)10 附录: (21)1 引言本系统利用DS18B20进行测温,基于单片机AT89S52进行温度控制,具有硬件电路简单,控温精度高、功能强,体积小,简单灵活等优点,可以应用于控制温度在-55℃到+125℃之间的各种场合,可以实现温度的实时采集、显示功能。
单总线协议-以DS18B20举例一、概述1-wire 单总线是Maxim 全资子公司Dallas 的一项专有技术。
与目前多数标准串行数据通信方式,如SPI/I2C/MICROWIRE 不同,它采用单根信号线,既传输时钟,又传输数据,而且数据传输是双向的。
它具有节省I/O 口线资源、结构简单、成本低廉、便于总线扩展和维护等诸多优点。
1-wire 单总线适用于单个主机系统,能够控制一个或多个从机设备。
当只有一个从机位于总线上时,系统可按照单节点系统操作;而当多个从机位于总线上时,则系统按照多节点系统操作。
为了较为全面地介绍单总线系统,将系统分为三个部分讨论:硬件结构、命令序列和信号方式信号类型和时序。
二、硬件结构顾名思义,单总线只有一根数据线。
设备(主机或从机)通过一个漏极开路或三态端口,连接至该数据线,这样允许设备在不发送数据时释放数据总线,以便总线被其它设备所使用。
单总线端口为漏极开路其内部等效电路如图1 所示。
单总线要求外接一个约5k 的上拉电阻;这样,单总线的闲置状态为高电平。
不管什么原因,如果传输过程需要暂时挂起,且要求传输过程还能够继续的话,则总线必须处于空闲状态。
位传输之间的恢复时间没有限制,只要总线在恢复期间处于空闲状态(高电平)。
如果总线保持低电平超过480us,总线上的所有器件将复位。
另外在寄生方式供电时,为了保证单总线器件在某些工作状态下(如温度转换期间EEPROM写入等)具有足够的电源电流,必须在总线上提供强上拉(如图1所示的MOSFET )。
三、命令序列典型的单总线命令序列如下:第一步:初始化第二步:ROM命令(跟随需要交换的数据)第三步:功能命令(跟随需要交换的数据)每次访问单总线器件,必须严格遵守这个命令序列,如果出现序列混乱,则单总线器件不会响应主机。
但是,这个准则对于搜索ROM命令和报警搜索命令例外,在执行两者中任何一条命令之后,主机不能执行其后的功能命令,必须返回至第一步。
基于ds18b20温度带上限程序--LCD1602液晶显示这是用1602 来显示的,程序是修改前面几个实验的,当温度=40 度时电风扇转动,为参加电子比赛做的单片机系统实验。
程序为汇编语言(ASM),带详细注释,值得新手朋友参考!全部程序:ORG 0000H;单片机内存分配申明! TEMPER_L EQU 29H;用于保存读出温度的低8 位TEMPER_H EQU 28H;用于保存读出温度的高8 位FLAG1 EQU 38H;是否检测到DS18B20 标志位a_bit equ 20h ;数码管个位数存放内存位置b_bit equ 21h ;数码管十位数存放内存位置RS EQU P3.7;确定具体硬件的连接方式RW EQU P3.6 ;确定具体硬件的连接方式E EQU P3.5 ;确定具体硬件的连接方式;主程序MAIN:LCALL GET_TEMPER;调用读温度子程序MOV A,29HMOV C,40H;将28H 中的最低位移入CRRC AMOV C,41HRRC AMOV C,42HRRC AMOV C,43HRRC AMOV 29H,Aclr csetb p3.0;zhelikais 从这里开始是我填加的温度控制CJNE A,#28H,FITSETB P3.0AJMP DISLEDFIT:CPL CMOV P3.0,C;jiesu 到这里结束DISLED:LCALL DISPLAY;调用数码管显示子程序AJMP MAIN;DS18B20复位初始化子程序INIT_1820:SETB P2.2NOPCLR P2.2;主机发出延时537 微秒的复位低脉冲MOV R1,#3TSR1:MOV R0,#107DJNZ R0,$DJNZ R1,TSR1SETB P2.2;然后拉高数据线NOPNOPNOPMOV R0,#25HTSR2:JNB P2.2,TSR3;等待DS18B20 回应DJNZ R0,TSR2LJMP TSR4 ; 延时TSR3:SETB FLAG1 ; 置标志位,表示DS1820 存在CLR P1.7;检查到DS18B20 就点亮P1.7LED,与传感器通信成功LJMP TSR5TSR4:CLR FLAG1 ; 清标志位,表示DS1820 不存在CLR P1.1; 未检查到DS18B20 就点亮P1.1LED,与传感器通信失败LJMPTSR7TSR5:MOV R0,#117TSR6:DJNZ R0,TSR6 ; 时序要求延时一段时间TSR7:SETB P2.2RET;读出转换后的温度值的子程序GET_TEMPER:SETB。
这是一个利用1602液晶显示温度和蜂鸣器报警的函数;使用的测温器件是单总线DS18B20;#include<reg52.h>#include<intrins.h>#include<math.h>#define uchar unsigned char#define uint unsigned intsbit dula=P2^6; //数码管的段选sbit wela=P2^7; //数码管的位选sbit RW=P1^1; //1602sbit RS=P1^0; //1602sbit LCDEN=P2^5;sbit DS=P2^2; //DS18B20的总线sbit FM=P2^3; //蜂鸣器void delayUs(){_nop_();//微秒级的延时}void delayMs(uint a) //毫秒级的延时。
{uint i,j;for(i=a;i>0;i--)for(j=100;j>0;j--);}void writecom(uchar com) //向1602写命令;{RS=0;P0=com;LCDEN=1;delayUs();LCDEN=0;delayMs(1);}void writedat(uchar dat) //写数据。
P0=dat;LCDEN=1;delayUs();LCDEN=0;delayMs(1);}void init() // 1602初始化{RW=0;dula=0;wela=0;writecom(0x38);writecom(0x0c);writecom(0x06);writecom(0x01);}void writeString(uchar *str) //向1602写字符串。
{uchar length;uchar i=0;do{length=1+i;i++;} while(str[i]);for(i=length;i>0;i--){writedat(str[length-i]);}}int DSinit() //DS18B20的初始化{uint i;DS=0;i=100;while(i>0) i--;while(i>0) i--;while(DS) //检验是否初始化成功{i++;if(i>40000)return 0;}return 1;}void DSwait(){uint i;while(DS);while(~DS);i=4;while(i>0) i--;}bit readbit() //读一个比特{uint i;bit b;DS=0;i++;DS=1;i++;i++;b=DS;i=8;while(i>0) i--;return b;}uchar readbyte()// 利用前面的函数读一个字节{uint i;uchar j,dat;dat=0;for(i=0;i<8;i++){j=readbit();//赋值给最低位dat=(j<<7)|(dat>>1);//每位放到高位;return dat;}void writebyte(uchar dat)//写一个字节;{uint i;uchar j;bit b;for(j=0;j<8;j++){b=dat&0x01;dat>>=1;if(b){DS=0;i++;i++;i++;DS=1;i=8;while(i>0)i--;}else{DS=0;i=8;while(i>0)i--;DS=1;i++;i++;}}}void sendChangecom(){DSinit();DSwait();delayMs(1);writebyte(0xcc);writebyte(0x44);void sendReadcom(){DSinit();DSwait();delayMs(1);writebyte(0xcc);writebyte(0xbe);}int getTmpvalue(){uint tmpvalue;int value;float t;uchar low,high;sendReadcom();low=readbyte();high=readbyte();tmpvalue=high,tmpvalue<<=8;tmpvalue|=low;value = tmpvalue;t=value*0.0625;value=t*100+(value>0?0.5:-0.5); return value;}void display(int v){int count;char datas[]={0,0,0,0,0,0};uint tmp=abs(v);datas[0]=tmp/10000;datas[1]=tmp%10000/1000;datas[2]=tmp%1000/100;datas[3]=tmp%100/10;datas[4]=tmp%10;{writedat('-');}else{writedat('+');}if(datas[0]!=0)writedat('0'+datas[0]);for(count = 1;count!=5;count++){writedat('0'+datas[count]);if(count==2)writedat('.');}}void warning(int x){if((x/100)>26){ delayMs(100);FM=~FM;delayMs(100);}}void main(){char table[]="WENDU:";while(!DSinit());init();P1=0x00;writecom(0x80);sendChangecom();writeString(table );while(1){delayMs(1000);writecom(0xc0);delayMs(850);warning(getTmpvalue());sendChangecom();}}。