內容:以AT89C51單片機為核心,設計一個具有實時時鐘功能和溫度測量功能的智能化測量儀器。要求具有實時時鐘顯示和校時功能,溫度測量顯示功能等。 硬件主要包括DS12887實時時鐘電路、555轉換電路、8只共陽LED數碼管及相應的顯示控制和驅動電路、鍵盤電路等。 編寫相程序,編程并控制DS12887芯片,獲得日期和時間值;利用按鍵可實現日期和時間初值的設置,以及測量值、日期和時間的顯示切換功能;根據溫度與頻率的關系顯示溫度。 做得不好,多包涵。
原理圖:
0.png (216.19 KB, 下載次數: 80)
下載附件
2017-7-1 17:48 上傳
單片機源程序:
- #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)
2017-7-1 13:54 上傳
點擊文件名下載附件
原理圖 下載積分: 黑幣 -5
新建 Microsoft Word 文檔.docx
(19.47 KB, 下載次數: 50)
2017-7-1 13:55 上傳
點擊文件名下載附件
源程序 下載積分: 黑幣 -5
|