内容:以AT89C51单片机为核心,设计一个具有实时时钟功能和温度测量功能的智能化测量仪器。要求具有实时时钟显示和校时功能,温度测量显示功能等。 硬件主要包括DS12887实时时钟电路、555转换电路、8只共阳LED数码管及相应的显示控制和驱动电路、键盘电路等。 编写相程序,编程并控制DS12887芯片,获得日期和时间值;利用按键可实现日期和时间初值的设置,以及测量值、日期和时间的显示切换功能;根据温度与频率的关系显示温度。 做得不好,多包涵。
原理图:
单片机源程序:
- #include <reg51.h>
- #include <stdio.h>
- #include <math.h>
- #include <absacc.h>
- #define uchar unsigned char
- #define uint unsigned int
- #define sec XBYTE[0x7f00]
- #define seca XBYTE[0x7f01]
- #define min XBYTE[0x7f02]
- #define mina XBYTE[0x7f03]
- #define hour XBYTE[0x7f04]
- #define houra XBYTE[0x7f05]
- #define day XBYTE[0x7f06]
- #define date XBYTE[0x7f07]
- #define month XBYTE[0x7f08]
- #define year XBYTE[0x7f09]
- #define A XBYTE[0x7f0A]
- #define B XBYTE[0x7f0B]
- #define C XBYTE[0x7f0C]
- #define D XBYTE[0x7f0D]
- uchar wendu[8];/*温度数组*/
- uchar show[4][8];/*显示数组,第一行存储年月日数据,第二行存储时分秒数据,第三行存储温度和频率数据,第四行存储农历年月日数据*/
- uchar Buffer[8];/*中间寄存器*/
- uchar weixuan;
- uchar page=0;/*显示页面选择*/
- uchar shanshuo=0;/*闪烁标志位 初始为不闪烁状态*/
- uint nsec,nmin,nhour,nday,ndate,nmonth,nyear;/*更新后时间*/
- uint lyear,lmonth,ldate;/*农历年月日*/
- uint t1_num,frequency,tempture;/*定时次数 频率 温度*/
- uint s3_num=0;/*闪烁(修改)位置选择*/
- sbit s2=P1^5;
- sbit s3=P1^6;
- sbit s4=P1^7;
- sbit P3_5=P3^5;/*对T1引脚定义*/
- sbit key_on=P3^3;/*对INT1引脚定义*/
- uchar code table[13]={ /*数码管段码*/
- 0x03,0x9f,0x25,0x0d,0x99,0x49,
- 0x41,0x1F,0x01,0x09,0xff,0x39,0x63
- };
- void delay(uint z);/*延时函数*/
- void DS12887_init();/*时钟芯片初始化函数*/
- void DS12887_read();/*读时钟芯片函数*/
- void DS12887_write();/*写时钟芯片函数*/
- void change();/*数据处理函数*/
- void display();/*位选及显示函数*/
- void T0andT1_init();/*定时器T0,T1初始化函数*/
- void int0_init();/*INT0初始化函数*/
- void int1_init();/*INT1初始化函数*/
- void key_service();/*按键服务函数*/
- void flash();/*闪烁函数*/
- void add();/*加1函数*/
- void nongli();/*农历处理函数*/
- void LED_duan(uchar i);/*段选函数*/
- void main()
- {
- uint n;
- DS12887_init();/*时间初始化*/
- DS12887_read();
- int0_init();
- T0andT1_init();
- int1_init();
-
- while(1)
- {
- change();
- display();
- nongli();
- n++;
- if(n==20)
- {
- shanshuo=!shanshuo;
- n=0;
- }/*当循环20次时,闪烁标志位取反,即修改位置的数码管能正常显示对应段码*/
- }
- }
- /*初始化DS12887*/
- void DS12887_init()
- {
- B=0x92;/*禁止芯片内部的更新周期操作*/
- A=0x20;/*初始化A寄存器*/
- sec=0x00;
- min=0x30;
- hour=0x08;
- day=0x04;
- date=0x08;
- month=0x06;
- year=0x17;/*写入初始时间和日期 2017年6月8日周四 8点30分0秒*/
- ACC=C;
- ACC=D;/*通过读寄存器来清零标志位*/
- B=0x12; /*24小时制,BCD码输出,更新中断允许,芯片工作*/
- }
- /*读DS12887*/
- void DS12887_read()
- {
- nsec=(sec/16)*10+sec%16;
- nmin=(min/16)*10+min%16;
- nhour=(hour/16)*10+hour%16;
- nday=(day/16)*10+day%16;
- ndate=(date/16)*10+date%16;
- nmonth=(month/16)*10+month%16;
- nyear=(year/16)*10+year%16;
- }
- /*写DS12887*/
- void DS12887_write()
- {
- sec=(nsec/10)*16+nsec%10;
- min=(nmin/10)*16+nmin%10;
- hour=(nhour/10)*16+nhour%10;
- day=(nday/10)*16+nday%10;
- date=(ndate/10)*16+ndate%10;
- month=(nmonth/10)*16+nmonth%10;
- year=(nyear/10)*16+nyear%10;
- }
- /*延时函数*/
- void delay(uint z)
- {
- uint x,y;
- for(x=z;x>0;x--)
- for(y=110;y>0;y--);/*延时z ms*/
- }
- /*时间数据处理*/
- void change()
- {
- show[0][0] = 2;
- show[0][1] = 0;
- show[0][2] = nyear/10;
- show[0][3] = nyear%10;
- show[0][4] = nmonth/10;
- show[0][5] = nmonth%10;
- show[0][6] = ndate/10;
- show[0][7] = ndate%10;
- show[1][0] = nhour/10;
- show[1][1] = nhour%10;
- show[1][2] = nmin/10;
- show[1][3] = nmin%10;
- show[1][4] = nsec/10;
- show[1][5] = nsec%10;
- show[1][6] = 10;
- show[1][7] = nday%10;
- show[2][0] = wendu[0];
- show[2][1] = wendu[1];
- show[2][2] = wendu[2];
- show[2][3] = wendu[3];
- show[2][4] = wendu[4];
- show[2][5] = wendu[5];
- show[2][6] = wendu[6];
- show[2][7] = wendu[7];
- show[3][0] = 2;
- show[3][1] = 0;
- show[3][2] = lyear/10;
- show[3][3] = lyear%10;
- show[3][4] = lmonth/10;
- show[3][5] = lmonth%10;
- show[3][6] = ldate/10;
- show[3][7] = ldate%10;
- }
- /*段选函数*/
- void LED_duan(uchar i)
- {
-
- SBUF=table[i];/*段码值先存入缓冲寄存器中*/
- delay(1);/*数据串口传输时间*/
- TI=0;/*数据发送完毕,数据串口传输位清零*/
- }
- /*位选及显示函数*/
- void display()
- {
- uchar i;
- weixuan=0xfe;
- for(i=0;i<8;i++)
- {Buffer[i]=show[ page][i];}
- flash();
- for(i=0;i<8;i++) /*每次左移选通一位*/
- {
-
- P1=weixuan;
- LED_duan(Buffer[i]);
- weixuan=weixuan<<1; /*位选择,左移一位*/
- weixuan=weixuan|0x01;
- if(weixuan==0xff)
- weixuan=0xfe;
-
- }
-
- }
- /*外部中断0初始化*/
- void int0_init()
- {
- SCON = 0x00;/*串口使用方式0*/
- IT0 = 0;/*外部中断0的中断触发方式控制位*/
- EX0 = 1;/*INT0开启*/
- EA = 1;/*CPU开中断*/
- }
-
- void int0_service() interrupt 0/*外部中断0更新中断*/
- {
- if(A==0x20)/*时钟信息可读*/
- {DS12887_read();
- ACC=C;}
- }
- void T0andT1_init()/*定时器初始化*/
- {
- SCON=0x00;/*串口工作方式0*/
- P3_5 = 0;/*选通温度采集*/
- TMOD=0x15;/*定时器1定时工作方式1,定时器0计数*/
- TH0=0;
- TL0=0;/*计数器装载初值*/
- TH1=(65536-50000)/256;
- TL1=(65536-50000)%256;/*0.05s 定时器装载初值*/
- TR1=1;
- TR0=1;/*定时器启/停控制位置1*/
- ET1=1;/*定时器1溢出中断允许位*/
- EA=1;/*中断允许总控制位*/
-
- }
- /*定时器中断,采集温度处理*/
- void t1_wendu(void) interrupt 3
- {
- TR0=0;/*先让T0、T1停止工作*/
- TR1=0;/*启停控制位*/
- P3_5=0;/*选通温度采集*/
- t1_num++;
- if(t1_num==20)/*定时1s*/
- {
- t1_num = 0;
- frequency=TH0*256+TL0; /*计数*/
- tempture=(frequency)*11/62-113; /*温度值转化显示数值*/
- wendu[0] = tempture/10;
- wendu[1] = tempture%10;
- wendu[2] = 11;
- wendu[3] = 12;/*摄氏度符号*/
- wendu[4] = frequency/1000;
- wendu[5] = frequency%1000/100;
- wendu[6] = frequency%1000%100/10;
- wendu[7] = frequency%1000%100%10;
- TH0=TL0=0;
- }
- TH1=(65536-50000)/256;
- TL1=(65536-50000)%256;/*定时器重新装载初值*/
- TR0=1;
- TR1=1;
- }
- void int1_init()
- {
- SCON = 0x00;/*串口使用方式0*/
- IT1 = 0;/*外部中断1的中断触发方式控制位*/
- EX1 = 1;/*INT1开启*/
- EA = 1;/*CPU开中断*/
- }
-
- void int1_service() interrupt 2/*外部中断1判断是否有键按下*/
- {
- if(key_on == 0)/*有键按下时执行程序*/
- {
- delay(10);/*延时10ms,按键消除抖动*/
- if(key_on == 0)
- {
- key_service();
- key_on= 1;
- while(key_on == 0);
- }
- }
- }
- void key_service()/*按键服务程序*/
- {
- if(s2==0)
- {
- page=(page+1)%4; /*page变量代表数码管要显示的内容 page=0数码管显示年月日 page=1数码管显示时分秒 page=2数码管显示温度和频率 page=3数码管显示农历的年月日*/
-
- }
- if(s3==0)
- {
- s3_num++;/*8个数码管两两分为4组 s3_num代表闪烁位位置*/
- if(s3_num==5)
- s3_num=0;/*不选中数码管*/
- }
- if(s4==0)
- {
- add();
- }
- }
- /*闪烁函数*/
- void flash()
- {
-
- if((s3_num!=0)&&(page!=2)&&shanshuo==0)
- {
- Buffer[(s3_num-1)*2]=10;
- Buffer[(s3_num-1)*2+1]=10;/*对所选中位置的数码管给段码0xff(全灭)*/
- }
- }
- /*按键加1函数*/
- void add()
- {
- uint m,n,y,c,w,d;
- if(s4 == 0)/*修改数据程序*/
- {
- if(page==0)
- {
- switch(s3_num)
- {
- case 2: nyear++;
- m = nyear;
- if(m == 100)/*年变量达到100年*/
- {
- nyear=0;
- }
- DS12887_write();
- break;
- case 3: nmonth++;
- m = nmonth;
- if(m==13) /*月变量达到12*/
- {
- nmonth=1;
- }
- DS12887_write();
- break;
- case 4: ndate++;
- m = ndate;
- if(nmonth==1||nmonth==3||nmonth==5||nmonth==7||nmonth==8||nmonth==10||nmonth==12)
- {
- if(m==32) /*大月日变量达到32*/
- {
- ndate=1;
- }
- }
- if(nmonth==4||nmonth==6||nmonth==9||nmonth==11)
- {
- if(m==31) /*小月日变量达到31*/
- {
- ndate=1;
- }
- }
- if(nmonth==2)
- {
- if((nyear%4==0&&nyear%100!=0)||(nyear%400==0))/*闰年*/
- {
- if(m==30) /*闰年2月日变量达到30*/
- {
- ndate=1;
- }
-
- }
- else
- {
- if(m==29)/*非闰年2月日变量达到29*/
- ndate=1;
- }
- }
- DS12887_write();
- break;
- default: return;
-
- }
- /*利用蔡勒公式计算星期*/
- y=nyear;
- c=20;
- n=nmonth;
- d=ndate;
- if(n==1||n==2)
- {
- y--;
- n=n+12;
- }
- w=y+y/4+c/4-2*c+13*(n+1)/5+d-1;
- while(w<0)
- {w=w+7;}
- nday=w%7;
- if(nday==0)
- nday=7;}
- DS12887_write();/*通过此段程序可实现星期随年月日的改变而准确变化*/
- }
- else if(page==1)
- {
- switch(s3_num)
- {
- case 1: nhour++;
- m = nhour;
- if(m==24) /*小时变量达到24*/
-
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
全部资料下载地址:
智能仪表原理图.doc
(56 KB, 下载次数: 28)
新建 Microsoft Word 文档.docx
(19.47 KB, 下载次数: 50)
|