第11章 51单片机的温度和时间采集模块

合集下载

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温度采集,LCD显示汇编程序(附带proteus仿真图)

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

TEMP_ZH EQU 24H ;实测温度值存放单元TEMPL EQU 25H TEMPH EQU 26HTEMP_TH EQU 27H ;高温报警值存放单元TEMP_TL EQU28H ;TEMPHC EQU 29H ;TEMPLC EQU 2AHTEMPFC EQU 2BHK1 EQU P1.4K2 EQU P1.5 ;K3 EQU P1.6 ;K4 EQU P1.7 ;BEEP EQU P3.7 ;RELAY EQU P1.3 ;LCD_X EQU 2FH ;LCDLCD_RS EQU P2.0 ;LCDLCD_RW EQU P2.1 ;LCDLCD_EN EQU P2.2 ;LCDFLAG1 EQU 20H.0 ;DS18B20 KEY_UD EQU 20H.1 ;DQEQU P3.3低温报警值存放单元正、负温度值标记查询按键设置/调整键调整键确定键蜂鸣器指示灯字符显示位置寄存器选择信号读写信号允许信号是否存在标志设定按键的增、减标志数据信号;;DS18B20ORG 00HLJMP MAINORG 0030H MAIN:MOV SP,#60H MOV A,#00HMOV R0,#20H MOV R1,#10H CLEAR:MOV @R0,A INC R0DJNZ R1,CLEAR LCALL SET_LCD LCALL RE_18B20 START:LCALL RST JNB FLAG1,START1 LCALL MENU_OK信息子程序MOV TEMP_TH,#055H MOV TEMP_TL,#019H LCALL RE_18B20ALCALL WRITE_E2 ;LCALL TEMP_BJ ;JMP START2;将20H~2FH单元清零;调用18B20复位子程序;DS1820不存在;DS1820存在,调用显示正确设置TH初值85度设置TL初值25度调用暂存器操作子程序写入DS18B20显示温度标记;;;START1: LCALL MENU_ERROR;调用显示出错信息子程序LCALL TEMP_BJ ;显示温度标记SJMP $START2: LCALL RST;调用DS18B20复位子程序JNBFLAG1,START1;DS18B20不存在MOV A,#0CCHLCALL WRITEMOV A,#44HLCALL WRITELCALL RSTMOV A,#0CCHLCALL WRITEMOV A,#0BEHLCALL WRITELCALL READ子程序LCALL CONVTEMP程序LCALL DISPBCDLCALL CONVLCALL TEMP_COMP值比较子程序;跳过ROM匹配命令;温度转换命令;跳过ROM匹配;读温度命令;调用DS18B20数据读取操作;调用温度数据BCD码处理子;调用温度数据显示子程序;调用LCD显示处理子程序;调用实测温度值与设定温度LCALLPROC_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值写入DS18B20 LCALL WRITE_E2PROC_K2: LCALL MENU_OKLCALL TEMP_BJPROC_END:RET;******************************************************SET_ALARM:LCALL LOOK_ALARMAS0: JB K1,AS00LCALL BEEP_BLJNB K1,$CPL 20H.1 ;UP/DOWNAS00: JB 20H.1,ASZ01 ;20H.1=1 JMP ASJ01 ;20H.1=0ASZ01: JB K2,ASZ02 ;THLCALL BEEP_BLINC TEMP_THMOV A,TEMP_THCJNE A,#120,ASZ011MOV TEMP_TH,#0ASZ011: LCALL LOOK_ALARM设定温度报警值标记,增加,减小值调整(增加)TH、TLMOV R5,#10LCALL DELAYJMP ASZ01ASZ02: JB K3,ASZ03;TL值调整(增加)LCALL BEEP_BLINC TEMP_TLMOV A,TEMP_TLCJNE A,#99,ASZ021MOV TEMP_TL,#00HASZ021: LCALL LOOK_ALARM MOV R5,#10LCALL DELAYJMP ASZ02ASZ03: JB K4,AS0LCALL BEEP_BLJNB K4,$RETASJ01: JB K2,ASJ02LCALL BEEP_BLDEC TEMP_THMOV A,TEMP_THCJNE A,#0FFH,ASJ011;确定调整;TH值调整(减少)JMP ASJ022ASJ011: 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:MOVA,TEMP_THSUBBA,TEMP_ZH;减数>被减数,则JC CHULI1;借位标志位C=1,转MOV A,TEMPFCCJNEA,#0BH,COMPSJMPCHULI2COMP:MOV A,TEMP_ZHSUBB A,TEMP_TL ;JC CHULI2 ;MOV DPTR,#BJ5LCALL TEMP_BJ3CLR RELAYRETCHULI1: MOV DPTR,#BJ3LCALL TEMP_BJ3SETB RELAY ;LCALL BEEP_BLRETCHULI2: MOV DPTR,#BJ4LCALL TEMP_BJ3SETB RELAY ;减数>被减数,则借位标志位C=1,转;点亮指示灯熄灭指示灯蜂鸣器响熄灭指示灯;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,#0 MOV 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,TSR1程序SETB DQ;拉高数据线NOPNOPNOPMOV R0,#32HTSR2: JNB DQ,TSR3;等待DS18B20回应DJNZ R0,TSR2JMP TSR4 ;延时TSR3: SETB FLAG1 ;置1标志位,表示DS1820存在JMP TSR5 TSR4: CLR FLAG1 ;清0标志位,表示DS1820不存在JMP TSR7 TSR5: 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;把暂存器里的温度报警值拷贝到EEROM LCALL 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_DATAD_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微妙以上RRCA ;把一个字节DATA分成8个BIT环移给CMOV DQ,C;写入一位MOV R3,#3CHDJNZ R3,$ ;等待100微妙SETB DQ;重新释放总线NOPDJNZ R2,WR1 ;写入下一位SETB DQRET;**********************DS18B20数据读取操作子程序**************************MOV R4,#4;将温度低位、高位、TH、TL从DS18B20中读出MOV R1,#TEMPL元RE00: MOV R2,#8RE01: CLR CYSETB DQNOPNOPCLR DQNOPNOPNOPSETB DQMOV R3,#09DJNZ R3,$MOV C,DQMOV R3,#3CH;存入25H、26H、27H、28H单;读前总线保持为低;开始读总线释放;延时18微妙;从DS18B20总线读得一位DJNZ R3,$;等待100微妙RRC A;把读得的位值环移给ADJNZ R2,RE01;读下一位MOV @R1,ADJNZ 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 ;MOV DPTR,#TEMPDOTTABMOVC A,@A+DPTRMOV TEMPLC,A ;TEMPLC LOW=分BCD MOV A,TEMPL ;ANL A,#0F0H ;SWAP AMOV TEMPL,AMOV A,TEMPH ;ANL A,#0FHSWAP AORL A,TEMPL ;乘0.0625小数部整数部分取出高四位取出低四位重新组合MOV TEMP_ZH,ALCALL HEX2BCD1MOV TEMPL,AANL A,#0F0HSWAP AORL A,TEMPHC ;TEMPHCBCDMOV TEMPHC,AMOV A,TEMPLANL A,#0FHSWAP A ;TEMPLC HI =BCD ORL A,TEMPLCMOV TEMPLC,AMOV A,R4JZ TEMPC12ANL A,#0FHSWAP AMOV R4,AMOV A,TEMPHC ;TEMPHC HI =BCD ANL A,#0FHLOW=十位数个位数百位数ORL A,R4TEMPC12: 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_PRINTLCALL TEMP_BJ1MOV A,TEMP_TH;加载TH数据MOV LCD_X,#3LCALL SHOW_DIG2H ;MOV A,#0CEHLCALL TEMP_BJ1MOV A,TEMP_TLMOV LCD_X,#12LCALL SHOW_DIG2L ;RETM_ALAX1: DB " LOOK ALERT CODE",0 M_ALAX2: DB "TH:TL:",0TEMP_BJ1: LCALL WCOMMOV DPTR,#BJ2MOV R1,#0MOV R0,#2BBJJ2: MOV A,R1MOVC A,@A+DPTRLCALL WDATA;设置显示位置显示数据;加载TL数据;设置显示位置显示数据;指针指到显示信息区INC R1DJNZ 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 LCDP2显示子程序POP B INC 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,73HMOV LCD_X,#6CJNE A,#1,CONV1JMP CONV2CONV1: CJNE A,#0BH,CONV11MOV A,#"-"JMP CONV111CONV11: MOV A,#" "CONV111: MOV B,LCD_XLCALL LCDP2JMP CONV3CONV2: LCALL SHOW_DIG2CONV3: INC LCD_X MOV A,72HLCALL SHOW_DIG2INC LCD_XMOV A,71HLCALL 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的CGRAMRET;*****************************************************************INIT_LCD:MOV A,#38H ;2行显示,字形5*7点阵LCALL WCOMLCALL DELAY1MOV A,#38HLCALL WCOMLCALL DELAY1MOV A,#38HLCALL WCOMLCALL DELAY1MOV A,#0CH ;开显示,显示光标,光标不闪烁LCALL WCOMLCD 初始化LCALL 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;***************************清除****************************CLR_LINE:MOV R0,#24CL1: MOV A,#' 'LCALL WDATADJNZ R0,CL11行LCD的字符RETDE:MOV R7,#250DJNZ R7,$RET;****************************LCD间接控制方式命令写入*************************WCOM:MOV P0,A ;写入命令CLR LCD_RS ;RS=L,RW=L,D0-D7=指令码,E=高脉冲CLR LCD_RW SETB LCD_ENLCALL DELAY1CLR LCD_ENRET;****************************LCD间接控制方式数据写入*************************WDATA:MOV P0,A ;写入数据SETB LCD_RSCLR LCD_RWSETB LCD_ENLCALL DECLR LCD_ENLCALL 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,#10LCALL DELAYRETDEX1: 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单片机多点温度采集系统程序清单

51单片机多点温度采集系统程序清单

#include <AT89X52.h>#include <Intrins.h>#define DATA P1 //1602驱动端口//ROM操作命令#define READ_ROM 0x33 //读ROM#define SKIP_ROM 0xCC //跳过ROM#define MATCH_ROM 0x55 //匹配ROM#define SEARCH_ROM 0xF0 //搜索ROM#define ALARM_SEARCH 0xEC //告警搜索//存储器操作命令#define ANEW_MOVE 0xB8 //重新调出E^2数据#define READ_POWER 0xB4 //读电源#define TEMP_SWITCH 0x44 //启动温度变换#define READ_MEMORY 0xBE //读暂存存储器#define COPY_MEMORY 0x48 //复制暂存存储器#define WRITE_MEMORY 0x4E //写暂存存储器//数据存储结构typedef struct tagTempData{unsigned char btThird; //百位数据unsigned char btSecond; //十位数据unsigned char btFirst; //个位数据unsigned char btDecimal; //小数点后一位数据unsigned char btNegative; //是否为负数}TEMPDATA;TEMPDATA m_TempData;//引脚定义sbit DQ = P2^7; //数据线端口sbit RS= P2^0;sbit RW= P2^1;sbit E= P2^2;//DS18B20序列号,通过调用GetROMSequence()函数在P1口读出(读8次)const unsigned char code ROMData1[8] = {0x28, 0x33, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0xD7};const unsigned char code ROMData2[8] = {0x28, 0x30, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0x8E};//U2const unsigned char code ROMData3[8] = {0x28, 0x31, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0xB9};//U3const unsigned char code ROMData4[8] = {0x28, 0x32, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0xE0};//U4const unsigned char code ROMData5[8] = {0x28, 0x34, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0x52};//U5const unsigned char code ROMData6[8] = {0x28, 0x35, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0x65};//U6const unsigned char code ROMData7[8] = {0x28, 0x36, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0x3C};//U7const unsigned char code ROMData8[8] = {0x28, 0x37, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0x0B};//U8//判断忙指令void Busy(){DATA = 0xff;RS = 0;RW = 1;while(DATA & 0x80){E = 0;E = 1;}}//写指令程序void WriteCommand(unsigned char btCommand) {Busy();RS = 0;RW = 0;E = 1;DATA = btCommand;E = 0;}//写数据程序void WriteData(unsigned char btData){Busy();RS = 1;RW = 0;E = 1;DATA = btData;E = 0;}void Clear(){WriteCommand(1);}//初始化void Init(){WriteCommand(0x0c); //开显示,无光标显示WriteCommand(0x06); //文字不动,光标自动右移WriteCommand(0x38); //设置显示模式:8位2行5x7点阵}//显示单个字符void DisplayOne(bit bRow, unsigned char btColumn, unsigned char btData, bit bIsNumber) {if (bRow) WriteCommand(0xc0 + btColumn);else WriteCommand(0x80 + btColumn);if (bIsNumber) WriteData(btData + 0x30);else WriteData(btData);}//显示字符串函数void DisplayString(bit bRow, unsigned char btColumn, unsigned char *pData) {while (*pData != '\0'){if (bRow) WriteCommand(0xc0 + btColumn);//显示在第1行else WriteCommand(0x80 + btColumn); //显示在第0行WriteData(*(pData++)); //要显示的数据btColumn++; //列数加一}}//延时16us子函数void Delay16us(){unsigned char a;for (a = 0; a < 4; a++);}//延时60us子函数void Delay60us(){unsigned char a;for (a = 0; a < 18; a++);}//延时480us子函数void Delay480us(){unsigned char a;for (a = 0; a < 158; a++); }//延时240us子函数void Delay240us(){unsigned char a;for (a = 0; a < 78; a++); }//延时500ms子函数void Delay500ms(){unsigned char a, b, c;for (a = 0; a < 250; a++)for (b = 0; b < 3; b++)for (c = 0; c < 220; c++);}//芯片初始化void Initialization(){while(1){DQ = 0;Delay480us(); //延时480usDQ = 1;Delay60us(); //延时60usif(!DQ) //收到ds18b20的应答信号{DQ = 1;Delay240us(); //延时240usbreak;}}}//写一个字节(从低位开始写)void WriteByte(unsigned char btData){unsigned char i, btBuffer;for (i = 0; i < 8; i++){btBuffer = btData >> i;if (btBuffer & 1){DQ = 0;_nop_();_nop_();DQ = 1;Delay60us();}else{DQ = 0;Delay60us();DQ = 1;}}}//读一个字节(从低位开始读) unsigned char ReadByte(){unsigned char i, btDest;for (i = 0; i < 8; i++){btDest >>= 1;DQ = 0;_nop_();_nop_();DQ = 1;Delay16us();if (DQ) btDest |= 0x80;Delay60us();}return btDest;}//序列号匹配void MatchROM(const unsigned char *pMatchData) {unsigned char i;Initialization();WriteByte(MATCH_ROM);for (i = 0; i < 8; i++) WriteByte(*(pMatchData + i)); }//得到64位ROM序列(在P1口显示,必须与Proteus联调且在单步调试下才能得到) /*void GetROMSequence(){unsigned char i;Initialization();WriteByte(READ_ROM);for (i = 0; i < 8; i++)P1 = ReadByte();}*///读取温度值TEMPDATA ReadTemperature(){TEMPDATA TempData;unsigned int iTempDataH;unsigned char btDot, iTempDataL;static unsigned char i = 0;TempData.btNegative = 0; //为0温度为正i++;if (i == 9) i = 1;Initialization();WriteByte(SKIP_ROM); //跳过ROM匹配WriteByte(TEMP_SWITCH); //启动转换Delay500ms(); //调用一次就行Delay500ms();Initialization();//多个芯片的时候用MatchROM(ROMData)换掉WriteByte(SKIP_ROM)switch (i){case 1 : MatchROM(ROMData1); break; //匹配1case 2 : MatchROM(ROMData2); break; //匹配2case 3 : MatchROM(ROMData3); break; //匹配3case 4 : MatchROM(ROMData4); break; //匹配4case 5 : MatchROM(ROMData5); break; //匹配5case 6 : MatchROM(ROMData6); break; //匹配6case 7 : MatchROM(ROMData7); break; //匹配7case 8 : MatchROM(ROMData8); break; //匹配8}//WriteByte(SKIP_ROM); //跳过ROM匹配(单个芯片时用这句换掉上面的switch)WriteByte(READ_MEMORY); //读数据iTempDataL = ReadByte();iTempDataH = ReadByte();iTempDataH <<= 8;iTempDataH |= iTempDataL;if (iTempDataH & 0x8000){TempData.btNegative = 1;iTempDataH = ~iTempDataH + 1; //负数求补}//为了省去浮点运算带来的开销,而采用整数和小数部分分开处理的方法(没有四舍五入)btDot = (unsigned char)(iTempDataH & 0x000F); //得到小数部分iTempDataH >>= 4; //得到整数部分btDot *= 5; //btDot*10/16得到转换后的小数数据btDot >>= 3;//数据处理TempData.btThird = (unsigned char)iTempDataH / 100;TempData.btSecond = (unsigned char)iTempDataH % 100 / 10;TempData.btFirst = (unsigned char)iTempDataH % 10;TempData.btDecimal = btDot;return TempData;}//数据处理子程序void DataProcess(){m_TempData = ReadTemperature();if (m_TempData.btNegative) DisplayOne(1, 6, '-', 0);else DisplayOne(1, 6, m_TempData.btThird, 1);DisplayOne(1, 7, m_TempData.btSecond, 1);DisplayOne(1, 8, m_TempData.btFirst, 1);DisplayOne(1, 10, m_TempData.btDecimal, 1);}void main(){//GetROMSequence();Clear();Init();DisplayString(0, 0, " Temperature");DisplayOne(1, 9, '.', 0);while (1) DataProcess();}。

51单片机时钟显示+温度显示

51单片机时钟显示+温度显示

湘南学院物电系学院:电气工程学院题目:单片机LCD时钟显示和温度测量学生姓名:专业班级:指导老师:教研室主任:2012年6月29日一、概述:本次设计的LCD时钟显示和温度测量系统是由中央控制器、温度检测器、时钟系统、显示器及键盘部分组成。

控制器采用单片机STC89C51RC,温度检测部分采用DS18B20温度传感器,时钟系统用时钟芯片DS1302,用LCD液晶1602作为显示器,用蜂鸣器构成闹铃模块。

单片机通过时钟芯片DS1302获取时间数据,对数据处理后显示时间;温度传感器DS18B20采集温度信号送该给单片机处理;单片机再把时间数据和温度数据送液晶显示器1602显示;键盘是用来调整时间的。

二、方案设计及方案论证1. 时钟显示和温度测量的总体设计思路按照系统的设计功能要求,本时钟显示和温度测量系统的设计必须采用单片机软件系统实现,用单片机的自动控制能力配合按键控制,来控制时钟、温度的调整及显示。

获得时钟显示和温度测量数据信息,单片机对其进行一系列的处理,最后通过液晶显示出来。

2.时钟显示和温度测量系统方案论证2.1时钟系统方案选择方案1:通过单片机内部的定时器/计数器,用软件实现,直接用单片机的定时器编程以实现时钟;方案2:用专门的时钟芯片实现时钟的记时,再把时间数据送入单片机,由单片机控制显示。

虽然用软件实现时钟硬件线路简单,但是程序运行的每一步都需要时间,多一步或少一步程序都会影响记时的准确度,对定时器定时也不是十分准确,时钟精度很低,对于我们实现所需要的功能造成软件编程非常复杂。

用专用时钟芯片硬件成本相对较高,但它的精度很高,软件编程很简单。

综上所述,选择方案2。

本次设计采用具有涓细电流充电能力的低功耗实时时钟电路DS1302。

它可以对年、月、日、周日、时、分、秒进行计时,且具有闰年补偿等多种功能。

它采用主电源和备用电源双电源供电。

它的工作电压范围2.0~5.5V,在2.2V时,小于300nA。

基于51 单片机的温度采集系统设计

基于51 单片机的温度采集系统设计

1引言温度与人们的生产生活密切相关,传统的温度采集方法不但费时费力,而且精度差,可靠性也得不到保证,早已满足不了现在各行各业对温度测量的要求[1]。

单片机和温度传感器的出现和运用使得人们对温度的采集和处理方式得到了极大的革新,选取和应用合适的单片机和温度传感器能够提高温度的测量精度和可靠性。

本文基于AT89C51单片机设计的温度采集系统可实时采集环境温度,性能稳定可靠,成本低廉,使用便捷。

2温度采集系统的硬件设计本文设计的温度采集系统利用AT89C51单片机作为数据处理和控制单元,整个电路由温度采集系统模块、单片机控制模块、报警警告模块、温度显示模块和键盘输入模块组成。

首先,温度传感器DS18B20[2]将采集到的温度通过控制总线输入单片机,完成对外界温度的采集;其次,51单片机对接收的温度数据进行分析处理,驱动数码管显示温度信息;最后,把当前环境温度值与使用外部输入键盘设置的上限和下限温度值进行比较,在环境温度超过设定值时触发警报装置进行报警。

温度采集系统框图如图1所示。

图1温度采集系统框图3温度采集系统的软件设计温度采集电路开启运行后,系统将执行温度采集、对采集到的温度值进行处理、超限度警报、键盘输入上下限值和温度显示五项功能。

利用DS18B20将环境温度转化为电信号,然后将采集的温度信号送入单片机处理,进而判断温度的正负值并将温度值和用户设置的温度上下限值进行比较,【基金项目】陕西省自然科学基础研究计划资助项目(2019JQ-493)。

【作者简介】吴迎春(1979-),女,河南唐河人,讲师,从事电子技术研究。

基于51单片机的温度采集系统设计Design of the Temperature Acquisition System Based on 51Single Chip Microcomputer吴迎春,曾利霞(咸阳师范学院物理与电子工程学院,陕西咸阳712000)WU Ying-chun,ZENG Li-xia(College of Physics &Electronic Engineering,Xianyang Normal University,Xianyang 712000,China)【摘要】论文利用AT89C51单片机和DS18B20温度传感器设计了一款能够实现对环境温度进行实时采集并当环境温度超过设定值时进行自动报警的温度采集系统。

51单片机的温度和时间显示源程序

51单片机的温度和时间显示源程序
}
}
uintget_tem()
{
uchartem_L,tem_H;
DS18B20_init();
delay(1);
temwritebyte(0xcc); //写跳过ROM指令;
temwritebyte(0xbe); //读数据
tem_L=temreadbyte();
tem_H=temreadbyte();
write_1602dat('E');
break;
case 3:write_1602dat('W'); //星期数据为3时显示
write_1602dat('E');
write_1602dat('D');
break;
case 4:write_1602dat('T'); //星期数据为4是显示
write_1602dat('H');
tem=tem_H<<8|tem_L;
f_tem=tem*0.0625;
tem=f_tem;//*10+0.5;****好啊家0.5缩小误差;
return (tem);
}
/********液晶写入指令函数与写入数据函数,以后可调用**************/
write_1602com(ucharcom) //****液晶写入指令函数****
dat=0;
for(i=0;i<8;i++)
{
j=temreadbit() ;
dat=;
}
return(dat);
}
voidtemwritebyte(ucharinstru)

51单片机的多路温度采集系统程序

51单片机的多路温度采集系统程序ORG 0000HAJMP MAIN;BUF EQU 40H ;显示缓冲区MOTATA EQU 50H ;AD0809数据存放于此WH EQU 48H ;温度上限数据存放区WL EQU 58H ;温度下限数据存放区BUFF1S EQU 38H;BUFF1MS EQU 39H;BUFF5S EQU 3AH;INNAL EQU 3CH;ALARMBUF EQU 33HBUFFH EQU 31H ;八路LED报警信号红灯BUFFL EQU 32H ;八路LED报警信号绿灯BACK EQU 34H ;利用与BUF地址的重复修改路数CHANNEL EQU 35HTEMPBUF EQU 36HREAD_AD BIT 30H ;是否要读写AD0809的标志位DISPIN BIT 31H;SETWARN BIT 32HSOLIDISP BIT 33HENTER BIT P1.2SETH BIT 35HSETL BIT 36HSETIN BIT P1.3ABYTEIN BIT p1.1ORG 0003HAJMP INT_0;ORG 000BHLJMP INT_T0ORG 0100HMAIN: MOV SP, #70H ;设置堆栈位置SETB READ_AD ;初始化标志位SETB EA ;开总中断CLR SETWARN ;清除温度设置标志位SETB SETIN ;当其为0时表示要进行通道数采集LCALL INITWARN ;初始化温度上下限LCALL INIT_2 ;初始化2#工作寄存器区;主循环,启动ADC0809,从第一个通道开始读取LOOP: JNB READ_AD,DIS ;若不读AD0809,则调显示,次标志位也表示1s延时结束;延时已完毕,则计算要显示的温度路数及温度值送缓冲区LCALL WARN ;报警CLR READ_AD ;清楚标志位LCALL READ ;读取一次AD0809LCALL DLY1MS ;此处加1ms的延时,否则数码管会因中断的存在而产生闪动 LCALL ADJUST ;调整显示;在此完成键盘检测及显示任务DIS: LCALL DISPLAY;LCALL KEYCHK ;调键盘检测子程序CJNE A,#0FFH, AKEY ;若有键按下,则跳转LJMP LOOP ;若没有则循环AKEY: LCALL KEYFUNC;CJNE A,#0FFH,CALLRPD ;验证按下的键是否为数字键,若是则处理输入LJMP LOOP ;不为数字键则返回循环CALLRPD: LCALL KEYRPD;SJMP LOOP;;*********初始化2#工作寄存器区************INIT_2: PUSH PSW ;初始化2号工作寄存器区SETB RS1;CLR RS0 ;选择2号工作寄存器区MOV R2, #00H ;存放要显示的路数CLR DISPIN ;初始化路显示标志位;MOV R0, #MOTATA ;R0充当指向MOTATA的指针POP PSW;RET;;*******调整指针*********PADJUST:ONADJUST: DJNZ R2,INADJUST;RET;返回INADJUST: INC R0;SJMP ONADJUST;;*************计算并调整显示缓存区的数据*******ADJUST: PUSH PSW ;保护SETB RS1;CLR RS0 ;选择2号工作寄存器区CJNE R2,#08H,NE08;GE08: MOV R2,#00H;MOV R0,#MOTATA;SJMP LESS08;NE08: JNC GE08;LESS08: JB SETWARN, DISPWARN ;若在设定温度,则也不调整显示JB SOLIDISP, ADJEND ;若为固定显示,则跳过调整JB DISPIN,DLY_5S ;若有键盘值输入,则延时5秒来暂时固定显示INC R0 ;调整R0,使其指向下一个要显示的温度值地址 INC R2 ;调整R2mov channel,r2;SJMP ADJEND;DLY_5S: DJNZ BUFF5S,ADJEND;CLR DISPIN;LJMP ADJENDDISPWARN: JB SETH,DISHIGH ;若在调整上限值则跳转到上限温度显示JB SETL,DISLOW ;若在调整下限值则跳转到下限温度显示SJMP ADJEND ;若不在调整则显示输入路数的当前检测温度值DISLOW: MOV R0,#WL ;将指针调整到温度上限存放区SJMP ADAPT ;跳转到指针调整处DISHIGH:MOV R0,#WH ;将指针调整到温度下限存放区ADAPT: MOV R2,CHANNEL ;调整R2的值为通道数LCALL PADJUST ;指针指向R2 ADJEND: LCALL LOADTEMP ;将当前指针指向数据放到缓冲区POP PSW;RET;;**************** 将当前指针指向数据放到缓冲区******** LOADTEMP: LCALL COMPUTE ;调用COMPUTE得到要显示的当前温度值MOV R1,#BUF;MOV A,channel;MOV @R1,A ;将路数送入显示缓冲区INC R1 ;调整到要显示温度值的缓冲区JB SETH,DISPH ;若设定温度上限,则显示HJB SETL,DISPL ;若设定温度下限,则显示LMov a,#10h ;消隐SJMP DISP2DISPH: MOV A,#11HSJMP DISP2DISPL: MOV A,#12HDISP2: mov @r1,a;INC R1;MOV A,R5;ANL A,#0FH;MOV @R1,A ; 最低位 INC R1;MOV A,R5;ANL A,#0F0H;SWAP A;MOV @R1,A ;次低位 ,应当在此处添加小数点INC R1;MOV A,R4;ANL A,#0FH;MOV @R1,A ;次高位 INC R1;MOV A,R4;ANL A,#0F0H;SWAP A;MOV @R1,A ;最高位RET;;*************读取一次0809的内容***********READ: MOV R6,#08H ;用中断的方式读取一次AD0809MOV R0,#MOTATA ;0号工作寄存器区MOV DPTR,#0FFFEH ;A0作为地址MOV A,#00H ;表示先检测第一个通道MOV INNAL,A ;将检测的路数保存MOVX @DPTR,A ;开启ADC0809 SETB EX0 ;开外部中断0RET ;若已读取完毕,则返回;**********************显示子程序************;要显示的数据入口为BUF(6位);1号工作寄存器区DISPLAY: PUSH PSW ;压栈保护SETB RS0;CLR RS1 ;切换工作寄存器区到 1MOV R0,#BUFMOV R7,#06HMOV R1,#01HNEXTDIS: MOV A,@R0MOV DPTR,#TABLEMOVC A,@A+DPTR ;取段码CJNE R7,#03H,NODIP ;显示小数点ANL A,#07FHNODIP: MOV DPTR,#0FFDCHMOVX @DPTR,A ;送段码MOV DPTR,#0FFDDHMOV A,R1MOVX @DPTR,A ;送位码RL AMOV R1,ALCALL DLY1MSINC R0 ;调整显示DJNZ R7,NEXTDIS;POP PSW;RET;**************************延时1ms****************************DLY1MS: MOV BUFF1MS,#0F9HDJNZ BUFF1MS,$RET;*************************按键检查子程序******************** KEYCHK:MOV A,#00H ;查看是否有键按下MOV DPTR,#0FFDDHMOVX @DPTR,AMOV DPTR,#0FFDEHMOVX A,@DPTRCPL AANL A,#0FHJNZ TEST ;若有键按下则检测,无则返回。

基于51单片机的温湿度DHT11采集

一、设计目的温湿度控制系统早已经成为当今社会研究的热门领域之一,同时温湿度也是现今工农业生产生活中必须要首先考虑的重要因素之一。

因此现今社会生产生活中就迫切需要一种价格廉价、容易操作而且精确度高的温湿度控制系统。

本系统设计就是利用AT89C52单片机对温湿度参量进行检测进而实现对温湿度参量的控制。

本系统设计通过使用AT89C52单片机、DHT11传感器模块、LCD1602液晶显示屏模块以及LED闪烁和蜂鸣器报警模块。

简单的系统设计就可以根本上满足本系统设计的系统设计要求。

DHT11数字温湿度传感器负责把采集到的温湿度信号传送给AT89C52单片机。

温湿度经过AT89C52单片机处理,然后AT89C52准确地把温湿度信号发送到LCD1602液晶显示屏模块,温湿度数据就可以准确地显示到LCD1602液晶屏上面,同时我们可以分别对温度和湿度设置上下限,越限LED闪烁和蜂鸣器报警模块。

二、设计要求和方案选择•LCD1602能够实时、准确的显示AT89C52采样温度值和湿度值,显示设定报警的温度和风扇的状态。

•DHT11采集温度及湿度值,AT89C52能够将DHT11输送过来的采集信息,准确的判断标准值与设定值之间的差异,及时的启动报警装置〔LED闪烁和蜂鸣器〕进行报警。

•根据采集温湿度的数据进行判断,控制继电器进行风扇的开闭传感器选择方案•方案一:利用两个传感器分别检测温度和湿度值,温度检测模块选用DS18B20温度传感器(+-0.5℃)。

湿度检测模块选用HS1101电容式湿度传感器(+-5%RH)。

这两款传感器都是我们大学实践电子设计中非常常见和常用的传感器。

•方案二:检测温湿度数值选用DHT11传感器作为系统设计的温湿度检测模块。

DHT11传感器能够同时对温度和湿度数值进行检测,而且其精确度能过完全满足本课程设计的精度要求。

湿度、温度测量误差:+-5%、+-2度•经过上述分析,方案一虽然精度更精确。

51单片机温度采集与显示设计

51单片机温度采集与显示设计前言在现代科技快速发展的时代,物联网技术已经深入各行各业,其广泛应用促使了传感器技术的日益普及。

而温度传感器作为一种常用的传感器类型,广泛应用于环境监测、工业自动化以及生活中的智能家居等领域。

本文将介绍如何利用51单片机进行温度采集与显示的设计。

一、硬件设计1.1 温度传感器选择在温度传感器的选择方面,我们可以根据不同的应用需求选择不同类型的传感器。

例如,当我们需要测量较高温度范围时,可以选择热电偶传感器;而当需要测量精度较高的低温范围时,可以选择PT100温度传感器。

根据具体应用需求选择合适的温度传感器非常重要。

1.2 电路设计对于51单片机温度采集与显示设计,我们需要设计一个简单的电路来连接温度传感器和单片机。

电路主要包括温度传感器、AD转换芯片以及显示模块。

具体电路连接关系如下图所示:(图略)二、软件设计2.1 单片机编程环境搭建在进行51单片机编程之前,我们需要搭建相应的编程环境。

常用的51单片机编程软件有Keil MDK等,我们根据实际情况选择适合自己的编程软件,并进行相应的安装和配置。

2.2 代码编写在代码编写方面,我们可以利用C语言编写相应的程序来实现温度采集与显示的功能。

首先,我们需要初始化相应的引脚和寄存器,配置AD转换芯片以及显示模块。

接着,我们可以借助单片机的AD转换功能获取温度传感器的电压信号,并通过相应的算法将电压转换为温度数值。

最后,将获取到的温度数值通过显示模块展示出来。

三、实验结果与应用3.1 实验结果通过实验,我们成功地设计出了一个基于51单片机的温度采集与显示系统。

系统可以准确地采集温度传感器的信号,并将温度数值以数字形式显示在屏幕上。

通过对比实际温度和显示数值,可以发现系统具有较高的测量精度和稳定性。

3.2 应用前景基于51单片机的温度采集与显示系统可以广泛应用于各个领域。

在工业自动化中,可以用于实时监测设备的温度,并及时采取措施以防止设备过热。

基于51单片机的温度数据采集程序

/*基于51单片机的温度数据采集程序*/ #include <reg52.h>#include <intrins.h>#define uint unsigned int#define uchar unsigned charuchar set_up; //温度设定值uint temper;sbit FM=P2^3; //蜂鸣器报警sbit DQ=P2^4;sbit dula=P2^6; //数码管段选sbit wela=P2^7; //数码管位选sbit key1=P3^4; //按键sbit key2=P3^5;sbit key3=P3^6;sbit key4=P3^7;uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};void delay(uint z) //延时函数1ms{uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}void delay_reset(uint t) //延时函数11us{for(;t>0;t--);}void DS18B20_reset(void) //DS18B20初始化函数{bit flag=1;while (flag){while (flag){DQ = 1;delay_reset(1);DQ = 0;delay_reset(50); // 延时550usDQ = 1;delay_reset(6); //延时66usflag=DQ;}delay_reset(45); //延时500usflag=~DQ;}DQ=1;}void write_byte(uchar val) //DS18B20写一个字节函数{uchar i;for (i=0; i<8; i++){DQ = 1;_nop_();DQ = 0;_nop_();_nop_();DQ = val & 0x01; //最低位移出delay_reset(6);val >>= 1; //右移一位}DQ = 1;delay_reset(1);}uchar read_byte(void) //DS18B20读一个字节函数{uchar i,value=0;for (i=0; i<8; i++){DQ=1;_nop_();value >>= 1;DQ = 0;_nop_();_nop_();DQ = 1;_nop_();_nop_();if (DQ)value|=0x80;delay_reset(6); //延时66us }DQ=1;return(value);}void display(uchar temp) //数码管显示函数{uchar bai,shi,ge;bai = temp/100; //百位shi= temp%100/10; //十位ge= temp%10; //个位dula=1;P0=table[bai];dula=0;P0=0xff;wela=1;P0=0xfe;wela=0;delay(1);dula=1;P0=table[shi];dula=0;P0=0xff;wela=1;P0=0xfd;wela=0;delay(1);dula=1;P0=table[ge];dula=0;P0=0xff;wela=1;P0=0xfb;wela=0;delay(1);}uint Get_Tem() //获取温度函数{uchar a,b;DS18B20_reset(); //初始化write_byte(0xCC); //忽略ROM指令write_byte(0x44); //温度转换指令delay(500); // 等待温度转换完成DS18B20_reset(); //初始化write_byte(0xCC); //忽略ROM指令write_byte(0xBE); //读暂存器指令a = read_byte(); //读取到的第一个字节为温度LSBb = read_byte(); //读取到的第一个字节为温度MSBtemper=b; //先把高八位有效数据赋于tempertemper<<= 8; //把以上8位数据从temper低八位移到高八位temper=temper|a; //两字节合成一个整型变量temper=temper*0.0625; //得到真实十进制温度值return temper;}void keyscan() //按键扫描函数{if(key1==0) //调节设定值键{delay(10); //按键去抖if(key1==0)display(set_up);while(!key1); //直到按键释放,否则不退出循环while(key4) //判断有无返回键按下{if(key2==0) //设定值加1键{delay(10);if(key2==0){if(set_up>=125)set_up=0;elseset_up++;}while(!key2);display(set_up);}if(key3==0) //设定值减1键{delay(10);if(key3==0){if(set_up==0)set_up=125;elseset_up--;}while(!key3);display(set_up);}}if(key4==0) //返回键{delay(10);if(key4==0)display(Get_Tem());}while(!key4);}}main(){while(1){keyscan();if(Get_Tem()>=set_up) //温度超过设定值报警FM=0;elseFM=1;display(Get_Tem()); //显示实时温度}}。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
《单片机应用技术实例教程(C51版)》
--高等院校嵌入式人才培养规划教材
第11章 51单片机的温度和时 间采集模块
本章主要内容
11.1 在51单片应用系统中获取温度 11.2 DS18B20温度传感器 11.3 51单片机的时间采集通道 11.4 并行总线接口时钟模块DS12C887 11.5 应用案例11.1-多点温度采集系统的实现 11.6 应用案例11.2-简单数字时钟的实现 11.7 本章总结
前一页
11.4.2 DS12C887的电路
DS12C887的应用电路如图11.14所示,51单片机的P0端口作为数据/地址总线连接到 DS12C887的数据/地址总线,DS12C887的MOT引脚直接连接到地选择Intel总线模式,/CS引 脚连接到51单片机的P2.7作为外部地址控制,同时使用单片机的ALE输出信号来控制 DS12C887的AS信号,单片机的WR和RD信号分别连接到DS12C887的R/W和DS引脚, DS12C887的中断信号引脚/IRQ通过一个上拉电阻连接到51单片机的INT0引脚上,如下图所示 的DS12C887的地址为0x7FFF~0x807F。
前一页
首页
11.4 并行总线接口时钟模块 DS12C887
11.4.1 DS12C887基础 11.4.2 DS12C887的电路 11.4.3 DS12C887的操作步骤和驱动函数
前一页
首页
11.4.1 DS12C887基础
DS12C887模块由内部控制寄存器、日期时间寄存器、时间日期技术电路等组成,具有以下特点。 ●内置晶体振荡器和锂电池,可以在无外部供电的情况下保存数据10年以上。 ●具有秒、分、时、星期、日、月、年计数,并有闰年修正功能。 ●时间显示可以选择24小时模式或者带有“AM”和“PM”指示的12小时模式。 ●时间、日历和闹钟均具有二进制码和BCD码两种形式。 ●提供闹钟中断、周期性中断、时钟更新周期结束中断,3个中断源可以通过软件编程进行控制。 ●内置128字节RAM,其中15字节为时间和控制寄存器,113字节可以用作通用RAM,所有 RAM单元都具有掉电保护功能,因此可被用作非易失性RAM。 ●可以提供可输出可编程的方波信号。 DS12C887芯片的内部带有时钟、星期和日期等信息寄存器,实时时间信息就存放在这些非易失 寄存器中,与51单片机一样,DS12C887采用的也是8位地址/数据复用的总线方式,它同样具有 一个锁存引脚,通过读、写、锁存信号的配合,可以实现数据的输入输出:控制DS12C887内部 的控制寄存器、读取DS12C887内部的时间信息寄存器。DS12C887的各种寄存器在其内部空间 都有相应的固定地址,因此,单片机通过正确的寻址和寄存器操作就可以获取所需要的时间信 息。 表11.8(详见教材)是DS12C887的控制寄存器A的内部结构示意。 表11.9 (详见教材)是DS12C887的控制寄存器B的内部结构示意。 表11.10 (详见教材)是DS12C887的控制寄存器C的内部结构示意。 表11.11 (详见教材)是DS12C887的控制寄存器D的内部结构示意。
多点温度采集模块中涉及的典型器件说明图表11.12(详见教材)所示。 前一页
11.5.3多点温度采集系统的应用代码
多点温度采集系统的应用代码设计的重点是如何实现对同一条1-wire 总线上多个DS18B20的数据进行读取,其软件可以分为DS18B20驱 动函数模块和1602液晶显示驱动模块两个部分。 多点温度采集系统的DS18B20驱动函数和例11.1中所介绍的有所区别, 它包括了初始化函数void Initialization(),向DS18B20写入一个字节的 函数void WriteByte(unsigned char btData),从DS18B20读出一个字 节的函数unsigned char ReadByte(),ROM匹配函数void MatchROM(const unsigned char *pMatchData)和温度读取函数 TEMPDATA ReadTemperature(),其中最关键的函数是TEMPDATA ReadTemperature,其流程如右图所示。 在例11.3所示的应用代码中, 定义了一个结构体tagTempData用于存放当前的温度输出,为了便于 显示,把温度数据数据都拆开存放到结构体中。 【例11.3】多点温度采集系统的应用代码。(实例代码详见教材) 【例11.4】多点温度采集系统对应的C51语言代码。(实例代码详见 教材)
前一页
11.6.2简单数字时钟的电路结构
数字时钟的电路如下图所示,51单片机使用P0口和DS12C887进行数据交互,使用P2.0~P2.3 作为DS12C887的控制引脚;同时使用P1引脚扩展了一个1602液晶模块用于显示时间信息。
前一页
11.5.2多点温度采集系统的电路结构
多点温度采集系统硬件设计的重点是如何和多个DS18B20进行数据交互获得当前的温度。多点 温度采集系统的电路如下图所示,51单片机使用P1端口和P2.0~P2.2引脚扩展了一片1602液晶 作为多点温度采集系统的显示模块,使用P2.7引脚模拟1-wire总线时序扩展了8个DS18B20提 供温度数据。
前一页
11.5 应用案例11.1-多点温度采 集系统的实现
11.5.1多点温度采集系统的设计 11.5.2多点温度采集系统的电路结构 11.5.3多点温度采集系统的应用代码
前一页
首页
11.5.1多点温度采集系统的设计
设计多点温度采集系统,需要考虑如下几个方面的内容。 ●需要1个能将温度数据转换为采集数据的传感器,其相关指标必须符合采集系统的需求: 由于8个采集点都在10m范围之内,采集温度范围又在-30~+50℃,并且精度只有0.5℃, 所以可以采用1-wire接口的数字温度传感器DS18B20。 ●需要1个能显示温度数据的显示模块:由于只需要显示简单的字符和数字,所以可以使 用1602液晶模块完成相应的工作。 ●51单片机通过何种方式来和传感器进行数据交互:DS18B20数字温度传感器提供了1wire总线接口,51单片机可以使用普通I/O引脚模拟相应的总线时序和传感器进行通信。 ●需要设计合适的单片机软件。
前一页
首页
11.2 DS18B20温度传感器
11.2.1 DS18B20基础 11.2.2 DS18B20的电路 11.2.3 DS18B20的操作步骤和驱动函数
前一页
首页
11.2.1 DS18B20基础
DS18B20的主要特点如下。 ●具有3~5.5V很广范围工作电压,并且可以使用寄生电容供电的方式,此时只需要在数据线 上连接一个电容即可完成供电。 ●所有的应用模块都集中在一个和普通三极管大小相同的芯片内,使用过程中不需要任何外 围器件。 ●可测量温度区间为-55~125℃,其中在-10~85℃的区间内测量精度为0.5℃。 ●测量分辨率可以设置为9位~12位,对应的最小温度刻度为0.5℃、0.25℃、0.125℃和 0.0625℃; 图11.5 DS18B20的实物示意 ●在9位精度时候转化过程仅耗时93.75ms,在12位精度时则需要750ms; ●支持在同一条1-wire总线上挂接多个DS18B20器件形成多点测试,在数据传输过程中可以 跟随CRC校验。 DS18B20主要由内部ROM、温度传感器、高速缓存以及数据接口4个模块组成,如下图所示。
前一页
11.1在51单片应用系统中获取温度
在51单片机应用系统中获取温度信号的方法通常有如下两种。 ●使用数字温度传感器采集:通常利用两个不同温度系数的晶振控制两个计数器进行计数,利 用温度对晶振精度影响的差异测量温度。 ●使用PT铂电阻采集:利用PT金属在不同温度下的电阻值不同的原理来测量温度。 需要注意的是,PT铂电阻根据温度变化的其实只是其电阻值,所以在实际使用过程中需要额外 的辅助器件将其转化为电压信号并且通过调整后送到模拟—数字转化器件才能让51单片机处理, 其组成如下左图所示。 而数字温度传感器在实际使用中则直接和51单片机连接即可,如下右图所示,其具有体积小、 电路简单的优势,但是数字温度传感器通常对安装位置有要求,例如,不能将其贴在被加热物 体(如锅炉)的外壁上。
前一页
11.2.3 DS18B20的操作步骤和驱动函数
51单片机使用普通I/O引脚模拟1-wire总线时序扩展DS18B20的操作步骤如下。 (1)复位1-wire总线。 (2)根据1-wire总线上挂接的器件情况发送匹配或者跳过ROM命令。 (3)设置需要采集温度的上下限区间。 (4)设置采样精度。 (5)启动采集并且等待完成之后读取温度数据。 例11.1是51单片机使用普通I/O引脚模拟1-wire总线时序扩展DS18B20的驱动函数,其中调用 了第9章的9.3.3小节中介绍的1-wire总线驱动函数,提供了用于DS18B20初始化的 DS18b20_int函数和用于从DS18B20读取温度数据的函数DS18b20_readTemp。 【例11.1】DS18B20的驱动函数。 (实例代码详见教材)
前一页
11.4.3 DS12C887的操作步骤和驱动函数
51单片机使用地址—数据总线扩展DS12C887的操作步骤如下。 (1)根据外部扩展方法计算出DS12C887的内部地址单元和寄存器的地址。 (2)使DS12C887进入设置模式,设置初始时钟信息。 (3)根据需要设置相关的闹钟或者输出波形信息。 (4)读取相关的时钟信息。 例11.2是51单片机使用地址—数据总线扩展DS12C887的驱动函数,应用代码首先定义了 DS12C887的命令常数,然后使用_at_关键字定义了DS12C887的内部寄存器地址,提供了如 下函数用于对DS12C887进行操作。 【例11.2】DS12C887的驱动函数。 (实例代码详见教材)
前一页
11.3 51单片的时间采集通道
时间传感器是指能给51单片机的应用系统提供当前时间和日期信息的模块,比起使用51单片机 内置的定时计数器来实现软件定时,时间传感器具有不占用单片机内部资源(需要占用引脚)、 软件相对简单、时间精度较高和掉电不会丢失数据的优点。 单片机应用系统通常使用如下3种方式来获得时间信息。 ●使用单片机的内部定时器进行定时,使用软件算法来计算当前的时间信息。 ●从专用的实时时钟芯片来获取当前的时间信息,实时时钟芯片RTC(Real Time Clock)是 一种可以自行对当前时间信息进行计算并且可以通过相应的数据接口将时间信息输出的芯片。 ●从GPS模块获取当前的实际时钟信息。 这3种方法的优缺点如表11.7(详见教材)所示。
相关文档
最新文档