静态显示万年历,需要的就赞一赞吧!
所有资料下载:
LED万年历的proteus仿真电路及C语言程序设计.zip
(141.79 KB, 下载次数: 49)
单片机源程序:
- //Title:calendar
- #include <REGX51.H>
- #define uchar unsigned char
- #define uint unsigned int
- sbit DATA=P1^2; //数据(PA0)
- sbit SCK=P1^0; //移位时钟(PA1)
- sbit RCK=P1^1; //锁存时钟(PA2)
- sbit P20=P2^0;
- sbit P21=P2^1;
- sbit P33=P3^3;
- sbit DS1302_CLK = P1^7; //实时时钟时钟线引脚
- sbit DS1302_IO = P1^6; //实时时钟数据线引脚
- sbit DS1302_RST = P1^5;//实时时钟复位线引脚
- sbit ACC0 = ACC^0;
- sbit ACC7 = ACC^7;
- char hide_sec,hide_min,hide_hour,hide_day,hide_week,hide_month,hide_year; //秒,分,时到日,月,年位闪的计数
- sbit Set = P3^0; //模式切换键
- sbit Up = P3^1; //加法按钮
- sbit Down = P3^2; //减法按钮
- sbit out = P3^4; //立刻跳出调整模式按钮
-
- char done,count,temp,flag,up_flag,down_flag;
- uchar DS1302[8]={4,5,6,7,8,6,9}; //秒,分,时,日,月,星期,年
- uint f;
-
- uchar t[14];
- uchar k;
- uchar code Seg[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00};
- void display(uchar L1,uchar L2,uchar L3,uchar L4,uchar L5,uchar L6,uchar L7,uchar L8,
- uchar L9,uchar L10,uchar L11,uchar L12,uchar L13,uchar L14);
- /***********DS1302时钟部分子程序******************/
- typedef struct __SYSTEMTIME__
- {
- unsigned char Second;
- unsigned char Minute;
- unsigned char Hour;
- unsigned char Week;
- unsigned char Day;
- unsigned char Month;
- unsigned char Year;
- unsigned char DateString[14];
- }SYSTEMTIME; //定义的时间类型
- SYSTEMTIME CurrentTime;
-
- #define DS1302_SECOND 0x81 //时钟芯片的寄存器位置,存放时间
- #define DS1302_MINUTE 0x83
- #define DS1302_HOUR 0x85
- #define DS1302_WEEK 0x8A
- #define DS1302_DAY 0x87
- #define DS1302_MONTH 0x89
- #define DS1302_YEAR 0x8D
- void DS1302InputByte(unsigned char d) //实时时钟写入一字节(内部函数)
- {
- unsigned char i;
- ACC = d;
- for(i=8; i>0; i--)
- {
- DS1302_IO = ACC0; //相当于汇编中的 RRC
- DS1302_CLK = 1;
- DS1302_CLK = 0;
- ACC = ACC >> 1;
- }
- }
- unsigned char DS1302OutputByte(void) //实时时钟读取一字节(内部函数)
- {
- unsigned char i;
- for(i=8; i>0; i--)
- {
- ACC = ACC >>1; //相当于汇编中的 RRC
- ACC7 = DS1302_IO;
- DS1302_CLK = 1;
- DS1302_CLK = 0;//在下降沿数据从移位寄存器输出
- }
- return(ACC);
- }
- void Write1302(unsigned char ucAddr, unsigned char ucDa) //ucAddr: DS1302地址, ucData: 要写的数据
- {
- DS1302_RST = 0;
- DS1302_CLK = 0;
- DS1302_RST = 1;//只有在clk为低时,才能将rst置高
- DS1302InputByte(ucAddr); // 地址,命令
- DS1302InputByte(ucDa); // 写1Byte数据
- DS1302_CLK = 1;//上升沿将数据写入DS1302内部移位寄存器
- DS1302_RST = 0;
- }
- unsigned char Read1302(unsigned char ucAddr) //读取DS1302某地址的数据
- {
- unsigned char ucData;
- DS1302_RST = 0;
- DS1302_CLK = 0;
- DS1302_RST = 1;//启动数据传送
- DS1302InputByte(ucAddr|0x01); // 地址,命令 ,读操作
- ucData = DS1302OutputByte(); // 读1Byte数据,应在上升沿前读取
- DS1302_CLK = 1;
- DS1302_RST = 0;
- return(ucData);
- }
- void DS1302_GetTime(SYSTEMTIME *Time) //获取时钟芯片的时钟数据到自定义的结构型数组
- {
- unsigned char ReadValue;
- ReadValue = Read1302(DS1302_SECOND);
- Time->Second = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);//16进制转为10进制
- ReadValue = Read1302(DS1302_MINUTE);
- Time->Minute = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
- ReadValue = Read1302(DS1302_HOUR);
- Time->Hour = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
- ReadValue = Read1302(DS1302_DAY);
- Time->Day = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
- ReadValue = Read1302(DS1302_WEEK);
- Time->Week = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
- ReadValue = Read1302(DS1302_MONTH);
- Time->Month = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
- ReadValue = Read1302(DS1302_YEAR);
- Time->Year = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
- }
- void DateToStr(SYSTEMTIME *Time) //将时间年,月,日,星期数据转换成液晶显示字符串,放到数组里DateString[]
- { if(hide_year<5) //这里的if,else语句都是判断位闪烁,<2显示数据,>2就不显示,输出字符串为 2007/07/22
- {
- Time->DateString[0] = 2;
- Time->DateString[1] = 0;
- Time->DateString[2] = Time->Year/10;
- Time->DateString[3] = Time->Year%10;
- }
- else
- {
-
- Time->DateString[2] =10 ;
- Time->DateString[3] =10 ;
- }
-
- if(hide_month<5)
- {
- Time->DateString[4] = Time->Month/10;
- Time->DateString[5] = Time->Month%10;
- }
- else
- {
- Time->DateString[4] =10;
- Time->DateString[5] =10;
- }
-
- if(hide_day<5)
- {
- Time->DateString[6] = Time->Day/10;
- Time->DateString[7] = Time->Day%10;
- }
- else
- {
- Time->DateString[6] =10;
- Time->DateString[7] =10;
- }
-
- if(hide_hour<5)
- {
- Time->DateString[8] = Time->Hour/10;
- Time->DateString[9] = Time->Hour%10;
- }
- else
- {
- Time->DateString[8] =10;
- Time->DateString[9] =10;
- }
-
- if(hide_min<5)
- {
- Time->DateString[10] = Time->Minute/10;
- Time->DateString[11] = Time->Minute%10;
- }
- else
- {
- Time->DateString[10] =10;
- Time->DateString[11] =10;
- }
-
- if(hide_sec<5)
- {
- Time->DateString[12] = Time->Second/10 ;
- Time->DateString[13] = Time->Second%10 ;
- }
- else
- {
- Time->DateString[12] =10;
- Time->DateString[13] =10;
- }
-
- }
- void show_time() //显示程序
- { uchar i;
- uchar j;
-
- DS1302_GetTime(&CurrentTime); //获取时钟芯片的时间数据
- DateToStr(&CurrentTime);
- for(j=0;j<14;j++)
- {t[j]=Seg[CurrentTime.DateString[13-j]];}
-
- RCK=0;//锁存置低
-
-
- for(j=0;j<14;j++)
- {
- for(i=0;i<8;i++)
- {
- SCK=0; //移位脉冲置低
- DATA=t[j]&0x80;
- t[j]=t[j]<<1;
- SCK=1;//上升沿时数据寄存器的数据移位
- }
- }
-
-
- RCK=1; //上升沿时移位寄存器的数据进入数据存储寄存器
-
- }
- /*延时子程序*/
- void mdelay(uint delay)
- { uint i;
- for(;delay>0;delay--)
- {for(i=0;i<62;i++) //1ms延时.
- {;}
- }
- }
- void outkey() //跳出调整模式,返回默认显示
- { uchar Second;
- if(out==0)
- { mdelay(8);
- count=0;
- hide_sec=0,hide_min=0,hide_hour=0,hide_day=0,hide_week=0,hide_month=0,hide_year=0;
- Second=Read1302(DS1302_SECOND);
-
- Write1302(0x80,Second&0x7f);
-
- done=0;
- while(out==0);
-
- }
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////
- void Upkey()//升序按键
- {
- Up=1;
- if(Up==0)
- {
- mdelay(8);
-
- switch(count)
- {/*case 1:
- temp=Read1302(DS1302_SECOND); //读取秒数
- temp=temp+1; //秒数加1
- up_flag=1; //数据调整后更新标志
- if((temp&0x7f)>0x59) //超过59秒,清零
- temp=0;
- break;*/
- case 2:
- temp=Read1302(DS1302_MINUTE); //读取分数
- temp=temp+1; //分数加1
- up_flag=1;
- if((temp&0x0F)>9)temp=temp+6;
- if(temp>=0x60) temp=0;
- break;
- case 3:
- temp=Read1302(DS1302_HOUR); //读取小时数
- temp=temp+1; //小时数加1
- if((temp&0x0F)>9)temp=temp+6;
- if(temp>=0x24) temp=0;
- up_flag=1;
-
- break;
-
- case 4:
- temp=Read1302(DS1302_DAY); //读取日数
- temp=temp+1; //日数加1
- up_flag=1;
- if((temp&0x0F)>9)temp=temp+6;
- if(temp>=0x32) temp=1;
- break;
- case 5:
- temp=Read1302(DS1302_MONTH);// 读取月数
- temp=temp+1; //月数加1
- up_flag=1;
- if((temp&0x0F)>9)temp=temp+6;
- if(temp>=0x13) temp=1;
- break;
- case 6:
- temp=Read1302(DS1302_YEAR); //读取年数
- temp=temp+1; //年数加1
- up_flag=1;
- if((temp&0x0F)>9)temp=temp+6;
- if(temp>=0xA0) temp=0;
- break;
- default:break;
- }
-
- while(Up==0);
-
- }
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////
- void Downkey()//降序按键
- {
- Down=1;
- if(Down==0)
- {
- mdelay(8);
- switch(count)
- {/*case 1:
- temp=Read1302(DS1302_SECOND); //读取秒数
- temp=temp-1; //秒数减1
- down_flag=1; //数据调整后更新标志
- if(temp==0x7f) //小于0秒,返回59秒
- temp=0x59;
- break;*/
- case 2:
- temp=Read1302(DS1302_MINUTE); //读取分数
- temp=temp-1; //分数减1
- down_flag=1;
- if((temp&0x0F)>9)temp=temp-6;
- if(temp==0) temp=0x59;
- break;
- case 3:
- temp=Read1302(DS1302_HOUR); //读取小时数
- temp=temp-1; //小时数减1
- down_flag=1;
- if((temp&0x0F)>9)temp=temp-6;
- if(temp==0) temp=0x59;
- break;
-
- case 4:
- temp=Read1302(DS1302_DAY); //读取日数
- temp=temp-1; //日数减1
- down_flag=1;
- if((temp&0x0F)>9)temp=temp-6;
- if(temp==0) temp=0x31;
- break;
- case 5:
- temp=Read1302(DS1302_MONTH); //读取月数
- temp=temp-1; //月数减1
- down_flag=1;
- if((temp&0x0F)>9)temp=temp-6;
- if(temp==0) temp=0x12;
- break;
- case 6:
- temp=Read1302(DS1302_YEAR); //读取年数
- temp=temp-1; //年数减1
- down_flag=1;
- if((temp&0x0F)>9)temp=temp-6;
- if(temp==0) temp=0x50;
- break;
- default:break;
- }
-
- while(Down==0);
-
- }
- }
- void Setkey()//模式选择按键
- {
- Set=1;
- if(Set==0)//有按键按下
- {
- mdelay(8);
- count=count+1; //Setkey按一次,count就加1
- done=1; //进入调整模式
- while(Set==0);
-
- }
- }
- void keydone()//按键功能执行
- { uchar Second;
- if(flag==0) //关闭时钟,停止计时
- {
- temp=Read1302(0x81);
- Write1302(0x80,temp|0x80);//ch=1,时钟振荡停止
-
- flag=1;
- }
- Setkey(); //扫描模式切换按键
- switch(count)
- {case 1:do //count=1,调整秒
- {
- outkey(); //扫描跳出按钮
- Upkey(); //扫描加按钮
- Downkey(); //扫描减按钮
- if(up_flag==1||down_flag==1) //数据更新,重新写入新的数据
- {
-
- Write1302(0x80,temp|0x80); //写入新的秒数
-
- up_flag=0;
- down_flag=0;
- }
- hide_sec++; //位闪计数
- if(hide_sec>9)
- hide_sec=0;
- show_time(); //液晶显示数据
- }while(count==2);break;
- case 2:do //count=2,调整分
- {
- hide_sec=0;
- outkey();
- Upkey();
- Downkey();
- if(temp>0x59)
- temp=0;
- if(up_flag==1||down_flag==1)
- {
-
- Write1302(0x82,temp); //写入新的分数
-
- up_flag=0;
- down_flag=0;
- }
- hide_min++;
- if(hide_min>9)
- hide_min=0;
- show_time();
- }while(count==3);break;
- case 3:do //count=3,调整小时
- {
- hide_min=0;
- outkey();
- Upkey();
- Downkey();
- if(up_flag==1||down_flag==1)
- {
-
- Write1302(0x84,temp); //写入新的小时数
-
- up_flag=0;
- down_flag=0;
- }
- hide_hour++;
- if(hide_hour>9)
- hide_hour=0;
- show_time();
- }while(count==4);break;
-
- case 4:do //count=5,调整日
- {
- hide_hour=0;
- outkey();
- Upkey();
- Downkey();
- if(up_flag==1||down_flag==1)
- {
-
- Write1302(0x86,temp); //写入新的日数
-
- up_flag=0;
- down_flag=0;
- }
- hide_day++;
- if(hide_day>9)
- hide_day=0;
- show_time();
- }while(count==5);break;
- case 5:do //count=6,调整月
- {
- hide_day=0;
- outkey();
- Upkey();
- Downkey();
- if(up_flag==1||down_flag==1)
- {
-
- Write1302(0x88,temp); //写入新的月数
-
- up_flag=0;
- down_flag=0;
- }
- hide_month++;
- if(hide_month>9)
- hide_month=0;
- show_time();
- }while(count==6);break;
- case 6:do //count=7,调整年
- {
- hide_month=0;
- outkey();
- Upkey();
- Downkey();
- if(up_flag==1||down_flag==1)
- {
- Write1302(0x8c,temp); //写入新的年数
-
- up_flag=0;
- down_flag=0;
- }
- hide_year++;
- if(hide_year>9)
- hide_year=0;
- show_time();
- }while(count==7);break;
- case 7: count=0;hide_year=0; //count7, 跳出调整模式,返回默认显示状态
- Second=Read1302(DS1302_SECOND);
-
- Write1302(0x80,Second&0x7f);//ch=0时,时钟启动
-
- done=0;
- break; //count=7,开启中断,标志位置0并退出
- default:break;
- }
- }
-
-
- main()
- {
- uchar i;
- flag=1; //时钟停止标志
- up_flag=0;
- down_flag=0;
- done=0; //进入默认显示
- for(i=0;i<=6;i++)
- Write1302(0x80+2*i,DS1302[i]);
-
-
- while(1)
- {
- P33=0;
- while(done==1)
- keydone(); //进入调整模式
- while(done==0)
- {
- show_time();
- flag=0;
- Setkey(); //扫描各功能键
- }
- }
- }
-
复制代码
|