51單片機利用內(nèi)部定時器做的萬年歷仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
51hei.png (16.15 KB, 下載次數(shù): 77)
下載附件
2019-12-22 21:58 上傳
單片機源程序如下:
- #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; // 定義時間參數(shù)結(jié)構(gòu)體
- 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; //定時器參數(shù)
- //判斷年
- 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 )
- {
- //存儲平年每月的天數(shù)
- 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 )
- {
- //存儲平年每月的天數(shù)
- 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 ) //延時函數(shù) 單位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調(diào)用一次
- {
- 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 ) ) { //檢測天數(shù) 和年月有關(guān)
- 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 ) { //設(shè)置按鍵按下 總共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 ) //年加調(diào)節(jié)
- times.year++;
- if ( flagset == 2 ) { //月加調(diào)節(jié)
- if ( times.month < 12 )
- times.month++;
- else
- times.month = 1;
- }
- if ( flagset == 3 ) {//天加調(diào)節(jié)
- if ( times.day < days_of_months ( times.year , times.month ) )
- times.day++;
- else
- times.day = 1;
- }
- if ( flagset == 4 ) { //時加調(diào)節(jié)
- if ( times.hour < 23 )
- times.hour++;
- else
- times.hour = 0;
- }
- if ( flagset == 5 ) { //分加調(diào)節(jié)
- if ( times.min < 59 )
- times.min++;
- else
- times.min = 0;
- }
- if ( flagset == 6 ) { //分加調(diào)節(jié)
- 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; //計數(shù)寄存器高8位
- vTL = ( 65536 - 1000 ) % 256; //計數(shù)寄存器低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調(diào)用一次
- }
- }
復制代碼
所有資料51hei提供下載:
758110408keil(1).zip
(163.51 KB, 下載次數(shù): 119)
2019-12-21 13:47 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|