找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4858|回复: 7
收起左侧

51单片机利用内部定时器做的万年历,Proteus仿真+程序

  [复制链接]
ID:586177 发表于 2019-12-21 13:48 | 显示全部楼层 |阅读模式
51单片机利用内部定时器做的万年历仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
51hei.png

单片机源程序如下:
  1. #include "reg52.h"
  2. #include "LCD1602.h"
  3. #include "stdio.h"
  4. #include "math.h"
  5. typedef struct {
  6.         int year;
  7.         unsigned char month;
  8.         unsigned char day;
  9.         unsigned char hour;
  10.         unsigned char min;
  11.         unsigned char sec;
  12. } times_t;         //        定义时间参数结构体
  13. times_t times;

  14. unsigned char strline1[16]="Date:0000-00-00";
  15. unsigned char strline0[16]="Time:00-00-00";



  16. unsigned char vTH , vTL , flagset = 0; //定时器参数
  17. //判断年
  18. int leapyear ( int year ) //判断传来的year是否为闰年//
  19. {
  20.         if ( ( year % 4 == 0 ) && ( year % 100 != 0 ) || ( year % 400 == 0 ) ) {
  21.                 return 0; //是闰年返回值0
  22.         } else
  23.                 return 1; //不是闰年返回值1
  24. }

  25. //返回这个月一共有多少天
  26. int days_of_month ( int year , unsigned char month )
  27. {
  28.         //存储平年每月的天数
  29.         const int month_days [ 12 ] = { 31 , 28 , 31 , 30 , 31 , 30 , 31 , 31 , 30 , 31 , 30 , 31 };
  30.         if ( 2 == month && leapyear ( year ) )
  31.                 return 29; // 如果是闰年2月,返回29天
  32.         else
  33.                 return month_days [ month - 1 ];  //正常返回
  34. }
  35. int days_of_months ( int year , unsigned char month )
  36. {
  37.         //存储平年每月的天数
  38.         const int month_days [ 12 ] = { 31 , 28 , 31 , 30 , 31 , 30 , 31 , 31 , 30 , 31 , 30 , 31 };
  39.         if ( 2 == month && leapyear ( year ) )
  40.                 return 29; // 如果是闰年2月,返回29天
  41.         else
  42.                 return month_days [ month - 1 ];  //正常返回
  43. }

  44. void Delayms ( unsigned int count )        //延时函数 单位1ms
  45. {
  46.         unsigned int i , j;
  47.         for ( i = 0; i < count ; i++ )
  48.                 for ( j = 0; j < 120 ; j++ )
  49.                         ;
  50. }

  51. void DisLcdplayDate(void)
  52. {
  53.   
  54.     strline1 [ 5 ] = times.year / 1000 % 10+'0';
  55.     strline1 [ 6 ] = times.year / 100 % 10+'0';
  56.         strline1 [ 7 ] = times.year / 10 % 10+'0';
  57.         strline1 [ 8 ] = times.year % 10+'0';
  58.         strline1 [ 10 ] = times.month / 10 % 10+'0';
  59.         strline1 [ 11 ] = times.month % 10+'0';
  60.         strline1 [ 13 ] = times.day / 10 % 10+'0';
  61.         strline1 [ 14 ] = times.day % 10+'0';


  62. }

  63. void DisLcdplayTime(void)
  64. {
  65. strline0[5]         = times.hour / 10 % 10+'0';
  66. strline0[6]         = times.hour  % 10+'0';
  67. strline0[8]         = times.min / 10 % 10+'0';
  68. strline0[9]         = times.min  % 10+'0';
  69. strline0[11]         = times.sec / 10 % 10+'0';
  70. strline0[12]         = times.sec  % 10+'0';
  71. }


  72.   void displayLcd(void)
  73.   {
  74.           DisLcdplayDate();
  75.         DisLcdplayTime();
  76.           if(flagset==0)
  77.         {

  78.         LCDPrint(0,0, strline0);
  79.         LCDPrint(0,1, strline1);
  80.         }
  81.         else if(flagset==1)
  82.         {
  83.         LCDPrint(2,0,"Set Year");
  84.         LCDPrint(0,1, strline1);
  85.         }
  86.         else        if(flagset==2)
  87.         {
  88.         LCDPrint(2,0,"Set Month");
  89.         LCDPrint(0,1, strline1);
  90.         }
  91.         else        if(flagset==3)
  92.         {
  93.         LCDPrint(2,0,"Set Day");
  94.         LCDPrint(0,1, strline1);
  95.         }
  96.         else        if(flagset==4)
  97.         {
  98.         LCDPrint(2,0,"Set Hour");
  99.         LCDPrint(0,1, strline0);
  100.         }
  101.         else        if(flagset==5)
  102.         {
  103.         LCDPrint(2,0,"Set Min");
  104.         LCDPrint(0,1, strline0);
  105.         }
  106.                 else        if(flagset==6)
  107.         {
  108.         LCDPrint(2,0,"Set Second");
  109.         LCDPrint(0,1, strline0);
  110.         }
  111.   }
  112. void TimeRun ( void )         //定时器1s调用一次
  113. {
  114.         if ( times.sec < 59 ) {                //检测秒钟是否大于59
  115.                 times.sec++;
  116.         } else {
  117.                 times.sec = 0;
  118.                 if ( times.min < 59 ) {         //检测分钟是否大于59
  119.                         times.min++;
  120.                 } else {
  121.                         times.min = 0;
  122.                         if ( times.hour < 23 ) {   //检测时大于大于23
  123.                                 times.hour++;
  124.                         } else {
  125.                                 times.hour = 0;
  126.                                 if ( times.day < days_of_month ( times.year , times.month ) ) {          //检测天数 和年月有关
  127.                                         times.day++;
  128.                                 } else {
  129.                                         times.day = 1;
  130.                                         if ( times.month < 12 ) { //检测月是否大于12
  131.                                                 times.month++;
  132.                                         } else {
  133.                                                 times.month = 1;
  134.                                                 times.year++;
  135.                                         }
  136.                                 }
  137.                         }

  138.                 }
  139.         }

  140. }

  141. sbit Key0 = P3 ^ 2;        //按键定义
  142. sbit Key1 = P3 ^ 3;          //按键定义
  143. sbit Key2 = P3 ^ 4;          //按键定义

  144.   void KeyScan()
  145.   {
  146.                   if ( Key0 == 0 ) {          //设置按键按下 总共5次
  147.                        DelaymsLcd(10);
  148.                                    if ( Key0 == 0 ) {
  149.                         if ( flagset < 6 )
  150.                                 flagset++;
  151.                         else
  152.                                 flagset = 0;
  153.                                 LCD_Clear();
  154.                         while ( Key0 == 0 )
  155.                                 ;
  156.                                 }
  157.                 }
  158.                 if ( Key1 == 0 ) {         //加操作
  159.                DelaymsLcd(10);
  160.                                    if ( Key1 == 0 ) {
  161.                         if ( flagset == 1 )         //年加调节
  162.                                 times.year++;
  163.                         if ( flagset == 2 ) {          //月加调节
  164.                                 if ( times.month < 12 )
  165.                                         times.month++;
  166.                                 else
  167.                                         times.month = 1;
  168.                         }
  169.                         if ( flagset == 3 ) {//天加调节
  170.                                 if ( times.day < days_of_months ( times.year , times.month ) )
  171.                                         times.day++;
  172.                                 else
  173.                                         times.day = 1;
  174.                         }
  175.                         if ( flagset == 4 ) {  //时加调节
  176.                                 if ( times.hour < 23 )
  177.                                         times.hour++;
  178.                                 else
  179.                                         times.hour = 0;
  180.                         }
  181.                         if ( flagset == 5 ) {         //分加调节
  182.                                 if ( times.min < 59 )
  183.                                         times.min++;
  184.                                 else
  185.                                         times.min = 0;
  186.                         }
  187.                          if ( flagset == 6 ) {         //分加调节
  188.                                 if ( times.sec < 59 )
  189.                                         times.sec++;
  190.                                 else
  191.                                         times.sec = 0;
  192.                         }
  193.                         while ( Key1 == 0 )
  194.                                 ;
  195.                                 }
  196.                 }
  197.                 if ( Key2 == 0 ) {        //减操作
  198.                                           DelaymsLcd(10);
  199.                                    if ( Key2 == 0 ) {
  200.                         if ( flagset == 1 ) {         //减年操作
  201.                                 if ( times.year > 0 )
  202.                                         times.year--;
  203.                         }
  204.                         if ( flagset == 2 ) {         //月减操作
  205.                                 if ( times.month > 1 )
  206.                                         times.month--;
  207.                                 else
  208.                                         times.month = 12;
  209.                         }
  210.                         if ( flagset == 3 ) {         //天减操作
  211.                                 if ( times.day > 1 )
  212.                                         times.day--;
  213.                                 else
  214.                                         times.day = days_of_months ( times.year , times.month );
  215.                         }
  216.                         if ( flagset == 4 ) { //时减操作
  217.                                 if ( times.hour > 0 )
  218.                                         times.hour--;
  219.                                 else
  220.                                         times.hour = 23;
  221.                         }
  222.                         if ( flagset == 5 ) {         //分操作
  223.                                 if ( times.min > 0 )
  224.                                         times.min--;
  225.                                 else
  226.                                         times.min = 59;
  227.                         }
  228.                                 if ( flagset ==6 ) {         //分操作
  229.                                 if ( times.sec > 0 )
  230.                                         times.sec--;
  231.                                 else
  232.                                         times.sec = 59;
  233.                         }
  234.                         while ( Key2 == 0 )
  235.                                 ;
  236.                                 }
  237.                 }
  238.   }
  239. void main ( )
  240. {
  241.         int i;
  242.         times.year = 2019; //初始化时间
  243.         times.month = 12;
  244.         times.day = 12;
  245.         times.hour = 7;
  246.         times.min = 59;
  247.         times.sec = 53;
  248.         LCD_Init();
  249.         vTH = ( 65536 - 1000 ) / 256;                           //计数寄存器高8位
  250.         vTL = ( 65536 - 1000 ) % 256;                           //计数寄存器低8位
  251.         TH0 = vTH;
  252.         TL0 = vTL;
  253.         TMOD |= 0x01;                           //工作方式为16位定时器
  254.         ET0 = 0x01;                           //允许TC0中断
  255.         TR0 = 1;
  256.         EA = 1;
  257.         while ( 1 ) {

  258.         KeyScan();

  259.         displayLcd();         
  260.         }

  261. }



  262. void Time0 ( void )interrupt 1
  263. {
  264.         static int mil=0;

  265.         TH0=vTH;
  266.         TL0=vTL;
  267.          
  268.         if(mil<999)         //延时999ms
  269.         {
  270.                 mil++;
  271.         }
  272.         else
  273.         {
  274.                 mil=0;
  275.                 if(flagset==0) TimeRun(); //1s调用一次
  276.         }
  277. }
复制代码

所有资料51hei提供下载:
758110408keil(1).zip (163.51 KB, 下载次数: 118)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:682186 发表于 2020-1-6 15:58 | 显示全部楼层
楼楼,编译并不成功,LCDPrint(0,0, strline0);这里并没有定义
回复

使用道具 举报

ID:675991 发表于 2020-9-29 13:38 | 显示全部楼层
闰年计算有误吧?
回复

使用道具 举报

ID:870180 发表于 2021-1-5 11:23 | 显示全部楼层
楼主,为啥烧录后,连接线路,lcd只显示下面一行,还只有黑格,一点数据都没有
回复

使用道具 举报

ID:702127 发表于 2021-1-6 14:15 | 显示全部楼层
闰年的返回值反了
回复

使用道具 举报

ID:586177 发表于 2021-4-26 17:43 | 显示全部楼层
羊羊22 发表于 2021-1-5 11:23
楼主,为啥烧录后,连接线路,lcd只显示下面一行,还只有黑格,一点数据都没有

是不是你的电位器没调好
回复

使用道具 举报

ID:586177 发表于 2021-4-26 17:45 | 显示全部楼层
thornthorn1 发表于 2020-1-6 16:00
LCDPrint(0,0, strline0);这里没有定义,无法编译成功

不应该呀,我当时上传的时候是好使的,这个仿真图是论坛管理员仿真截屏的图,是好用的

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:911036 发表于 2021-4-27 06:52 来自手机 | 显示全部楼层
孤独的小黑 发表于 2021-4-26 17:45
不应该呀,我当时上传的时候是好使的,这个仿真图是论坛管理员仿真截屏的图,是好用的

学习,楼主强大!编译仿真成功了 谢谢
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表