Altium Designer画的原理图和PCB图如下:(51hei附件中可下载工程文件)
全部资料下载地址:
时钟电路图及PCB工程.zip
(6.91 MB, 下载次数: 106)
单片机源代码为
- #include<reg52.h>
- #include<intrins.h>
- #define uint unsigned int
- #define uchar unsigned char
- sbit lcdrs=P2^4;
- sbit lcdrw=P2^5;
- sbit lcden=P2^6;
- sbit key1=P2^2;
- sbit key2=P2^1;
- sbit key3=P2^0;
- sbit FM=P1^0;
- uchar counter,cycle;
- uchar key_counter = 0; //定义光标闪烁以及修改操作数的标记
- uchar second0,second1,minute0,minute1,hour0,hour1;
- uchar table[][3]={"SUN","MON","TUE","WEN","THU","FRI","SAT"};
- uchar year[4],day[2],month[2],date; //日期变量
- uchar small_mon,leap_year;
- uchar k;
- void state() //检查日期状态函数(即判断是否闰年,是否小月的函数)
- {
- switch(month[0]) //2,4,6,9,11月是小月
- {
- case 1:
- if(month[1] == 1) //若是11月,则是小月
- small_mon = 1;
- else //若是1月,则不是小月
- small_mon = 0; break;
- case 2:
- case 4:
- case 6:
- case 9: small_mon = 1; break;
- default:small_mon = 0;break;
- }
-
- k=year[3]*1000+year[2]*100+year[1]*10+year[0];
- if(k%4==0&&k%100!=0||k%400==0)
- leap_year=1;
- else
- leap_year=0;
- }
- void Dater() //日期函数
- {
- state();
- day[0]++;
- date=(date+1)%7;
- switch(day[0]) //日变化
- {
- case 10:
- {
- if(day[1] == 2 && month[0] == 2 && month[1] == 0) //20日的个位能到10,说明是闰年,把2月30号转变为3月1号
- {
- day[0] = 1;
- day[1] = 0;
- month[0]++;
- }
- else //日期个位满10进1
- {
- day[0] = 0;
- day[1]++;
- }
- } break;
- case 1:
- {
- if(day[1] == 3 && small_mon) //小月31号时把日期置为1号,月份+1
- {
- day[0] = 1;
- day[1] = 0;
- month[0]++;
- }
- } break;
- case 2:
- {
- if(day[1] == 3)
- {
- day[0] = 1;
- day[1] = 0;
- month[0]++;
- }
- }break;
- case 9:
- {
- if(day[1] == 2 && !leap_year && month[0] == 2 && month[1] == 0) //平年时,把2月29号变为3月1号
- {
- day[0] = 1;
- day[1] = 0;
- month[0]++;
- }
- } break;
- default: break;
- }
- switch(month[0]) //月变化
- {
- case 10: //个位逢10进1
- {
- month[0] = 0;
- month[1]++;
- } break;
- case 3: //当十位是1,个位逢3则年进1
- {
- if(month[1] == 1)
- {
- month[0] = 1;
- month[1] = 0;
- year[0]++;
- }
- } break;
- }
- if(year[0] > 9) //相应年变化
- {
- year[0] = 0;
- year[1]++;
- if(year[1] > 9)
- {
- year[1] = 0;
- year[2]++;
- if(year[2] > 9)
- {
- year[2] = 0;
- year[3]++;
- if(year[3] > 9)
- year[3] = 0;
- }
- }
- }
- }
- void clock() //时钟函数
- {
- second0++;
- if(second0 > 9)
- {
- second0 = 0;
- second1++;
- if(second1 > 5)
- {
- second1 = 0;
- minute0++;
- if(minute0 > 9)
- {
- minute0 = 0;
- minute1++;
- if(minute1 > 5)
- {
- minute1 = 0;
- hour0++;
- if(hour0 == 4 && hour1 == 2)
- {
- hour0 = hour1 = 0;
- Dater();
- }
- else if(hour0 > 9)
- {
- hour0 = 0;
- hour1++;
- }
- }
- }
- }
- }
- }
- void delay(uint z) //延时函数ms
- {
- uint x,y;
- for(x = z;x > 0;x--)
- for(y = 110;y > 0;y--) ;
- }
- void write_com(uchar com) //写指令到LCD液晶显示
- {
- lcdrs = 0; //选择指令寄存器
- lcdrw = 0; //选择写
- P0 = com; //把命令字送入P0口
- delay(1); //延时,让1602准备接收数据
- lcden = 1; //使能线电平变化,命令送入1602的8位数据口
- delay(1); //等待接收
- lcden = 0;
- }
- void write_data(uchar data0) //写数据到LCD液晶显示
- {
- lcdrs = 1; //选择数据寄存器
- lcdrw = 0; //选择写
- P0 = data0; //把数据送入P0口
- delay(1); //延时,让1602准备接收数据
- lcden = 1; //使能线电平变化,数据送入8位数据口
- delay(1); //等待接收
- lcden = 0;
- }
- void disp_time() //显示时间
- {
- write_com(0xc4); //设定显示地址为下排第5位
- write_data(hour1 + 0x30); //小时
- write_data(hour0 + 0x30);
- write_data(0x3a); //显示冒号
- write_data(minute1 + 0x30); //分钟
- write_data(minute0 + 0x30);
- write_data(0x3a); //冒号
- write_data(second1 + 0x30);//秒
- write_data(second0 + 0x30);
- if(key_counter != 0 ) //按功能键key1次数不为0
- {
- switch(key_counter)
- {
- case 1:
- write_com(0x80+0x4b); //定位回光标闪烁位置,第二行第12位
- break;
- case 2:
- write_com(0x80+0x48); //第二行第9位
- break;
- case 3:
- write_com(0x80+0x45); //第二行第6位
- break;
- case 4:
- write_com(0x80+0x0e); //第一行第15位
- break;
- case 5:
- write_com(0x80+0x0b); //第一行第12位
- break;
- case 6:
- write_com(0x80+0x08); //第一行第9位
- break;
- case 7:
- write_com(0x80+0x03); //第一行第4位
- break;
- }
- write_com(0x0f); //关光标
- delay(150);
- }
- }
- void disp_date() //显示日期
- {
- write_com(0x81); //定义回第一行第2位
- for(cycle = 0; cycle < 3;cycle++)// 显示星期
- write_data(table[date][cycle]);
- write_data(0x20); //显示空格
- for(cycle = 0;cycle < 4;cycle++) //显示年
- write_data(year[3 - cycle]+0x30);
- write_data(0x2d); //显示'/'
- write_data(month[1]+0x30); //显示月
- write_data(month[0]+0x30);
- write_data(0x2d); //显示'/'
- write_data(day[1]+0x30); //显示日
- write_data(day[0]+0x30);
- }
- void di() //蜂鸣器发声函数
- {
- FM=0;
- delay(100);
- FM=1;
- }
- void setting_detect() //按键扫描函数
- {
- if(key1==0)
- {
- delay(5);
- if(key1==0) //消除抖动
- {
- while(!key1); //等待松手
- TR0=0; //TRO==0
- di(); //蜂鸣器滴
- key_counter++; //功能键按下次数加一
- do
- {
- disp_date(); //显示星期+日期
- disp_time(); //显示时间
- if(key1==0) //按键“切换”
- {
- delay(5);
- if(key1==0)
- {
- while(!key1);
- di();
- key_counter++;
- }
- }
- if(key2==0) //按键“加”
- {
- delay(5);
- if(key2==0)
- {
- while(!key2);
- di();
- switch(key_counter) //判断功能键按下次数
- {
- case 1: //一次则秒加一
- second0++;
- if(second0 > 9)
- {
- second0 = 0;
- second1++;
- if(second1 == 6)
- second1 = 0;
- } break;
- case 2: //两次则分加一
- minute0++;
- if(minute0 > 9)
- {
- minute0 = 0;
- minute1++;
- if(minute1 == 6)
- minute1 = 0;
- } break;
- case 3: //三次则时加一
- hour0++;
- if(hour1 == 2 && hour0 > 3)
- {
- hour0 = 0;
- hour1 = 0;
- }
- else if(hour0 > 9)
- {
- hour0 = 0;
- hour1++;
- }
- break;
- case 4: //四次则日加一
- day[0]++;
- if(day[0] == 2 && day[1] == 3)
- {
- day[0] = 1;
- day[1] = 0;
- }
- if(day[0] == 10)
- {
- day[0] = 0;
- day[1]++;
- }
- break;
- case 5: //五次则月加一
- month[0]++;
- if(month[0] == 3 && month[1] == 1)
- {
- month[0] = 1;
- month[1] = 0;
- }
- if(month[0] == 10)
- {
- month[0] = 0;
- month[1] = 1;
- }
- break;
- case 6: //六次则年加一
- year[0]++;
- if(year[0] > 9)
- {
- year[0] = 0;
- year[1]++;
- if(year[1] > 9)
- {
- year[1] = 0;
- year[2]++;
- if(year[2] > 9)
- {
- year[2] = 0;
- year[3]++;
- if(year[3] > 9)
- year[3] = 0;
- }
- }
- }
- break;
- case 7: //七次则星期加一
- date=(date+1)%7;
- break;
- }
- }
- }
- if(key3==0) //按键“减”
- {
- delay(5);
- if(key3==0)
- {
- while(!key3);
- di();
- switch(key_counter)
- {
- case 1:
- if(second0 == 0)
- {
- second0 = 9;
- if(second1 == 0)
- second1 = 5;
- else
- second1--;
- }
- else
- second0--;
- break;
- case 2:
- if(minute0 == 0)
- {
- minute0 = 9;
- if(minute1 == 0)
- minute1 = 5;
- else
- minute1--;
- }
- else
- minute0--;
- break;
- case 3:
- if(hour0 == 0)
- {
- if(hour1 == 0)
- {
- hour0 = 3;
- hour1 = 2;
- }
- else
- {
- hour0 = 9;
- hour1--;
- }
- }
- else
- hour0--;
- break;
- case 4:
- if(day[0] == 1 && day[1] == 0)
- day[1] = 3;
- if(day[0] == 0)
- {
- day[0] = 9;
- day[1]--;
- }
- else
- day[0]--;
- break;
- case 5:
- if(month[0] == 1 && month[1] == 0)
- {
- month[0] = 2;
- month[1] = 1;
- }
- else if(month[0] == 0)
- {
- month[0] = 9;
- month[1]--;
- }
- else
- month[0]--;
- break;
- case 6:
- if(year[0] == 0)
- {
- year[0] = 9;
- if(year[1] == 0)
- {
- year[1] = 9;
- if(year[2] == 0)
- {
- year[2] = 9;
- if(year[3] == 0)
- year[3] = 9;
- else
- year[3]--;
- }
- else
- year[2]--;
- }
- else
- year[1]--;
- }
- else
- year[0]--;
- break;
- case 7:
- date=(date+6)%7;
- break;
- }
- }
- }
- }
- while(key_counter != 8);
- key_counter = 0; //退出设置时关掉光标显示
- TR0=1;
- }
- }
- }
- void Lcd_init() //显示屏初始化
- {
- lcden = 0;
- write_com(0x01); //清屏
- write_com(0x02); //位置复位为左上方
- write_com(0x06); //光标右移
- write_com(0x0e); //显示开,有光标,闪烁
- write_com(0x38); //两行,每行16字符,5*7点阵
- }
- void timer0() interrupt 1 //定时器
- {
- TH0 = (65536-39970)/256;
- TL0 = (65536-39970)%6;
- counter++;
- if(counter == 25)
- {
- counter = 0;
- clock();
- }
- }
- void Timer_init() //定时器初始化
- {
- TMOD = 0x01;
- TH0 = (65536-29995)/256;
- TL0 = (65536-29995)%6;
- EA = 1;
- ET0 = 1;
- TR0 = 1;
- }
- void Date_init() //日期初始化
- {
- date = 4;
- day[0] = 0;
- day[1] = 2;
- month[0] = 4;
- month[1] = 0;
- year[0] = 7;
- year[1] = 1;
- year[2] = 0;
- year[3] = 2;
- }
- void Time_init() //时间初始化
- {
- second0 = 0;
- second1 = 3;
-
- minute0 = 0;
- minute1 = 3;
-
- hour0 = 2;
- hour1 = 1;
-
- counter = 0;
- }
- void main() //主函数
- {
- Lcd_init();
- Time_init();
- Date_init();
- Timer_init();
- while(1)
- {
- disp_date();
- disp_time();
- setting_detect();
- }
- }
复制代码
|