51单片机与ds18b20程序

合集下载

51单片机+1602+DS18B20的温度报警程序+实物设计(按键可调温度阈值)

51单片机+1602+DS18B20的温度报警程序+实物设计(按键可调温度阈值)

51单片机+1602+DS18B20的温度报警程序+实物设计(按键可调温度阈值)实现功能:51单片机做的温度显示,温度显示在LCD1602液晶屏上。

然后按键可以调整温度阈值,温度高于或低于所设温度,蜂鸣器就会响……单片机源程序如下:1./**************************************************************************************2.3.* 基于单片机的实时温度报警系统设计*4.5.(1)DS18b20采集到的温度可以实时地在数码管或者在液晶上显示出来;6.(2)用三个独立键盘设置阀值,包括设置键,加键,减键和确认键;7.(3)按下设置键时,数码管或者液晶上显示2S“H”字,随后温度闪烁显示,进入设置阀值最大值状态;8.再次按下设置键,数码管或者液晶上显示2S“L”字,随后温度闪烁显示,进入设置阀值最小值状态,9.第三次按下设置键(此时相当于确认键),系统保存设置好的阀值并进入正常的温度显示状态;10.(此程序功能与第三点有出入)11.(4)当采集到的温度大于阀值最大值或者小于阀值最小值时蜂鸣器发出声音报警。

12.13.注释:k1:温度加 k2:温度减 k3:低温度阈值设置 k4:高温度阈值设置14.15.适用单片机:STC89C52RC 适用开发板:普中科技 CH—6800ES V2.0 晶振:12MHZ16.17.***************************************************************************************/18.19.#include "reg52.h" //此文件中定义了单片机的一些特殊功能寄存器20.#include "lcd.h"21.#include "temp.h"22.#include "intrins.h"23.#include "key.h"24.25.typedef unsigned int u16; //对数据类型进行声明定义26.typedef unsigned char u8;27.28.u8 Disp[]= "Temp: ";29.u8 Disp2[]= "Xiaoliyu Design ";30.31.extern unsigned int LTemp; //低阈值温度32.extern unsigned int LLTemp;33.unsigned int DTemp; //高阈值温度34.unsigned int DLTemp;35.36.u16 NowTemp=35; //当前温度37.u16 IntFlag1=0; //外部中断1标志位38.u16 IntFlag0=0; //外部中断0标志位39.40.sbit Beep=P1^5; //设置蜂鸣器引脚41.sbit LA=P2^2;42.sbit LB=P2^3;43.sbit LC=P2^4;44.45.void delay10us(void);46.void delay100us(void);47.void delay10ms(void);48.void delay1s(void);49.void Int1Init();50.void Int0Init();51.void Timer0Init();52.53./*******************************************************************************54.* 函数名 : main55.* 函数功能 : 主函数56.* 输入 : 无57.* 输出 : 无58.*******************************************************************************/59.void main(void)60.{61. u8 i;62. Int1Init(); //外部中断1初始化63. Int0Init(); //外部中断0初始化64. LcdInit(); //LCD1602初始化65. Timer0Init(); //定时器0初始化66.67. LA =1;68. LB =0;69. LC =0;70.71.////////////////////////////////////////////////////////////////////////////////72.73. for(i=0;i<16;i++) //初始化LCD屏(第一行)74. {75. LcdWriteData(Disp[i]);76. }77.78. delay100us();79. LcdWriteCom(0xC0); //初始化LCD屏(第二行)80.81. for(i=0;i<16;i++)82. {83. LcdWriteData(Disp2[i]);84. }85.86. /////////////////////////////////////////////////////////////////////87.88. while(1)89. {90.91. LcdWriteCom(0x85);92. datapros(Ds18b20ReadTemp()); //获取DS18B20温度93. for(i=0;i<11;i++) //温度信息写入160294. {95. LcdWriteData(DisplayData[i]);96. }97.98.99. if(IntFlag1==1) //若外部中断1标志位为1,则进入高温度阈值设置界面100. {101. LcdMenu();102. if(IntFlag1==0) //若外部中断1标志位为0,则退出高温度阈值设置界面103. { //重载温度显示页面参数104. LcdInit();105. for(i=0;i<16;i++)106. {107. LcdWriteData(Disp[i]);108. }109. delay100us();110.111. LcdWriteCom(0xC0);112. for(i=0;i<16;i++)113. {114. LcdWriteData(Disp2[i]);115. }116.117. }118. delay10ms();119.120. }121.122.123. if(IntFlag0==1) //若外部中断0标志位为1,则进入低温度阈值设置界面124. {125.126. LcdMenuL();127. if(IntFlag0==0) //若外部中断0标志位为0,则退出低温度阈值设置界面128. { //重载温度显示页面参数129. LcdInit();130. for(i=0;i<16;i++)131. {132. LcdWriteData(Disp[i]);133. }134. delay100us();135.136. LcdWriteCom(0xC0);137. for(i=0;i<16;i++)138. {139. LcdWriteData(Disp2[i]);140. }141.142. }143. delay10ms();144. }145.146.147. NowTemp=dataReturn(Ds18b20ReadTemp()); //获取当前温度148. DTemp=(LTemp/100); //获取高温度阈值149. DLTemp=(LLTemp/100); //获取低温度阈值150.151. if((NowTemp>=DTemp)|(NowTemp<=DLTemp)) //如果当前温度大于高温度阈值或小于低温度阈值,则打开定时器0启动蜂鸣器152. {153. ET0=1; //打开定时器0中断允许154. led=~led;155. delay10us();156. }157. else158. {159. ET0=0; //关闭定时器0中断允许160. delay10us();161. }162.163. }164.165./////////////////////////////////////////////////////////////////////////// /////166.167.}168.169./************************************************************************** *****170.* 函数名 : delay10ms171.* 函数功能 : 延时函数10ms172.* 输入 : 无173.* 输出 : 无174.*************************************************************************** ****/175.176.void delay10ms(void)177.{178. unsigned char a,b,c;179. for(c=1;c>0;c--)180. for(b=38;b>0;b--)181. for(a=130;a>0;a--);182.}183.184./************************************************************************** *****185.* 函数名 : delay100us186.* 函数功能 : 延时函数100us187.* 输入 : 无188.* 输出 : 无189.*************************************************************************** ****/190.191.void delay100us(void)192.{193. unsigned char a,b;194.for(b=1;b>0;b--)195. for(a=47;a>0;a--);196.}197.198./************************************************************************** *****199.* 函数名 : delay10us200.* 函数功能 : 延时函数10us201.* 输入 : 无202.* 输出 : 无203.*************************************************************************** ****/204.205.void delay10us(void)206.{207. unsigned char a,b;208. for(b=1;b>0;b--)209. for(a=2;a>0;a--);210.}211.212./************************************************************************** *****213.* 函数名 : Int1Init214.* 函数功能 : 延时函数10us215.* 输入 : 无216.* 输出 : 无217.*************************************************************************** ****/218.219.void Int1Init()220.{221. //设置INT1222. IT1=1;//跳变沿出发方式(下降沿)223. EX1=1;//打开INT1的中断允许。

51单片机 DS18B20温控保温汇编程序

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。

51单片机+ds1302+DS18b20温度时钟(电路图+C语言程序)

51单片机+ds1302+DS18b20温度时钟(电路图+C语言程序)

时钟电路图:*■11PCB板:酱时井務ft是用诵m-pdfMerisi 口叵因Fjr 齐舱 C :s ® 工细理沖缶皿ndm - * TfS ' 4' 包田U i > 'ir ft ZS:MZ fH钟些fl是用说町-Pdf Wirrcf闻礒雜sbit dis_ bitlsbit dis_ bit2sbit dis_ bit3sbit dis_ bit4sbit dis_ bit5sbit dis_ bit6sbit ledl _bitsbit led2 ! bit=P2A7; II定义数码管控制口=P2A6; II定义数码管控制口=卩2八4; II定义数码管控制口=卩2八3; II定义数码管控制口=P2A1; II定义数码管控制口=P2A0; II定义数码管控制口=P2A2; II定时LED勺控制口=P2A5; II定时LED勺控制口单片机程序:/*===================================================================调试要求:1. MCU:AT89S52 芯片或AT89C522. 晶振:12MHz功能:多功能时钟+温度计/#inelude <reg52. h>#inelude vintrins . h>訂开始 LJ-雲匕®务如1痒3月计ttVl. •呈T』d"吐拠席射■ w耳pg文宇■[豹…SS时軽件思冃说#define uehar #define uint unsigned char unsigned intsbit s1_bit =P1A 0; // 定义S1 控制口 sbit s2_bit =P01; // 定义 S2控制口 sbit s3_bit =P02; // 定义 S3控制口 sbit dq_ds18b20 =P3A3;// 定义控制 DS18B20 sbit speak =P3A7; //定义蜂鸣器控制口sbit clk_ds1302 =P3A6; // 定义控制 DS1302勺时钟线 sbit io_ds1302 =P3A5;//定义控制DS1302勺串行数据 sbit rest_ds1302 =P3A4;#define smg_data P0 //定义数码管数据口void delay_3us(); //3US 的延时程序 void delay_8us(ui nt t);//8US 延时基准程序void delay_50us(ui nt t); //void display1(uchar dis_data); void display2(uchar dis_data); void display3(uchar dis_data); void display4(uchar dis_data); void display5(uchar dis_data); void display6(uchar dis_data);void init_t0(); //定时器0初始化函数 void dis_led(); //LED 处理函数 void judge_s1(); //S1 按键处理函数void judge_s2(); //S2 按键处理函数 void judge_s3(); //S3 按键处理函数void dis(uchar s6,uchar s5,uchar s4,uchar s3,uchar s2,uchar s1); 示子程序 void dis_sa n( uchar s6,uchar s5,uchar s4,uchar s3,uchar s1,uchar san); 〃闪烁显示子程序 void judge_dis(); //显示处理函数 void judge_clock(); // 显示处理函数 void set_ds1302(); // 设置时间void get_ds1302();// 读取当前时间void w_1byte_ds1302(uchar t); // 向 DS130写一个字节的数据 uchar r_1byte_ds1302(); // 从DS130读一个字节的数据//DS18B20测温函数定义延时50*T 微妙函数的声明//数码管1显示子程序 //数码管2显示子程序 //数码管3显示子程序 //数码管4显示子程序 //数码管5显示子程序 //数码管6显示子程序//显 s2,ucharvoid w_1byte_ds18b20(uchar value); // 向DS18B2写一个字节ucharr_1byte_ds18b20( void ); // 从DS18B2读取一个字节的数据voidrest_ds18b20( void ); //DS18B20复位程序void readtemp_ds18b20( void ); // 读取温度void dis_temp(); //温度显示函数//共阳数码管断码表const uchar tabl1[16] ={ 0xc0,0xf9,0xa4,0xb0,0x99,0x92,// 0 1 2 3 4 50x82,0xf8,0x80,0x90,0x86,0x87,0xFF,//6 7 8 9 E T B0xc6,0xbf,0xff };// C -const uchar tabl3[] ={ 0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,0x05,0x06,0x06,0x07,0x08,0x08,0x09,0x09 };uchar t0_crycle;uchar hour_co un t, minu te_c oun t,sec on d_co un t,msec ond_count;uchar clock_hour,clock_m inu te;uchar coun tdow n_sec ond;uchar coun tdow n_hour,co un tdow n_min ute;uchar clock_en; //闹钟关闭和开启的标志,1开启,0关闭uchar flag1,sec on d_flag,za ncun 1,za ncun 2,za ncun3;uchar zancun4 ,za ncun 5,za ncun 6,za ncun7;uchar clock_flag,co un tdow n_flag;uchar msec on d_mi nute,msec on d_sec on d,mseco nd_mseco nd,mseco nd_flag; // 秒表相关参数uint speak_c ount;uchar templ,temph,temp_flag;uchar t_b,t_s,t_g,t_x,temp_flag2; //从左到右分别存储温度百位,十位,个位,小数位uchar tab23[3]; 〃二{0x40,0x59,0x23,0x28,0x11,0x06,0x09};// 上电时默认的时间//主程序void main(){P3 =0x00;flag1 =0;zancun3 =0;msecond_minute =0; //置秒表相关参数为0msecond_second =0;msec on d_msec ond =0;speak =1;//关闭蜂鸣器speak_co unt =0;clock_hour =0;clock_m inute =0;clock_flag =0;countdown_flag =0; //倒计时标志位为0clock_en =0;//开机时默认关闭闹钟ini t_t0();TRO =1;//// set_ds1302();〃设置DS1302勺初始时间//接下来开始编写让数码管显示的程序while (1){get_ds1302();judge_dis(); // 显示处理judge_s1();judge_s2();judge_s3();judge_clock(); //闹钟处理程序} _}void timerO() interrupt 1{TH0=(65536-50000)/256;TL0=(65536 - 50000)%256; t0_crycle ++;if (t0_crycle ==2) // 0.1 秒{t0_crycle =0;msec on d_flag =1;msec ond_count ++;if (msecond_count==10)//1 秒{ _msec on d_co unt =0;sec on d_flag =1;}}}//**************************************************//显示处理函数void judge_dis(){if (flag1 ==0){if (second_flag ==1){ _zancun7 ++;sec on d_flag =0;} _if (zancun7 <1){if (temp_flag2 ==1){ 一readtemp_ds18b20(); // 读取温度temp_flag2 =0;厂dis_temp(); //温度显示函数}if (zancun7 >=1){temp_flag2 =1;zancun4 =hour_count &0xf0;zancun4 >>=4;zancun5 =minute_count&0xf0;zancun5 >>=4;zancun6 =sec on d_co unt&0xf0;zancun6 >>=4;dis(za ncun4 ,hour_co unt &0x0f,za ncun5,minu te_co unt &0x0f,za ncun 6,sec ond_ cou nt &0x0f);dis_led();if (zancun7 ==5)zancun7 =0;}}if (flag1 !=0){switch (flag1){case 1:dis(5,10,11,1,12,12); // 显示SET1led1_bit =1;led2_bit =1;break;case 2:dis(5,10,11,2,12,12); // 显示SET2break;case 3:dis(5,10,11,3,12,12); // 显示SET3break;case 4:dis(5,10,11,4,12,12); // 显示SET4break;case 5:dis(5,10,11,5,12,12); // 显示SET5break;case 6:dis_san(zancun1 / 10,zancunl %10,zancun2/ 10,zancun2 %0,12,12,1); break;case 7:dis_san(zancun1 / 10,zancunl %10,zancun2/ 10,zancun2 %0,12,12,2); break;case 8:dis_san(zancun1 / 10,zancunl %10,zancun2/ 10,zancun2 %0,12,12,3); break;case 9: //进入修改时间,时间分位个位闪烁dis_san(zancun1 / 10,zancunl %10,zancun2/ 10,zancun2 %0,12,12,4); break;case 10: //进入修改闹钟,闹钟小时十位闪烁dis_san(zancunl / 10,zancunl %10,zancun2/ 10,zancun2 %0,12,zancun3,1); break;case 11://进入修改闹钟,闹钟小时个位闪烁dis_san(zancun1 / 10,zancunl %10,zancun2/ 10,zancun2%0,12,zancun3,2); break;case 12: //进入修改闹钟,闹钟小时十位闪烁dis_sa n(zan cu n1 / 10,za ncun1 %10,za ncun 2/ 10,za ncu n2%0,12,za ncun 3,3);break;case 13: //进入修改闹钟,闹钟小时个位闪烁dis_sa n(zan cu n1 / 10,za ncun1 %10,za ncun 2/ 10,za ncu n2%0,12,za ncun 3,4);break;case 14: //进入修改闹钟的开关dis_sa n(zan cu n1 / 10,za ncun1 %10,za ncun 2/ 10,za ncu n2%0,12,za ncun 3,6);break;case 15:dis_sa n(zancun1 / 10,za ncun1 %10,za ncun 2/ 10,za ncun 2%0,za ncun3/ 10,za ncun 3%10,1);break;case 16:dis_san(zancun1 / 10,zancunl %10,zancun2/10,zancun2%0,zancun3/ 10,zancun3%10,2);break;case 17:dis_san(zancun1 / 10,zancunl %10,zancun2/ 10,zancun2%0,zancun3/ 10,zancun 3%10,3);break;case 18:dis_sa n(zancun1 / 10,za ncun1 %10,za ncun 2/ 10,za ncun 2%0,za ncun3/ 10,za ncun 3%10,4);break;case 19:dis_sa n(zancun1 / 10,za ncun1 %10,za ncun 2/ 10,za ncun 2%0,za ncun3/ 10,za ncun 3%10,5);break;case 20:dis_sa n(zancun1 / 10,za ncun1 %10,za ncun 2/ 10,za ncun 2%0,za ncun3/ 10,za ncun 3%10,6);break;case 21:if (second_flag ==1){ _sec on d_flag =0;countdown_second --;if (countdown_second ==255){ _coun tdow n_sec ond =59;countdown_minute --;if (countdown_minute ==255){ _coun tdow n_min ute =59;countdown_hour --;if (countdown_hour ==255){flag1 =22;coun tdow n_min ute =0;coun tdow n_hour =0;coun tdow n_sec ond =0;coun tdow n_flag=1;_ } } } }dis(countdown_hour / 10,countdown_hour %10,countdown_minute / 10,countdown _minute%10,countdown_second/ 10,countdown_second%10); //break; case 22:{ speak =1;}dis(countdown_hour / 10,countdown_hour %10,countdown_minute / 10,countdown _minute%10,countdown_second/ 10,countdown_second%10); //break; case 23: dis(msecond_minute / 10,msecond_minute%10,msecond_second/ 10,msecond_sec on d%10,mseco nd_msec on d%0,12);break; case 24:if (msecond_flag ==1) { _msec on d_flag =0; msec on d_msec ond ++;if (msecond_msecon (==10){msec on d_msec ond =0; msec on d_sec ond ++;if (msecond_second==60) { _msecond_second =0; msec ond_minute ++;if (countdown_flag { _speak=0;if (second_flag { _sec on d_flag coun tdow n_flag} _ } else>0 &&countdown_flag <7)==1) =0; ++;if (msecond_minute==1OO) { _msec ond_minute =99;flagl =23;}}}}dis(msecond_minute / 10,msecond_minute%10,msecond_second/ 10,msecond_sec on d%10,mseco nd_msec on d%0,12);break;case 25:dis(zancun3 / 10,zancun3 %0,zancun2 / 10,zancun2 %10,zancun1 /10,zancun1 %0 );break;default :break;}}}//**************************************************〃S1按键处理函数void judge_s1(){ _s1_bit =1;//置IO为1,准备读入收据if (s1_bit ==0)//判断是否有按键按下{delay_50us(1); //延时,去除机械抖动if (s1_bit ==0){switch (flag1){case 0:case 1:case 2:case 3:case 4:case 6:case 7:case 8:case 10:case 11:case 12:case 13:case 15:case 16:case 17:case 18:case 19: flag1++;break;case 9: flag1=6;break;case 14: flag1=10;break;case 20: flag1=15;break;case 5:case 21:case 22:case 23: //系统从秒表状态复位case 24: //系统从秒表状态复位case 25: //系统从计数器复位flag1 =0;break;default :break;}while (s1_bit ==0){ _judge_dis();}〃等待按键释放}}}〃************************************************** 〃S2按键处理函数void judge_s2(){ _s2_bit =1; //置IO为1,准备读入收据if (s2_bit ==0)//判断是否有按键按下=0;{delay_50us(1); //延时,去除机械抖动 if (s2_bit ==0) { switch (flagl) { flag1 =6; zancun4 =hour_count &0xf0;zancun4 >>=4; zancun6 =hour_count &0x0f;zancun1=zancun4*10+zancun6; //zancun 1=hour_co unt; zancun5 =minute_count &0xf0; zancun5 >>=4; zancun6 =minute_count &0x0f; zancun2 =za ncun5* 10+za ncun6; case 1: //在显示SET 状态下按S2牛,进入修改时间 // zancun2=minu te_co unt; break; case 2: //在显示SET2犬态下按S2,进入设置闹钟 zancunl =clock_hour; zancun2 =clock_m inu te; flagl =10; break; case 6: //修改时钟小时十位状态下按 case 7: //修改时钟小时个位状态下按 case 8: //修改时钟分钟十位状态下按 case 9: //修改时钟分钟个位状态下按 〃zancun4=za ncun 1/10; 测S:SM tab23[2] =zancun1/10* 16+za ncu n1%10; tab23[1] hour_c ount minu te_c ount sec ond_co unt tab23[0]set_ds1302(); flag1//zancun 5=za ncun2&0 xf0; //zancun 5>>=4; =zancun2/10* 16+za ncu n2%10; =tab23[2]; =tab23[1]; =0; //设置DS130的初始时间 =0;break; case 10: //修改闹钟小时十位状态下按S2case 11: //修改闹钟小时个位状态下按S2case 12: //修改闹钟分钟十位状态下按S2 case 13: //修改闹钟分钟个位状态下按S2 case 14: //修改闹钟使能状态下按S2clock_hour clock_m inute clock_e n flag1=zancun1; =zancun2; =zancun3;=0;break;case 3:flagl =15;zancunl =co un tdow n_hour;zancun2 =co un tdow n_minu te;zancun3 =co un tdow n_sec ond;break;case 15:case 16:case 17:case 18:case 19:case 20:coun tdow n_hour =zancun1;coun tdow n_minute =za ncun2;coun tdow n_sec ond =za ncun3;flag1 =21;coun tdow n_flag =0;break;case 22:flag1 =21;break;case 21:flag1 =22;break;case 4:flag1 =23; //秒表暂停msec ond_minute =0;msecond_second =0;msec on d_msec ond =0;break;case 23:flag1 =24;break;case 24:flag1 =23;break;case 5:flagl =25;//进入计数器模式zancunl =0;zancun2 =0;zancun3 =0;break; default :break;}while (s2_bit ==0){ _judge_dis();}//等待按键释放}}}//**************************************************//S3按键处理函数void judge_s3(){ _s3_bit =1;//置IO为1,准备读入收据if (s3_bit ==0)//判断是否有按键按下{delay_50us(1); //延时,去除机械抖动if (s3_bit ==0){ _switch (flag1){case 6: //修改时间小时的十位数zancun1 +=10;if (zancun1 >=24)zancun1 =zancun 1%10;break;case 7: //修改时间小时的个位数za ncun1 =za ncu n1/10* 10+(za ncun1 %10+1) %10;if (zancun1 >=24)zancun1 =20;break;case 8: //修改时间分钟的十位数zancun2 +=10;if (zancun2 >=60)zancun2-=60;break;case 9: //修改时间分钟的个位数za ncun2 =za ncun2/10* 10+(za ncun2 %10+1) %10;break;case 10: //修改闹钟小时的十位数zancunl +=10;if (zancunl >=24)zancunl =zancun 1%10; break;case 11: //修改闹钟小时的个位数zancunl =za ncu n1/10* 10+(za ncun1 %10+1) %10;if (zancun1 >=24)zancun1 =20;break;case 12: //修改闹钟分钟的十位数zancun2 +=10;if (zancun2 >=60)zancun2-=60; break;case 13: //修改闹钟分钟的个位数zan cu n2 =za ncun2/10* 10+(za ncun2 %10+1) %10;break;case 14:zancun3 A=1;break;case 15: //修改倒计时小时的十位数zancun1 +=10;if (zancun1 >=100)zancun 1 -=100; break;case 16: //修改倒计时小时的个位数zancun1 =za ncu n1/10* 10+(za ncun1 %10+1) %10;break;case 17: //修改倒计时分钟的十位数zancun2 +=10;if (zancun2 >=60)zancun2-=60; break;case 18: //修改倒计时分钟的个位数zan cu n2 =za ncun2/10* 10+(za ncun2 %10+1) %10;break;case 19: //修改倒计时秒的十位数zancun3 +=10;if (zancun3 >=60)zancun3-=60; break;case 20: //修改倒计时秒的个位数zan cu n3 =za ncun3/10* 10+(za ncun3 %10+1) %10;break;case 21:case 22: //coun tdow n_hour =zancun1;coun tdow n_minute =za ncun2;coun tdow n_sec ond =za ncun3;flagl =21;break;case 23:case 24: //秒表复位flag1 =24;msec ond_minute =0;msecond_second =0;msec on d_msec ond =0;break;case 25:zancun1 ++;if (zancun1 ==100){zancun1 =0;zancun2 ++;if (zancun2 ==100){zancun2 =0;zancun3 ++;}}break;default : break;}while (s3_bit ==0){ _judge_dis();}〃等待按键释放}}} //显示处理函数void judge_clock() {zancun4 =hour_count &0xf0;zancun4 >>=4;zancun6 =hour_count &0x0f;zancun4 *=10;zancun4 +=za ncun6;zancun5=minute_count &0xf0;if (san ==1){zancun5 >>=4;zancun6 =minute_count &0x0f;zancun5 *=10;zancun5 +=za ncun6;if (msecond_count<=5) {speak =0; speak_co unt ++;}else{speak =1;}}else{speak =1;}}〃****************************************////闪烁显示子程序void dis_sa n( uchar s6,uchar s5,uchar s4,uchar s3,uchars1,uchar san){if (clock_hour ==zancun4 &&clock_minute ==zancun5){ 一 一if (clock_en { _ speak_co unt clock_flag speak_co unt} _ } else{clock_flag =0;} _if{ (clock_flag ==1 ==1&&clock_flag ==0)=0; //开启蜂鸣器=1;=0;&&speak_count <400)s2,ucharif (msecond_count<5) { _ display1(s6);}}else{display1(s6);}if (san ==2){if (msecond_count<5) { _ display2(s5);}}else{display2(s5);}if (san ==3){if (msecond_count<5) { _ display3(s4);}}else{display3(s4);}if (san ==4){if (msecond_count<5) { _ display4(s3);}}else{display4(s3);}if (san ==5){if (msecond_count<5){ _ display5(s2);}}else{display5(s2);}if (san ==6){if (msecond_count<5){ _ display6(s1);}}else{ display6(s1);}}〃****************************************//时钟显示程序void dis(uchar s6,uchar s5,uchar s4,uchar s3,uchar s2,uchar s1) { display1(s6);display2(s5);display3(s4);display4(s3);display5(s2);display6(s1);}〃********************************************************************************************void init_tO(){ _TMOD0x01;〃设定定时器工作方式1,定时器定时50毫秒TH0=(65536-50000)/256;TL0=(65536- 50000)%256;EA=1; //开总中断ET0=1; //允许定时器0中断t0_crycle =0; //定时器中断次数计数单元}//LED处理函数void dis_led(){if (msecond_count<5){ _Ied1_bit =1;Ied2_bit =1;}else{led1_bit =0;led2_bit =0;}}〃***************************************************************//功能:把数据1显示在数码管1上void display6(uchar dis_data){ _smg_data =tabl1[dis_data]; // 送显示断码dis_bit6 =0; // 锁存数据delay_50us(40); dis_bit6 =1;}〃***************************************************************//功能:把数据1显示在数码管1上void display5(uchar dis_data){ _smg_data =tabl1[dis_data]; // 送显示断码dis_bit5 =0; // 锁存数据delay_50us(40);dis_bit5 =1;} _〃***************************************************************//功能:把数据1显示在数码管1上void display4(uchar dis_data){ _smg_data =tabl1[dis_data]; // 送显示断码dis_bit4 =0; // 锁存数据delay_50us(40);dis_bit4 =1;} 〃***************************************************************//功能:把数据1显示在数码管1上void display3(uchar dis_data){ _smg_data =tabl1[dis_data]; // 送显示断码dis_bit3 =0; // 锁存数据delay_50us(40);dis_bit3 =1;}〃***************************************************************//功能:把数据1显示在数码管1上void display1(uchar dis_data){ _smg_data =tabl1[dis_data]; // 送显示断码dis_bit1 =0; // 锁存数据delay_50us(40);dis_bit1 =1;}〃***************************************************************//功能:把数据1显示在数码管1上void display2(uchar dis_data){ _smg_data =tabl1[dis_data]; // 送显示断码dis_bit2 =0; // 锁存数据delay_50us(40);dis_bit2 =1;}〃******************************************************************* *******************************// 函数名称:void delay_50US(unsigned int t)//功能:延时50*t(us)void delay_50us(uint t){ _unsigned char j;for (;t >0;t --){for (j =19;j >0;j --);}}〃******************************************************************* ************〃8微秒延时基准程序void delay_8us(uint t){while (-- t);}************〃3微秒延时程序void delay_3us() {}〃******************************************************************* ************//子程序功能:向DS18B2写一字节的数据void w_1byte_ds18b20(uchar value){uchar i =0;for (i =0;i <8;i ++){dq_ds18b20 =1;delay_3us();dq_ds18b20 =0; delay_8us(2);if ( value & 0x01) dq_ds18b20 =1; 〃DQ = 1 delay_50us(1); // 延时50us 以上delay_8us(2);value >>=1;}dq_ds18b20 =1; //DQ = 1}//读一个字节uchar r_1byte_ds18b20( void){ 一一uchar i =0;uchar value = 0;for (i =0;i <8;i ++){value >>=1;dq_ds18b20 =0;// DQ_L;delay_3us();dq_ds18b20 =1; 〃DQ_H;delay_8us(2);if (dq_ds18b20==1) value |= 0x80;delay_8us(6); // 延时40us}dq_ds18b20 =1;return value ;}11 ・**************************************************〃ds18b20复位子程序void rest_ds18b20( void){rest:delay_3us(); // 稍做延时delay_3us();dq_ds18b20 =1;delay_3us();dq_ds18b20 =0;// DQ_L; delay_50us(11); 〃480us<T<960usdq_ds18b20 =1; // 拉高总线delay_8us(5);if (dq_ds18b20==1){return ;}delay_50us(2); // 延时90usif (dq_ds18b20==1){return ;}else{goto rest;}}〃****************************************************//读取温度void readtemp_ds18b20( void){ _uchar temp32;rest_ds18b20();w_1byte_ds18b20(0xcc); //跳过读序列号的操作w_1byte_ds18b20(0x44); // 启动温度转换delay_8us(2);rest_ds18b20();w_1byte_ds18b20(0xcc); //跳过读序列号的操作w_1byte_ds18b20(0xbe); //读取温度寄存器等(共可读9个寄存器)前两个就是温度templ =r_1byte_ds18b20();temph =r_1byte_ds18b20();if ((temph &0xf0)) //判断温度的正负性{temp_flag =0; //温度为负数标志temph =-temph;tempi =-templ;t_x =tabl3[templ & OxOf]; // 计算温度的小数temp32 =temph & OxOf;temp32 <<=4;tempi >>=4;temp32 =temp32 | tempi;t_b =temp32/100%10; //计算温度的百位数据t_s =temp32/10%0;〃计算温度的十位数据t_g =temp32%0;〃计算温度的个位数据5else //为正数{t_x =tabl3[templ & 0x0f]; // 计算温度的小数temp32 =temph & 0x0f;temp32 <<=4;templ >>=4;temp32 =temp32 | templ;t_b =temp32/100%10; //计算温度的百位数据t_s =temp32/10%0;〃计算温度的十位数据t_g =temp32%0;〃计算温度的个位数据temp_flag =1;} _}void dis_temp() //温度显示函数{ _if (temp_flag =1){ _if (t_b ==0){dis(12,12,t_s,t_g,13,12);}else{dis(12,t_b,t_s,t_g,13,12);}}else{dis(14,t_b,t_s,t_g,13,12);}}/ / """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" / / , ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ############ //;子程序名:w_1byte_ds1302//;功能:向DS130写一个字节的数据void w_1byte_ds1302(uchar t){uchar i;for (i =0;i <8;i ++){if (t & 0x01){io_ds1302=1;}else{io_ds1302 =0;}clk_ds1302 =1;delay_3us();delay_3us();clk_ds1302 =0;delay_3us();delay_3us();t >>=1;}}/ / , ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ######//;子程序名:r_1byte_ds1302()//;功能:从DS130读一个字节的数据uchar r_1byte_ds1302(){ 一一uchar i,temp11 =0;io_ds1302 =1;//置10为1,准备读入数据for (i =0;i <8;i ++){temp11 >>=1;if (io_ds1302) temp11 |= 0x80;clk_ds1302 =1;delay_3us();delay_3us();clk_ds1302 =0;delay_3us();}return (temp11);}/ / """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""/ / , JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ """""""""""""""ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff//;子程序名:setbds1302//;功能:设置DS130初始时间,并启动计时void set_ds1302(){uchar i,j;rest_ds1302 =0;delay_3us();clk_ds1302 =0;delay_3us();rest_ds1302 =1;delay_3us();w_1byte_ds1302(0x8e); // 写控制命令字delay_3us();w_1byte_ds1302(0x00); // 写保护关闭clk_ds1302 =1;delay_3us();for (i =0,j =0x80;i <7;i ++,j +=2){rest_ds1302 =0;delay_3us();clk_ds1302 =0;delay_3us();rest_ds1302 =1;delay_3us();w_1byte_ds1302(j);delay_3us();w_1byte_ds1302(tab23[i]);delay_3us();delay_3us();clk_ds1302 =1;delay_3us();rest_ds1302 =0;delay_3us();delay_3us();} _rest_ds1302 =0;delay_3us();clk_ds1302 =0;delay_3us();rest_ds1302 =1;delay_3us();w_1byte_ds1302(0x8e); delay_3us();w_1byte_ds1302(0x80); clk_ds1302 =1;delay_3us();rest_ds1302 =0;delay_3us();}/ / """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" / / , ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff //;子程序名:get1302void get_ds1302(){ _uchar temp11[7],i,j;for (i =0;i <7;i ++){temp11[i] =0;}for (i =0,j =0x81;i <7;i ++,j +=2){rest_ds1302 =0;delay_3us();clk_ds1302 =0;delay_3us();delay_3us();w_1byte_ds1302(j);temp11[i] =r_1byte_ds1302();delay_3us();clk_ds1302 =1;delay_3us();rest_ds1302 =0;delay_3us();} _if (temp11[0] != 0xff){second_count =temp11[0]; }if (temp11[1] != 0xff) // 数据验证{minute_count =temp11[1]; }if (temp11[2] != 0xff) // 数据验证{hour_count =temp11[2]; }// date=temp[3];//mon th=temp[4];// week=temp[5];//year=temp[6];}/*===================================================================调试要求:1. MCU:AT89S52 芯片或AT89C522. 晶振:12MHz功能:多功能时钟+温度计/#inelude <reg52. h>#inelude vintrins . h>sbit dis_bit1 =P2A 7; //定义数码管控制口sbit dis_bit2 =卩2八6;//定义数码管控制口sbit dis_bit3 =卩2八4;//定义数码管控制口sbit dis_bit4 =卩2八3;//定义数码管控制口sbit dis_bit5 =卩2八1; //定义数码管控制口sbit dis_bit6 =P2A0; //定义数码管控制口sbit led1_bit =卩2八2; // 定时 LED 勺控制口sbit led2_bit =卩2八5; // 定时 LED 勺控制口sbit s1_bit =P1A0; // 定义S1 控制口sbit s2_bit =P01; // 定义 S2空制口sbit s3_bit =P02; // 定义 S3控制口sbit dq_ds18b20 =P3A3;// 定义控制 DS18B20 sbit speak =P3A7; //定义蜂鸣器控制口sbit clk_ds1302 =P3A6; // 定义控制 DS1302勺时钟线 sbit io_ds1302 =P3A5;//定义控制DS1302勺串行数据sbit rest_ds1302 =P3A4;#define smg_data P0 //定义数码管数据口 void delay_3us(); //3US 的延时程序 void delay_8us(ui nt t); //8US 延时基准程序void delay_50us(ui nt t); // void display1(uehardis_data); voiddisplay2(uehar dis_data); void display3(uehar dis_data); void display4(uehar dis_data); void display5(uehar dis_data); void display6(uehar dis_data);void init_t0(); //定时器0初始化函数void dis_led(); //LED 处理函数void judge_s1();//S1 按键处理函数 void judge_s2(); //S2 按键处理函数void judge_s3(); //S3 按键处理函数 void dis(uehar s6,uehar s5,uehar s4,uehar s3,uehar s2,uehar s1); 示子程序 void dis_sa n( uchar s6,uehar s5,uehar s4,uehar s3,uehars1,uchar san); 〃闪烁显示子程序void judge_dis(); //显示处理函数void judge_clock(); // 显示处理函数void set_ds1302(); // 设置时间void get_ds1302(); // 读取当前时间#define uehar#define uintunsigned char unsigned int延时50*T 微妙函数的声明//数码管1显示子程序 //数码管2显示子程序 //数码管3显示子程序//数码管4显示子程序//数码管5显示子程序//数码管6显示子程序 //显s2,ueharvoid w_1byte_ds1302(uchar t); // 向DS130写一个字节的数据uchar r_1byte_ds1302(); // 从DS130读一个字节的数据〃*******************************************************************//DS18B20测温函数定义void w_1byte_ds18b20(uchar value); // 向DS18B2写一个字节ucharr_1byte_ds18b20( void ); // 从DS18B2读取一个字节的数据voidrest_ds18b20( void ); //DS18B20复位程序void readtemp_ds18b20( void ); // 读取温度void dis_temp(); //温度显示函数//共阳数码管断码表const uchar tabl1[16] ={ 0xc0,0xf9,0xa4,0xb0,0x99,0x92,// 0 1 2 3 4 50x82,0xf8,0x80,0x90,0x86,0x87,0xFF,//6 7 8 9 E T B0xc6,0xbf,0xff };// C -const uchar tabl3[] ={ 0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,0x05,0x06,0x06,0x07,0x08,0x08,0x09,0x09 };uchar t0_crycle;uchar hour_co un t, minu te_c oun t,sec on d_co un t,msec ond_count;uchar clock_hour,clock_m inu te;uchar coun tdow n_sec ond;uchar coun tdow n_hour,co un tdow n_min ute;uchar clock_en; //闹钟关闭和开启的标志,1开启,0关闭uchar flag1,sec on d_flag,za ncun 1,za ncun 2,za ncun3;uchar zancun4 ,za ncun 5,za ncun 6,za ncun7;uchar clock_flag,co un tdow n_flag;uchar msec on d_mi nute,msec on d_sec on d,mseco nd_mseco nd,mseco nd_flag; // 秒表相关参数uint speak_c ount;uchar templ,temph,temp_flag;uchar t_b,t_s,t_g,t_x,temp_flag2; //从左到右分别存储温度百位,十位,个位,小数位上电时默认的uchar tab23[3]; 〃二{0x40,0x59,0x23,0x28,0x11,0x06,0x09};//时间//主程序void main(){P3 =0x00;flag1 =0;zancun3 =0;msecond_minute =0; //置秒表相关参数为0msecond_second =0;msec on d_msec ond =0;speak =1;//关闭蜂鸣器speak_co unt =0;clock_hour =0;clock_m inute =0;clock_flag =0;countdown_flag =0; //倒计时标志位为0clock_en =0;//开机时默认关闭闹钟ini t_t0();TR0 =1;//// set_ds1302();〃设置DS130的初始时间//接下来开始编写让数码管显示的程序while (1){get_ds1302();judge_dis(); // 显示处理judge_s1();judge_s2();judge_s3();judge_clock(); //闹钟处理程序} _}void timer0() interrupt 1{TH0=(65536-50000)/256;TL0=(65536- 50000)%256;t0_crycle ++;if (t0_crycle ==2) // 0.1 秒{t0_crycle =0;msec on d_flag =1;msec ond_count ++;if (msecond_count==10)//1 秒。

51单片机与ds18b20程序

51单片机与ds18b20程序

#include <>#include <>#define uchar unsigned char#define uint unsigned intsbit DQ = P2^2; //数据口define interfacesbit dula = P2^6; //数码管段选sbit wela = P2^7; //数码管位选uint temp; //温度值 variable of temperature//不带小数点unsigned char code table[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//带小数点unsigned char code table1[] ={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef};/*************精确延时函数*****************/void delay(unsigned char i){while(--i);}/******************************************此延时函数针对的是12Mhz的晶振delay(0):延时518us 误差:518-2*256=6delay(1):延时7us (原帖写"5us"是错的)delay(10):延时25us 误差:25-20=5delay(20):延时45us 误差:45-40=5delay(100):延时205us 误差:205-200=5delay(200):延时405us 误差:405-400=5*******************************************//*****************DS18B20******************/void Init_Ds18b20(void) //DS18B20初始化send reset and initialization command{DQ = 1; //DQ复位,不要也可行。

51单片机与DS18B20测温的C程序——完整版

51单片机与DS18B20测温的C程序——完整版

/*-----------------------------------------------名称:18B20温度传感器修改:无内容:18B20单线温度检测的应用样例程序,请将18b20插紧,然后在数码管可以显示XX.XC,C表示摄氏度,如显示25.3C表示当前温度25.3度------------------------------------------------*/#include<reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义#include<math.h>#include<INTRINS.H>#define uchar unsigned char#define uint unsigned int/******************************************************************//* 定义端口*//******************************************************************/sbit seg1=P2^0;sbit seg2=P2^1;sbit seg3=P2^2;sbit DQ=P1^3;//ds18b20 端口sfr dataled=0x80;//显示数据端口/******************************************************************//* 全局变量*//******************************************************************/uint temp;uchar flag_get,count,num,minute,second;uchar code tab[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//7段数码管段码表共阳uchar str[6];/******************************************************************//* 函数声明*//******************************************************************/void delay1(uchar MS);unsigned int ReadTemperature(void);void Init_DS18B20(void);unsigned char ReadOneChar(void);void WriteOneChar(unsigned char dat);void delay(unsigned int i);/******************************************************************//* 主函数*//******************************************************************/main(){unsigned char TempH,TempL;TMOD|=0x01;//定时器设置TH0=0xef;P2=0x00;count=0;while(1){str[5]=0x39; //显示C符号str[1]=tab[TempH/100]; //十位温度str[2]=tab[(TempH%100)/10]; //十位温度str[3]=tab[(TempH%100)%10]|0x80; //个位温度,带小数点str[4]=tab[TempL];if(flag_get==1) //定时读取当前温度{temp=ReadTemperature();if(temp&0x8000){str[0]=0x40;//负号标志temp=~temp; // 取反加1temp +=1;}elsestr[0]=0;TempH=temp>>4;TempL=temp&0x0F;TempL=TempL*6/10;//小数近似处理flag_get=0;}}}/******************************************************************/ /* 定时器中断*/ /******************************************************************/ void tim(void) interrupt 1 using 1//中断,用于数码管扫描和温度检测间隔{TH0=0xef;//定时器重装值TL0=0xf0;num++;if (num==50){num=0;flag_get=1;//标志位有效second++;if(second>=60){second=0;minute++;if(count==1){P2=0;dataled=str[0];}//数码管扫描if(count==2){P2=1;dataled=str[1];}if(count==3){ P2=2;dataled=str[2];}if(count==4){ P2=3;dataled=str[3];}if(count==5){ P2=4;dataled=str[4];}if(count==6){ P2=5;dataled=str[5];count=0;}}/******************************************************************/ /* 延时函数*/ /******************************************************************/ void delay(unsigned int i)//延时函数{while(i--);}/******************************************************************/ /* 初始化*/ /******************************************************************/ void Init_DS18B20(void){unsigned char x=0;DQ = 1; //DQ复位delay(8); //稍做延时DQ = 0; //单片机将DQ拉低delay(80); //精确延时大于480usDQ = 1; //拉高总线delay(10);x=DQ; //稍做延时后如果x=0则初始化成功x=1则初始化失败delay(5);/******************************************************************/ /* 读一个字节*/ /******************************************************************/ unsigned char ReadOneChar(void){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(5);}return(dat);}/******************************************************************/ /* 写一个字节*/ /******************************************************************/ void WriteOneChar(unsigned char dat){unsigned char i=0;for (i=8; i>0; i--){DQ = 0;DQ = dat&0x01;delay(5);DQ = 1;dat>>=1;}delay(5);}/******************************************************************/ /* 读取温度*/ /******************************************************************/ unsigned int ReadTemperature(void){unsigned char a=0;unsigned int b=0;unsigned int t=0;Init_DS18B20();WriteOneChar(0x44); // 启动温度转换delay(200);Init_DS18B20();WriteOneChar(0xCC); //跳过读序号列号的操作WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器)前两个就是温度a=ReadOneChar(); //低位b=ReadOneChar(); //高位b<<=8;t=a+b;return(t);}。

ds18b20的完整程序(c51)

ds18b20的完整程序(c51)
820 C51 子程序 //这里以 11.0592M 晶体为例,不同的晶体速度可能需要调整延时的时间 //sbit DQ =P2^1;//根据实际情况定义端口 typedef unsigned char byte; typedef unsigned int word; //延时 void delay(word useconds) { for(;useconds>0;useconds--); } //复位 byte ow_reset(void) { byte presence; DQ = 0; //pull DQ line low delay(29); // leave it low for 480us DQ = 1; // allow line to return high delay(3); // wait for presence presence = DQ; // get presence signal delay(25); // wait for end of timeslot return(presence); // presence signal returned } // 0=presence, 1 = no part //从 1-wire 总线上读取一个字节 byte read_byte(void) { byte i; byte value = 0; for (i=8;i>0;i--) { value>>=1; DQ = 0; // pull DQ low to start timeslot DQ = 1; // then return high delay(1); //for (i=0; i<3; i++); if(DQ)value|=0x80; delay(6); // wait for rest of timeslot } return(value); } //向 1-WIRE 总线上写一个字节

51单片机写DS18B20的驱动

51单片机写DS18B20的驱动

51单片机写DS18B20的驱动初始化操作方法:单片机先给总线一个高电平,略微延时,然后拉低总线,至少延时480us(我们取600us),然后拉高总线,等待15~60us 的时间(我们取80us),此后DS18B20 如果响应,则会发出0,拉低总线,否则为1,单片机检测是否响应的时间在60~240us 之内,之后释放总线,程序如下:bitDS18B20_init()//初始化{uchar i;bit flag_response=0;DQ=1;_nop_();_nop_();DQ=0;delay_us(90); //延时600usDQ=1;delay_us(10); //延时80usfor(i=0;i{_nop_();_nop_();_nop_();_nop_(); _nop_();if(!DQ){ flag_response=1;break;}}delay_us(63);//延时420usDQ=1;//释放总线return(flag_response);}写操作方法:由于是单总线,读写操作都分为写0 和写1,从一个字节的最低位逐次往DS18B20 里写,先使总线产生一个由1 到0 的跳变,等待15us(我们取13us),然后判断要写的那位是1 还是0,如果是1,则拉高总线,0 则不去操作总线(因为总线开始产生跳变时已被拉低),等待45us(我们取64us)以后释放总线(这段时间DS18B20 会采样,如上图所示),程序如下:void DS18B20_write(uchar dat)//写1 个字节{uchar i;for(i=0;i{DQ=1;_nop_(); _nop_();DQ=0;delay_us(1);//延时13usif(dat&0x01)DQ=1;delay_us(8);//延时64usDQ=1;//释放总线dat>>=1;}}读操作方法:使总线产生一个由1 到0 的跳变,等待1us,马上拉高总线,等待大约12 个us(datasheet 推荐的采样时间是快接近15us 的时候,我们略微提前),单片机采样,如果总线被拉低,则读出的是0,否则就读出1,然后延。

51单片机Ds18b20温度传感器程序

51单片机Ds18b20温度传感器程序

* 实验名 : 18B20温度显示试验* 实验说明 : 数码管显示温度值,并且将温度值通过串口发送到电脑上。

* 连接方式 : 见连接图temp.h#ifndef __TEMP_H_#define __TEMP_H_#include<reg51.h>//---重定义关键词---//#ifndef uchar#define uchar unsigned char#endif#ifndef uint#define uint unsigned int#endif//--定义使用的IO口--//sbit DSPORT=P3^7;//--声明全局函数--//void Delay1ms(uint );uchar Ds18b20Init();void Ds18b20WriteByte(uchar com);uchar Ds18b20ReadByte();void Ds18b20ChangTemp();void Ds18b20ReadTempCom();int Ds18b20ReadTemp();#endiftemp.c#include"temp.h"/******************************************************************************** 函数名: Delay1ms* 函数功能: 延时函数* 输入: 无* 输出: 无*******************************************************************************/void Delay1ms(uint y){uint x;for( ; y>0; y--){for(x=110; x>0; x--);}}/******************************************************************************** 函数名: Ds18b20Init* 函数功能: 初始化* 输入: 无* 输出: 初始化成功返回1,失败返回0*******************************************************************************/ uchar Ds18b20Init(){uchar i;DSPORT = 0;//将总线拉低480us~960usi = 70;while(i--);//延时642usDSPORT = 1;//然后拉高总线,如果DS18B20做出反应会将在15us~60us后总线拉低i = 0;while(DSPORT)//等待DS18B20拉低总线{Delay1ms(1);i++;if(i>5)//等待>5MS{return 0;//初始化失败}}return 1;//初始化成功}/******************************************************************************** 函数名: Ds18b20WriteByte* 函数功能: 向18B20写入一个字节* 输入: com* 输出: 无*******************************************************************************/void Ds18b20WriteByte(uchar dat){uint i, j;for(j=0; j<8; j++){DSPORT = 0;//每写入一位数据之前先把总线拉低1usi++;DSPORT = dat & 0x01; //然后写入一个数据,从最低位开始i=6;while(i--); //延时68us,持续时间最少60usDSPORT = 1;//然后释放总线,至少1us给总线恢复时间才能接着写入第二个数值dat >>= 1;}}/******************************************************************************** 函数名: Ds18b20ReadByte* 函数功能: 读取一个字节* 输入: com* 输出: 无*******************************************************************************/ uchar Ds18b20ReadByte(){uchar byte, bi;uint i, j;for(j=8; j>0; j--){DSPORT = 0;//先将总线拉低1usi++;DSPORT = 1;//然后释放总线i++;i++;//延时6us等待数据稳定bi = DSPORT;//读取数据,从最低位开始读取/*将byte左移一位,然后与上右移7位后的bi,注意移动之后移掉那位补0。

51单片机DS18B20温度测量制作(有程序电路)

51单片机DS18B20温度测量制作(有程序电路)

51单片机DS18B20温度测量制作(有程序电路)单总线温度传感器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万年历温度时间按键控制1602显示51单片机程序

DS18B20万年历温度时间按键控制1602显示51单片机程序

uint year=2015;
uchar month=2;
uchar day=27,daytemp;
uchar weekdayflag=5;
char H=12;
char M=0;
char S=0;
uchar displaybuf[9];
uchar code cdis1[20]= {"0123456789:.C- "};
sbit LCD_RS = P2^0; //LCD1602数据/命令选择端
sbit LCD_RW = P2^1; //LCD1602读/写选择端
sbit LCD_EN = P2^2; //LCD1602使能端
sbit DQ=P3^3; //DS18B20信号端
delayNOP();
}
//液晶初始化
void lcd_init() //1602液晶初始化函数
{
delay(5);
write_control(0x38); //16*2显示,5*7点阵,8位数据
**********************************************************/
void delayNOP()
{
_nop_(); //一个机器周期1us延时
_nop_();
_nop_();
_nop_();
_nop_();
delayNOP(); //5us延时
result = (bit)(P0&0x80); //确保STA7为0,说明为“闲”状态,为1位“忙”操作;(bit)(P0&0x80)为强制类型转换
LCD_EN = 0; //读取数据结束之后,复位执行使能操作

基于51单片机和DS18B20的数字温度计设计说明

基于51单片机和DS18B20的数字温度计设计说明

基于51单片机和DS18B20的数字温度计设计说明
1.硬件设计:
-51单片机:选择合适的型号,如STC89C52或AT89C52等。

-DS18B20温度传感器:该传感器是一种数字温度传感器,具有单总线接口和高精度测量能力。

-接口电路:将51单片机和DS18B20传感器连接起来,要注意电平转换和信号线的阻抗匹配。

2.软件设计:
-初始化:在主函数中,首先对单片机进行初始化设置,包括时钟设置、串口配置等。

-DS18B20通信协议:使用单总线协议与DS18B20传感器进行通信,包括发送复位信号、读写数据等操作。

-温度测量:通过向DS18B20发送读取温度的命令,从传感器中读取温度值并保存。

-数据传输:将温度值转换为可显示的格式,如摄氏度或华氏度,并通过串口输出或LED显示。

3.程序流程:
-初始化单片机,设置时钟和串口参数。

-进入主循环,循环执行以下操作:
-发送复位信号,启动温度转换。

-等待转换完成,发送读取温度命令。

-读取温度值,并进行数据处理转换。

-输出温度值。

4.其他功能:
-可以添加LCD显示模块,将温度值显示在液晶屏上。

-可以添加按键输入模块,通过按键切换温度单位或进行其他操作。

需要注意的是,该设计只是一个简单的示例,实际应用中可能需要根据具体需求进行扩展和修改。

同时,在程序设计过程中,也要注意低功耗和数据稳定性等方面的考虑。

基于51单片机——Ds18B20温度采集,LCD显示汇编程序(附带proteus仿真图)

基于51单片机——Ds18B20温度采集,LCD显示汇编程序(附带proteus仿真图)

TEMP_ZH EQU 24H ;实测温度值存放单元TEMPL EQU 25HTEMPH EQU 26HTEMP_TH EQU 27H ;高温报警值存放单元TEMP_TL EQU 28H ;低温报警值存放单元TEMPHC EQU 29H ;正、负温度值标记TEMPLC EQU 2AHTEMPFC EQU 2BHK1 EQU P1.4 ;查询按键K2 EQU P1.5 ;设置/调整键K3 EQU P1.6 ;调整键K4 EQU P1.7 ;确定键BEEP EQU P3.7 ;蜂鸣器RELAY EQU P1.3 ;指示灯LCD_X EQU 2FH ;LCD 字符显示位置LCD_RS EQU P2.0 ;LCD 寄存器选择信号 LCD_RW EQU P2.1 ;LCD 读写信号LCD_EN EQU P2.2 ;LCD 允许信号FLAG1 EQU 20H.0 ;DS18B20是否存在标志 KEY_UD EQU 20H.1 ;设定按键的增、减标志 DQ EQU P3.3 ;DS18B20数据信号ORG 0000HLJMP MAINORG 0030HMAIN: MOV SP,#60HMOV A,#00HMOV R0,#20H ;将20H~2FH 单元清零MOV R1,#10HCLEAR: MOV @R0,AINC R0DJNZ R1,CLEARLCALL SET_LCDLCALL RE_18B20START: LCALL RST ;调用18B20复位子程序JNB FLAG1,START1 ;DS1820不存在LCALL MENU_OK ;DS1820存在,调用显示正确信息子程序MOV TEMP_TH,#055H ;设置TH初值85度MOV TEMP_TL,#019H ;设置TL初值25度LCALL RE_18B20A ;调用暂存器操作子程序LCALL WRITE_E2 ;写入DS18B20LCALL TEMP_BJ ;显示温度标记JMP START2START1: LCALL MENU_ERROR ;调用显示出错信息子程序 LCALL TEMP_BJ ;显示温度标记SJMP $START2: LCALL RST ;调用DS18B20复位子程序JNB FLAG1,START1 ;DS18B20不存在MOV A,#0CCH ;跳过ROM匹配命令LCALL WRITEMOV A,#44H ;温度转换命令LCALL WRITELCALL RSTMOV A,#0CCH ;跳过ROM匹配LCALL WRITEMOV A,#0BEH ;读温度命令LCALL WRITELCALL READ ;调用DS18B20数据读取操作子程序LCALL CONVTEMP ;调用温度数据BCD 码处理子程序LCALL DISPBCD ;调用温度数据显示子程序LCALL CONV ;调用LCD显示处理子程序LCALL TEMP_COMP ;调用实测温度值与设定温度值比较子程序LCALL PROC_KEY ;调用键扫描子程序SJMP START2 ;循环;*************************** 键扫描子程序*****************************PROC_KEY:JB K1,PROC_K1LCALL BEEP_BLJNB K1,$MOV DPTR,#M_ALAX1MOV A,#1LCALL LCD_PRINTLCALL LOOK_ALARMJB K3,$LCALL BEEP_BLJMP PROC_K2PROC_K1: JB K2,PROC_ENDLCALL BEEP_BLJNB K2,$MOV DPTR,#RST_A1MOV A,#1LCALL LCD_PRINTLCALL SET_ALARMLCALL RE_18B20 ;将设定的TH,TL值写入DS18B20LCALL WRITE_E2PROC_K2: LCALL MENU_OKLCALL TEMP_BJPROC_END:RET;*************************** 设定温度报警值TH、TL ***************************SET_ALARM:LCALL LOOK_ALARMAS0: JB K1,AS00LCALL BEEP_BLJNB K1,$CPL 20H.1 ;UP/DOWN 标记AS00: JB 20H.1,ASZ01 ;20H.1=1,增加JMP ASJ01 ;20H.1=0,减小ASZ01: JB K2,ASZ02 ;TH值调整(增加)LCALL BEEP_BLINC TEMP_THMOV A,TEMP_THCJNE A,#120,ASZ011MOV TEMP_TH,#0ASZ011: LCALL LOOK_ALARMLCALL DELAYJMP ASZ01ASZ02: JB K3,ASZ03 ;TL值调整(增加) LCALL BEEP_BLINC TEMP_TLMOV A,TEMP_TLCJNE A,#99,ASZ021MOV TEMP_TL,#00HASZ021: LCALL LOOK_ALARMMOV R5,#10LCALL DELAYJMP ASZ02ASZ03: JB K4,AS0 ;确定调整LCALL BEEP_BLJNB K4,$RETASJ01: JB K2,ASJ02 ;TH值调整(减少) LCALL BEEP_BLDEC TEMP_THMOV A,TEMP_THCJNE A,#0FFH,ASJ011ASJ011: LCALL LOOK_ALARMMOV R5,#10LCALL DELAYJMP AS0ASJ02: JB K3,ASJ03 ;TL值调整(减少)LCALL BEEP_BLDEC TEMP_TLMOV A,TEMP_TLCJNE A,#0FFH,ASJ021JMP ASJ022ASJ021: LCALL LOOK_ALARM ;MOV R5,#10LCALL DELAYJMP AS0ASJ022: CPL 20H.1JMP ASZ01ASJ03: JMP ASZ03RETRST_A1: DB " SET ALERT CODE " ,0;*********************** 实测温度值与设定温度值比较子程序**********************TEMP_COMP:MOV A,TEMP_THSUBB A,TEMP_ZH ;减数>被减数,则JC CHULI1 ;借位标志位C=1,转 MOV A,TEMPFCCJNE A,#0BH,COMPSJMP CHULI2COMP: MOV A,TEMP_ZHSUBB A,TEMP_TL ;减数>被减数,则JC CHULI2 ;借位标志位C=1,转MOV DPTR,#BJ5LCALL TEMP_BJ3CLR RELAY ;点亮指示灯RETCHULI1: MOV DPTR,#BJ3LCALL TEMP_BJ3SETB RELAY ;熄灭指示灯LCALL BEEP_BL ;蜂鸣器响RETCHULI2: MOV DPTR,#BJ4LCALL TEMP_BJ3SETB RELAY ;熄灭指示灯LCALL BEEP_BL ;蜂鸣器响RET;-----------------------------------------TEMP_BJ3: MOV A,#0CEHLCALL WCOMMOV R1,#0MOV R0,#2BBJJ3: MOV A,R1MOVC A,@A+DPTRLCALL WDATAINC R1DJNZ R0,BBJJ3RETBJ3: DB ">H"BJ4: DB "<L"BJ5: DB " !";;**************************** 显示温度标记子程序***************************TEMP_BJ: MOV A,#0CBHLCALL WCOMMOV DPTR,#BJ1 ;指针指到显示消息MOV R1,#0MOV R0,#2BBJJ1: MOV A,R1MOVC A,@A+DPTRLCALL WDATAINC R1DJNZ R0,BBJJ1RETBJ1: DB 00H,"C";******************************** 显示正确信息子程序***************************MENU_OK: MOV DPTR,#M_OK1 ;指针指到显示消息MOV A,#1 ;显示在第一行LCALL LCD_PRINTMOV DPTR,#M_OK2 ;指针指到显示消息MOV A,#2 ;显示在第一行LCALL LCD_PRINTRETM_OK1: DB " DS18B20 OK ",0M_OK2: DB " TEMP: ",0;******************************** 显示出错信息子程序***************************MENU_ERROR:MOV DPTR,#M_ERROR1 ;指针指到显示消息MOV A,#1 ;显示在第一行LCALL LCD_PRINTMOV DPTR,#M_ERROR2 ;指针指到显示消息1MOV A,#2 ;显示在第一行LCALL LCD_PRINTRETM_ERROR1: DB " DS18B20 ERROR ",0M_ERROR2: DB " TEMP: ---- ",0;****************************DS18B20复位子程序*****************************RST: SETB DQNOPCLR DQMOV R0,#6BH ;主机发出延时复位低脉冲MOV R1,#04HTSR1: DJNZ R0,$MOV R0,#6BHDJNZ R1,TSR1SETB DQ ;拉高数据线NOPNOPNOPMOV R0,#32HTSR2: JNB DQ,TSR3 ;等待DS18B20回应DJNZ R0,TSR2JMP TSR4 ; 延时TSR3: SETB FLAG1 ; 置1标志位,表示DS1820存在JMP TSR5TSR4: CLR FLAG1 ; 清0标志位,表示DS1820不存在 JMP TSR7TSR5: MOV R0,#06BHTSR6: DJNZ R0,$ ; 时序要求延时一段时间TSR7: SETB DQRET;************************ DS18B20暂存器操作子程序***************************RE_18B20:JB FLAG1,RE_18B20ARETRE_18B20A:LCALL RSTMOV A,#0CCH ;跳过ROM匹配LCALL WRITEWR_SCRAPD:MOV A,#4EH ;写暂器LCALL WRITEMOV A,TEMP_TH ;TH(报警上限)LCALL WRITEMOV A,TEMP_TL ;TL(报警下限)LCALL WRITEMOV A,#7FH ;12位精度LCALL WRITERET;************************ 复制暂存器子程序*******************************WRITE_E2:LCALL RSTMOV A,#0CCH ;跳过ROM匹配LCALL WRITEMOV A,#48H ;把暂存器里的温度报警值拷贝到EEROMLCALL WRITERET;*********************** 重读EEROM子程序********************************READ_E2:LCALL RSTMOV A,#0CCH ;跳过ROM匹配LCALL WRITEMOV A,#0B8H ;把EEROM里的温度报警值拷贝回暂存器LCALL WRITERET;************************ 将自定义字符写入LCD的CGRAM中*********************STORE_DATA:MOV A,#40HLCALL WCOMMOV R2,#08HMOV DPTR,#D_DATAMOV R3,#00HS_DATA: MOV A,R3MOVC A,@A+DPTRLCALL WDATA ;写入数据INC R3DJNZ R2,S_DATARETD_DATA: DB 0CH,12H,12H,0CH,00H,00H,00H,00H;*********************** DS18B20数据写入操作子程序************************WRITE: MOV R2,#8 ;一共8位数据CLR CWR1: CLR DQ ;开始写入DS18B20总线要处于复位(低)状态MOV R3,#07DJNZ R3,$ ;总线复位保持16微妙以上RRC A ;把一个字节DATA 分成8个BIT 环移给CMOV DQ,C ;写入一位MOV R3,#3CHDJNZ R3,$ ;等待100微妙SETB DQ ;重新释放总线NOPDJNZ R2,WR1 ;写入下一位SETB DQRET;********************** DS18B20数据读取操作子程序**************************READ: MOV R4,#4 ;将温度低位、高位、TH、TL从DS18B20中读出MOV R1,#TEMPL ;存入25H、26H、27H、28H单元RE00: MOV R2,#8RE01: CLR CYSETB DQNOPNOPCLR DQ ;读前总线保持为低NOPNOPNOPSETB DQ ;开始读总线释放MOV R3,#09 ;延时18微妙DJNZ R3,$MOV C,DQ ;从DS18B20总线读得一位MOV R3,#3CHDJNZ R3,$ ;等待100微妙RRC A ;把读得的位值环移给ADJNZ R2,RE01 ;读下一位MOV @R1,AINC R1DJNZ R4,RE00RET;************************ 温度值BCD 码处理子程序*************************CONVTEMP: MOV A,TEMPH ;判温度是否零下ANL A,#08HJZ TEMPC1 ;温度零上转CLR CMOV A,TEMPL ;二进制数求补(双字节)CPL A ;取反加1ADD A,#01HMOV TEMPL,AMOV A,TEMPHCPL AADDC A,#00HMOV TEMPH,AMOV TEMPHC,#0BH ;负温度标志MOV TEMPFC,#0BHSJMP TEMPC11TEMPC1: MOV TEMPHC,#0AH ;正温度标志MOV TEMPFC,#0AHTEMPC11: 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,#064HDIV ABMOV R4,AMOV A,#0AHXCH A,BDIV ABSWAP AORL A,BRETTEMPDOTTAB: DB 00H,00H,01H,01H,02H,03H,03H,04H ; 小数部分码表DB 05H,05H,06H,06H,07H,08H,08H,09H;********************** 查询温度报警值子程序***************************LOOK_ALARM: MOV DPTR,#M_ALAX2 ;指针指到显示信息区MOV A,#2 ;显示在第二行LCALL LCD_PRINTMOV A,#0C6HLCALL TEMP_BJ1MOV A,TEMP_TH ;加载TH数据MOV LCD_X,#3 ;设置显示位置LCALL SHOW_DIG2H ;显示数据MOV A,#0CEHLCALL TEMP_BJ1MOV A,TEMP_TL ;加载TL数据MOV LCD_X,#12 ;设置显示位置LCALL SHOW_DIG2L ;显示数据RETM_ALAX1: DB " LOOK ALERT CODE",0M_ALAX2: DB "TH: TL: ",0TEMP_BJ1: LCALL WCOMMOV DPTR,#BJ2 ;指针指到显示信息区 MOV R1,#0MOV R0,#2BBJJ2: MOV A,R1MOVC A,@A+DPTRLCALL WDATADJNZ R0,BBJJ2RETBJ2: DB 00H,"C";************************** LCD显示子程序**********************************SHOW_DIG2H: MOV B,#100DIV ABADD A,#30HPUSH BMOV B,LCD_XLCALL LCDP2POP BMOV A,#0AHXCH A,BDIV ABADD A,#30HINC LCD_XPUSH BMOV B,LCD_XLCALL LCDP2INC LCD_XMOV A,BMOV B,LCD_XADD A,#30HLCALL LCDP2RETSHOW_DIG2L: MOV B,#100DIV ABMOV A,#0AHXCH A,BDIV ABADD A,#30HPUSH BMOV B,LCD_XLCALL LCDP2POP BINC LCD_XMOV A,BMOV B,LCD_XADD A,#30HLCALL 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 ;百位DISPBCD2: RET;*************************** LCD 显示数据处理子程序*************************CONV: MOV A,73H ;加载百位数据MOV LCD_X,#6 ;设置位置CJNE A,#1,CONV1JMP CONV2CONV1: CJNE A,#0BH,CONV11MOV A,#"-" ;"-"号显示JMP CONV111CONV11: MOV A,#" " ;"+"号不显示CONV111: MOV B,LCD_XLCALL LCDP2JMP CONV3CONV2: LCALL SHOW_DIG2 ;显示数据CONV3: INC LCD_XMOV A,72H ;十位LCALL SHOW_DIG2INC LCD_XMOV A,71H ;个位LCALL SHOW_DIG2INC LCD_XMOV A,#'.'MOV B,LCD_XLCALL LCDP2MOV A,70H ;加载小数点位INC LCD_X ;设置显示位置LCALL SHOW_DIG2 ;显示数据RET;*************************** 第二行显示数字子程序*************************SHOW_DIG2:ADD A,#30HMOV B,LCD_XLCALL LCDP2RET;*************************** 第二行显示数字子程序*************************LCDP2: PUSH ACCMOV A,B ;设置显示地址ADD A,#0C0H ;设置LCD的第二行地址LCALL WCOM ;写入命令POP ACC ;由堆栈取出ALCALL WDATA ;写入数据RET;*************************** 对LCD 做初始化设置及测试*************************SET_LCD: CLR LCD_ENLCALL INIT_LCD ;初始化 LCDLCALL STORE_DATA ;将自定义字符存入LCD的CGRAM RET;****************************** LCD初始化***********************************INIT_LCD: MOV A,#38H ;2行显示,字形5*7点阵LCALL WCOMLCALL DELAY1MOV A,#38HLCALL WCOMLCALL DELAY1MOV A,#38HLCALL WCOMLCALL DELAY1MOV A,#0CH ;开显示,显示光标,光标不闪烁 LCALL WCOMLCALL DELAY1MOV A,#01H ;清除 LCD 显示屏LCALL WCOMLCALL DELAY1RET;***************************** 清除LCD的第一行字符**************************CLR_LINE1:MOV A,#80H ;设置 LCD 的第一行地址LCALL WCOMMOV R0,#24 ;设置计数值C1: MOV A,#' ' ;载入空格符至LCDLCALL WDATA ;输出字符至LCDDJNZ R0,C1 ;计数结束RET;************************* LCD的第一行或第二行显示字符**********************LCD_PRINT:CJNE A,#1,LINE2 ;判断是否为第一行LINE1: MOV A,#80H ;设置 LCD 的第一行地址LCALL WCOM ;写入命令LCALL CLR_LINE ;清除该行字符数据MOV A,#80H ;设置 LCD 的第一行地址LCALL WCOM ;写入命令JMP FILLLINE2: MOV A,#0C0H ;设置 LCD 的第二行地址LCALL WCOM ;写入命令LCALL CLR_LINE ;清除该行字符数据MOV A,#0C0H ;设置 LCD 的第二行地址LCALL WCOMFILL: CLR A ;填入字符MOVC A,@A+DPTR ;由消息区取出字符CJNE A,#0,LC1 ;判断是否为结束码RETLC1: LCALL WDATA ;写入数据INC DPTR ;指针加1JMP FILL ;继续填入字符RET;*************************** 清除1行LCD 的字符****************************CLR_LINE: MOV R0,#24CL1: MOV A,#' 'LCALL WDATADJNZ R0,CL1RETDE: MOV R7,#250DJNZ R7,$RET;**************************** LCD 间接控制方式命令写入*************************WCOM: MOV P0,A ;写入命令CLR LCD_RS ;RS=L,RW=L,D0-D7=指令码,E=高脉冲 CLR LCD_RWSETB LCD_ENLCALL DELAY1CLR LCD_ENRET;**************************** LCD 间接控制方式数据写入*************************WDATA: MOV P0,A ;写入数据SETB LCD_RSCLR LCD_RWSETB LCD_ENLCALL DELCALL DERET;************************** 在LCD的第一行显示字符**************************LCDP1: PUSH ACCMOV A,B ;设置显示地址ADD A,#80H ;设置LCD的第一行地址LCALL WCOM ;写入命令POP ACC ;由堆栈取出ALCALL WDATA ;写入数据RET;****************************** 声光报警子程序*******************************BEEP_BL: MOV R6,#100BL2: LCALL DEX1CPL BEEPCPL RELAYDJNZ R6,BL2MOV R5,#10RETDEX1: MOV R7,#180DE2: NOPDJNZ R7,DE2RET;****************************** 延时子程序*******************************DELAY: MOV R6,#50DL1: MOV R7,#100DJNZ R7,$DJNZ R6,DL1DJNZ R5,DELAYRETDELAY1: MOV R6,#25 ;延时5毫秒DL2: MOV R7,#100DJNZ R7,$DJNZ R6,DL2RETEND。

51单片机驱动DS18B20温度传感器程序及心得

51单片机驱动DS18B20温度传感器程序及心得

51单片机驱动DS18B20温度传感器程序及心得关于DS18B20温度传感器,在没有硬件设备的辅助下,写内部程序有些困难,因为看不到实际信号波形。

对于单片机,我。

渐渐的有些心灰意冷。

虽然掌握了1_WIRE总线,却少了很多喜悦,下雨了。

它是我的爱好,我付出了很多,可是我看不到实际的前景。

以我个人之力,要步入尖端芯片领域,很困难,在这里,采棉花是个普遍性的大问题,大型机械设备缺陷很多,如果以微控制芯片提高精度,我想效益会相当可观,可是技术瓶颈难以逾越。

硬件研发,失败了,所有投入赴之东流,成功了,回报丰厚。

现在,各行各业都处于饱和,没有成熟先进的技术,很难有立足之地,,,,,我开始重新审视我的选择。

艰难。

/*建立时间: 2013年5月2日;前言: 我用软件仿真,测算延时时间,效果不错,但是根据教程,复位时,先释放总线(wd高电平),然后主机拉低wd,持续时间为400--960微妙.后主机拉高wd,持续15-60微妙,后从机,会拉低电平持续时间是60--240微妙(此时表示复位成功),如果从机没有将总线拉低,则复位失败.然后,主机拉高电平60--240微妙.复位结束;可,实验证明,在,从机,拉低总线电平后,持续一定时间,从机还会将总线拉高!这是教程中的一个重大错误!temperature sensor reset module finishing time: 23:08:00(温度传感器复位模块完成时间 )temperature sensor 操作过程:1. reset DS18B20;2. 发出Skip ROM 命令(CCH); (跳跃ROM命令)3. 发出Convert T命令(44H); (温度转换命令)4. reset DS18B20;5. 发出Skip ROM命令(CCH);(跳跃ROM命令)6. 发出读取命令(BEH);7. 读出两个字节的温度;8. 温度格式转换;2013年5月8日22:56:44DS18B20 Temperature sensor read data module accomplish;(温度传感器读数据模块完成)现在还有温度显示模块没有完成,硬件是1602液晶屏......2013年5月9日19:32:31今天,温度传感器的程序主体结构全部完成!!!!! 不容易啊,值得庆祝一下!!!!!!一共写了7天程序!{陆陆续续};喝个品酸乳果汁.......*/#include ;typedef unsigned char uint8 ;typedef unsigned int uint16;sbit wd = P3^2; //定义数据单总线;sbit e =P1^5; // 定义1602液晶显示器数据使能端口; sbit rs=P1^0; // 定义数据/指令选择端口;sbit rw=P1^1; // 定义读/写选择端口;sbit BF=P0^7; // 定义繁忙位;bit w=0; //定义一个全局一位变量;//===========1602液晶显示器模块;=============== busy() //液晶屏繁忙检测函数;{ e=0;rs=0;rw=0;P0=0xff;do{ e=0;//使能位清零;rs=0;//指令;rw=1;//读;e=1;//数据传输启动;}while(BF); //如果BF==0;则液晶处于空闲状态; e=0;}play_data(uint8 wr) //液晶写入数据;{busy();//繁忙检测;P0=wr;//装载数据;rs=1;//数据;rw=0;//写入;e=1;//传输开始;e=0;//传输结束;}play_cmd(uint8 cmd) //液晶写入指令; {busy(); //繁忙检测;P0=cmd; //装载数据;rs=0;//指令;rw=0;//写入;e=1;//传输开始;e=0;//传输结束;}reset_1602()//1602液晶显示器初始化函数;play_cmd(0x38);play_cmd(0x0c);play_cmd(0x06);play_cmd(0x01);}//=========温度传感器延时模块============================// sbit led= P1^0;delay(uint8 num )//如果unm等于1;延时16.28微妙; {while(num--); //如果num大于一,则16.28+(num-1)*6.51.}delay2()//此函数延时3.26微秒;{uint8 j=0;j=9;}delay3()uint16 s=60000;while(s--);}reset_1820() //========复位温度传感器; ======== {while(wd){wd=1;delay(140);//拉高总线,延时大概921微妙左右;(延时值自定); wd=0;//总线由单片机拉低,下为延时函数,大概800微秒左右;delay(61); //1个此函数会延时400微妙左右;delay(61); //两个是800微妙左右;wd=1;//主机拉高总线,68微秒左右;delay(9);//延时68微妙左右if(wd==0)//如果wd是0就终止复位;(代表复位成功);{while(wd==0);//总线一旦为低,那么就等待从机再将总线拉高. break;//终止while循环;(reset function end)}else{wd=1;delay(20);//延时140微妙;}}delay(30); //此时总线为高电平并延时205微妙,复位成功!;// if(wd)led=0;//此语句为检验是否复位成功;P1^0外接9012三极管接led小灯;}write_byte(uint8 dat){uint8 i=0;for(i=0;i;>;=1;delay(6); //A点到此处用时65.11微秒;wd=1;//总线释放;delay2(); //延时3.26微秒;}}//========此函数执行完成之后总线为高电平; uint8 read_byte() //=====读8位数据;==================={uint8 j=0, dat =0;for(j=0;j;>;=1;wd=0; // A点 mcu拉低电平3.26微秒;delay2();// 延时3.26微秒;wd=1;if(wd){dat|=0x80;}//读完数据后A点到此处是11.93微秒,保持在15微秒之内;delay(9);// A点到此处80.29微秒; 理想时间范围是60--120微秒;wd=1; //释放总线;delay2(); //延时3.26微秒;}return dat;}start_sensor()//启动传感器;{reset_1820();write_byte(0xcc); //跳跃命令;write_byte(0x44); //转换temperature(温度)命令; }uint8 read_temp()//从温度传感器度温度数据过程;{uint8 ak[2];uint16 dat=0 , j=0;reset_1820();//复位温度传感器write_byte(0xcc); //跳跃rom命令;write_byte(0xbe) ; // 发出读数据命令;ak[0]=read_byte(); //读取第一个字节数据;ak[1]=read_byte(); //读取第二个字节数据;dat=ak[1];//要把两个八位数据载入1个16位变量里;dat;>;11)==0x1f) //此语句是负温度进入.0x1f是二进制5个全1;{dat=(~dat)+1;//负温度要取反加一操作;dat/=16;//传感器给的温度系数要除以16后,得到的数才是常规温度系数;w=0;//此语句是在主函数中用来判断是正温度还是负温度;return dat; //向主函数返回数据,并终止函数; }j=dat;if((j>;>;11)==0)//如果是零则是正温度;{dat/=16;//数据直接除以16,就得到了常规温度系数;w=1;//1代表正;return dat; //向主函数返回数据,并终止函数;}return 130; //向主函数返回数据,并终止函数;}delay_ms() //延时1秒;{uint8 i=250;uint16 j=608;while(j--){ while(i--);i=250;}}error() //测温出错;{uint8 i=5, j=0 ,ak[]=&quot;Error!&quot;; while(i--)play_cmd(0x82);while(ak[j]!='\0'){play_data(ak[j++]);} j=0;delay3();play_cmd(0x01);delay3();}}main(){uint8dat=0 ,j=3,len=0 ,num[]=&quot;start.....&quot;;reset_1602();while(j--)//这是启动电源时,液晶显示:start....(并闪烁3次){play_cmd(0x82);while(num[len]!='\0'){play_data(num[len++]);}len=0;delay3();play_cmd(0x01);delay3();}while(1){start_sensor();//启动温度传感器;delay_ms();//等待1秒;dat = read_temp(); //读取温度数据并赋给dat变量;if(dat==130)//如果返回来的数据是130,表明采集温度出错;{error();}else if(w==1) //如果w是1,就代表正温度.输出;{play_cmd(0x83);play_data(dat/10+'0');play_data(dat%10+'0');}else//否则,就是负温度,输出时前面加一个负号;{play_cmd(0x82);play_data('-');play_data(dat/10+'0');play_data(dat%10+'0');}} //我的亲娘四舅奶奶啊!!!!!!终于完成了!!!!2013年5月9日19:32:10}。

DS18B20温度测试程序(51单片机数码管显示)+电路图

DS18B20温度测试程序(51单片机数码管显示)+电路图

DS18B20温度测试程序(51单片机数码管显示)+电路图•下面是电路图采用4位数码管显示程序一共有2个文件:/****************************************************************************** *****************************************ds18b20.h 头文件******************************************************************************* ****************************************/#ifndef _DS18B20_H_#define _DS18B20_H_#include <reg51.h>#define led P1#define ledw P2extern unsigned char f;extern void ds18b20_reset();extern void dela(unsigned char i);extern void ds18b20_write(unsigned char dat);extern unsigned char ds18b20_read();extern unsigned char ds18b20_temp();extern unsigned char ledtab[];#endif/****************************************************************************** **************************************ds18b20.c 文件******************************************************************************* *************************************/#include"ds18b20.h"#define uchar unsigned char#define uint unsigned int#define led P1#define ledw P2uchar ledtab[]={0xc0,0xf9,0xa4, 0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};sbit dq=P3^7 ;uchar delay,f;//uchar f;void dela(uchar i) //5us t=5+i*2{while(--i);}void ds18b20_reset(){while(1){dq=1;dq=0;delay=250; //540us延时,当delay=1时延时为2us ,T=2*xwhile(--delay);dq=1;delay=25;while(--delay);while(dq==0){delay=220;while(--delay);if(dq==1)break;}delay=150;while(--delay);break;}}void ds18b20_write(uchar dat) {uchar i=0;for(i=0;i<8;i++){dq=1;dq=0;delay=3;while(--delay);dq=dat&0x01;delay=35;while(--delay);dq=1;dat=dat>>1;}}uchar ds18b20_read(){uchar i=0,m=0;for(i=0;i<8;i++){//m>>=1dq=1;dq=0;delay=4;while(--delay);dq=1;delay=4;while(--delay);if(dq==1)m|=0x01<<i;//m=m|0x80;delay=25;while(--delay);dq=1;delay=1;while(--delay);}return m;}uchar ds18b20_temp(){uchar temp=0,temph=0,templ=0,k=0; ds18b20_reset();ds18b20_write(0xcc);ds18b20_write(0x44);ds18b20_reset();ds18b20_write(0xcc);ds18b20_write(0xbe);templ=ds18b20_read();temph=ds18b20_read();if((temph&0xf80)!=0){f=1;templ=~templ;temph=~temph;k=templ+1;templ=k;if(templ>0xff){temph++;}}elsef=0;templ=templ>>4;temph=temph<<4;temp=templ|temph;return temp;}/****************************************************************************** ************************************main.c 主文件******************************************************************************* ************************************/#include<reg51.h>#include"ds18b20.h"#define uchar unsigned charvoid main(){uchar a=0,b=0,c=0,temp=0;while(1){temp=ds18b20_temp();a=temp/100;b=temp0/10;c=temp;if(f==1){led=0xbf;ledw=1;dela(5000);ledw=0;dela(600);}led=ledtab[c]; ledw=8;dela(5000); ledw=0;dela(600) ;led=ledtab[b]; ledw=4;dela(5000); ledw=0;dela(600) ;led=ledtab[a]; ledw=2;dela(5000);ledw=0;dela(600) ; }}。

基于51单片机DS18B20温度传感器的C语言程序和电路

基于51单片机DS18B20温度传感器的C语言程序和电路

基于51单片机DS18B20温度传感器的C 语言程序和电路DS18B2C 在外形上和三极管很像,有三只脚。

电压范围为 3.0 V 至5.5 V 无需备用电源 测量温度 位 温度转换为 12 位数字格式最大值为 750 毫秒 用户可定义的非易失性温度报警设置 应用范围包 敏感系统。

F 面是DS18B20勺子程序,本人用过完全可行的: #include<reg51.h> #include<intrins.h>#define uchar unsigned char #define uint unsigned int sbit DQ=P2A 0;void reset(); void write_byte(uchar val); uchar read_byte(void); void read_temp(); void work_temp(); uchar data temp_data[2]={0x00,0x00};uchar datadisplay[5]={0x00,0x00,0x00,0x00,0x00}; // 对于温度显示值值 uchar code ditab[16]={0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,0x05,0x06,0x06,0x07,0x0 数部分查表 main() {while(1) {自己添加 ;void delay1(uint t) {for(;t>0;t--); }/////// 温度控制子函数 void reset(){uchar presence=1; while(presence){ while(presence){DQ=1;_nop_();_nop_(); DQ=0;delay1(50); DQ=1; delay1(6);presence=DQ;}delay1(45); presence=~DQ; }//DS18B20//DS18B20 写命令函数 //DS18B20 读 1 字节函数// 温度读取函数 // 温度数据处理函数DQ=1;}void write_byte(uchar val){uchar i;for(i=8;i>0;i--){DQ=1;_nop_();_nop_();DQ=0;_nop_();_nop_();_nop_();_nop_();_nop_();DQ=val&0x01;delay1(6);val=val/2;}DQ=1;_nop_();}uchar read_byte(void){uchar i;uchar value=0;for(i=8;i>0;i--){DQ=1;_nop_();_nop_();value>>=1;DQ=0; _nop_();_nop_();_nop_();_nop_(); DQ=1;_nop_();_nop_();_nop_();_nop_();if(DQ)value|=0x80;delay1(6);}DQ=1;return(value);void read_temp(){reset();write_byte(0xcc);write_byte(0xbe);temp_data[0]=read_byte();temp_data[1]=read_byte();reset();write_byte(0xcc);write_byte(0x44);}void work_temp(){if(temp_data[1]>127){ temp_data[1]=(256-temp_data[1]); temp_data[0]=(256-temp_data[0]); n=1; // 需要前面宏定义}display[4]=temp_data[0]&0x0f; // 低位的低4 位display[0]=ditab[display[4]]; // 小数点后的数值display[4]=((temp_data[0]&0xf0) >> 4)|((temp_data[1]&0x0f)<<4); // 小数display[3]=display[4] / 100; display[1]=display[4] % 100;display[2]=display[1] / 10;display[1]=display[1] % 10;}电路:Bi -ij-F16欢迎您的下载,资料仅供参考!致力为企业和个人提供合同协议,策划案计划书,学习课件等等打造全网一站式需求。

ds18b20 51单片机测温 自我总结+源程序

ds18b20 51单片机测温 自我总结+源程序

DS18B20总结复位时序/****************************************************************** - 功能描述:DS18B20复位- 隶属模块:DS18B20模块- 函数属性:内部- 参数说明:无- 返回说明:返回值为0说明复位成功,否则失败- 注:初始化是正确操作DS18B20是重要一步,必须复位成功******************************************************************/unsigned char DS18B20_Reset(){unsigned char x=0;DQ=1; //DQ拉高DQ=0; //单片机将DQ拉低delay(1800);//延时480us~960usDQ=1; //DQ拉高//以上是由单片机产生“复位脉冲”delay(100); //延时15us~60usx=DQ; //DS18B20产生“存在脉冲”//检测DQ 如果为低,说明复位成功,DS18B20存在//如果为高,说明复位失败,DS18B20损坏或不存在while(!DQ); //直到DQ为高return x; //返回复位结果}写时序/****************************************************************** - 功能描述:向DS18B20写入一个位(DS18B20的写时间片)- 隶属模块:DS18B20模块- 函数属性:内部- 参数说明:bdat:要写入的值,非0为1- 返回说明:无- 注:DS18B20的写时间片对时间的要求较为严格。

因此将此代码移植到其它CPU或场合时要注意延时函数******************************************************************/void DS18B20_WriteSlot(unsigned char bdat){DQ=1; //将数据线置为高电平delay(10); //两次写时间片间隔大于1usDQ=0; //开始一个写时间片delay(10); //写时间片的低电平保持1us以上DQ=bdat;delay(180); //写时间片开始15us后DS18B20对数据线进行采样//写时间片最短60usDQ=1;}/****************************************************************** - 功能描述:向DS18B20写入一个字节- 隶属模块:DS18B20模块- 函数属性:内部- 参数说明:dat:将要向DS18B20写入字节- 返回说明:无- 注:此函数调用写时间片来实现字节的写入******************************************************************/void DS18B20_WriteByte(unsigned char dat){unsigned char i=0;for(i=0;i<8;i++) //调用8次写时间片实现写入字节(8个位){DS18B20_WriteSlot(dat&(1<<i));}}读时序/****************************************************************** - 功能描述:从DS18B20读取一个位(DS18B20的读时间片)- 隶属模块:DS18B20模块- 函数属性:内部- 参数说明:无- 返回说明:读到的值,1或0- 注:DS18B20的读时间片对时间的要求较为严格。

DS18B20-51单片机汇编程序

DS18B20-51单片机汇编程序

DS18B20程序,51单片机汇编程序,仅需修改前几行即可。

晶振大小12M,转换完全正确。

DQ BIT P1.3 ;温度传感器接口TEMP_L EQU 29H ;用于保存读出温度的低字节TEMP_H EQU 28H ;用于保存读出温度的高字节TEMP_XIAO EQU 27H ;用于保存温度的小数部分TEMP_GE EQU 26H ;用于保存温度的个位部分TEMP_SHI EQU 25H ;用于保存温度的十位部分DQ_DELAY EQU 40H/*****************************************DS18B20温度转换程序,包括转换成小数、个位、十位*****************************************/// lOOP:// ACALL DS_GET_TEMP ;读取DS18B20温度// ACALL DOFOR_TEMP ;转换为十进制的十位、各位和小树部分// AJMP lOOPDS_RST: ;DS18B20复位函数SETB DQNOPCLR DQMOV DQ_DELAY,#66 ;延时约660usACALL DELAYSETB DQMOV DQ_DELAY,#6 ;延时约60usACALL DELAYMOV C,DQJC DS_RSTMOV DQ_DELAY , #24 ;延时约240usACALL DELAYSETB DQRETDS_WR_BYTE: ;写指令函数SETB DQMOV R4,#8CLR CDS_WR_LOOP:CLR DQMOV DQ_DELAY , #1 ;延时10us,短一些较好ACALL DELAYRRC AMOV DQ , CMOV DQ_DELAY , #5 ;延时50us,因为采样有效期为15-45usACALL DELAYSETB DQNOPDJNZ R4,DS_WR_LOOPRETDS_RD_BYTE: ;读指令函数MOV R4,#8DS_RD_LOOP:CLR CSETB DQNOPNOPCLR DQNOPNOPNOPSETB DQMOV DQ_DELAY,#1 ;延时约10usACALL DELAYMOV C,DQMOV DQ_DELAY,#5 ;延时50usACALL DELAYRRC ADJNZ R4,DS_RD_LOOPMOV @R1,ARETDS_GET_TEMP: ;读取温度函数CLR EA ;由于DS18B20对时序要求较严格,所以采样期间关中断SETB DQACALL DS_RST ;执行指令之前,必须复位MOV A,#0CCH ;忽略64位ROM地址,直接发送存储器指令ACALL DS_WR_BYTEMOV A,#044H ;发送开始转换指令ACALL DS_WR_BYTESETB EA ;转换期间可以开中断MOV DQ_DELAY,#200 ;转换时间最长750ms,延时了800ms。

基于51单片机的DS18B20温度传感器驱动程序加详解

基于51单片机的DS18B20温度传感器驱动程序加详解

基于51单片机的DS18B20温度传感器驱动程序加详解//此部分为18B20的驱动程序//本程序验证通过,晶振为12MHz#include <reg52.H>#include <intrins.h>sbit D18B20=P3^7; //DQ接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); //配置上下限即处理位数(9/10/11) void ReadID (void); //读取器件ID,即ROM中的数据void TemperatuerResult(void); //最终数据输出//bit flag;unsigned int idata Temperature,D[10]; //定义温度数组unsigned char idata temp_buff[9]; //定义RAM数据暂存数组//存储读取的字节,read scratchpad为9字节,read rom ID为8字节unsigned char idata id_buff[8]; //定义ROM数据暂存数组unsigned char idata *p,TIM; //指针变量unsigned char idata crc_data; //CRC计算变量定义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, 12 8, 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, 196, 154, 101, 59, 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, 231, 185, 140, 210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113, 147, 2 05,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, 2 38,50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 1 45, 207, 45, 115,202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139,87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 2 44, 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, 2 15, 137, 107, 53};//CRC数据表//Function:延时处理void TempDelay (unsigned char idata us){while(us--);}//Function:18B20初始化void Init18b20 (void){D18B20=1; //侦测到下跳沿,初始化_nop_();D18B20=0;TempDelay(160); //delay480 us (480)_nop_();D18B20=1; //释放总线TempDelay(30); //delay 96 us (60-112)_nop_();_nop_();_nop_(); //18B20侦测到此上升沿,会自动应答//发送presence信号//if(D18B20==0)// flag = 1; //detect 1820 success!//else// flag = 0; //detect 1820 fail!TempDelay(30); //delay 96 us(60-240)_nop_(); //发送应答脉冲_nop_();D18B20 = 1; //释放总线}//Function:向18B20写入一个字节void WriteByte (unsigned char idata wr) //单字节写入{unsigned char idata i;for (i=0;i<8;i++){D18B20 = 1;_nop_();D18B20 = 0; //侦测到下跳沿,初始化_nop_();D18B20=wr&0x01; //写数据在(60-120)us内TempDelay(30); //delay 96(60-120)us_nop_();_nop_(); //至少大于1us恢复时间D18B20=1; //释放总线wr >>= 1; //一个字节8位,总共写8次}}//Function:读18B20的一个字节unsigned char ReadByte (void) //读取单字节{unsigned char idata i,u=0;for(i=0;i<8;i++){D18B20 = 1;_nop_();D18B20 = 0; //负跳沿,初始化u >>= 1;D18B20 = 1; //释放总线if(D18B20==1)u |= 0x80;TempDelay (3); //15us内采样_nop_();}return(u);}//Function:读18B20void read_bytes (unsigned char idata j){unsigned char idata i;for(i=0;i<j;i++){*p = ReadByte();p++;}}//Function:CRC校验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);//返回i=8时的crc_data}//若为0,校验正确,即此时的temp_buff[8]=0x00; //Function:读取温度void GemTemp (void){read_bytes (9);if (CRC(9)==0) //校验正确{ //暂存器第0字节低8位,第一字节为高8位。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit DQ = P2^2; //数据口define interface
sbit dula = P2^6; //数码管段选
sbit wela = P2^7; //数码管位选
uint temp; //温度值variable of temperature
//不带小数点
unsigned char code table[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d, 0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
//带小数点
unsigned char code table1[] =
{0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef};
/*************精确延时函数*****************/
void delay(unsigned char i)
{
while(--i);
}
/******************************************
此延时函数针对的是12Mhz的晶振
delay(0):延时518us 误差:518-2*256=6
delay(1):延时7us (原帖写"5us"是错的)
delay(10):延时25us 误差:25-20=5
delay(20):延时45us 误差:45-40=5
delay(100):延时205us 误差:205-200=5
delay(200):延时405us 误差:405-400=5
*******************************************/
/*****************DS18B20******************/
void Init_Ds18b20(void) //DS18B20初始化send reset and initialization command
{
DQ = 1; //DQ复位,不要也可行。

delay(1); //稍做延时
DQ = 0; //单片机拉低总线
delay(250); //精确延时,维持至少480us
DQ = 1; //释放总线,即拉高了总线
delay(100); //此处延时有足够,确保能让DS18B20发出存在脉冲。

}
uchar Read_One_Byte() //读取一个字节的数据read a byte date
//读数据时,数据以字节的最低有效位先从总线移出
{
uchar i = 0;
uchar dat = 0;
for(i=8;i>0;i--)
{
DQ = 0; //将总线拉低,要在1us之后释放总线
//单片机要在此下降沿后的15us内读数据才会有效。

_nop_(); //至少维持了1us,表示读时序开始
dat >>= 1; //让从总线上读到的位数据,依次从高位移动到低位。

DQ = 1; //释放总线,此后DS18B20会控制总线,把数据传输到总线上
delay(1); //延时7us,此处参照推荐的读时序图,尽量把控制器采样时间放到读时序后的15us内的最后部分
if(DQ) //控制器进行采样
{
dat |= 0x80; //若总线为1,即DQ为1,那就把dat的最高位置1;若为0,则不进行处理,保持为0
}
delay(10); //此延时不能少,确保读时序的长度60us。

}
return (dat);
}
void Write_One_Byte(uchar dat)
{
uchar i = 0;
for(i=8;i>0;i--)
{
DQ = 0; //拉低总线
_nop_(); //至少维持了1us,表示写时序(包括写0时序或写1时序)开始
DQ = dat&0x01; //从字节的最低位开始传输
//指令dat的最低位赋予给总线,必须在拉低总线后的15us内,
//因为15us后DS18B20会对总线采样。

delay(10); //必须让写时序持续至少60us
DQ = 1; //写完后,必须释放总线,
dat >>= 1;
delay(1);
}
}
uint Get_Tmp() //获取温度get the temperature
{
float tt;
uchar a,b;
Init_Ds18b20(); //初始化
Write_One_Byte(0xcc); //忽略ROM指令
Write_One_Byte(0x44); //温度转换指令
Init_Ds18b20(); //初始化
Write_One_Byte(0xcc); //忽略ROM指令
Write_One_Byte(0xbe); //读暂存器指令
a = Read_One_Byte(); //读取到的第一个字节为温度LSB
b = Read_One_Byte(); //读取到的第一个字节为温度MSB
temp = b; //先把高八位有效数据赋于temp
temp <<= 8; //把以上8位数据从temp低八位移到高八位temp = temp|a; //两字节合成一个整型变量
tt = temp*0.0625; //得到真实十进制温度值
//因为DS18B20可以精确到0.0625度
//所以读回数据的最低位代表的是0.0625度
temp = tt*10+0.5; //放大十倍
//这样做的目的将小数点后第一位也转换为可显示数字
//同时进行一个四舍五入操作。

return temp;
}
/****************数码码动态显示函数**************/
void Display(uint temp) //显示程序
{
uchar A1,A2,A3;
A1 = temp/100; //百位
A2 = temp%100/10; //十位
A3 = temp%10; //个位
dula = 0;
P0 = table[A1]; //显示百位
dula = 1; //打开段选,对应74573的锁存位,高电平不锁存
dula = 0;
wela = 0;
P0 = 0x7e;
wela = 1; //打开位选
wela = 0;
delay(0);
dula = 0;
P0 = table1[A2]; //显示十位,使用的是有小数点的数组(因为temp值扩大了10倍,虽然是十位,实际为个位)
dula = 1;
dula = 0;
wela = 0;
P0 = 0x7d;
wela = 1;
wela = 0;
delay(0);
P0 = table[A3]; //显示个位
dula = 1;
dula = 0;
P0 = 0x7b;
wela = 1;
wela = 0;
delay(0);
}
void main()
{
while(1)
{
Display(Get_Tmp());
}
}。

相关文档
最新文档