51单片机利用内部定时器做的万年历仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
单片机源程序如下:
- #include "reg52.h"
- #include "LCD1602.h"
- #include "stdio.h"
- #include "math.h"
- typedef struct {
- int year;
- unsigned char month;
- unsigned char day;
- unsigned char hour;
- unsigned char min;
- unsigned char sec;
- } times_t; // 定义时间参数结构体
- times_t times;
-
- unsigned char strline1[16]="Date:0000-00-00";
- unsigned char strline0[16]="Time:00-00-00";
- unsigned char vTH , vTL , flagset = 0; //定时器参数
- //判断年
- int leapyear ( int year ) //判断传来的year是否为闰年//
- {
- if ( ( year % 4 == 0 ) && ( year % 100 != 0 ) || ( year % 400 == 0 ) ) {
- return 0; //是闰年返回值0
- } else
- return 1; //不是闰年返回值1
- }
- //返回这个月一共有多少天
- int days_of_month ( int year , unsigned char month )
- {
- //存储平年每月的天数
- const int month_days [ 12 ] = { 31 , 28 , 31 , 30 , 31 , 30 , 31 , 31 , 30 , 31 , 30 , 31 };
- if ( 2 == month && leapyear ( year ) )
- return 29; // 如果是闰年2月,返回29天
- else
- return month_days [ month - 1 ]; //正常返回
- }
- int days_of_months ( int year , unsigned char month )
- {
- //存储平年每月的天数
- const int month_days [ 12 ] = { 31 , 28 , 31 , 30 , 31 , 30 , 31 , 31 , 30 , 31 , 30 , 31 };
- if ( 2 == month && leapyear ( year ) )
- return 29; // 如果是闰年2月,返回29天
- else
- return month_days [ month - 1 ]; //正常返回
- }
- void Delayms ( unsigned int count ) //延时函数 单位1ms
- {
- unsigned int i , j;
- for ( i = 0; i < count ; i++ )
- for ( j = 0; j < 120 ; j++ )
- ;
- }
- void DisLcdplayDate(void)
- {
-
- strline1 [ 5 ] = times.year / 1000 % 10+'0';
- strline1 [ 6 ] = times.year / 100 % 10+'0';
- strline1 [ 7 ] = times.year / 10 % 10+'0';
- strline1 [ 8 ] = times.year % 10+'0';
- strline1 [ 10 ] = times.month / 10 % 10+'0';
- strline1 [ 11 ] = times.month % 10+'0';
- strline1 [ 13 ] = times.day / 10 % 10+'0';
- strline1 [ 14 ] = times.day % 10+'0';
-
- }
- void DisLcdplayTime(void)
- {
- strline0[5] = times.hour / 10 % 10+'0';
- strline0[6] = times.hour % 10+'0';
- strline0[8] = times.min / 10 % 10+'0';
- strline0[9] = times.min % 10+'0';
- strline0[11] = times.sec / 10 % 10+'0';
- strline0[12] = times.sec % 10+'0';
- }
- void displayLcd(void)
- {
- DisLcdplayDate();
- DisLcdplayTime();
- if(flagset==0)
- {
- LCDPrint(0,0, strline0);
- LCDPrint(0,1, strline1);
- }
- else if(flagset==1)
- {
- LCDPrint(2,0,"Set Year");
- LCDPrint(0,1, strline1);
- }
- else if(flagset==2)
- {
- LCDPrint(2,0,"Set Month");
- LCDPrint(0,1, strline1);
- }
- else if(flagset==3)
- {
- LCDPrint(2,0,"Set Day");
- LCDPrint(0,1, strline1);
- }
- else if(flagset==4)
- {
- LCDPrint(2,0,"Set Hour");
- LCDPrint(0,1, strline0);
- }
- else if(flagset==5)
- {
- LCDPrint(2,0,"Set Min");
- LCDPrint(0,1, strline0);
- }
- else if(flagset==6)
- {
- LCDPrint(2,0,"Set Second");
- LCDPrint(0,1, strline0);
- }
- }
- void TimeRun ( void ) //定时器1s调用一次
- {
- if ( times.sec < 59 ) { //检测秒钟是否大于59
- times.sec++;
- } else {
- times.sec = 0;
- if ( times.min < 59 ) { //检测分钟是否大于59
- times.min++;
- } else {
- times.min = 0;
- if ( times.hour < 23 ) { //检测时大于大于23
- times.hour++;
- } else {
- times.hour = 0;
- if ( times.day < days_of_month ( times.year , times.month ) ) { //检测天数 和年月有关
- times.day++;
- } else {
- times.day = 1;
- if ( times.month < 12 ) { //检测月是否大于12
- times.month++;
- } else {
- times.month = 1;
- times.year++;
- }
- }
- }
- }
- }
- }
- sbit Key0 = P3 ^ 2; //按键定义
- sbit Key1 = P3 ^ 3; //按键定义
- sbit Key2 = P3 ^ 4; //按键定义
-
- void KeyScan()
- {
- if ( Key0 == 0 ) { //设置按键按下 总共5次
- DelaymsLcd(10);
- if ( Key0 == 0 ) {
- if ( flagset < 6 )
- flagset++;
- else
- flagset = 0;
- LCD_Clear();
- while ( Key0 == 0 )
- ;
- }
- }
- if ( Key1 == 0 ) { //加操作
- DelaymsLcd(10);
- if ( Key1 == 0 ) {
- if ( flagset == 1 ) //年加调节
- times.year++;
- if ( flagset == 2 ) { //月加调节
- if ( times.month < 12 )
- times.month++;
- else
- times.month = 1;
- }
- if ( flagset == 3 ) {//天加调节
- if ( times.day < days_of_months ( times.year , times.month ) )
- times.day++;
- else
- times.day = 1;
- }
- if ( flagset == 4 ) { //时加调节
- if ( times.hour < 23 )
- times.hour++;
- else
- times.hour = 0;
- }
- if ( flagset == 5 ) { //分加调节
- if ( times.min < 59 )
- times.min++;
- else
- times.min = 0;
- }
- if ( flagset == 6 ) { //分加调节
- if ( times.sec < 59 )
- times.sec++;
- else
- times.sec = 0;
- }
- while ( Key1 == 0 )
- ;
- }
- }
- if ( Key2 == 0 ) { //减操作
- DelaymsLcd(10);
- if ( Key2 == 0 ) {
- if ( flagset == 1 ) { //减年操作
- if ( times.year > 0 )
- times.year--;
- }
- if ( flagset == 2 ) { //月减操作
- if ( times.month > 1 )
- times.month--;
- else
- times.month = 12;
- }
- if ( flagset == 3 ) { //天减操作
- if ( times.day > 1 )
- times.day--;
- else
- times.day = days_of_months ( times.year , times.month );
- }
- if ( flagset == 4 ) { //时减操作
- if ( times.hour > 0 )
- times.hour--;
- else
- times.hour = 23;
- }
- if ( flagset == 5 ) { //分操作
- if ( times.min > 0 )
- times.min--;
- else
- times.min = 59;
- }
- if ( flagset ==6 ) { //分操作
- if ( times.sec > 0 )
- times.sec--;
- else
- times.sec = 59;
- }
- while ( Key2 == 0 )
- ;
- }
- }
- }
- void main ( )
- {
- int i;
- times.year = 2019; //初始化时间
- times.month = 12;
- times.day = 12;
- times.hour = 7;
- times.min = 59;
- times.sec = 53;
- LCD_Init();
- vTH = ( 65536 - 1000 ) / 256; //计数寄存器高8位
- vTL = ( 65536 - 1000 ) % 256; //计数寄存器低8位
- TH0 = vTH;
- TL0 = vTL;
- TMOD |= 0x01; //工作方式为16位定时器
- ET0 = 0x01; //允许TC0中断
- TR0 = 1;
- EA = 1;
- while ( 1 ) {
- KeyScan();
- displayLcd();
- }
- }
-
- void Time0 ( void )interrupt 1
- {
- static int mil=0;
-
- TH0=vTH;
- TL0=vTL;
-
- if(mil<999) //延时999ms
- {
- mil++;
- }
- else
- {
- mil=0;
- if(flagset==0) TimeRun(); //1s调用一次
- }
- }
复制代码
所有资料51hei提供下载:
758110408keil(1).zip
(163.51 KB, 下载次数: 119)
|