51单片机+ds1302+DS18b20温度时钟(电路图+C语言程序)
我的51单片机之 温度传感器18B20 的C语言和汇编编程
{
TCZ=TCZ%100;//只显示小于 100 的整数温度
}
TC[1]=TCZ/10;
TC[0]=TCZ%10;
}
Hale Waihona Puke }void main() {
LEDCODE=0xFF; LED1=0; while(1) {
ReadTemp(); Disp(); } }
四、汇编程序: ;********************************************************************
温度传感器 18B20 实验
一、功能: 插上 18B20,上电后,数码管显示相应的环境温度。
二、电路图:
三、C 程序: //******************************************************************** //读取 18B20 输出的温度数据(2 位)并在数码管上显示;made by luqichao //********************************************************************
unsigned char Reset(); unsigned char ReadByte(); void WriteByte(unsigned char Data); void ReadTemp(); //延时 void delay(unsigned char n) {
unsigned char i; for(i=0;i<n;i++) { } }
Data>>=1; CLK=0; NOP();NOP();NOP();NOP();NOP();NOP();//6us CLK=1; NOP();NOP();NOP();NOP();NOP();//4us Temp=CLK; if(Temp) {
#DS18B20多点测温(51_C程序)
DS18B20多点测温<读序列,匹配序列,51 C程序,1602显示)因为本人在前两天找DS18B20多点测温<51C程序),网上下载了很多,但是都不是很理想,后来,自己总结前人的知识,重新写了这个程序。
其中包括程序一:单个读序列号。
程序二,匹配并且读两个DS18B20,当然,读多个与读两个基本原理一样,只要加上其序列号等即可。
本程序所有显示都是用LCD160 2显示。
程序一:度序列号,并用1602显示,1602从左到右分别是低到高位。
#include<reg51.h>#define uchar unsigned char#define uint unsigned intsbit DQ=P3^7。
//ds18b20与单片机连接口sbit RS=P3^0。
sbit RW=P3^1。
sbit EN=P3^2。
unsigned char code str1[]={""}。
unsigned char code str2[]={" "}。
uchar fCode[8]。
uchar data disdata[5]。
uint tvalue。
//温度值uchar tflag。
//温度正负标志/*************************lcd1602程序**************************/void delay1ms(unsigned int ms>//延时1毫秒<不够精确的){unsigned int i,j。
for(i=0。
i<ms。
i++>for(j=0。
j<100。
j++>。
}void wr_com(unsigned char com>//写指令//{ delay1ms(1>。
RS=0。
RW=0。
EN=0。
P2=com。
delay1ms(1>。
EN=1。
delay1ms(1>。
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 秒。
玩转DS1302和DS18B20
玩转DS1302和DS18B20对于市面上的大多数51单片机开发板来说。
ds1302和ds18b20应该是比较常见的两种外围芯片。
ds130 2是具有SPI总线接口的时钟芯片。
ds18b20则是具有单总线接口的数字温度传感器。
下面让我们分别来认识并学会应用这两种芯片。
首先依旧是看DS1302的datasheet中的相关介绍。
上面是它的一些基本的应用介绍。
下面是它的引脚的描述。
下面是DS1302的时钟寄存器。
我们要读取的时间数据就是从下面这些数据寄存器中读取出来的。
当我们要想调整时间时,可以把时间数据写入到相应的寄存器中就可以了。
这是DS1302内部的31个RAM寄存器。
在某些应用场合我们可以应用到。
如我们想要做一个带定时功能的闹钟。
则可以把闹钟的时间写入到31个RAM寄存器中的任意几个。
当单片机掉电时,只要我们的DS 1302的备用电池还能工作,那么保存在其中的闹钟数据就不会丢失~~由于对于这些器件的操作基本上按照数据手册上面提供的时序图和相关命令字来进行操作就可以了。
因此在我们应用这些器件的时候一定要对照着手册上面的要求来进行操作。
如果觉得还不够放心的话。
可以到网上下载一些参考程序。
对着手册看别人的程序,看别人的思路是怎么样的。
DS1302和单片机的连接很简单。
只需一根复位线,一根时钟线,一根数据线即可。
同时它本身还需要接一个32.768KHz的晶振来提供时钟源。
对于晶振的两端可以分别接一个6PF左右的电容以提高晶振的精确度。
同时可以在第8脚接上一个3.6V的可充电的电池。
当系统正常工作时可以对电池进行涓流充电。
当系统掉电时,DS1302由这个电池提供的能量继续工作。
下面让我们来驱动它。
sbit io_DS1302_RST = P2^0 ;sbit io_DS1302_IO = P2^1 ;sbit io_DS1302_SCLK = P2^2 ;//-------------------------------------常数宏---------------------------------//#define DS1302_SECOND_WRITE 0x80 //写时钟芯片的寄存器位置#define DS1302_MINUTE_WRITE 0x82#define DS1302_HOUR_WRITE 0x84#define DS1302_WEEK_WRITE 0x8A#define DS1302_DAY_WRITE 0x86#define DS1302_MONTH_WRITE 0x88#define DS1302_YEAR_WRITE 0x8C#define DS1302_SECOND_READ 0x81 //读时钟芯片的寄存器位置#define DS1302_MINUTE_READ 0x83#define DS1302_HOUR_READ 0x85#define DS1302_WEEK_READ 0x8B#define DS1302_DAY_READ 0x87#define DS1302_MONTH_READ 0x89#define DS1302_YEAR_READ 0x8D//-----------------------------------操作宏----------------------------------//#define DS1302_SCLK_HIGH io_DS1302_SCLK = 1 ;#define DS1302_SCLK_LOW io_DS1302_SCLK = 0 ;#define DS1302_IO_HIGH io_DS1302_IO = 1 ;#define DS1302_IO_LOW io_DS1302_IO = 0 ;#define DS1302_IO_READ io_DS1302_IO#define DS1302_RST_HIGH io_DS1302_RST = 1 ;#define DS1302_RST_LOW io_DS1302_RST = 0 ;/******************************************************* 保存时间数据的结构体*******************************************************/struct{uint8 Second ;uint8 Minute ;uint8 Hour ;uint8 Day ;uint8 Week ;uint8 Month ;uint8 Year ;}CurrentTime ;/************************************************************** **************** * Function: static void v_DS1302Write_f( uint8 Content ) * * Description:向DS1302写一个字节的内容* * Parameter:uint8 Content : 要写的字节** **************************************************************** ***************/static void v_DS1302Write_f( uint8 Content ){uint8 i ;for( i = 8 ; i > 0 ; i-- ){if( Content & 0x01 ){DS1302_IO_HIGH}else{DS1302_IO_LOW}Content >>= 1 ;DS1302_SCLK_HIGHDS1302_SCLK_LOW}}/************************************************************** **************** * Function: static uint8 v_DS1302Read_f( void ) * * Description: 从DS1302当前设定的地址读取一个字节的内容* * Parameter: ** Return: 返回读出来的值(uint8) **************************************************************** ***************/ static uint8 v_DS1302Read_f( void ){uint8 i, ReadValue ;DS1302_IO_HIGHfor( i = 8 ; i > 0 ; i-- ){ReadValue >>= 1 ;if( DS1302_IO_READ ){ReadValue |= 0x80 ;}else{ReadValue &= 0x7f ;}DS1302_SCLK_HIGHDS1302_SCLK_LOW}return ReadValue ;}/************************************************************** ***************** Function: void v_DS1302WriteByte_f( uint8 Address, uint8 Content ) ** Description: 从DS1302指定的地址写入一个字节的内容** Parameter: Address: 要写入数据的地址** Content: 写入数据的具体值** Return: * ******************************************************************* ***********/void v_DS1302WriteByte_f( uint8 Address, uint8 Content ){DS1302_RST_LOWDS1302_SCLK_LOWDS1302_RST_HIGHv_DS1302Write_f( Address ) ;v_DS1302Write_f( Content ) ;DS1302_RST_LOWDS1302_SCLK_HIGH}/************************************************************** ***************** Function: uint8 v_DS1302ReadByte_f( uint8 Address ) ** Description:从DS1302指定的地址读出一个字节的内容** Parameter:Address: 要读出数据的地址** ** Return: 指定地址读出的值(uint8) **************************************************************** ***************/uint8 v_DS1302ReadByte_f( uint8 Address ){uint8 ReadValue ;DS1302_RST_LOWDS1302_SCLK_LOWDS1302_RST_HIGHv_DS1302Write_f( Address ) ;ReadValue = v_DS1302Read_f() ;DS1302_RST_LOWDS1302_SCLK_HIGHreturn ReadValue ;}/************************************************************** ***************** Function: void v_ClockInit_f( void ) ** Description:初始化写入DS1302时钟寄存器的值(主程序中只需调用一次即可) * * Parameter:** ** Return: **************************************************************** ***************/void v_ClockInit_f( void ){if( v_DS1302ReadByte_f( 0xc1) != 0xf0 ){v_DS1302WriteByte_f( 0x8e, 0x00 ) ; //允许写操作v_DS1302WriteByte_f( DS1302_YEAR_WRITE, 0x08 ) ; //年v_DS1302WriteByte_f( DS1302_WEEK_WRITE, 0x04 ) ; //星期v_DS1302WriteByte_f( DS1302_MONTH_WRITE, 0x12 ) ; //月v_DS1302WriteByte_f( DS1302_DAY_WRITE, 0x11 ) ; //日v_DS1302WriteByte_f( DS1302_HOUR_WRITE, 0x13 ) ; //小时v_DS1302WriteByte_f( DS1302_MINUTE_WRITE, 0x06 ) ; //分钟v_DS1302WriteByte_f( DS1302_SECOND_WRITE, 0x40 ) ; //秒v_DS1302WriteByte_f( 0x90, 0xa5 ) ; //充电v_DS1302WriteByte_f( 0xc0, 0xf0 ) ; //判断是否初始化一次标识写入v_DS1302WriteByte_f( 0x8e, 0x80 ) ; //禁止写操作}}/************************************************************** ***************** Function: void v_ClockUpdata_f( void ) ** Description:读取时间数据,并保存在结构体CurrentTime中** Parameter:** ** Return:**************************************************************** ***************/void v_ClockUpdata_f( void ){CurrentTime.Second =v_DS1302ReadByte_f( DS1302_SECOND_READ ) ;CurrentTime.Minute = v_DS1302ReadByte_f( DS1302_MINUTE_READ ) ;CurrentTime.Hour = v_DS1302ReadByte_f( DS1302_HOUR_READ ) ;CurrentTime.Day = v_DS1302ReadByte_f( DS1302_DAY_READ ) ;CurrentTime.Month = v_DS1302ReadByte_f( DS1302_MONTH_READ ) ;CurrentTime.Week = v_DS1302ReadByte_f( DS1302_WEEK_READ ) ;CurrentTime.Year = v_DS1302ReadByte_f( DS1302_YEAR_READ ) ;}有了上面的这些函数我们就可以对DS1302进行操作了。
51单片机实现基于DS1302_1602_18B20的多功能电子时钟_带测温功能
#include<reg51.h>#define uchar unsigned char#define uint unsigned int/*------------------寄存器地址定义------------*/#define WRITE_SECOND 0x80#define WRITE_MINUTE 0x82#define WRITE_HOUR 0x84#define WRITE_DAY 0x86#define WRITE_MONTH 0x88#define WRITE_YEAR 0x8C#define WRITE_PROTECT 0x8E#define WRITE_WEEK 0x8A#define WRITE_CURRENT 0x90#define READ_SECOND 0x81#define READ_MINUTE 0x83#define READ_HOUR 0x85#define READ_DAY 0x87#define READ_MONTH 0x89#define READ_WEEK 0x8B#define READ_YEAR 0x8Dsbit RST=P3^5; //DS1302片选sbit DIO=P3^4; //DS1302数据信号sbit SCLK=P3^6; //DS1302时钟信号sbit ACC7=ACC^7;sbit ACC0=ACC^0;unsigned char count;sbit beep=P1^4;void INITIAL_1302();unsigned char READ_1302(unsigned char addr);void WRITE_1302(unsigned char addr,unsigned char date); sbit LCD_E=P2^7; //液晶使能端sbit LCD_RS=P2^6; //液晶数据命令选择端sbit LCD_RW=P2^5; //液晶读写选择端sbit key0=P3^2; //功能键sbit key1=P3^3; //增大键sbit key2=P3^4; //减小键sbit DQ=P3^7; //18b20温度输入输出端char hour,minute,second,week,day,month,year,tem; unsigned char num,flag;unsigned char str1[]=" 20 - - ";unsigned char str2[]=" : : C";void delay(unsigned char z);void LCD_WRITE_COM(unsigned char com);void LCD_WRITE_DA TA(unsigned char date);void LCD_WRITE_SFM(unsigned char addr,unsigned char date);void LCD_WRITE_NYR(unsigned char addr,unsigned char date);void LCD_WRITE_WEEK(unsigned char week);void LCD_INITIAL();void LCD_WRITE_TEMP(uchar addr,uchar temp);void keyscan();void INITIAL_TEMER0();uchar TMPH ,TMPL;void w1602c(uchar com);void w1602d(uchar data01);void delay2(uint ms);void delay3(uint us);uchar resert(void);uchar read_byte();void write_byte(uchar val);uint get_temp();void display();void delay3(uint us); //18b20uchar resert(void); //18b20uchar read_byte(); //18b20void write_byte(uchar val); //18b20uint get_temp(); //18b20void main(){LCD_INITIAL(); //液晶初始化INITIAL_1302(); //DS1302初始化INITIAL_TEMER0(); //定时器初始化while(1){keyscan(); //按键扫描if(flag==0) //当标志位为0,允许读取DS1302数据,将数据送入液晶显示{second=READ_1302(0x81);LCD_WRITE_SFM(10,second);minute=READ_1302(0x83);LCD_WRITE_SFM(7,minute);hour=READ_1302(0x85);LCD_WRITE_SFM(4,hour);week=READ_1302(0x8b);LCD_WRITE_WEEK(week);day=READ_1302(0x87);LCD_WRITE_NYR(9,day);month=READ_1302(0x89);LCD_WRITE_NYR(6,month);year=READ_1302(0x8d);LCD_WRITE_NYR(3,year);tem=get_temp();LCD_WRITE_TEMP(13,tem);}}}/**********************1602BU份******************************************************/void delay(unsigned char z) //1602de延时函数{unsigned char x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}void LCD_WRITE_COM(unsigned char com){LCD_RS=0;LCD_RW=0;LCD_E=1;P0=com;delay(5);LCD_E=0;}void LCD_WRITE_DA TA(unsigned char date){LCD_RS=1;LCD_RW=0;LCD_E=1;P0=date;delay(5);LCD_E=0;}void LCD_WRITE_SFM(unsigned char addr,unsigned char date) {unsigned char shi,ge;shi=date/10;ge=date%10;LCD_WRITE_COM(0x80+0x40+addr);LCD_WRITE_DATA(0x30+shi);LCD_WRITE_DATA(0x30+ge);}void LCD_WRITE_NYR(unsigned char addr,unsigned char date) {char shi,ge;shi=date/10;ge=date%10;LCD_WRITE_COM(0x80+addr);LCD_WRITE_DATA(0x30+shi);LCD_WRITE_DATA(0x30+ge);}void LCD_WRITE_WEEK(unsigned char week){LCD_WRITE_COM(0x80+12);switch(week){case 1: LCD_WRITE_DA TA('M');delay(5);LCD_WRITE_DATA('O');delay(5);;LCD_WRITE_DATA('N');break;case 2: LCD_WRITE_DA TA('T');delay(5);LCD_WRITE_DATA('U');delay(5);LCD_WRITE_DATA('E');break;case 3: LCD_WRITE_DA TA('W');delay(5);LCD_WRITE_DATA('E');delay(5);LCD_WRITE_DATA('D');break;case 4: LCD_WRITE_DA TA('T');delay(5);LCD_WRITE_DATA('H');delay(5);LCD_WRITE_DATA('U');break;case 5: LCD_WRITE_DA TA('F');delay(5);LCD_WRITE_DATA('R');delay(5);LCD_WRITE_DATA('I');break;case 6: LCD_WRITE_DA TA('S');delay(5);LCD_WRITE_DATA('A');delay(5);LCD_WRITE_DATA('T');break;case 7: LCD_WRITE_DA TA('S');delay(5);LCD_WRITE_DATA('U');delay(5);LCD_WRITE_DATA('N');break;}}void LCD_WRITE_TEMP(uchar addr,uchar temp){char shi,ge;shi=temp/10;ge=temp%10;LCD_WRITE_COM(0x80+0x40+addr);LCD_WRITE_DATA(0x30+shi);LCD_WRITE_DATA(0x30+ge);}void LCD_INITIAL(){unsigned char i;LCD_WRITE_COM(0x38);LCD_WRITE_COM(0x0c);LCD_WRITE_COM(0x06); //经本人试验证明1602初始化不清屏也可实现LCD_WRITE_COM(0x80);for(i=0;i<16;i++){LCD_WRITE_DATA(str1[i]);delay(5);}LCD_WRITE_COM(0x80+0x40);//液晶第二行显示for(i=0;i<16;i++){LCD_WRITE_DATA(str2[i]);delay(5);}}/***************************1302部分***************************************************/void WRITE_1302(unsigned char addr,unsigned char date) {unsigned char i;RST=0;SCLK=0;RST=1;for(i=8;i>0;i--){SCLK=0;ACC=addr;DIO=ACC0;addr>>=1;SCLK=1;}for(i=8;i>0;i--){SCLK=0;ACC=date;DIO=ACC0;date>>=1;SCLK=1;}RST=0;}unsigned char READ_1302(unsigned char addr){unsigned char i,date1,date2;RST=0;SCLK=0;RST=1;for(i=8;i>0;i--){SCLK=0;ACC=addr;DIO=ACC0;addr>>=1;SCLK=1;}for(i=8;i>0;i--){ACC7=DIO;SCLK=1;ACC>>=1;SCLK=0;}RST=0;date1=ACC;date2=date1/16;date1=date1%16;date1=date1+date2*10;return(date1) ;}void INITIAL_1302(){WRITE_1302(WRITE_SECOND,READ_1302(READ_SECOND)&0x7f); //启动DS1302}/**************************键盘扫描部分***************************************************/void keyscan(){if(key0==0)//确认功能键按下{delay(20);if(key0==0)//去抖{while(!key0);//释放num++;switch(num){case 1: flag=1; //修改时间,禁止从DS1302读数据TR0=0; //定时器关LCD_WRITE_COM(0x0f); //光标开始闪烁LCD_WRITE_COM(0x80+3);//第一次按下,光标定位到年位置break;case 2: LCD_WRITE_COM(0x80+6);//第二次按下,光标定位到月位置break;case 3: LCD_WRITE_COM(0x80+9);//第三次按下,光标定位到日位置break;case 4: LCD_WRITE_COM(0x80+12);//第四次按下,光标定位到星期位置break;case 5: LCD_WRITE_COM(0x80+0x40+4);//第五次按下,光标定位到时位置break;case 6: LCD_WRITE_COM(0x80+0x40+7);//第六次按下,光标定位到分位置break;case 7: LCD_WRITE_COM(0x80+0x40+10);//第七次按下,光标定位到秒位置break;case 8: num=0;//第八次按下,记录清零LCD_WRITE_COM(0x0c);//不显示光标WRITE_1302(WRITE_PROTECT,0x00); //允许写操作WRITE_1302(0x80,(second/10*16)+second%10);//将调节后的秒写入DS1302WRITE_1302(0x82,(minute/10*16)+minute%10);//将调节后的分写入DS1302WRITE_1302(0x84,(hour/10*16)+hour%10);//将调节后的时写入DS1302WRITE_1302(0x8a,(week/10*16)+week%10);//将调节后的星期写入DS1302WRITE_1302(0x86,(day/10*16)+day%10);//将调节后的日写入DS1302WRITE_1302(0x88,(month/10*16)+month%10);//将调节后的月写入DS1302WRITE_1302(0x8c,(year/10*16)+year%10);//将调节后的年写入DS1302WRITE_1302(WRITE_PROTECT,0x80); //开写保护flag=0; //时间修改完毕,允许液晶从DS1302读数据TR0=1;break;}}}if(num!=0){if(key1==0)//确认增大键按下{delay(20);if(key1==0)//增大键确实按下{while(!key1);switch(num){case 1: year++;//调节年if(year==100)year=0;LCD_WRITE_NYR(3,year);//将调节后的年送入液晶显示LCD_WRITE_COM(0x80+3);//光标回到指定处break;case 2: month++;//调节月if(month==13)month=0;LCD_WRITE_NYR(6,month);//将调节后的月送入液晶显示LCD_WRITE_COM(0x80+6);//光标回到指定处break;case 3: day++;//调节日if(day==32)day=0;LCD_WRITE_NYR(9,day);//将调节后的日送入液晶显示LCD_WRITE_COM(0x80+9);//光标回到指定处break;case 4: week++;if(week==8)week=0;LCD_WRITE_WEEK(week);//将调节后的星期送入液晶显示LCD_WRITE_COM(0x80+12);//光标回到指定处break;case 5: hour++;if(hour==24)hour=0;LCD_WRITE_SFM(4,hour);//将调节后的小时送入液晶显示LCD_WRITE_COM(0x80+0x40+4);//光标回到指定处break;case 6: minute++;if(minute==60)minute=0;LCD_WRITE_SFM(7,minute);//将调节后的分送入液晶显示LCD_WRITE_COM(0x80+0x40+7);//光标回到指定处break;case 7: second++;if(second==60)second=0;LCD_WRITE_SFM(10,second);//将调节后的秒送入液晶显示LCD_WRITE_COM(0x80+0x40+10);//光标回到指定处break;default:break;}}}if(key2==0)//确认减小键按下{delay(20);if(key2==0)//减小键确实按下{while(!key2);switch(num){case 1: year--;//调节年if(year==-1)year=99;LCD_WRITE_NYR(3,year);LCD_WRITE_COM(0x80+3);break;case 2: month--;//调节月if(month==-1)month=12;LCD_WRITE_NYR(6,month);LCD_WRITE_COM(0x80+6);break;case 3: day--;//调节日if(day==-1)day=31;LCD_WRITE_NYR(9,day);LCD_WRITE_COM(0x80+9);break;case 4: week--;//调节星期if(week==0)week=7;LCD_WRITE_WEEK(week);LCD_WRITE_COM(0x80+12);break;case 5: hour--;//调节时if(hour==-1)hour=23;LCD_WRITE_SFM(4,hour);LCD_WRITE_COM(0x80+0x40+4);break;case 6: minute--;//调节分if(minute==-1)minute=59;LCD_WRITE_SFM(7,minute);LCD_WRITE_COM(0x80+0x40+7);break;case 7: second--;//调节秒if(second==-1)second=59;LCD_WRITE_SFM(10,second);LCD_WRITE_COM(0x80+0x40+10);break;default:break;}}}}}/*******************************蜂鸣器部分******************************************//*-----------定时器0初始化-------------------------*/void INITIAL_TEMER0(){TMOD=0x01;TH0=(65536-20000)/256;TL0=(65536-20000)%256; //晶振频率12MHZ 定时20ms作右TR0=1;EA=1;ET0=1;}/*-------------------------------------------*/void timer0()interrupt 1{TH0=(65536-20000)/256;TL0=(65536-20000)%256; //重装count++;if(count==50) //1秒到{count=0;beep=0; //蜂鸣器响delay(5);beep=1; //蜂鸣器灭}if(tem>=30){beep=0;}}/*****************************18b20部分*********************************************888*/void delay3(uint us){uint s;for(s=0;s<us;s++);}uchar resert(void){uchar ready;DQ=0;delay3(32) ;DQ=1;delay3(3);ready=DQ;delay3(25);return ready;}uchar read_byte(){uchar i,j;uchar value=0;for(i=0;i<8;i++){DQ=0;DQ=1;for(j=0;j<3;j++);if(DQ){value|=0x01<<i;}delay3(6) ;}return value;}void write_byte(uchar val) {uchar i,temp;for(i=0;i<8;i++){temp=val>>i;temp=temp&0x01;DQ=0;if(temp==1)DQ=1;delay3(5);DQ=1;}DQ=1;}uint get_temp(){float f_temp;uint temp;P2=0x00;resert();delay3(50);write_byte(0xcc);write_byte(0x44);resert();write_byte(0xcc);write_byte(0xbe);TMPL = read_byte();TMPH = read_byte();temp = TMPH;temp <<= 8;TMPL=TMPL&0xf0;temp = temp | TMPL;f_temp=temp*0.0625;temp=f_temp;return temp;}。
51+DS1302+DS18B20+LCD1602,显示时间,温度,可调时
实时时钟芯片DS1302应用,DS18B20应用实例——可调时钟,LCD1602显示:(时间+温度)说明:需要按程序中定义的接口。
按自己接口,只要在程序中修改接口定义即可。
1、DS1302引脚排列:如下图引脚说明:1)Vcc1:后备电源,VCC2:主电源。
在主电源关闭的情况下,也能保持时钟的连续运行。
DS1302由Vcc1或Vcc2两者中的较大者供电。
当Vcc2大于Vcc1+0.2V时,Vcc2给DS1302供电。
当Vcc2小于Vcc1时,DS1302由Vcc1供电。
2)X1、X2:振荡源,外接32.768kHz晶振。
3)RST:复位/片选线,通过把RST输入驱动置高电平来启动所有的数据传送。
RST输入有两种功能:首先,RST接通控制逻辑,允许地址/命令序列送入移位寄存器;其次,RST提供终止单字节或多字节数据的传送手段。
当RST为高电平时,所有的数据传送被初始化,允许对DS1302进行操作。
如果在传送过程中RST 置为低电平,则会终止此次数据传送,I/O引脚变为高阻态。
上电运行时,在Vcc>2.0V之前,RST必须保持低电平。
只有在SCLK 为低电平时,才能将RST置为高电平。
4)I/O为串行数据输入输出端(双向)。
5)SCLK为时钟输入端。
2、 DS1302的控制字节DS1302 的控制字如下图所示。
控制字节的最高有效位(位7)必须是逻辑1,如果它为0,则不能把数据写入DS1302中,位6如果为0,则表示存取日历时钟数据,为1表示存取RAM数据;位5至位1指示操作单元的地址;最低有效位(位0)如为0表示要进行写操作,为1表示进行读操作,控制字节总是从最低位开始输出。
3、数据输入输出(I/O)在控制指令字输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,数据输入从低位即位0开始。
同样,在紧跟8位的控制指令字后的下一个SCLK脉冲的下降沿读出DS1302的数据,读出数据时从低位0位到高位7。
ds1302+ds18b20+闹钟按键可调万年历c语言程序
#include<reg51.h>#include<intrins.h>#define uint unsigned int#define uchar unsigned charuint nian,yue,ri,week,shi,fen,miao,shuju,naoshi,naofen;uchar ds1302_addr,ds1302_data,temp,temp1,bz=0,shanshuo=0;uchar r0,r1,nh,nl,yh,yl,rh,rl,sh,sl,fh,fl,mh,ml,wh,wl,nsh,nsl,nfh,nfl; uchar moshibz,jiabz,jianbz,kaishibz,naobz,speek;uchartab[11]={0Xc0,0Xf9,0Xa4,0Xb0,0X99,0X92,0X82,0Xf8,0X80,0X90,0xff}; sbit rst=P1^0;sbit clk=P1^1;sbit io=P1^2;sbit DQ=P1^3;sbit zz=P1^7;sbit moshi=P1^6;sbit jia=P1^5;sbit jian=P1^4;sbit kaishi=P3^1;sbit nao=P3^0;sbit led=P2^7;sbit ACC0=ACC^0;sbit ACC7=ACC^7;/*****************延时函数*********************/void d elay(uchar k) //延时程序,约0.1ms{uchar n,m;for(n=0;n<k;n++){for(m=0;m<120;m++);}}/*****************写地址子函数*********************/void w rit_addr(uchar ds1302_addr) //读ds1302 函数{ACC=ds1302_addr;rst=1;for(r1=8;r1>0;r1--){io=ACC0;clk=0;clk=1;ACC=ACC>>1;}}/*****************写数据子函数*********************/void w rit_data(uchar ds1302_data){ACC=ds1302_data;rst=1;for(r1=8;r1>0;r1--){io=ACC0;clk=0;clk=1;ACC=ACC>>1;}rst=0;}/*****************写入ds1302函数*********************/ void write(uchar add,ss) {clk=0;_nop_();rst=0;_nop_();rst=1;_nop_();writ_addr(add);_nop_();writ_data(ss);_nop_();clk=1;_nop_();rst=0;_nop_();}uchar read_data(void) {for(r1=8;r1>0;r1--){ACC7=io;clk=1;clk=0;ACC=ACC>>1;}return ACC;}/*****************读ds1302函数*********************/ void read(uchar addc) { uchar kk;clk=0;_nop_();_nop_();rst=1;_nop_();writ_addr(addc);_nop_();kk=read_data();_nop_();clk=1;_nop_();rst=0;_nop_();ds1302_data=(kk/16)*10+(kk%16); }/*****************//读ds1302 函数*********************/void r ed_dsl302(void){read(0x8d);nian=ds1302_data;read(0x8b);week=ds1302_data;read(0x89);yue=ds1302_data;read(0x87);ri=ds1302_data;read(0x85);shi=ds1302_data;read(0x83);fen=ds1302_data;read(0x81);miao=ds1302_data;}/*****************//写ds1302函数*********************//*void writl302(void){write(0x8e,0x00);write(0x8c,nian);write(0x8a,week);write(0x88,yue);write(0x86,ri);write(0x84,shi);write(0x82,fen);write(0x80,miao);*//*****************初始化函数*********************/void t0_init(void){IE=0X82;TMOD=0X01;TH0=0x3c;TL0=0XB0;TR0=1;r0=0;}/*****************定时器0函数*********************/void t imer() interrupt 1 {TH0=0x3c; //TL0=0XB0;r0++;if(r0==10){r0=0;shanshuo=~shanshuo;}}/*****************闹钟显示函数*********************/void n aozhong(void){P2=0xff;P2=tab[nsh];P0=0xfb;delay(2);P0=0xFF;P2=0xff;P2=tab[nsl];P0=0xF7;delay(2);P0=0xFF;P2=0xff;P2=tab[nfh];P0=0xfe;delay(2);P0=0xFF;P2=tab[nfl];P0=0xFd;delay(2);P0=0xFF;P2=0xff;P2=tab[wh];P0=0xbf;delay(2);P0=0xFF;P2=0xff;P2=tab[wl];P0=0x7f;delay(2);P0=0xFF;P2=0xff;P2=tab[mh];P0=0xef;delay(2);P0=0xFF;P2=0xff;P2=tab[ml];P0=0xdf;delay(2);P0=0xFF;}/*****************全部显示函数************************/ void d isplay(void){if(speek==1){naozhong();}else{P2=0xff;P2=tab[mh];P0=0xef;delay(2);P0=0xFF;P2=0xff;P2=tab[ml];P0=0xdf;delay(2);P2=0xff;P2=tab[fh]; P0=0xfb; delay(2);P0=0xFF;P2=0xff;P2=tab[fl]; P0=0xF7; delay(2);P0=0xFF;P2=0xff;P2=tab[sh]; P0=0xfe; delay(2);P0=0xFF;P2=0xff;P2=tab[sl]; P0=0xFd; delay(2);P0=0xFF;P2=0xff;P2=tab[rh]; P3=0xbf; delay(2);P3=0xFF;P2=0xff;P2=tab[rl]; P3=0x7f; delay(2);P3=0xFF;P2=0xff;P2=tab[yh]; P3=0xef; delay(2);P3=0xFF;P2=0xff;P2=tab[yl]; P3=0xdf; delay(2);P3=0xFF;P2=0xff;P2=tab[nh];delay(2);P3=0xFF;P2=0xff;P2=tab[nl];P3=0xF7;delay(2);P3=0xFF;P2=0xff;zz=0;P2=tab[week];delay(2);zz=1;P2=0xff;P2=tab[wh];P0=0xbf;delay(2);P0=0xFF;P2=0xff;P2=tab[wl];P0=0x7f;delay(2);P0=0xFF;}P2=0xff;P2=tab[wh];P0=0xbf;delay(2);P0=0xFF;P2=0xff;P2=tab[wl];P0=0x7f;delay(2);P0=0xFF;}/*****************闹钟切换函数*********************/ void n aokey(void){if(nao==0){if(naobz==0){naobz=1;speek=!speek;}}if(nao!=0){naobz=0;}}/*****************按键函数*********************/ void k ey(void){if(kaishi==0){if(kaishibz==0){kaishibz=1;bz=7;}}if(kaishi!=0){kaishibz=0;}if(moshi==0){if(moshibz==0){moshibz=1;if(bz==7){bz=0;}else{bz++;}}}if(moshi!=0){moshibz=0;}}/*****************按键加函数*********************/ void s hangtiao(void){if(jia==0){if(jiabz==0){jiabz=1;if(shuju==59){shuju=0;}else{shuju++;}}}if(jia!=0){jiabz=0;}}/*****************按键减函数*********************/void x iatiao(void){if(jian==0){if(jianbz==0){jianbz=1;if(shuju==0){shuju=20;}else{shuju--;}}}if(jian!=0){jianbz=0;}}/*****************分离函数*********************/void f enli(void){if(fen==59&miao==56){led=0;}else{led=1;}if(speek==1){if(bz==1){shuju=naoshi; //先用十进制家,加完后必须转化成十六进制写入shangtiao();xiatiao();naoshi=shuju;if(shanshuo==1){nsh=10;nsl=10;}else{nsh=naoshi/10;nsl=naoshi%10;}}else{nsh=naoshi/10;nsl=naoshi%10;if(bz==2){shuju=naofen;shangtiao();xiatiao();naofen=shuju;if(shanshuo==1){nfh=10;nfl=10;}else{nfh=naofen/10;nfl=naofen%10;}}else{bz=0;nfh=naofen/10;nfl=naofen%10;}}}else{if(bz==1){shuju=nian; //先用十进制家,加完后必须转化成十六进制写入shangtiao();xiatiao();nian=shuju;nian=(nian/10)*16+(nian%10);write(0x8c,nian);nian=(nian/16)*10+(nian%16);if(shanshuo==1){nh=10;nl=10;}else{nh=nian/10;nl=nian%10;}}else{nh=nian/10;nl=nian%10;if(bz==2){shuju=yue;shangtiao();xiatiao();yue=shuju;yue=(yue/10)*16+(yue%10);write(0x88,yue);yue=(yue/16)*10+(yue%16);if(shanshuo==1){yh=10;yl=10;}else{yh=yue/10;yl=yue%10;}}else{yh=yue/10;yl=yue%10;if(bz==3){shuju=ri;shangtiao();xiatiao();ri=shuju;ri=(ri/10)*16+(ri%10);write(0x86,ri);ri=(ri/16)*10+(ri%16);if(shanshuo==1){rh=10;rl=10;}else{rh=ri/10;rl=ri%10;}}else{rh=ri/10;rl=ri%10;if(bz==4){shuju=shi;shangtiao();xiatiao();shi=shuju;shi=(shi/10)*16+(shi%10);write(0x84,shi);shi=(shi/16)*10+(shi%16);if(shanshuo==1){sh=10;sl=10;}else{sh=shi/10;sl=shi%10;}}else{sh=shi/10;sl=shi%10;if(bz==5){shuju=fen;shangtiao();xiatiao();fen=shuju;fen=(fen/10)*16+(fen%10);write(0x82,fen);fen=(fen/16)*10+(fen%16);if(shanshuo==1){fh=10;fl=10;}else{fh=fen/10;fl=fen%10;}}else{fh=fen/10;fl=fen%10;if(bz==6){shuju=week;shangtiao();xiatiao();week=shuju;week=(week/10)*16+(week%10);write(0x82,week);week=(week/16)*10+(week%16);if(shanshuo==1){week=10;}else{;}}else{;}}}}}}}mh=miao/10;ml=miao%10;wh=temp/10;wl=temp%10;}/***********ds18b20延迟子函数(晶振12MHz)*******/void delay_18B20(unsigned int i){while(i--);}/**********ds18b20初始化函数**********************/void Init_DS18B20(void){unsigned char x=0;DQ = 1; //DQ复位delay_18B20(8); //稍做延时DQ = 0; //单片机将DQ拉低delay_18B20(80); //精确延时大于480usDQ = 1; //拉高总线delay_18B20(14);x = DQ;//稍做延时后如果x=0则初始化成功x=1则初始化失败delay_18B20(20);}/***********ds18b20读一个字节**************/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_18B20(4);}return(dat);}/*************ds18b20写一个字节****************/void WriteOneChar(unsigned char dat){unsigned char i=0;for (i=8; i>0; i--){DQ = 0;DQ = dat&0x01;delay_18B20(5);DQ = 1;dat>>=1;}}/**************读取ds18b20当前温度************/void wendu(void){uchar a=0;uchar b=0;uchar flag; //初始化是否成功标志位0,成功1,失败Init_DS18B20();WriteOneChar(0xCC); //跳过读序号列号的操作WriteOneChar(0x44);//启动温度转换delay_18B20(100); // this message is very importantInit_DS18B20();WriteOneChar(0xCC); //跳过读序号列号的操作WriteOneChar(0xBE);//读取温度寄存器等(共可读9个寄存器)前两个就是温度delay_18B20(100);a=ReadOneChar();//读取温度值低8位b=ReadOneChar();//读取温度值高8位if(flag)//初始化失败{a=0x00;b=0x00;}temp1=b<<4;temp1+=(a&0xf0)>>4;//小数点前的数据// temp2=a&0x0f;//小数点后的数据temp=temp1;//temp=((b*256+a)>>4);//当前采集温度值除16得实际温度值//temp1 = t/100%10;//温度值十位// temp2 = t/10%10; //温度值个位// temp3 = t%10; //温度值十分位}/*****************比较函数*********************/void b ijiao(void){if(shi==naofen&fen==naoshi){led=0;if(naofen==naofen+1){led=1;}}else{led=1;}}/**********************主函数**********************/void m ain(void){bz=0;shanshuo=1;nian=0x13;yue=0x8;ri=0x11;shi=0x20;fen=0x44;miao=0x10;week=0x07;// writl302(); //因为ds1302只须写入一次,所以将此处屏蔽。
51单片机课程设计(DS1302时钟、18B20温度计)
摘要:该设计实现了24小时制的时间显示及设定、年月日星期的显示及设定、闹钟的设定、温度的检测及显示等功能。
设计共分为四大部分,分别是控制部分、时钟部分、温度检测部分和人机交互部分。
以单片机(AT89C51)组成的最小系统为整个设计的控制核心,单片机通过对时钟芯片(DS1302)的控制完成时钟的功能,通过对温度传感器(18B20)的控制完成温度检测的功能,最后通过对数码管、蜂鸣器及按键的控制完成时间和温度的显示以及调整时间、设定闹钟等功能。
关键词:电子钟;温度计;单片机目录摘要: (1)第一章设计任务 (3)第二章电路设计 (3)2.1电路方案的比较 (3)2.2根据设计绘制框图及原理图 (5)第三章工作原理 (7)3.1 单片机的工作原理 (7)3.2 DS18B20的工作原理 (8)3.3DS1302的工作原理 (10)3.4数码管的工作原理 (12)第四章调试与验证 (12)4.1程序调试 (12)4.2仿真验证 (15)参考文献 (15)附录 (16)附录一使用说明 (16)附录二元件清单 (16)附录三 pcb版图 (17)附录四程序清单 (18)第一章设计任务1、基本要求(1)能够实现时间的正确显示,并且可以对表进行调整。
(2)能够实现年月日及星期的显示,并且可以对日期进行调整。
(3)能够实现对温度的及时检测,并且可以正确显示。
(4)用protel99se绘制设计的原理图,并生成PCB图。
(5)用protues实现对设计的仿真。
2、提高要求(1)能够实现闹铃的设定。
(2)为了使显示画面更美观,信息量更大,尝试使用液晶显示器(1602或12864)对时间和温度进行显示。
(3)将硬件实物做出来。
第二章电路设计2.1电路方案的比较1、时钟电路的设计方案一:时钟电路可由555定时器组成,通过555定时器构成1Hz脉冲发生电路(如图2-1),然后将脉冲机输入单片机,经单片机计算生成时钟。
脉冲信号从555的3号引脚输出,通过电阻和电容可以得到不同频率的脉冲。
ds18b20的C语言完整程序(c51)
ds18b20的C语言完整程序(c51)(可组网数字式温度传感器)发布日期:[2005-05-10]作者:(sparkstar)//DS1820 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 lowdelay(29); // leave it low for 480usDQ = 1; // allow line to return highdelay(3); // wait for presencepresence = DQ; // get presence signaldelay(25); // wait for end of timeslotreturn(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 timeslotDQ = 1; // then return highdelay(1); //for (i=0; i<3; i++);if(DQ)value|=0x80;delay(6); // wait for rest of timeslot}return(value);}//向 1-WIRE 总线上写一个字节void write_byte(char val){byte i;for (i=8; i>0; i--) // writes byte, one bit at a time {DQ = 0; // pull DQ low to start timeslotDQ = val&0x01;delay(5); // hold value for remainder of timeslotDQ = 1;val=val/2;}delay(5);}//读取温度char Read_Temperature(void){union{byte c[2];int x;}temp;ow_reset();write_byte(0xCC); // Skip ROMwrite_byte(0xBE); // Read Scratch Padtemp.c[1]=read_byte();temp.c[0]=read_byte();ow_reset();write_byte(0xCC); //Skip ROMwrite_byte(0x44); // Start Conversionreturn temp.x/2;}。
玩转DS1302和DS18B20
对于市面上的大多数51单片机开发板来说。
ds1302和ds18b20应该是比较常见的两种外围芯片。
ds130 2是具有SPI总线接口的时钟芯片。
ds18b20则是具有单总线接口的数字温度传感器。
下面让我们分别来认识并学会应用这两种芯片。
首先依旧是看DS1302的datasheet中的相关介绍。
上面是它的一些基本的应用介绍。
下面是它的引脚的描述。
下面是DS1302的时钟寄存器。
我们要读取的时间数据就是从下面这些数据寄存器中读取出来的。
当我们要想调整时间时,可以把时间数据写入到相应的寄存器中就可以了。
这是DS1302内部的31个RAM寄存器。
在某些应用场合我们可以应用到。
如我们想要做一个带定时功能的闹钟。
则可以把闹钟的时间写入到31个RAM寄存器中的任意几个。
当单片机掉电时,只要我们的DS 1302的备用电池还能工作,那么保存在其中的闹钟数据就不会丢失~~由于对于这些器件的操作基本上按照数据手册上面提供的时序图和相关命令字来进行操作就可以了。
因此在我们应用这些器件的时候一定要对照着手册上面的要求来进行操作。
如果觉得还不够放心的话。
可以到网上下载一些参考程序。
对着手册看别人的程序,看别人的思路是怎么样的。
DS1302和单片机的连接很简单。
只需一根复位线,一根时钟线,一根数据线即可。
同时它本身还需要接一个32.768KHz的晶振来提供时钟源。
对于晶振的两端可以分别接一个6PF左右的电容以提高晶振的精确度。
同时可以在第8脚接上一个3.6V的可充电的电池。
当系统正常工作时可以对电池进行涓流充电。
当系统掉电时,DS1302由这个电池提供的能量继续工作。
下面让我们来驱动它。
sbit io_DS1302_RST = P2^0 ;sbit io_DS1302_IO = P2^1 ;sbit io_DS1302_SCLK = P2^2 ;//-------------------------------------常数宏---------------------------------//#define DS1302_SECOND_WRITE 0x80 //写时钟芯片的寄存器位置#define DS1302_MINUTE_WRITE 0x82#define DS1302_HOUR_WRITE 0x84#define DS1302_WEEK_WRITE 0x8A#define DS1302_DAY_WRITE 0x86#define DS1302_MONTH_WRITE 0x88#define DS1302_YEAR_WRITE 0x8C#define DS1302_SECOND_READ 0x81 //读时钟芯片的寄存器位置#define DS1302_MINUTE_READ 0x83#define DS1302_HOUR_READ 0x85#define DS1302_WEEK_READ 0x8B#define DS1302_DAY_READ 0x87#define DS1302_MONTH_READ 0x89#define DS1302_YEAR_READ 0x8D//-----------------------------------操作宏----------------------------------//#define DS1302_SCLK_HIGH io_DS1302_SCLK = 1 ;#define DS1302_SCLK_LOW io_DS1302_SCLK = 0 ;#define DS1302_IO_HIGH io_DS1302_IO = 1 ;#define DS1302_IO_LOW io_DS1302_IO = 0 ;#define DS1302_IO_READ io_DS1302_IO#define DS1302_RST_HIGH io_DS1302_RST = 1 ;#define DS1302_RST_LOW io_DS1302_RST = 0 ;/******************************************************* 保存时间数据的结构体*******************************************************/struct{uint8 Second ;uint8 Minute ;uint8 Hour ;uint8 Day ;uint8 Week ;uint8 Month ;uint8 Year ;}CurrentTime ;/****************************************************************************** * Function: static void v_DS1302Write_f( uint8 Content ) * * Description:向DS1302写一个字节的内容** Parameter:uint8 Content : 要写的字节** *******************************************************************************/static void v_DS1302Write_f( uint8 Content ){uint8 i ;for( i = 8 ; i > 0 ; i-- ){if( Content & 0x01 ){DS1302_IO_HIGH}else{DS1302_IO_LOW}Content >>= 1 ;DS1302_SCLK_HIGHDS1302_SCLK_LOW}}/****************************************************************************** * Function: static uint8 v_DS1302Read_f( void ) ** Description: 从DS1302当前设定的地址读取一个字节的内容* * Parameter: ** Return: 返回读出来的值(uint8) *******************************************************************************/ static uint8 v_DS1302Read_f( void ){uint8 i, ReadValue ;DS1302_IO_HIGHfor( i = 8 ; i > 0 ; i-- ){ReadValue >>= 1 ;if( DS1302_IO_READ ){ReadValue |= 0x80 ;}else{ReadValue &= 0x7f ;}DS1302_SCLK_HIGHDS1302_SCLK_LOW}return ReadValue ;}/******************************************************************************* Function: void v_DS1302WriteByte_f( uint8 Address, uint8 Content ) ** Description: 从DS1302指定的地址写入一个字节的内容** Parameter: Address: 要写入数据的地址** Content: 写入数据的具体值** Return: * ******************************************************************************/void v_DS1302WriteByte_f( uint8 Address, uint8 Content ){DS1302_RST_LOWDS1302_SCLK_LOWDS1302_RST_HIGHv_DS1302Write_f( Address ) ;v_DS1302Write_f( Content ) ;DS1302_RST_LOWDS1302_SCLK_HIGH}/******************************************************************************* Function: uint8 v_DS1302ReadByte_f( uint8 Address ) ** Description:从DS1302指定的地址读出一个字节的内容** Parameter:Address: 要读出数据的地址** ** Return: 指定地址读出的值(uint8) *******************************************************************************/uint8 v_DS1302ReadByte_f( uint8 Address ){uint8 ReadValue ;DS1302_RST_LOWDS1302_SCLK_LOWDS1302_RST_HIGHv_DS1302Write_f( Address ) ;ReadValue = v_DS1302Read_f() ;DS1302_RST_LOWDS1302_SCLK_HIGHreturn ReadValue ;}/******************************************************************************* Function: void v_ClockInit_f( void ) ** Description:初始化写入DS1302时钟寄存器的值(主程序中只需调用一次即可) * * Parameter:** ** Return: *******************************************************************************/void v_ClockInit_f( void ){if( v_DS1302ReadByte_f( 0xc1) != 0xf0 ){v_DS1302WriteByte_f( 0x8e, 0x00 ) ; //允许写操作v_DS1302WriteByte_f( DS1302_YEAR_WRITE, 0x08 ) ; //年v_DS1302WriteByte_f( DS1302_WEEK_WRITE, 0x04 ) ; //星期v_DS1302WriteByte_f( DS1302_MONTH_WRITE, 0x12 ) ; //月v_DS1302WriteByte_f( DS1302_DAY_WRITE, 0x11 ) ; //日v_DS1302WriteByte_f( DS1302_HOUR_WRITE, 0x13 ) ; //小时v_DS1302WriteByte_f( DS1302_MINUTE_WRITE, 0x06 ) ; //分钟v_DS1302WriteByte_f( DS1302_SECOND_WRITE, 0x40 ) ; //秒v_DS1302WriteByte_f( 0x90, 0xa5 ) ; //充电v_DS1302WriteByte_f( 0xc0, 0xf0 ) ; //判断是否初始化一次标识写入v_DS1302WriteByte_f( 0x8e, 0x80 ) ; //禁止写操作}}/******************************************************************************* Function: void v_ClockUpdata_f( void ) ** Description:读取时间数据,并保存在结构体CurrentTime中** Parameter:** ** Return:*******************************************************************************/void v_ClockUpdata_f( void ){CurrentTime.Second = v_DS1302ReadByte_f( DS1302_SECOND_READ ) ;CurrentTime.Minute = v_DS1302ReadByte_f( DS1302_MINUTE_READ ) ;CurrentTime.Hour = v_DS1302ReadByte_f( DS1302_HOUR_READ ) ;CurrentTime.Day = v_DS1302ReadByte_f( DS1302_DAY_READ ) ;CurrentTime.Month = v_DS1302ReadByte_f( DS1302_MONTH_READ ) ;CurrentTime.Week = v_DS1302ReadByte_f( DS1302_WEEK_READ ) ;CurrentTime.Year = v_DS1302ReadByte_f( DS1302_YEAR_READ ) ;}有了上面的这些函数我们就可以对DS1302进行操作了。
基于51单片机ds1302和ds18b20芯片方案设计书的电子日历
用DS1302时钟芯片、A T89C51单片机、温度传感器DS18B20、LCD液晶1602设计的电子日历,proteus仿真及C程序.#include<reg51.h> //包含单片机寄存器的头文件#include<intrins.h> //包含_nop_()函数定义的头文件#define uchar unsigned char#define uint unsigned intsbit DQ=P3^7。
//ds18b20与单片机连接口uchar data disdata[5]。
uint tvalue。
//温度值uchar tflag。
//温度正负标志unsigned char code digit[10]={"0123456789"}。
//定义字符数组显示数字sbit DA TA=P3^6。
//位定义1302芯片的接口,数据输出端定义在P1.1引脚sbit RST=P3^4。
//位定义1302芯片的接口,复位端口定义在P1.1引脚sbit SCLK=P3^5。
//位定义1302芯片的接口,时钟输出端口定义在P1.1引脚//液晶引脚定义sbit RS=P2^0。
//寄存器选择位,将RS位定义为P2.0引脚sbit RW=P2^1。
//读写选择位,将RW位定义为P2.1引脚sbit E=P2^2。
//使能信号位,将E位定义为P2.2引脚sbit BF=P0^7。
/*****************************************************函数功能:延时若干微秒***************************************************/void delaynus(unsigned char n){unsigned char i。
for(i=0。
i<n。
i++)。
}void Write1302(unsigned char dat){unsigned char i。
万年历时钟(ds1302)+温度显示(ds18b20)原理图
P3.0 (RXD) P3.1 (TXD) P3.2 (INT0) P3.3 (INT1) P3.4 (T0) P3.5 (T1) X1 X2 IC2 89C51 P27 P26 P25 P24 P23 P22 P21 P20
Байду номын сангаас
28 27 26 25 24 23 22 21
LED2
DIG0_C
DIG4_B
DIG0_B
SD3
DP3
SG3
SD2
DP2
SG2
SD2
DP2
SG2
SD1
DP1
SG1
SD1
DP1
SC3
SC2
SC2
SC1
SC1
SE3
SE2
SE2
SE1
SE1
6
A4
d
h
g
d
h
g
d
h
g
d
h
g
d
h
g
e
c
e
c
e
c
e
c
e
c
R12 1.5k
S7 DP3 S6 SA3 S16 S5:减键,代码05 C S8 S6:加键,代码06 S7:调节时间,代码 07
R12 1.5k C7 104 C7 15P
5V 5V 1 2 3 4 5 CS1 6 CLK1 7 DATA1 8 9 KEY1 10 11 12 13 14 驱动第一排 VDD VDD NC VSS NC CS CLK DATA KEY SG SF SE SD SC HD7279A RESET RC CLKO DIG7 DIG6 DIG5 DIG4 DIG3 DIG2 DIG1 DIG0 DP SA SB 28 27 26 25 24 23 22 21 20 19 18 17 16 15
基于51单片机DS18B20温度传感器的C语言程序和电路
基于51单片机DS18B20温度传感器的C语言程序和电路DS18B20在外形上和三极管很像,有三只脚。
电压范围为3.0 V至5.5 V 无需备用电源测量温度位温度转换为12位数字格式最大值为750毫秒用户可定义的非易失性温度报警设置应用范围包敏感系统。
下面是DS18B20的子程序,本人用过完全可行的:#include<reg51.h>#include<intrins.h>#define uchar unsigned char#define uint unsigned intsbit DQ=P2^0;void reset(); //DS18B20 void write_byte(uchar val); //DS18B20写命令函数uchar read_byte(void); //DS18B20读1字节函数void read_temp(); //温度读取函数void work_temp(); //温度数据处理函数uchar data temp_data[2]={0x00,0x00};uchar data display[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;}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;}电路:。
基于DS18b20、DS1302的单片机测温与时钟显示系统
科技信息OIY论坛OSCIENCE&TECHNOLOGYINFORMATION2009年第3l期基于DSl8b20、DSl302的单片机测温与时钟显示系统周诗虎(武汉职业技术学院计算机系湖北武汉430074)【摘要】本系统采用AT89S52单片机和DSl8b20、DSl302配合,完成实时温度检测和时间日期显示。
并由本人制作完成了样机。
系统中还有一块64点阵LED显示屏,用以显示系统中所需的符号和简单汉字,并能滚动显英文字幕。
另外系统中还装有一个3*3矩阵键盘,用于系统操作与控制。
并接一个直流蜂呜器和一个交流蜂呜器,用以进行音响提示和播放音乐。
【关键词】单片机;DSl8b20;DSl302;显示屏;蜂呜器;矩阵键盘本系统采用AT89S52单片机和DSl8b20、DSl302配合.完成实时温度检测和时间日期显示。
系统配置包括:(1)一块“点阵LED显示屏,用以显示系统中所需的符号和简单汉字,并能滚动显英文字幕。
(2)一个3*3矩阵键盘,用于系统操作与控制。
(3)六个LED七段数码显示管,用于显示温度、时间、日期等。
(4)一个直流蜂呜器和一个交流蜂呜器,用以进行音响提示和播放音乐。
(5)内置和外接测温探头各一个.分别用于室温测量和特定对象的温度测量。
本人制作完成的实物样机如下图。
图实物照片1.系统功能3*3矩阵键盘从左至右键号依次为:0、1、2、3、4…567和8。
接通电源后首先由六个LED七段数码显示管显示实时时间时、分、秒,64点阵I正D显示屏显示星期。
当按一次1号键时,显示变为日期、时间轮流显示。
显示日期时六个LED七段数码显示管显示年、月、日。
再按一次1号键则又回到只显示时间。
若长按I号键将对DSl302进行复位。
按2号键可依次选择对时、分、日、月、年和星期进行调整。
所选被调整对象将闪烁显示。
星期调整完成后再次按2号键将返回原显示状态。
按3号键一次将进行加1调整,按4号键一次将进行加10调整。
51单片机的18B20、1302和LCM1602液晶显示温度与万年历显控制
摘要本设计以数字集成电路技术为基础,单片机技术为核心。
软件设计采用模块化结构,C语言编程。
系统通过LCD显示数据,可以显示日期(年、月、日、时、分、秒)以及温度。
在内容安排上首先描述系统硬件工作原理,着重介绍了各硬件接口技术和各个接口模块的功能;其次,详细的阐述了程序的各个模块和实现过程。
前言电子时钟是实现对年,月,日,时,分,秒数字显示的计时装置,广泛用于个人家庭,车站,码头,办公室,银行大厅等场所,成为人们日常生活中的必需品。
数字集成电路的发展和石英晶体振荡器的广泛应用,使得数字钟的精度远远超过老式钟表。
钟表的数字化给人们生产生活带来了极大的方便,在此基础上完成的电子时钟精度高,功能易于扩展。
可扩展成为诸如定时自动报警、按时自动打铃、时间程序自动控制、定时广播、自动起闭路灯、定时开关烘箱、通断动力设备、甚至各种定时电气的自动启用等电路。
所有这些,都是以钟表数字化为基础的。
因此,研究数字时钟及扩大其应用有着非常现实的意义。
本设计就是数字时钟简单的扩展应用。
1.1设计目标:利用单片机技术,以及模拟电子技术和数字电子技术的理论知识,设计实现MCS-51单片机对LCM1602液晶输出显示控制的这一基本要求。
1.2设计要求:本设计利用DS1302;DS18B20;LCD1602实现以下功能:(1) 显示日期功能(年、月、日、时、分、秒以及星期)(2) 可通过按键切换年、月、日及时、分、秒的显示状态(3) 可随时调校年、月、日或时、分、秒(4) 可每次增减一进行时间调节(5) 可动态完整显示年份,实现真正的万年历显示(6) 可显示温度2 设计方案2.1 控制器硬件控制电路主要用了AT89C52芯片处理器、LCD显示器等。
根据各自芯片的功能互相连接成电子万年历的控制电路。
软件控制程序主要有主控程序、电子万年历的时间控制程序、时间显示及星期显示和温度采集程序等组成。
主控程序中对整个程序进行控制,进行了初始化程序及计数器、还有键盘功能程序、以及显示程序等工作,时间控制程序是电子万年历中比较重要的部分。
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 语言程序和电路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欢迎您的下载,资料仅供参考!致力为企业和个人提供合同协议,策划案计划书,学习课件等等打造全网一站式需求。
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);}。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
时钟电路图:PCB板:单片机程序:/*=========================================================== =========调试要求:1.MCU:AT89S52芯片或AT89C522.晶振:12MHz功能:多功能时钟+温度计============================================================= =======*/#include<reg52.h>#include<intrins.h>#define uchar unsigned char#define uint unsigned intsbit dis_bit1=P2^7;//定义数码管控制口sbit dis_bit2=P2^6;//定义数码管控制口sbit dis_bit3=P2^4;//定义数码管控制口sbit dis_bit4=P2^3;//定义数码管控制口sbit dis_bit5=P2^1;//定义数码管控制口sbit dis_bit6=P2^0;//定义数码管控制口sbit led1_bit=P2^2;//定时LED的控制口sbit led2_bit=P2^5;//定时LED的控制口sbit s1_bit=P1^0; //定义S1控制口sbit s2_bit=P1^1; //定义S2控制口sbit s3_bit=P1^2; //定义S3控制口sbit dq_ds18b20=P3^3;//定义控制DS18B20sbit speak=P3^7; //定义蜂鸣器控制口sbit clk_ds1302=P3^6;//定义控制DS1302的时钟线sbit io_ds1302=P3^5;//定义控制DS1302的串行数据sbit rest_ds1302=P3^4;#define smg_data P0//定义数码管数据口void delay_3us();//3US的延时程序void delay_8us(uint t);//8US延时基准程序void delay_50us(uint t);//延时50*T微妙函数的声明void display1(uchar dis_data);//数码管1显示子程序void display2(uchar dis_data);//数码管2显示子程序void display3(uchar dis_data);//数码管3显示子程序void display4(uchar dis_data);//数码管4显示子程序void display5(uchar dis_data);//数码管5显示子程序void display6(uchar dis_data);//数码管6显示子程序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_san(uchar s6,uchar s5,uchar s4,uchar s3,uchar s2,uchar s1,uchar san);//闪烁显示子程序void judge_dis();//显示处理函数void judge_clock();//显示处理函数void set_ds1302();//设置时间void get_ds1302();//读取当前时间void w_1byte_ds1302(uchar t);//向DS1302写一个字节的数据uchar r_1byte_ds1302();//从DS1302读一个字节的数据//******************************************************************** ***//DS18B20测温函数定义void w_1byte_ds18b20(uchar value);//向DS18B20写一个字节uchar r_1byte_ds18b20(void);//从DS18B20读取一个字节的数据void rest_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,0x0 8,0x09,0x09};uchar t0_crycle;uchar hour_count,minute_count,second_count,msecond_count;uchar clock_hour,clock_minute;uchar countdown_second;uchar countdown_hour,countdown_minute;uchar clock_en;//闹钟关闭和开启的标志,1开启,0关闭uchar flag1,second_flag,zancun1,zancun2,zancun3;uchar zancun4,zancun5,zancun6,zancun7;uchar clock_flag,countdown_flag;uchar msecond_minute,msecond_second,msecond_msecond,msecond_flag;//秒表相关参数uint speak_count;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;msecond_msecond=0;speak=1;//关闭蜂鸣器speak_count=0;clock_hour=0;clock_minute=0;clock_flag=0;countdown_flag=0;//倒计时标志位为0clock_en=0;//开机时默认关闭闹钟init_t0();TR0=1;//// set_ds1302();//设置DS1302的初始时间//接下来开始编写让数码管显示的程序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;msecond_flag=1;msecond_count++;if(msecond_count==10)//1秒{msecond_count=0;second_flag=1;}}}//************************************************** //显示处理函数void judge_dis(){if(flag1==0){if(second_flag==1){zancun7++;second_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=second_count&0xf0;zancun6>>=4;dis(zancun4,hour_count&0x0f,zancun5,minute_count&0x0f,zancun6,second_count& 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,zancun1%10,zancun2/10,zancun2%10,12,12,1);break;case 7:dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,12,12,2);break;case 8:dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,12,12,3);break;case 9://进入修改时间,时间分位个位闪烁dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,12,12,4);break;case 10://进入修改闹钟,闹钟小时十位闪烁dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,12,zancun3,1);break;case 11://进入修改闹钟,闹钟小时个位闪烁dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,12,zancun3,2);break;case 12://进入修改闹钟,闹钟小时十位闪烁dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,12,zancun3,3);break;case 13://进入修改闹钟,闹钟小时个位闪烁dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,12,zancun3,4);break;case 14://进入修改闹钟的开关dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,12,zancun3,6);break;case 15:dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,zancun3/10,zancun3%10, 1);break;case 16:dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,zancun3/10,zancun3%10, 2);break;case 17:dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,zancun3/10,zancun3%10, 3);break;case 18:dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,zancun3/10,zancun3%10, 4);break;case 19:dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,zancun3/10,zancun3%10, 5);break;case 20:dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,zancun3/10,zancun3%10, 6);break;case 21:if(second_flag==1){second_flag=0;countdown_second--;if(countdown_second==255){countdown_second=59;countdown_minute--;if(countdown_minute==255){countdown_minute=59;countdown_hour--;if(countdown_hour==255){flag1=22;countdown_minute=0;countdown_hour=0;countdown_second=0;countdown_flag=1;}}}}dis(countdown_hour/10,countdown_hour%10,countdown_minute/10,countdown_min ute%10,countdown_second/10,countdown_second%10);//break;case 22:if(countdown_flag>0 && countdown_flag<7){speak=0;if(second_flag==1){second_flag=0;countdown_flag++;}}else{speak=1;}dis(countdown_hour/10,countdown_hour%10,countdown_minute/10,countdown_min ute%10,countdown_second/10,countdown_second%10);//break;case 23:dis(msecond_minute/10,msecond_minute%10,msecond_second/10,msecond_second %10,msecond_msecond%10,12);break;case 24:if(msecond_flag==1){msecond_flag=0;msecond_msecond++;if(msecond_msecond==10){msecond_msecond=0;msecond_second++;if(msecond_second==60){msecond_second=0;msecond_minute++;if(msecond_minute==100){msecond_minute=99;flag1=23;}}}}dis(msecond_minute/10,msecond_minute%10,msecond_second/10,msecond_second %10,msecond_msecond%10,12);break;case 25:dis(zancun3/10,zancun3%10,zancun2/10,zancun2%10,zancun1/10,zancun1%10);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)//判断是否有按键按下{delay_50us(1);// 延时,去除机械抖动if(s2_bit==0){switch (flag1){case 1: //在显示SET1状态下按S2件,进入修改时间flag1=6;zancun4=hour_count&0xf0;zancun4>>=4;zancun6=hour_count&0x0f;zancun1=zancun4*10+zancun6;//zancun1=hour_count;zancun5=minute_count&0xf0;zancun5>>=4;zancun6=minute_count&0x0f;zancun2=zancun5*10+zancun6;// zancun2=minute_count;break;case 2://在显示SET2状态下按S2,进入设置闹钟zancun1=clock_hour;zancun2=clock_minute;flag1=10;break;case 6://修改时钟小时十位状态下按S2件case 7://修改时钟小时个位状态下按S2件case 8://修改时钟分钟十位状态下按S2件case 9://修改时钟分钟个位状态下按S2件//zancun4=zancun1/10;tab23[2]=zancun1/10*16+zancun1%10;//zancun5=zancun2&0xf0;//zancun5>>=4;tab23[1]=zancun2/10*16+zancun2%10;hour_count=tab23[2];minute_count=tab23[1];second_count=0;tab23[0]=0;set_ds1302();//设置DS1302的初始时间flag1=0;break;case 10://修改闹钟小时十位状态下按S2case 11://修改闹钟小时个位状态下按S2case 12://修改闹钟分钟十位状态下按S2case 13://修改闹钟分钟个位状态下按S2case 14://修改闹钟使能状态下按S2 clock_hour=zancun1;clock_minute=zancun2;clock_en=zancun3;flag1=0;break;case 3:flag1=15;zancun1=countdown_hour;zancun2=countdown_minute;zancun3=countdown_second;break;case 15:case 16:case 17:case 18:case 19:case 20:countdown_hour=zancun1;countdown_minute=zancun2;countdown_second=zancun3;flag1=21;countdown_flag=0;break;case 22:flag1=21;break;case 21:flag1=22;break;case 4:flag1=23;//秒表暂停msecond_minute=0;msecond_second=0;msecond_msecond=0;break;case 23:flag1=24;break;case 24:flag1=23;break;case 5:flag1=25;//进入计数器模式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=zancun1%10;break;case 7://修改时间小时的个位数zancun1=zancun1/10*10+(zancun1%10+1)%10;if(zancun1>=24)zancun1=20;break;case 8://修改时间分钟的十位数zancun2+=10;if(zancun2>=60)zancun2-=60;break;case 9://修改时间分钟的个位数zancun2=zancun2/10*10+(zancun2%10+1)%10;break;case 10://修改闹钟小时的十位数if(zancun1>=24)zancun1=zancun1%10;break;case 11://修改闹钟小时的个位数zancun1=zancun1/10*10+(zancun1%10+1)%10;if(zancun1>=24)zancun1=20;break;case 12://修改闹钟分钟的十位数zancun2+=10;if(zancun2>=60)zancun2-=60;break;case 13://修改闹钟分钟的个位数zancun2=zancun2/10*10+(zancun2%10+1)%10;break;case 14:zancun3^=1;break;case 15://修改倒计时小时的十位数zancun1+=10;if(zancun1>=100)zancun1-=100;break;case 16: //修改倒计时小时的个位数zancun1=zancun1/10*10+(zancun1%10+1)%10;break;case 17://修改倒计时分钟的十位数zancun2+=10;if(zancun2>=60)zancun2-=60;break;case 18: //修改倒计时分钟的个位数zancun2=zancun2/10*10+(zancun2%10+1)%10;break;case 19://修改倒计时秒的十位数zancun3+=10;if(zancun3>=60)zancun3-=60;break;case 20: //修改倒计时秒的个位数zancun3=zancun3/10*10+(zancun3%10+1)%10;break;case 21:case 22://countdown_hour=zancun1;countdown_minute=zancun2;countdown_second=zancun3;flag1=21;break;case 23:case 24://秒表复位flag1=24;msecond_minute=0;msecond_second=0;msecond_msecond=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+=zancun6;zancun5=minute_count&0xf0;zancun5>>=4;zancun6=minute_count&0x0f;zancun5*=10;zancun5+=zancun6;if(clock_hour==zancun4 && clock_minute==zancun5){if(clock_en==1 && clock_flag==0){speak_count=0;//开启蜂鸣器clock_flag=1;speak_count=0;}}else{clock_flag=0;}if(clock_flag==1 && speak_count<400){if(msecond_count<=5){speak=0;speak_count++;}else{speak=1;}}else{speak=1;}}//****************************************////闪烁显示子程序void dis_san(uchar s6,uchar s5,uchar s4,uchar s3,uchar s2,uchar s1,uchar san) {if(san==1){if(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_t0(){TMOD=0x01;//设定定时器工作方式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){led1_bit=1;led2_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(){;;}//******************************************************************** ***********//子程序功能:向DS18B20写一字节的数据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 = 1delay_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;}//;**************************************************//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;templ=-templ;t_x=tabl3[templ & 0x0f];//计算温度的小数temp32=temph & 0x0f;temp32<<=4;templ>>=4;temp32=temp32 | templ;t_b=temp32/100%10;//计算温度的百位数据t_s=temp32/10%10;//计算温度的十位数据t_g=temp32%10;//计算温度的个位数据}else//为正数{t_x=tabl3[templ & 0x0f];//计算温度的小数temp32=temph & 0x0f;temp32<<=4;templ>>=4;temp32=temp32 | templ;t_b=temp32/100%10;//计算温度的百位数据t_s=temp32/10%10;//计算温度的十位数据t_g=temp32%10;//计算温度的个位数据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);}}//;################################################################### ###########//;子程序名:w_1byte_ds1302//;功能:向DS1302写一个字节的数据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;}}//;################################################################### #####//;子程序名:r_1byte_ds1302()//;功能:从DS1302读一个字节的数据uchar r_1byte_ds1302(){uchar i,temp11=0;io_ds1302=1;//置IO为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);}//;################################################################### ##############//;子程序名:setbds1302//;功能:设置DS1302初始时间,并启动计时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();rest_ds1302=0;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();}//;#################################################################-------//;子程序名: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();rest_ds1302=1;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];//month=temp[4];// week=temp[5];//year=temp[6];}/*=========================================================== =========调试要求:1.MCU:AT89S52芯片或AT89C522.晶振:12MHz功能:多功能时钟+温度计============================================================= =======*/#include<reg52.h>#include<intrins.h>#define uchar unsigned char#define uint unsigned intsbit dis_bit1=P2^7;//定义数码管控制口sbit dis_bit2=P2^6;//定义数码管控制口sbit dis_bit3=P2^4;//定义数码管控制口sbit dis_bit4=P2^3;//定义数码管控制口sbit dis_bit5=P2^1;//定义数码管控制口sbit dis_bit6=P2^0;//定义数码管控制口sbit led1_bit=P2^2;//定时LED的控制口sbit led2_bit=P2^5;//定时LED的控制口sbit s1_bit=P1^0; //定义S1控制口sbit s2_bit=P1^1; //定义S2控制口sbit s3_bit=P1^2; //定义S3控制口sbit dq_ds18b20=P3^3;//定义控制DS18B20sbit speak=P3^7; //定义蜂鸣器控制口sbit clk_ds1302=P3^6;//定义控制DS1302的时钟线sbit io_ds1302=P3^5;//定义控制DS1302的串行数据sbit rest_ds1302=P3^4;#define smg_data P0//定义数码管数据口void delay_3us();//3US的延时程序void delay_8us(uint t);//8US延时基准程序void delay_50us(uint t);//延时50*T微妙函数的声明void display1(uchar dis_data);//数码管1显示子程序void display2(uchar dis_data);//数码管2显示子程序void display3(uchar dis_data);//数码管3显示子程序void display4(uchar dis_data);//数码管4显示子程序void display5(uchar dis_data);//数码管5显示子程序void display6(uchar dis_data);//数码管6显示子程序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_san(uchar s6,uchar s5,uchar s4,uchar s3,uchar s2,uchar s1,uchar san);//闪烁显示子程序void judge_dis();//显示处理函数void judge_clock();//显示处理函数void set_ds1302();//设置时间void get_ds1302();//读取当前时间void w_1byte_ds1302(uchar t);//向DS1302写一个字节的数据uchar r_1byte_ds1302();//从DS1302读一个字节的数据//******************************************************************** ***//DS18B20测温函数定义void w_1byte_ds18b20(uchar value);//向DS18B20写一个字节uchar r_1byte_ds18b20(void);//从DS18B20读取一个字节的数据void rest_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,0x0 8,0x09,0x09};uchar t0_crycle;uchar hour_count,minute_count,second_count,msecond_count;uchar clock_hour,clock_minute;uchar countdown_second;uchar countdown_hour,countdown_minute;uchar clock_en;//闹钟关闭和开启的标志,1开启,0关闭uchar flag1,second_flag,zancun1,zancun2,zancun3;uchar zancun4,zancun5,zancun6,zancun7;uchar clock_flag,countdown_flag;uchar msecond_minute,msecond_second,msecond_msecond,msecond_flag;//秒表相关参数uint speak_count;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;msecond_msecond=0;speak=1;//关闭蜂鸣器speak_count=0;clock_hour=0;clock_minute=0;clock_flag=0;countdown_flag=0;//倒计时标志位为0clock_en=0;//开机时默认关闭闹钟init_t0();TR0=1;//// set_ds1302();//设置DS1302的初始时间//接下来开始编写让数码管显示的程序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;msecond_flag=1;msecond_count++;if(msecond_count==10)//1秒{msecond_count=0;second_flag=1;}}}//**************************************************//显示处理函数void judge_dis(){if(flag1==0){if(second_flag==1){zancun7++;second_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=second_count&0xf0;zancun6>>=4;dis(zancun4,hour_count&0x0f,zancun5,minute_count&0x0f,zancun6,second_count& 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,zancun1%10,zancun2/10,zancun2%10,12,12,1);break;case 7:dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,12,12,2);break;case 8:dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,12,12,3);break;case 9://进入修改时间,时间分位个位闪烁dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,12,12,4);break;case 10://进入修改闹钟,闹钟小时十位闪烁dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,12,zancun3,1);break;case 11://进入修改闹钟,闹钟小时个位闪烁dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,12,zancun3,2);break;case 12://进入修改闹钟,闹钟小时十位闪烁dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,12,zancun3,3);break;case 13://进入修改闹钟,闹钟小时个位闪烁dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,12,zancun3,4);break;case 14://进入修改闹钟的开关dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,12,zancun3,6);break;case 15:dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,zancun3/10,zancun3%10, 1);break;case 16:dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,zancun3/10,zancun3%10, 2);break;case 17:dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,zancun3/10,zancun3%10, 3);break;case 18:dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,zancun3/10,zancun3%10, 4);break;case 19:dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,zancun3/10,zancun3%10, 5);break;case 20:dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,zancun3/10,zancun3%10, 6);break;case 21:if(second_flag==1){second_flag=0;countdown_second--;if(countdown_second==255){。