找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 14166|回复: 31
收起左侧

带农历的电子万年历 单片机软件程序与proteus仿真

  [复制链接]
ID:161991 发表于 2017-1-16 11:35 | 显示全部楼层 |阅读模式
电子万年历软件程序。整个软件程序分模块编写:

      1.包含主程序模块main.c

      2.日历时钟程序模块ds1302.c

      3.年历转换程序模块lunarc.c

      4.键盘处理程序模块keyinput.c

      5.液晶显示程序模块12864.h

      6.字模模块model.h

WIN_20170116_112412.JPG
0.png

单片机主程序:
  1. #include <reg52.h>
  2. #include "12864.h"
  3. #include "model.h"
  4. #include "ds1302.h"
  5. #include "lunar.h"
  6. #include "keyinput.h"

  7. #define uchar unsigned char
  8. #define uint unsigned int
  9. #define NoUpLine         1
  10. #define UpLine           0
  11. #define NoUnderLine 1
  12. #define UnderLine        0
  13. #define FALSE        0
  14. #define TRUE    1

  15. uchar dispBuf[7];
  16. uchar T0_Count=0,Tmp_Count=0;
  17. bit T0_Flag,Tmp_Flag,Flash_Flag;

  18. SYSTIME sys;                   //系统日期
  19. SPDATE SpDat;                   //农历日期

  20. bit Hour_Flag=TRUE,Min_Flag=TRUE,Sec_Flag=TRUE;           //设置时间标志
  21. bit Year_Flag=TRUE,Mon_Flag=TRUE,Day_Flag=TRUE;

  22. uchar State_Set=0;     //设置时、分、秒、日、月、年等状态

  23. bit State_Flag=FALSE,Inc_Flag=FALSE,Dec_Flag=FALSE;        //三个按键是否按下的标志

  24. uchar code Mon2[2][13]={0,31,28,31,30,31,30,31,31,30,31,30,31,
  25.                                   0,31,29,31,30,31,30,31,31,30,31,30,31};

  26. /*****************************LCD显示函数******************************
  27. 入口参数:
  28.                 cDat:                要显示的数
  29.                 X:                        行数 0~7
  30.                 Y:          列数 0~127
  31.                 show_flag:  是否反白显示,0反白,1不反白
  32.                 upline:         上划线, 0表示带上划线
  33.                 underline:  下划线, 0表示带下划线
  34. ***********************************************************************/
  35. void LCD_ShowTime(char cDat,uchar X,uchar Y,bit show_flag,bit up,bit under){
  36.         uchar s[2];
  37.            s[0]=cDat/10+'0';
  38.         s[1]=cDat%10+'0';
  39.         en_disp(X,Y,2,Asc,s,show_flag,up,under);
  40. }
  41.                                                                                                                                   
  42. void Show_YMD(){          //年、月、日、星期、显示函数
  43.         uchar uiTempDat;
  44.            uiTempDat=RDS1302(0x88|0x01);
  45.         sys.cMon=((uiTempDat&0x1f)>>4)*10+(uiTempDat&0x0f);       
  46.         LCD_ShowTime(sys.cMon,2,5,Mon_Flag,NoUpLine,NoUnderLine);       
  47.         hz_disp(4,5,1,uMod[1],1,NoUpLine,NoUnderLine);                                //月
  48.         Show16X32(2,27,ucNum3216[sys.cDay/10],Day_Flag);                        //日
  49.         Show16X32(2,43,ucNum3216[sys.cDay%10],Day_Flag);                         
  50.         hz_disp(6,8,2,ucLunar[13],1,UpLine,UnderLine);                                            
  51.         if(sys.cWeek==7)
  52.         hz_disp(6,40,1,uMod[2],1,UpLine,UnderLine);                                        //星期
  53.         else
  54.     hz_disp(6,40,1,ucLunar[sys.cWeek],1,UpLine,UnderLine);                //星期
  55.     LCD_ShowTime(20,0,9,1,UpLine,UnderLine);
  56.           LCD_ShowTime(sys.cYear,0,25,Year_Flag,UpLine,UnderLine);
  57.     hz_disp(0,41,1,uMod[0],1,UpLine,UnderLine);                                        //年

  58.         SpDat=GetSpringDay(sys.cYear,sys.cMon,sys.cDay);                        //获得农历
  59.     if(SpDat.cMon==1)                                                                                           //显示农历月
  60.           hz_disp(4,64,1,ucLunar[15],1,UpLine,NoUnderLine);                        //"正"
  61.         else if(SpDat.cMon==11)
  62.           hz_disp(4,64,1,ucLunar[16],1,UpLine,NoUnderLine);                        //"冬"
  63.         else if(SpDat.cMon==12)
  64.           hz_disp(4,64,1,ucLunar[17],1,UpLine,NoUnderLine);                        //"腊"
  65.         else
  66.           hz_disp(4,63,1,ucLunar[SpDat.cMon],1,UpLine,NoUnderLine); //"二"~"十"
  67.          if(SpDat.cDay/10==1 && SpDat.cDay%10>0)                                        //显示"十" 例如"十四"而不是"一四"
  68.          hz_disp(4,95,1,ucLunar[10],1,UpLine,NoUnderLine);
  69.          else if(SpDat.cDay/10==2 && SpDat.cDay%10>0)               //显示"廿" 例如"廿三"而不是"二四"
  70.          hz_disp(4,95,1,ucLunar[19],1,UpLine,NoUnderLine);
  71.          else
  72.          hz_disp(4,95,1,ucLunar[SpDat.cDay/10],1,UpLine,NoUnderLine);  //正常数字
  73.         if(!(SpDat.cDay%10))                                                                        //"十"
  74.          hz_disp(4,111,1,ucLunar[10],1,UpLine,NoUnderLine);
  75.         else                                                                                                                //正常数字
  76.          hz_disp(4,111,1,ucLunar[SpDat.cDay%10],1,UpLine,NoUnderLine);

  77.          hz_disp(0,104,1,SX[(uint)(2000+SpDat.cYear)%12],1,UpLine,UnderLine);   //生肖

  78.          hz_disp(2,95,1,TianGan[(uint)(2000+SpDat.cYear)%10],1,NoUpLine,NoUnderLine); //天干
  79.          hz_disp(2,111,1,DiZhi[(uint)(2000+SpDat.cYear)%12],1,NoUpLine,NoUnderLine);  //地支
  80. }

  81. void LCD_ShowWNL(){          //万年历显示函数
  82.         LCD_ShowTime(sys.cSec,6,111,Sec_Flag,UpLine,UnderLine);                 //秒,每秒钟刷新
  83.         if(!sys.cSec || State_Set)                                                                     //分,普通模式每分钟刷新
  84.         LCD_ShowTime(sys.cMin,6,87,Min_Flag,UpLine,UnderLine);                 //    设置模式每次刷新
  85.          
  86.         if(!sys.cSec && !sys.cMin || State_Set)                                                 //时,普通模式每小时刷新
  87.     LCD_ShowTime(sys.cHour,6,63,Hour_Flag,UpLine,UnderLine);     //    设置模式每次刷新
  88.        
  89.         if(!sys.cSec && !sys.cMin && !sys.cHour || State_Set ){      //公历农历的年、月、日、星期
  90.                 Show_YMD();                                                                                                 //普通模式每天刷新
  91.                 if(State_Set==7) State_Set=0;                                                         //设置模式每次刷新
  92.         }       
  93. }

  94. void CAL_Init(){        //日期初始化函数
  95.         sys.cYear=0x13;        //BCD码表示的日历时间值
  96.         sys.cMon=0x06;
  97.         sys.cDay=0x030;
  98.         sys.cHour=0x23;
  99.         sys.cMin=0x59;
  100.         sys.cSec=0x55;
  101.         sys.cWeek=GetWeekDay(sys.cYear,sys.cMon,sys.cDay);
  102. }

  103. void SFR_Init(){                 //定时器1初始化函数
  104.         Flash_Flag=FALSE;
  105.         TMOD=0x11;
  106.         ET1=1;
  107.         TH1= (-10000)/256;
  108.         TL1= (-10000)%256;
  109.         EA=1;
  110. }

  111. void GUI_Init(){         //LCD图形初始化函数
  112.          LCD12864_init();
  113.          ClearLCD();
  114.          Rect(0,0,127,63,1);   //描绘框架
  115.          Line(62,0,62,62,1);
  116.          Line(0,48,127,48,1);
  117.          Line(0,15,127,15,1);
  118.          Line(24,15,24,48,1);
  119.          Line(63,32,128,32,1);

  120.          SetTime(sys);                                   //设置时间
  121.          GetTime(&sys);                                   //获得时间
  122.          
  123.          Show_YMD();
  124.          LCD_ShowTime(sys.cSec,6,111,Sec_Flag,UpLine,UnderLine);
  125.          en_disp(6,103,1,Asc,":",1,UpLine,UnderLine);
  126.          LCD_ShowTime(sys.cMin,6,87,Min_Flag,UpLine,UnderLine);
  127.          en_disp(6,79,1,Asc,":",1,UpLine,UnderLine);         
  128.      LCD_ShowTime(sys.cHour,6,63,Hour_Flag,UpLine,UnderLine);

  129.          hz_disp(2,64,1,ucLunar[11],1,NoUpLine,NoUnderLine);           //"农"
  130.          hz_disp(2,80,1,ucLunar[12],1,NoUpLine,NoUnderLine);           //"历"
  131.          hz_disp(4,79,1,uMod[1],1,UpLine,NoUnderLine);                           //"月"
  132. }

  133. void DecToBCD(){   //二-十进制转换函数
  134.         sys.cHour=(((sys.cHour)/10)<<4)+((sys.cHour)%10);
  135.         sys.cMin=(((sys.cMin)/10)<<4)+((sys.cMin)%10);
  136.         sys.cSec=((sys.cSec/10)<<4)+((sys.cSec)%10);
  137.           sys.cYear=((sys.cYear/10)<<4)+((sys.cYear)%10);
  138.         sys.cMon=((sys.cMon/10)<<4)+((sys.cMon)%10);
  139.         sys.cDay=((sys.cDay/10)<<4)+((sys.cDay)%10);
  140. }

  141. void Time_Set(){   //时间设置函数
  142.         if(State_Flag){                                        //设置键按下
  143.                 State_Flag=FALSE;
  144.                 State_Set++;
  145.                 if(State_Set==8) State_Set=0;
  146.         }

  147.         Hour_Flag=TRUE;Min_Flag=TRUE;Sec_Flag=TRUE;
  148.     Year_Flag=TRUE;Mon_Flag=TRUE;Day_Flag=TRUE;

  149.         switch(State_Set){              //设置类型
  150.                         case 0:                 //无设置
  151.                                 break;
  152.                         case 1:                                        //设置时
  153.                                 Hour_Flag=FALSE;
  154.                                 break;
  155.                         case 2:                                           //设置分
  156.                                 Min_Flag=FALSE;
  157.                                 break;
  158.                         case 3:                                         //设置秒
  159.                                 Sec_Flag=FALSE;
  160.                                 break;
  161.                         case 4:                                        //设置天
  162.                                  Day_Flag=FALSE;
  163.                                 break;
  164.                         case 5:
  165.                                  Mon_Flag=FALSE;     //设置月
  166.                                 break;
  167.                         case 6:
  168.                                  Year_Flag=FALSE;        //设置年
  169.                             break;
  170.                         case 7:                                        //无动作,设置此值为让"年"的反白消失。
  171.                                 break;
  172.           }          
  173.           
  174.         if(Inc_Flag){                                        //加键被按下
  175.                 Inc_Flag=FALSE;
  176.                 switch(State_Set)                {
  177.                         case 0:
  178.                                 break;
  179.                         case 1:                                            //小时加
  180.                                 sys.cHour++;
  181.                                 (sys.cHour)%=24;
  182.                                 break;
  183.                         case 2:                                            //分加1
  184.                                 sys.cMin++;
  185.                                 sys.cMin%=60;
  186.                                 break;
  187.                         case 3:                                         //秒加1
  188.                             sys.cSec++;
  189.                                 sys.cSec%=60;
  190.                                 break;
  191.                         case 4:                                         //天加1
  192.                                 (sys.cDay)=(sys.cDay%Mon2[YearFlag(sys.cYear)][sys.cMon])+1;                  
  193.                                 break;
  194.                         case 5:                                         //月加1
  195.                                 sys.cMon=(sys.cMon%12)+1;
  196.                                 break;
  197.                         case 6:
  198.                                 sys.cYear++;                 //年加1
  199.                                 sys.cYear=sys.cYear%100;
  200.                         break;
  201.                   }       
  202.                 DecToBCD();                                        //转为BCD数
  203.                 sys.cWeek=GetWeekDay(sys.cYear,sys.cMon,sys.cDay);    //算出星期
  204.                 SetTime(sys);                            //存入DS1302
  205.         }

  206.         if(Dec_Flag){                                         //减键按下
  207.                 Dec_Flag=FALSE;
  208.                 switch(State_Set){
  209.                         case 0:
  210.                                 break;
  211.                         case 1:          
  212.                                 sys.cHour=(sys.cHour+23)%24;  //时减1
  213.                                 break;
  214.                         case 2:                                                            //分减1
  215.                                 sys.cMin=(sys.cMin+59)%60;
  216.                                 break;
  217.                         case 3:                                                          //秒减1
  218.                                 sys.cSec=(sys.cSec+59)%60;
  219.                                 break;
  220.                         case 4:                                                          //天减1
  221.                                 sys.cDay=((sys.cDay+Mon2[YearFlag(sys.cYear)][sys.cMon]-1)%Mon2[YearFlag(sys.cYear)][sys.cMon]);                  
  222.                                 if(sys.cDay==0) sys.cDay=Mon2[YearFlag(sys.cYear)][sys.cMon];
  223.                                 break;
  224.                         case 5:                                                          //月减1
  225.                                 sys.cMon=(sys.cMon+11)%12;
  226.                                 if(sys.cMon==0) sys.cMon=12;
  227.                                 break;
  228.                         case 6:                                                          //年减1
  229.                                 sys.cYear=(sys.cYear+99)%100;
  230.                                 break;
  231.                   }       
  232.                 DecToBCD();
  233.                 sys.cWeek=GetWeekDay(sys.cYear,sys.cMon,sys.cDay);              
  234.                 SetTime(sys);       
  235.         }
  236. }

  237. void  main(){        //主函数
  238.          SFR_Init();
  239.          CAL_Init();
  240.          GUI_Init();
  241.          TR1=1;
  242.          while(1){
  243.                 GetTime(&sys);                //获得时间
  244.                 LCD_ShowWNL();                //显示万年历
  245.                 Time_Set();         //时间设置
  246.          }       
  247. }

  248. void timer1() interrupt  3 {  //定时器1中断服务函数
  249.         TH1= (-10000)/256;
  250.         TL1= (-10000)%256;
  251.         keyinput();                                        //读取按键
  252.         if (keyvalue&0x10){       
  253.                 State_Flag=TRUE;
  254.                 keyvalue &= 0xef;                //清键值,保证一直按下只执行一次按键动作。
  255.         }       
  256.         if (keyvalue&0x20 ){                //加
  257.                 Inc_Flag=TRUE;
  258.                 keyvalue &= 0xdf;                //清键值,保证一直按下只执行一次按键动作。
  259.         }       
  260.         if (keyvalue&0x40){                        //减
  261.                 Dec_Flag=TRUE;
  262.                 keyvalue &= 0xbf;                //清键值,保证一直按下只执行一次按键动作。
  263.         }
  264.        
  265. }
复制代码

0.png

资料下载:
带农历的万年历.zip (146.45 KB, 下载次数: 399)

评分

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

查看全部评分

回复

使用道具 举报

ID:71282 发表于 2017-2-5 18:42 | 显示全部楼层
谢谢分享,高手啊,有点小问题,12864怎么是黑的呢
回复

使用道具 举报

ID:71282 发表于 2017-2-5 18:51 | 显示全部楼层
12864引脚没有修改好,
应该是
sbit  LCD12864_EN         =P2^4;
sbit  LCD12864_RW         =P2^3;       //0:write ; 1:read
sbit  LCD12864_RS         =P2^2;           //0:the command .1:the data
sbit  LCD12864_CS_L       =P2^0;       //select the left of the lcd when 1
sbit  LCD12864_CS_R       =P2^1;  
sbit  LCD12864_RST                      =P2^5;
程序还有些问题的
回复

使用道具 举报

ID:71282 发表于 2017-2-5 18:54 | 显示全部楼层
运行效果如图
QQ截图20170205185008.jpg
回复

使用道具 举报

ID:76133 发表于 2017-11-17 11:43 | 显示全部楼层

谢谢分享,高手啊
回复

使用道具 举报

ID:252496 发表于 2017-11-26 22:34 | 显示全部楼层
讲真,要是急用就别下载了,浪费黑币,要修改的
回复

使用道具 举报

ID:329035 发表于 2018-5-13 18:33 | 显示全部楼层
学习学习
回复

使用道具 举报

ID:329308 发表于 2018-5-14 09:06 | 显示全部楼层
好东西
回复

使用道具 举报

ID:44037 发表于 2018-5-14 10:32 | 显示全部楼层
好东西  学习一下
2018-05-14_102258.jpg


2018-05-14_102529.jpg


回复

使用道具 举报

ID:350298 发表于 2018-6-12 15:34 | 显示全部楼层
谢谢大神呀,请问一下阳历农历日期是会一起变化的嘛,还是要手调呀
回复

使用道具 举报

ID:368502 发表于 2018-7-11 09:03 | 显示全部楼层
youqq 发表于 2017-2-5 18:51
12864引脚没有修改好,
应该是
sbit  LCD12864_EN         =P2^4;

你好,问一下 这段代码往哪加啊
回复

使用道具 举报

ID:368600 发表于 2018-7-12 10:52 | 显示全部楼层
哇,正好我在做这个,非常感谢
回复

使用道具 举报

ID:370060 发表于 2018-7-12 11:14 | 显示全部楼层
谢谢帮助,绝世神贴
回复

使用道具 举报

ID:360050 发表于 2018-7-25 22:12 | 显示全部楼层
有总程序嘛
回复

使用道具 举报

ID:360050 发表于 2018-7-25 22:58 | 显示全部楼层
楼主有总程序嘛
回复

使用道具 举报

ID:394197 发表于 2018-9-10 10:05 | 显示全部楼层
看不大懂LCD显示的东西
回复

使用道具 举报

ID:136393 发表于 2019-1-15 19:30 | 显示全部楼层
仿真显示屏不显示
回复

使用道具 举报

ID:454000 发表于 2019-1-16 00:48 | 显示全部楼层
不错不错,好例子!

评分

参与人数 3黑币 +65 收起 理由
钻牛尖滴刘尖尖 + 15
sheng7533967 + 15
Sawardeakar + 35

查看全部评分

回复

使用道具 举报

ID:494672 发表于 2019-5-12 15:30 | 显示全部楼层
感谢楼主分享
回复

使用道具 举报

ID:494672 发表于 2019-5-12 16:51 | 显示全部楼层
男人 发表于 2019-1-15 19:30
仿真显示屏不显示

把lcd的引脚改了 8 7 6这几个
回复

使用道具 举报

ID:316703 发表于 2019-5-13 13:13 | 显示全部楼层
改完引脚,编译完有显示了,可是内容布局等不对!
回复

使用道具 举报

ID:316703 发表于 2019-5-13 14:00 | 显示全部楼层
by64214 发表于 2018-5-14 10:32
好东西  学习一下

求高手赐教正确程序,谢谢了
回复

使用道具 举报

ID:316703 发表于 2019-5-13 14:46 | 显示全部楼层
这个程序需要改两个模块的脚定义,
一、显示模块:
1、按电路图改程序:
sbit  LCD12864_EN         =P2^4;
sbit  LCD12864_RW        =P2^3;      
sbit  LCD12864_RS         =P2^2;          
sbit  LCD12864_CS_L      =P2^1;     
sbit  LCD12864_CS_R      =P2^0;  
sbit  LCD12864_RST            =P2^5;

2.按程序修改电路图:
sbit  LCD12864_EN          =P1^2;
sbit  LCD12864_RW         =P1^1;      
sbit  LCD12864_RS          =P1^0;          
sbit  LCD12864_CS_L       =P2^0;      
sbit  LCD12864_CS_R       =P2^1;  
sbit  LCD12864_RST             =P2^5;

二、时钟模块;
1、按电路图改程序:
sbit DS1302_RST=P1^5;        
sbit DS1302_SCLK=P1^6;        

2.按程序修改电路图;
sbit DS1302_RST=P1^6;        
sbit DS1302_SCLK=P1^5;        
回复

使用道具 举报

ID:560874 发表于 2019-6-12 16:36 | 显示全部楼层
feiniao00o 发表于 2019-5-13 14:46
这个程序需要改两个模块的脚定义,
一、显示模块:
1、按电路图改程序:

请问有改完的版本吗?
回复

使用道具 举报

ID:435316 发表于 2019-6-25 22:12 | 显示全部楼层
抄袭的  
回复

使用道具 举报

ID:465318 发表于 2019-6-26 09:24 | 显示全部楼层
by64214 发表于 2018-5-14 10:32
好东西  学习一下

为什么调不动鸭
回复

使用道具 举报

ID:686729 发表于 2020-1-17 15:23 | 显示全部楼层
请问这书上是有的吗,请问书名是什么
回复

使用道具 举报

ID:165276 发表于 2020-2-1 21:09 | 显示全部楼层
casojie 发表于 2020-1-17 15:23
请问这书上是有的吗,请问书名是什么

书名《STC15增强型...》,具体忘了,是基于STC15F2K60S2写的
回复

使用道具 举报

ID:239620 发表于 2020-5-26 15:54 | 显示全部楼层
下载下来学习学习
回复

使用道具 举报

ID:1082181 发表于 2023-6-5 16:21 | 显示全部楼层
如何获得农历日期
回复

使用道具 举报

ID:1106219 发表于 2023-12-26 08:31 | 显示全部楼层
by64214 发表于 2018-5-14 10:32
好东西  学习一下

大神,该如何修改代码呢
回复

使用道具 举报

ID:34149 发表于 2023-12-27 12:04 | 显示全部楼层
12864要有串行方式的程序就更好了
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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