STC12C5A60S2+DS1302+DS18B20+LCD1602,晶振11.0592M
主要功能:時間溫度顯示,設置一個鬧表
溫度大于30度LED亮起,鬧表時間時分對應LED閃爍
4個按鍵分別對應設置、時間+、時間—、退出設置
鬧表時間保存于DS1302的RAM區。
開發中間遇到的主要問題:
一、STC12C5A60S2是1T的芯片,運行速度比89C52快,延時函數需要調整
二、DS1302模塊與STC12的連接線不能過長,調試過程開始線路過長,讀取模塊的結果會是0xff,各種找原因也不能解決,程序改得亂七八糟。各種百度各種改,最后看到一條有說線路過長可能是原因。最終對線路測量,兩段線電阻分別為0.4歐和0.5歐,長度分別為7cm和15cm,最終理論解決希望有大佬能夠幫忙解釋。
電路原理圖如下:

上圖是初始電路圖,圖中芯片為89C52,后改為STC12C5A60S2,個別細節
11.jpg (5.69 MB, 下載次數: 96)
下載附件
2021-3-24 19:07 上傳
1.jpg (5.23 MB, 下載次數: 65)
下載附件
2021-3-24 19:04 上傳
1.jpg (212.44 KB, 下載次數: 72)
下載附件
2021-3-24 21:34 上傳
上圖為最終結果
上圖上面箭頭為原來DS1302用排線連接位置,下面是最終位置
顯示全是????
單片機源程序如下:
- #include "STC12C5A60S2.H"
- #include <intrins.h>
- #include "delay.h"
- #include "lcd1602.h"
- #include "ds18b20.h"
- #include "ds1302.h"
- sbit led= P3^7;//led燈,替代蜂鳴器
- uchar count=0; //計時器計數
- uint temperature=0; //溫度,取實際溫度的10倍,輸出時最后一位前加小數點
- float ftempp; //浮點型溫度
- uchar *p1,*p2,*p3,*p4;//定義指針,分別對應日期,時間,芯片格式數據,設置光標位置
- uchar mdate[16];//用于顯示日期"20xx-xx-xx Mon."
- uchar mtime[9],ntime[6];//用于顯示時間"xx:xx:xx"和鬧表時間"XX:XX"末位寫0用于結束字符串輸出
- uchar stime[2];//用于保存鬧鐘時間
- uchar ttime[7];//={0x48,0x48,0x22,0x028,0x05,0x06,0x18};//用于初始化DS1302,和讀取時間
- sbit key1=P2^7;//時間調整按鍵,1設置
- sbit key2=P2^6;//2加
- sbit key3=P2^5;//3減
- sbit key4=P2^4;//4退出
- uchar n,stat=0;//設置狀態標志,0為正常顯示狀態
- //1-9為設置狀態1-年、2-月、3-日、4-周、5-時、6-分、7-秒、8-鬧表時、9-鬧表分
- uchar isryear(uchar year1)
- {
- int year,isrun;
- //判斷是否閏年,1為閏年,0為平年
- year=2000+year1/16*10+year1%16;
- if(year%4==0)
- {
- if(year%100!=0)
- {
- isrun=1;
- }
- else if(year%400)
- {
- isrun=1;
- }
- else
- {
- isrun=0;
- }
- }
- else
- {
- isrun=0;
- }
- return isrun;
- }
- void keyscan(uchar *tempt,uchar *stime)
- {
- uchar isrun;
- if(key1==0)//設置
- {
- delayms(30);
- if(key1==0)
- {
- stat++;//設置標志在0--9之間變化,0為正常顯示狀態,1--7打開光標閃爍并在7個時間選項中移動,8、9鬧表時間
- if(stat>9)
- stat=1;
- }
- while(!key1);
- }
- if(key2==0)//選中位置+1
- {
- delayms(30);
- if(key2==0)
- {
- switch(stat)
- {
- case 1://年
- {
- tempt[6]++;
- if((tempt[6]&0x0f)==0x0a)//逢10進1
- {
- tempt[6]+=0x10;
- tempt[6]=tempt[6]&0xf0;
- if(tempt[6]==0xa0)//逢100變0
- tempt[6]=0x00;
- }
- //判斷平年閏年2月是否溢出
- isrun=isryear(tempt[6]);
- if((tempt[4]==0x02)&&(tempt[3]>0x29)&&(isrun==1))
- tempt[3]=0x29;
- else if((tempt[4]==0x02)&&(tempt[3]>0x28)&&(isrun==0))
- tempt[3]=0x28;
- break;
- }
- case 2://月
- {
- tempt[4]+=0x01;
- if((tempt[4]&0x0f)==0x0a)//逢10進1
- {
- tempt[4]+=0x10;//前4位進位
- tempt[4]=tempt[4]&0xf0;//后4位置0
- }
- if(((tempt[4]&0x0f)==0x03)&((tempt[4]&0xf0)==0x10))//逢13變1
- tempt[4]=0x01;
- //檢查調整月之后的日期有沒有溢出
- isrun=isryear(tempt[6]);
- if((tempt[4]==0x02)&&(tempt[3]>0x29)&&(isrun==1))//29天月
- tempt[3]=0x29;
- else if((tempt[4]==0x02)&&(tempt[3]>0x28)&&(isrun==0))//28天月
- tempt[3]=0x28;
- else if(((tempt[4]==0x01)||(tempt[4]==0x03)||(tempt[4]==0x05)//31天月
- ||(tempt[4]==0x07)||(tempt[4]==0x08)||(tempt[4]==0x10)
- ||(tempt[4]==0x12))&&(tempt[3]>0x31))
- tempt[3]=0x31;
- else if(((tempt[4]==0x04)||(tempt[4]==0x06)||(tempt[4]==0x09)//30天月
- ||(tempt[4]==0x11))&&(tempt[3]>0x30))
- tempt[3]=0x30;
- break;
- }
- case 3://日
- {
- tempt[3]+=0x01;
- if((tempt[3]&0x0f)==0x0a)//逢10進1
- {
- tempt[3]+=0x10;
- tempt[3]=tempt[3]&0xf0;
- }
- //檢查調整月之后的日期有沒有溢出
- isrun=isryear(tempt[6]);
- if((tempt[4]==0x02)&&(tempt[3]>0x29)&&(isrun==1))
- tempt[3]=0x01;
- else if((tempt[4]==0x02)&&(tempt[3]>0x28)&&(isrun==0))
- tempt[3]=0x01;
- if(((tempt[4]==0x01)||(tempt[4]==0x03)||(tempt[4]==0x05)
- ||(tempt[4]==0x07)||(tempt[4]==0x08)||(tempt[4]==0x10)
- ||(tempt[4]==0x12))&&(tempt[3]==0x32))
- tempt[3]=0x01;
- if(((tempt[4]==0x04)||(tempt[4]==0x06)||(tempt[4]==0x09)
- ||(tempt[4]==0x11))&&(tempt[3]==0x31))
- tempt[3]=0x01;
- break;
- }
- case 4://星期
- {
- tempt[5]+=0x01;
- if(tempt[5]>0x07)
- tempt[5]=0x01;
- break;
- }
- case 5://時
- {
- tempt[2]+=0x01;
- if((tempt[2]&0x0f)==0x0a)
- {
- tempt[2]+=0x10;
- tempt[2]=tempt[2]&0xf0;
- }
- if(((tempt[2]&0x0f)==0x04)&((tempt[2]&0xf0)==0x20))
- tempt[2]=0x00;
- break;
- }
- case 6://分
- {
- tempt[1]+=0x01;
- if((tempt[1]&0x0f)==0x0a)
- {
- tempt[1]+=0x10;
- tempt[1]=tempt[1]&0xf0;
- }
- if(tempt[1]==0x60)
- tempt[1]=0x00;
- break;
- }
- case 7://秒
- {
- tempt[0]+=0x01;
- if((tempt[0]&0x0f)==0x0a)
- {
- tempt[0]+=0x10;
- tempt[0]=tempt[0]&0xf0;
- }
- if(tempt[0]==0x60)
- tempt[0]=0x00;
- break;
- }
- case 8://鬧表時
- {
- stime[1]+=0x01;
- if((stime[1]&0x0f)==0x0a)
- {
- stime[1]+=0x10;
- stime[1]=stime[1]&0xf0;
- }
- if(((stime[1]&0x0f)==0x04)&&((stime[1]&0xf0)==0x20))
- stime[1]=0x00;
- Ds1302Write(0x8e,0x00);//關閉寫保護
- Ds1302Write(0xc0,stime[0]);
- Ds1302Write(0xc2,stime[1]);
- Ds1302Write(0x8e,0x80);//打開寫保護
- break;
- }
- case 9://鬧表分
- {
- stime[0]+=0x01;
- if((stime[0]&0x0f)==0x0a)
- {
- stime[0]+=0x10;
- stime[0]=stime[0]&0xf0;
- }
- if(((stime[0]&0x0f)==0x00)&&((stime[0]&0xf0)==0x60))
- stime[0]=0x00;
- Ds1302Write(0x8e,0x00);//關閉寫保護
- Ds1302Write(0xc0,stime[0]);
- Ds1302Write(0xc2,stime[1]);
- Ds1302Write(0x8e,0x80);//打開寫保護
- break;
- }
- }
- }
- while(!key2);
- }
- if(key3==0)//選中位置-1
- {
- delayms(30);
- if(key3==0)
- {
- switch(stat)
- {
- case 1://年
- {
- if(tempt[6]==0x00)//逢00變99
- tempt[6]=0x99;
- else if((tempt[6]&0x0f)==0x00)//逢0進9
- {
- tempt[6]-=0x10;
- tempt[6]=tempt[6]|0x09;
- }
- else tempt[6]--;
- //檢查調整月之后的日期有沒有溢出
- isrun=isryear(tempt[6]);
- //判斷平年閏年2月是否溢出
- if((tempt[4]==0x02)&&(tempt[3]>0x29)&&(isrun==1))
- tempt[3]=0x29;
- else if((tempt[4]==0x02)&&(tempt[3]>0x28)&&(isrun==0))
- tempt[3]=0x28;
- break;
- }
- case 2://月
- {
- if(((tempt[4]&0x0f)==0x01)&((tempt[4]&0xf0)==0x00))//逢1變12
- tempt[4]=0x12;
- else if((tempt[4]&0x0f)==0x00)//10變9
- {
- tempt[4]=0x09;
- }
- else tempt[4]-=0x01;
- //檢查調整月之后的日期有沒有溢出
- isrun=isryear(tempt[6]);
- if((tempt[4]==0x02)&&(tempt[3]>0x29)&&(isrun==1))
- tempt[3]=0x29;
- else if((tempt[4]==0x02)&&(tempt[3]>0x28)&&(isrun==0))
- tempt[3]=0x28;
- else if(((tempt[4]==0x01)||(tempt[4]==0x03)||(tempt[4]==0x05)
- ||(tempt[4]==0x07)||(tempt[4]==0x08)||(tempt[4]==0x10)
- ||(tempt[4]==0x12))&&(tempt[3]>0x31))
- tempt[3]=0x31;
- else if(((tempt[4]==0x04)||(tempt[4]==0x06)||(tempt[4]==0x09)
- ||(tempt[4]==0x11))&&(tempt[3]>0x30))
- tempt[3]=0x30;
- break;
- }
- case 3://日
- {
- //檢查調整月之后的日期有沒有溢出
- isrun=isryear(tempt[6]);
- if((tempt[4]==0x02)&&(tempt[3]==0x01)&&(isrun==1))
- tempt[3]=0x29;
- else if((tempt[4]==0x02)&&(tempt[3]==0x01)&&(isrun==0))
- tempt[3]=0x28;
- else if(((tempt[4]==0x01)||(tempt[4]==0x03)||(tempt[4]==0x05)
- ||(tempt[4]==0x07)||(tempt[4]==0x08)||(tempt[4]==0x10)
- ||(tempt[4]==0x12))&&(tempt[3]==0x01))
- tempt[3]=0x31;
- else if(((tempt[4]==0x04)||(tempt[4]==0x06)||(tempt[4]==0x09)
- ||(tempt[4]==0x11))&&(tempt[3]==0x01))
- tempt[3]=0x30;
- else if((tempt[3]&0x0f)==0x00)//逢0借1變9
- {
- tempt[3]-=0x10;
- tempt[3]=tempt[3]|0x09;
- }
- else tempt[3]-=0x01;
- break;
- }
- case 4://星期
- {
- tempt[5]-=0x01;
- if(tempt[5]==0x00)
- tempt[5]=0x07;
- break;
- }
- case 5://時
- {
- if(tempt[2]==0x00)
- tempt[2]=0x23;
- else if((tempt[2]&0x0f)==0x00)
- {
- tempt[2]-=0x10;
- tempt[2]=tempt[2]|0x09;
- }
- else tempt[2]-=0x01;
- break;
- }
- case 6://分
- {
- if(tempt[1]==0x00)
- {
- tempt[1]=0x59;
- }
- else if((tempt[1]&0x0f)==0x00)
- {
- tempt[1]-=0x10;
- tempt[1]=tempt[1]|0x09;
- }
- else tempt[1]-=0x01;
- break;
- }
- case 7://秒
- {
- if(tempt[0]==0x00)
- tempt[0]=0x59;
- else if((tempt[0]&0x0f)==0x00)
- {
- tempt[0]-=0x10;
- tempt[0]=tempt[0]|0x09;
- }
- else tempt[0]-=0x01;
- break;
- }
- case 8://鬧表時
- {
- if(stime[1]==0x00)
- stime[1]=0x23;
- else if((stime[1]&0x0f)==0x00)
- {
- stime[1]-=0x10;
- stime[1]=stime[1]|0x09;
- }
- else stime[1]-=0x01;
- Ds1302Write(0x8e,0x00);//關閉寫保護
- Ds1302Write(0xc0,stime[0]);
- Ds1302Write(0xc2,stime[1]);
- Ds1302Write(0x8e,0x80);//打開寫保護
- break;
- }
- case 9://鬧表分
- {
- if(stime[0]==0x00)
- stime[0]=0x59;
- else if((stime[0]&0x0f)==0x00)
- {
- stime[0]-=0x10;
- stime[0]=stime[0]|0x09;
- }
- else stime[0]-=0x01;
- Ds1302Write(0x8e,0x00);//關閉寫保護
- Ds1302Write(0xc0,stime[0]);
- Ds1302Write(0xc2,stime[1]);
- Ds1302Write(0x8e,0x80);//打開寫保護
- break;
- }
- }
- }
- while(!key3);
- }
- if(key4==0)//設置
- {
- delayms(30);
- if(key4==0)
- {
- stat=0;
- }
- while(!key4);
- //退出設置讀取鬧表時間
- stime[0]=Ds1302Read(0xc1);
- stime[1]=Ds1302Read(0xc3);
- }
- if(stat>0)
- {
- Ds1302Write(0x8e,0x00);//關閉寫保護
- for(n=0;n<8;n++){
- Ds1302Write(WRITE_RTC_ADDR[n],tempt[n]);
- }
- Ds1302Write(0x8e,0x80);//打開寫保護
- }
- }
- void showtime()//顯示正常時間
- {
- Ds1302readTime(p3);//讀取時間
- dispros(p1,p2,p3);//轉換時間
- Lcdwritedat(0x80,mdate);//顯示日期
- Lcdwritedat(0x80+0x40,mtime);//顯示時間
- }
- void showntime()//顯示鬧表設置
- {
- stime[0]=Ds1302Read(0xc1);
- stime[1]=Ds1302Read(0xc3);
- ntime[0]=stime[1]/16+0x30;
- ntime[1]=stime[1]%16+0x30;
- ntime[2]=':';
- ntime[3]=stime[0]/16+0x30;
- ntime[4]=stime[0]%16+0x30;
- ntime[5]=0;
- Lcdwritedat(0x80,"Set Alarm Time: ");
- Lcdwritedat(0x80+0x40,ntime);//顯示時間
- Lcdwritedat(0x80+0x40+5," ");//顯示溫度之前空格
- }
- void Timer0Init()
- {
- TMOD=0x01; //設置定時器0工作方式為1
- TH0=(65536-45872)/256;
- TL0=(65536-45872)%256;
- ET0=1; //開啟定時器0中斷
- TR0=1; //開啟定時器
- EA=1; //打開總中斷
- }
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼 全部代碼51hei下載地址:
萬年歷.zip
(74.74 KB, 下載次數: 100)
2021-3-24 19:11 上傳
點擊文件名下載附件
參考各種例程,最終版本 下載積分: 黑幣 -5
|