找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2691|回复: 1
收起左侧

以简易数字钟为例 演示LCD1602的综合运用 附仿真与源码

[复制链接]
ID:268717 发表于 2018-7-27 07:20 | 显示全部楼层 |阅读模式
以简易数字钟为例 演示LCD1602的综合运用 程序+仿真+详细注释

仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
0.png 0.png 0.png

单片机源程序如下:
  1. #include<reg52.h>                 
  2. #define uchar  unsigned char
  3. #define uint  unsigned int
  4.   
  5. sbit RS=P3^5;         //寄存器选择位,将RS位定义为P2.0引脚
  6. //sbit RW=P2^1;         //读写选择位,将RW位定义为P2.1引脚
  7. sbit E=P3^4;          //使能信号位,将E位定义为P2.2引脚
  8. //sbit BF=P0^7;         //忙碌标志位,将BF位定义为P0.7引脚
  9.    
  10. uchar code table[]="2018-06-04 WEEK1";    //初始化液晶显示 1602
  11. uchar code table1[]="TIME: 08:01:44";        
  12. uchar count,s1num;  
  13. char second,minute,hour,day,month,year,week;

  14. sbit s1=P2^3;         //功能键
  15. sbit s2=P2^4;         //加键
  16. sbit s3=P2^5;         //减键  
  17. sbit s4=P2^6;         //保存并退出   

  18. void delay(uchar i)   // 延时函数
  19. {
  20.   uchar j;
  21.   while(i--)
  22.   for(j=110;j>0;j--);
  23. }

  24. //uchar BusyTest(void)  // 查忙程序
  25. //{  
  26. //  bit result;  
  27. //  RS=0;               //RS为低电平,RW为高电平时,可以读状态
  28. //  RW=1;  
  29. //  E=1;                //高脉冲写数据
  30. //  delay(4);           //延时,给硬件反应时间  
  31. //  result=BF;          //将忙碌标志电平赋给
  32. //  E=0;                //将E恢复低电平  
  33. //  return result;
  34. //}
  35. void WriteInstruction(uchar dictate)   //写命令操作
  36. {  
  37. //  while(BusyTest()==1);   //如果忙就等待  查忙指令  
  38.   RS=0;                   //RS和R/W同时为低电平时,可以写入指令
  39. //  RW=0;
  40.   E=0;                    //E置低电平(根据指令表,写指令时,E为高脉冲,
  41.   delay(2);               //延时,给硬件反应时间
  42.   P0=dictate;             //将数据送入P0口,即写入指令或地址
  43.   delay(4);               
  44.   E=1;                    //写入脉冲
  45.   delay(4);            
  46.   E=0;                    
  47. }

  48. void WriteData(uchar y)          //写数据操作
  49. {
  50. //  while(BusyTest()==1);
  51.   RS=1;                   //RS为高电平,RW为低电平时,可以写入数据
  52. //  RW=0;
  53.   E=0;                    //E置低电平(根据指令表,写指令时,E为高脉冲,
  54.   P0=y;                   //将数据送入P0口,即将数据写入液晶模块
  55.   delay(4);              
  56.   E=1;                  
  57.   delay(4);
  58.   E=0;
  59. }
  60. void LcdInitiate(void)          //设定初始液晶屏显示数据
  61. {
  62.   uchar num;
  63.   second=44;
  64.   minute=1;
  65.   hour=8;                                  //设定显示时间为08-01-44
  66.   week=1;
  67.   day=4;
  68.   month=6;
  69.   year=18;                                  //设定初始年月日
  70.   count=0;
  71.   s1num=0;
  72.   E=0;
  73.   delay(15);                   //延时15ms,首次写指令时应给LCD一段较长的反应时间
  74.   WriteInstruction(0x38);      //16×2显示,5×7点阵,8位数据接口  0011 1000
  75.   delay(5);                    
  76.   WriteInstruction(0x0c);      //显示开,无光标,光标不闪烁         0000 1100
  77.   delay(5);
  78.   WriteInstruction(0x06);      //光标自动右移,字符不移         0000 0110
  79.   delay(5);
  80.   WriteInstruction(0x01);      //清屏幕指令,将以前的显示内容清除
  81.   delay(5);
  82.   WriteInstruction(0x80);           //设置数据地址指针
  83.   for(num=0;num<16;num++)      //设置第一行的16个显示位·
  84.   {
  85.    WriteData(table[num]);
  86.    delay(5);
  87.   }                                                                                                                 
  88.   WriteInstruction(0x80+0x40); //将液晶屏的数据指针移到第二行第一个字处
  89.   for(num=0;num<14;num++)      //设置第二行的14个显示位
  90.   {
  91.    WriteData(table1[num]);
  92.    delay(5);
  93.   }
  94.   TMOD=0x01;                   //定时器中断初始化 方式1
  95.   TH0=(65536-50000)/256;           //取模  /*方式1低位使用了八位
  96.   TL0=(65536-50000)%256;           //求余   故最大数值为2^8=256       
  97.   EA=1;                                                   //开总中断
  98.   ET0=1;                                           //开内部定时器0中断
  99.   TR0=1;                                           //启动定时器
  100. }




  101. /*      时间日期计算与换算函数和写入输出函数                 */

  102. void write_nyr(uchar add,uchar date)
  103. {
  104.   uchar i,j;
  105.   i=date/10;
  106.   j=date%10;
  107.   WriteInstruction(0x80+add);
  108.   WriteData(0x30+i);
  109.   WriteData(0x30+j);
  110. }
  111. void write_sfm(uchar add,uchar date)
  112. {
  113.   uchar i,j;
  114.   i=date/10;
  115.   j=date%10;
  116.   WriteInstruction(0x80+0x40+add);
  117.   WriteData(0x30+i);
  118.   WriteData(0x30+j);
  119. }
  120. void write_week(uchar add,uchar date)
  121. {
  122.   WriteInstruction(0x80+add);
  123.   WriteData(0x30+date);
  124. }
  125. bit leap_year()
  126. {
  127.   int leap;
  128.   if((year%4==0&&year%100!=0)||year%400==0)
  129.   leap=1;//是闰年
  130.   else  
  131.   leap=0;//非闰年
  132.   return leap;
  133. }

  134. /*      功能键判别函数                 */

  135. void keyscan()
  136. {
  137.   if(s1==0) //第一个键是否按下
  138.   {
  139.    delay(5);
  140.    if(s1==0)
  141.    {
  142.         while(!s1);
  143.         s1num++;
  144.         if(s1num>7)
  145.         s1num=1;
  146.         if(s1num==1)//第一个键被按一次
  147.         {
  148.          TR0=0;
  149.          WriteInstruction(0x80+0x40+13);
  150.          WriteInstruction(0x0f);
  151.         }
  152.         if(s1num==2)
  153.         {
  154.          WriteInstruction(0x80+0x40+10);
  155.         }      
  156.         if(s1num==3)
  157.         {
  158.          WriteInstruction(0x80+0x40+7);
  159.         }
  160.         if(s1num==4)
  161.         {
  162.          WriteInstruction(0x80+9);
  163.         }
  164.         if(s1num==5)
  165.         {
  166.          WriteInstruction(0x80+6);
  167.         }
  168.         if(s1num==6)
  169.         {
  170.          WriteInstruction(0x80+3);
  171.         }
  172.         if(s1num==7)
  173.         {
  174.          WriteInstruction(0x80+15);
  175.         }
  176.    }
  177.   }
  178.   if(s1num!=0) //如果功能键被按下
  179.   {
  180.    if(s2==0) //第二个按下
  181.    {
  182.     delay(5);
  183.         if(s2==0)
  184.         {
  185.          while(!s2);
  186.          if(s1num==1) //第一个键被按一次,秒钟加一
  187.          {
  188.           second++;
  189.           if(second==60)
  190.           second=0;
  191.           write_sfm(12,second);
  192.           WriteInstruction(0x80+0x40+13);
  193.          }
  194.          if(s1num==2) //第一个键被按二次,分钟加一
  195.          {
  196.           minute++;
  197.           if(minute==60)
  198.           minute=0;
  199.           write_sfm(9,minute);
  200.           WriteInstruction(0x80+0x40+10);
  201.          }
  202.          if(s1num==3) //第一个键被按三次,时钟加一
  203.          {
  204.           hour++;
  205.           if(hour==24)
  206.           hour=0;
  207.           write_sfm(6,hour);
  208.           WriteInstruction(0x80+0x40+7);
  209.          }
  210.          if(s1num==4) //第一个键被按四次,日期加一
  211.          {
  212.           day++;
  213.           if(day==32)
  214.           day=1;
  215.           write_nyr(8,day);
  216.           WriteInstruction(0x80+9);
  217.          }
  218.          if(s1num==5) //第一个键被按五次,月加一
  219.          {
  220.           month++;
  221.       if(month==13)
  222.           month=1;
  223.           write_nyr(5,month);
  224.           WriteInstruction(0x80+6);
  225.          }
  226.          if(s1num==6) //年加一
  227.          {
  228.           year++;
  229.           if(year==99)
  230.           year=0;
  231.           write_nyr(2,year);
  232.           WriteInstruction(0x80+3);
  233.          }
  234.          if(s1num==7) //星期加一
  235.          {
  236.           week++;
  237.           if(week==8)
  238.           week=1;
  239.           write_week(15,week);
  240.           WriteInstruction(0x80+15);
  241.          }
  242.         }
  243.    }
  244.   if(s3==0) //第三个键被按下
  245.   {
  246.    delay(5);
  247.    if(s3==0)
  248.    {
  249.     while(!s3);
  250.     if(s1num==1)//秒减一
  251.     {
  252.             second--;
  253.          if(second==-1)
  254.          second=59;
  255.          write_sfm(12,second);
  256.          WriteInstruction(0x80+0x40+13);
  257.         }
  258.         if(s1num==2) //分减一
  259.         {
  260.          minute--;
  261.          if(minute==-1)
  262.          minute=59;
  263.          write_sfm(9,minute);
  264.          WriteInstruction(0x80+0x40+10);
  265.     }
  266.         if(s1num==3) //时减一
  267.         {
  268.          hour--;
  269.          if(hour==-1)
  270.          hour=23;
  271.          write_sfm(6,hour);
  272.          WriteInstruction(0x80+0x40+7);
  273.         }
  274.         if(s1num==4) //日减一
  275.         {
  276.          day--;
  277.          if(day==0)
  278.          day=31;
  279.          write_nyr(8,day);
  280.          WriteInstruction(0x80+9);
  281.         }
  282.         if(s1num==5) //月减一
  283.         {
  284.          month--;
  285.          if(month==0)
  286.          month=12;
  287.          write_nyr(5,month);
  288.          WriteInstruction(0x80+6);
  289.         }
  290.         if(s1num==6) //年减一
  291.         {
  292.          year--;
  293.          if(year==-1)
  294.          year=99;
  295.          write_nyr(2,year);
  296.          WriteInstruction(0x80+3);
  297.         }
  298.         if(s1num==7) //日期减一
  299.         {
  300.          week--;
  301.          if(week==0)
  302.          week=7;
  303.          write_week(15,week);
  304.          WriteInstruction(0x80+15);
  305.         }
  306.    }
  307.   }
  308.   if(s4==0)  //保存并退出   
  309.    {
  310.     s1num=0;
  311.     WriteInstruction(0x0c);
  312.     TR0=1;
  313.    }
  314.   }
  315. }
  316. void main(void)
  317. {
  318.   uchar k=0;
  319.   LcdInitiate(); //调用LCD初始化函数
  320.   while(1)
  321.   {
  322.    keyscan();
  323.    k=1;
  324.   }
  325. }
  326. void timer0() interrupt 1
  327. {
  328.   count++;
  329.   if(count==13)
  330.   {
  331.    count=0;
  332.    second++;
  333.    if(second==60) //秒计满60,秒归0,分+1
  334.    {
  335.     second=0;
  336.         minute++;
  337.         if(minute==60) //分计满60,分归0,时+1
  338.         {
  339.          minute=0;
  340.          hour++;
  341.          if(hour==24) //时计满24,时归0,星期+1,日+1
  342.      {
  343.           hour=0;
  344.           week++;
  345.           day++;
  346.           if(week==8)
  347.           week=1; //星期计满7,星期归1
  348.           if(month==1||month==3||month==5||month==7||month==8||month==10||month==12)//大月三十一天
  349.           {
  350.            if(day==32) //大月天数计满31,日归1,月+1
  351.            {
  352.             day=1;
  353.                 month++;
  354.            }
  355.           }
  356.           if(month==4||month==6||month==9||month==11) //小月三十天
  357.           {
  358.            if(day==31) //小月天数计满30,日归1,月+1
  359.            {
  360. ……………………

  361. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

所有资料51hei提供下载:
20161111144-李作鑫-LCD显示器.rar (81.24 KB, 下载次数: 46)
回复

使用道具 举报

ID:339500 发表于 2018-8-1 15:57 | 显示全部楼层
研究看看你的数字时钟,我的连LCD都弄不上去字
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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