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,个别细节
上图为最终结果
上图上面箭头为原来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, 下载次数: 99)
|