找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3229|回复: 2
收起左侧

1602LCD+52单片机做的计时器(全程小白亲自注释)

[复制链接]
ID:639140 发表于 2020-2-22 22:33 | 显示全部楼层 |阅读模式
“(分享文件)”
文章出自https://wenku.baidu.com/view/1e5616197375a417866f8f90.html
注释是本人自己添加 按照初学小白的理解 通俗易懂 若有错误请各位指出以免误人子 ,
蜂鸣器  按键 没有测试  水平有限 没看出控制它们程序在那段,请高手指出  自学艰难 全凭前人提携
以下是程序原来的原理图 和我自己开发板的型号(HC6800-MS原理图)官网有资料
捕获.PNG

控制端子已经匹配普中6800开发板
每隔一分钟,蜂鸣器响一次,按键按一下,计数器清0

单片机源程序如下:
  1. #include<reg51.h>
  2. #include<intrins.h>  //intrins.h,函数,应用于程序设计,一般出现在C51单片机编程中,一般程序中需要使用到空指令_nop_();字符循环移位指令_crol_等时使用。
  3.                      //crol_ 字符循环左移
  4.                        //_cror_ 字符循环右移
  5.     //_irol_ 整数循环左移
  6.     //_iror_ 整数循环右移
  7.     //_lrol_ 长整数循环左移
  8.     //_lror_ 长整数循环右移
  9.     //_nop_ 空操作 (相当于8051 NOP 指令)
  10.     //_testbit_ 测试并清零位 (相当于8051 JBC 指令)


  11. #define uchar unsigned char
  12. #define uint unsigned int
  13. sbit RS=P2^6;
  14. sbit RW=P2^5;
  15. sbit EN=P2^7;  
  16. uchar code dis2[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39};  //1-9
  17. uchar code p[]="-";//code 可以不加,加了之后就是固定了这个数组不能对其进行操作、、这个一定要注意。。。

  18. uchar j,k,kk,miao,miao1,fen,fen1,shi,shi1;
  19. void delay_ms(int x)//延时程序,延时1ms
  20. {

  21. uint i;

  22. while(x--)

  23. for(i=0;i<120;i++);
  24. }  
  25. uchar busy()//对LCD1602  判断是否忙

  26. {

  27. uchar status; //声明函数status

  28. RS=0; //读内部寄存器状态算是读指令选择  RS=0指令选择

  29. RW=1; //读操作

  30. EN=1;//使能信号也就是开始工作的意思 ,读操作一直高电平,写操作只是高脉冲

  31. delay_ms(1);

  32. status=P0;  //函数定义为P0,就是说p0是数据口 00-07 8个端子要是07是高电位就是1602忙碌 07是低电平就是闲

  33. EN=0; //读操作完成 拉低使能信号,为下次工作做准备

  34. return status; //return 返回函数 读取完P0口数据返回主函数
  35. }  
  36. void write_cmd(uchar cmd)//写命令程序,首先对其进行判忙

  37. {

  38. while((busy()&0x80)==0x80);//对返回进行或运算判断全1则1,如果为忙就进行等待


  39. RS=0; //命令选择

  40. RW=0; //写操作

  41. EN=0;// 片选信号拉低准备工作

  42. P0=cmd; //函数cmd的数据放到P0上

  43. EN=1; //片选信号开始工作

  44. delay_ms(1);

  45. EN=0;//拉低片选为下次做准备
  46. }  
  47. void write_data(uchar dat) //写数据函数函数dat
  48. {
  49. while((busy()&0x80)==0x80); //忙判断 或-全1则1

  50. RS=1; //数据选择

  51. RW=0; //写操作

  52. EN=0; //片选信号

  53. P0=dat; //P0读取dat

  54. EN=1; //开始传送

  55. delay_ms(1);

  56. EN=0; //拉低片选信号
  57. }  
  58. void canshu() //初始化1602函数  百度一大把
  59. {

  60. write_cmd(0x38);

  61. delay_ms(1);

  62. write_cmd(0x01);

  63. delay_ms(1);

  64. write_cmd(0x06);

  65. delay_ms(1);

  66. write_cmd(0x0c);

  67. delay_ms(1);
  68. }  
  69. *****************************************************************************


  70. ********************************************************************************
  71. /*void xianshi(uchar x,uchar y,uchar *str) //*str是指针字符串的指针,xy可能是数据指针函数
  72. {

  73. uint i=0; //声明函数i并且赋值0

  74. if(y==0) //当函数y=0时 为真  可能是写在第一行的意思

  75. write_cmd(0x80|x); //执行命令x和0x80(1000 0000)相与 全1是1得出命令 执行

  76. if(y==1)  //当函数y=1时 为真  可能是写在第二行的意思

  77. write_cmd(0xc0|x); //执行命令x和0xc0(1100 0000|x)相与 全1是1得出命令 执行 0xc0=0x80+0x40

  78. for(i=0;i<16;i++) //i值循环增加  不知所云

  79. {


  80. write_data(str[i]); //*str是指针字符串的指针,
  81.                     //str[i]的意思可能是把i变成字符串 当数据执行  出自百度介绍 不是很懂


  82. if(p=='\0') //字符串判断结束标志  如果p的ascii码为0  好像是把一个字符串赋值给数组:u8 str1[]={"cxjr.21ic.org"};
  83.               //实际上数组str1在内存中的实际存放情况为:
  84.             //  c x j r . 2 1 i c . o r g '\0'出自百度 介绍

  85.                //这后面的'\0'是由C编译系统自动加上的。所以在用字符串赋初值时一般无须指定数组的长度, 而由系统自行处理。


  86. break;

  87. }
  88. } */

  89. void aaa() interrupt 1 //定时器aaa函数中断入口1
  90. {

  91. TH0=(65535-50000)/256; //50ms一中断

  92. TL0=(65535-50000)%256;

  93. if(++kk==40) //k先+在判断是否=18 kk可能是中断函数 先++在计算是为了从0开始计数 后++可能从1 开始
  94. {
  95. miao++; //kk中断18次时间秒自加1
  96. if(miao==10) //当个位=10
  97. {
  98.     if(miao1++==5) //miao1 自加一次 直到5次以后秒数达到59 后条件导通程序往下一步走
  99.       {
  100.        if(fen++==10)
  101.         {
  102.          if(fen1++==5)
  103.            {
  104.             if(shi++==10)
  105.              {
  106.               
  107.               if(shi1++==1)
  108.                 {
  109.                   shi1=0;
  110.                    shi=0;
  111.                  }
  112.    
  113.                  shi=0;
  114.              }
  115.               fen1=0;
  116.             }
  117.           fen=0;
  118.           }
  119.        miao1=0;
  120.        }
  121.       miao=0;
  122.       }
  123.       kk=0;
  124.      }
  125.     }
  126. void main()  
  127. {
  128. P1=0x00;//我自己加的  要不然 开机显示小黑块  前一个帖子 有介绍 理由参照6800开发板原理图
  129. P2=0X06; //同上   
  130. canshu();
  131. //xianshi(0,0,p);//不清楚
  132. //xianshi(0,1,p+16);// 不清楚
  133. EA=1;
  134.   ET0=1;
  135. TMOD=0x01;
  136. TH0=(65535-50000)/256;//如果不准可对其进行修改,比如4000可能更准确  TL0=(65535-50000)%256;
  137. TL0=(65535-50000)%256;  TR0=1;
  138.   while(1)
  139.    {
  140.      write_cmd(0x80|1); //1000 0001  相与有1则一 这个是时的位置
  141.    
  142.      write_data(dis2[shi]); //dis2[]1-9数组名字 这个是时的显示
  143.      
  144.      write_cmd(0x80|2);//10000010 也就是十六进制0x82代表时的个位显示位置
  145.      
  146.      write_data(dis2[shi1]);//1-9数组选择小时的个位
  147.      
  148.      write_cmd(0x80|3);//地址0x83 在这个地址上写
  149.    
  150.      write_data(p[0]);//数据为第二个数组的0位 这个数组就一个-符号
  151.      write_cmd(0x80|4); //地址0x84  也就是分的十位
  152.      
  153.      write_data(dis2[fen1]); //写数据函数 写数组制定数据到分的十位
  154.      
  155.      write_cmd(0x80|5);//以下类同
  156.    
  157.      write_data(dis2[fen]);
  158.      
  159.      write_cmd(0x80|6);
  160.    
  161.      write_data(p[0]);
  162.      write_cmd(0x80|7);
  163.      
  164.      write_data(dis2[miao1]);

  165.      write_cmd(0x80|8);
  166.      write_data(dis2[miao]);
  167.     }
  168. }
复制代码


评分

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

查看全部评分

回复

使用道具 举报

ID:535242 发表于 2020-2-23 12:57 | 显示全部楼层
目前正在学习  加油
回复

使用道具 举报

ID:639140 发表于 2022-5-3 17:33 | 显示全部楼层
温故而知新 最近在家 又把注释理解添加一遍 按照初学的水平做到注释  很多人说注释做到不规范,这个正常 因为我连规范是什么都不清楚 只当又做了一次笔记

单片机源程序如下:
  1. #include<reg51.h>
  2. #include<intrins.h>  //intrins.h,函数,应用于程序设计,一般出现在C51单片机编程中,一般程序中需要使用到空指令_nop_();字符循环移位指令_crol_等时使用。
  3.                      //crol_ 字符循环左移
  4.                        //_cror_ 字符循环右移
  5.     //_irol_ 整数循环左移
  6.     //_iror_ 整数循环右移
  7.     //_lrol_ 长整数循环左移
  8.     //_lror_ 长整数循环右移
  9.     //_nop_ 空操作 (相当于8051 NOP 指令)
  10.     //_testbit_ 测试并清零位 (相当于8051 JBC 指令)


  11. #define uchar unsigned char

  12. #define uint unsigned int

  13. sbit RS=P2^6;

  14. sbit RW=P2^5;

  15. sbit EN=P2^7;  

  16. uchar code dis2[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39};  //1-9

  17. uchar code p[]="-";//code 可以不加,加了之后就是固定了这个数组不能对其进行操作、、这个一定要注意。。。

  18. uchar j,k,kk,miao,miao1,fen,fen1,shi,shi1;

  19. void delay_ms(int x)//延时程序,延时1ms

  20.   {

  21.     uint i;

  22.     while(x--)

  23.     for(i=0;i<120;i++);
  24.    }  
  25.     uchar busy()//对LCD1602  判断是否忙

  26.      {

  27.        uchar status; //声明函数status

  28.        RS=0; //读内部寄存器状态算是读指令选择  RS=0指令选择

  29.        RW=1; //读操作

  30.        EN=1;//使能信号也就是开始工作的意思 ,读操作一直高电平,写操作只是高脉冲

  31.        delay_ms(1);

  32.        status=P0;  //status是子函数声明的函数入口函数定义为P0,就是说p0是数据口 00-07 8个端子要是07是高电位就是1602忙碌 07是低电平就是闲,status是子函数声明的函数入口

  33.        EN=0;       //读操作完成 拉低使能信号,为下次工作做准备

  34.        return status; //return 返回函数 读取完P0口数据返回主函数
  35.       }  
  36.       


  37.        void write_cmd(uchar cmd)//写命令程序,首先对其进行判忙

  38.         {

  39.             while((busy()&0x80)==0x80);//对返回进行或运算判断全1则1,如果为忙就进行等待


  40.             RS=0; //命令选择

  41.             RW=0; //写操作

  42.             EN=0;// 片选信号拉低准备工作

  43.             P0=cmd; //函数cmd的数据放到P0上

  44.             EN=1; //片选信号开始工作

  45.             delay_ms(1);

  46.             EN=0;//拉低片选为下次做准备
  47.          }  


  48. void write_data(uchar dat) //写数据函数函数dat
  49.   {
  50.     while((busy()&0x80)==0x80); //忙判断 或-全1则1

  51.     RS=1; //数据选择

  52.     RW=0; //写操作

  53.     EN=0; //片选信号

  54.     P0=dat; //P0读取dat

  55.     EN=1; //开始传送

  56.     delay_ms(1);

  57.     EN=0; //拉低片选信号
  58.   }  
  59. void canshu() //初始化1602函数  百度一大把
  60. {

  61. write_cmd(0x38); //写命令函数 命令数据0X38=111000,初始化设置16*2显示 5*7点阵,8为数据接口

  62. delay_ms(1);

  63. write_cmd(0x01);//清屏

  64. delay_ms(1);

  65. write_cmd(0x06);//指针自动加1

  66. delay_ms(1);

  67. write_cmd(0x0c);//开光标显示 不显示

  68. delay_ms(1);
  69. }  
  70. *****************************************************************************

  71.           这里没有数据地址命令 因为数据地址再别的函数里面给定

  72. ********************************************************************************


  73. /*void xianshi(uchar x,uchar y,uchar *str) //*str是指针字符串的指针,xy可能是数据指针函数
  74. {

  75. uint i=0; //声明函数i并且赋值0

  76. if(y==0) //当函数y=0时 为真  可能是写在第一行的意思

  77. write_cmd(0x80|x); //执行命令x和0x80(1000 0000)相与 全1是1得出命令 执行

  78. if(y==1)  //当函数y=1时 为真  可能是写在第二行的意思

  79. write_cmd(0xc0|x); //执行命令x和0xc0(1100 0000|x)相与 全1是1得出命令 执行 0xc0=0x80+0x40

  80. for(i=0;i<16;i++) //i值循环增加  不知所云

  81. {


  82. write_data(str[i]); //*str是指针字符串的指针,
  83.                     //str[i]的意思可能是把i变成字符串 当数据执行  出自百度介绍 不是很懂


  84. if(p=='\0') //字符串判断结束标志  如果p的ascii码为0  好像是把一个字符串赋值给数组:u8 str1[]={"0000.0000.000"};
  85.               //实际上数组str1在内存中的实际存放情况为:
  86.             // '\0'出自百度 介绍

  87.                //这后面的'\0'是由C编译系统自动加上的。所以在用字符串赋初值时一般无须指定数组的长度, 而由系统自行处理。


  88. break;

  89. }
  90. } */  8*******************************************************

  91.      废函数卧槽 刚发现源程序这个子函数开头有斜杠 是个废函数
  92.    

  93.      **************************************************************



  94. void aaa() interrupt 1 //定时器aaa函数中断入口1
  95. {

  96.   TH0=(65535-50000)/256; //50ms一中断

  97.    TL0=(65535-50000)%256;

  98.    if(++kk==40) //****************k先+在判断是否=40 kk可能是中断函数 先++在计算是为了从0开始计数 后++可能从1 开始   语法格式等同于   ++kk
  99.                  ********************kk是全局变量                                                                                  if(k=40)
  100.    {
  101.      miao++; //********************kk中断40次时间秒自加1
  102.      
  103.      if(miao==10) //当个位=10
  104.        {
  105.           if(miao1++==5) //miao1 自加一次 直到5次以后秒数达到59 后条件导通程序往下一步走
  106.             {
  107.               if(fen++==10)
  108.                 {
  109.                   if(fen1++==5)
  110.                    {
  111.                      if(shi++==10)
  112.                       {
  113.               
  114.                        if(shi1++==1)
  115.                         {
  116.                           shi1=0;
  117.                            shi=0;
  118.                         }
  119.    
  120.                        shi=0;
  121.                       }
  122.                     fen1=0;
  123.                     }
  124.                      fen=0;
  125.                  }
  126.        miao1=0;
  127.        }
  128.       miao=0;
  129.       }
  130.       kk=0;
  131.      }
  132.     }
  133. void main()  
  134. {
  135. P1=0x00;//我自己加的  要不然 开机显示小黑块  前一个帖子 有介绍 理由参照6800开发板原理图

  136. P2=0X06; //同上   

  137. canshu();// //初始化1602函数  百度一大把

  138. xianshi(0,0,p);//子函数 没用  //

  139. xianshi(0,1,p+16);// 子函数 没用
  140. EA=1;
  141.   
  142. ET0=1;

  143. TMOD=0x01;

  144. TH0=(65535-50000)/256;//如果不准可对其进行修改,比如4000可能更准确  TL0=(65535-50000)%256;

  145. TL0=(65535-50000)%256;  TR0=1;
  146.   while(1)
  147.    {
  148.      write_cmd(0x80|1); //*********************1000 0001  相与有1则一 这个是时的位置               光标起始位置加一是小时十位的位置
  149.    
  150.      write_data(dis2[shi]); //************* //dis2[]1-9数组名字 这个是时的显示  
  151.                                 

  152.                                   write_data写数据函数 数据内容是数组dis2(全局变量)
  153.                                 

  154.                                   shi也是全局变量 shi=1 显示数组第一个字符1
  155.      
  156.      


  157. write_cmd(0x80|2);//10000010 也就是十六进制0x82代表时的个位显示位置
  158.      
  159.      write_data(dis2[shi1]);//1-9数组选择小时的个位
  160.      
  161.      write_cmd(0x80|3);//地址0x83 在这个地址上写
  162.    
  163.      write_data(p[0]);//数据为第二个数组的0位 这个数组就一个-符号
  164.      write_cmd(0x80|4); //地址0x84  也就是分的十位
  165.      
  166.      write_data(dis2[fen1]); //写数据函数 写数组制定数据到分的十位
  167.      
  168.      write_cmd(0x80|5);//以下类同
  169.    
  170.      write_data(dis2[fen]);
  171.      
  172.      write_cmd(0x80|6);
  173.    
  174.      write_data(p[0]);
  175.      write_cmd(0x80|7);
  176.      
  177.      write_data(dis2[miao1]);

  178.      write_cmd(0x80|8);
  179.      write_data(dis2[miao]);
  180.     }
  181. }
复制代码

回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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