找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机定时器LCD显示加音乐加流水灯程序

[复制链接]
ID:230208 发表于 2017-9-5 17:57 | 显示全部楼层 |阅读模式
单片机定时器LCD显示加音乐加流水灯

单片机源程序如下:

  1. #include<reg51.h>       //调用51单片机的头文件
  2. #define uchar unsigned char
  3. #define uint  unsigned  int
  4. //---------------------------------------
  5. //1602液晶相关I/O设置
  6. //sbit E=P2^3;               //1602液晶的E脚接在P2.3口上
  7. //sbit RW=P2^4;              //1602液晶的RW脚接在P2.4口上
  8. //sbit RS=P2^5;              //1602液晶的RS脚接在P2.5口上
  9. sbit E=P2^7;               //1602液晶的E脚接在P2.3口上
  10. sbit RW=P2^5;              //1602液晶的RW脚接在P2.4口上
  11. sbit RS=P2^6;              //1602液晶的RS脚接在P2.5口上
  12. sbit Busy=P0^7;

  13. //按键相关I/O设置
  14. sbit key1=P3^0;
  15. sbit key2=P3^1;
  16. sbit key3=P3^2;

  17. //sbit beep = P1^3;
  18. sbit beep = P1^5;

  19. uchar code word1[]={"   TIME  STOP   "};
  20. uchar code word2[]={"   TIME  SET!   "};
  21. uchar code word3[]={"   TIME  START  "};
  22. //---------------------------------------
  23. unsigned char i;
  24. unsigned char menu;
  25. signed int Time_bai,Time_ge;
  26. bit Adjust;
  27. //---------------------------------------
  28. //1602液晶寄存器设置
  29. unsigned int  DISbuf_ge,DISbuf_bai;     //设置16位的unsigend int型寄存器用来暂存1602要显示的内容
  30. //---------------------------------------
  31. uchar code SONG_TONE[]={212,212,190,212,159,169,212,212,190,212,142,159,

  32. 212,212,106,126,159,169,190,119,119,126,159,142,159,0};


  33. uchar code SONG_LONG[]={9,3,12,12,12,24,9,3,12,12,12,24,

  34. 9,3,12,12,12,12,12,9,3,12,12,12,24,0};
  35. void Display();
  36. void DelayMS(uint ms)
  37. {
  38.         uchar t;
  39.         while(ms--)
  40.         {
  41.                  for(t=0;t<120;t++);
  42.         }
  43. }
  44. void PlayMusic()

  45. {

  46.         uint i=0,j,k;
  47.        
  48.         while(SONG_LONG[i]!=0||SONG_TONE[i]!=0)
  49.        
  50.         { //播放各个音符,SONG_LONG 为拍子长度
  51.        
  52.                 for(j=0;j<SONG_LONG[i]*20;j++)
  53.                
  54.                 {
  55.                
  56.                         beep=~beep;
  57.                         if(Adjust==1)
  58.                                 break;
  59.                        
  60.                         //SONG_TONE 延时表决定了每个音符的频率
  61.                        
  62.                         for(k=0;k<SONG_TONE[i]/3;k++);
  63.                
  64.                 }
  65.                
  66.                  DelayMS(70);
  67.                  i++;
  68.        
  69.         }

  70. }
  71. void led()
  72. {
  73.         P2 = P2 << 1;           //第一次循环,led1亮,其他都不亮
  74.         if(P2 == 0x00)     //全部移出
  75.         P2 = 0x01;
  76. }
  77. //---------------------------------------
  78. //名称:1602液晶用延时函数
  79. //---------------------------------------
  80. void Delay1602(unsigned int t)
  81. {
  82.      unsigned int k;      //定义一个16位寄存器用来做延时用
  83.      for(k=0;k<t;k++);    //延时
  84. }

  85. //---------------------------------------
  86. //名称:1602液晶忙检测函数
  87. //---------------------------------------
  88. void LCD1602_busy(void)
  89. {
  90.      Busy=1;              //将P0.7置1,为读状态做准备
  91.      RS=0;                //RS=0、RW=1、E=1时,忙信号输出到DB7,由P0.7读入
  92.      RW=1;                //RS=0、RW=1、E=1时,忙信号输出到DB7,由P0.7读入
  93.      E=1;                 //RS=0、RW=1、E=1时,忙信号输出到DB7,由P0.7读入
  94.      while(Busy==1);      //由P0.7读入1,表示1602液晶忙,需要等待
  95.      E=0;                 //读完以后,恢复E的电平
  96. }

  97. //---------------------------------------
  98. //名称:1600写命令函数
  99. //适用:给力者GL9单片机开发学习系统
  100. //公司:宁波芯动电子有限公司
  101. //网址:www.MovingChip.com
  102. //日期:20120914
  103. //---------------------------------------
  104. void LCD1602_Write_com(unsigned char combuf)
  105. {
  106.      RS=0;                //选择指令寄存器
  107.      RW=0;                //选择写状态
  108.      P0=combuf;           //将命令字通过P0口送至DB
  109.      E=1;                 //E高电平将命令字写入1602液晶
  110.      E=0;                 //写完以后,恢复E的电平
  111. }

  112. //---------------------------------------
  113. //名称:1602写命令函数(带忙检测)
  114. //---------------------------------------
  115. void LCD1602_Write_com_busy(unsigned char combuf)
  116. {
  117.      LCD1602_busy();            //调用忙检测函数
  118.      LCD1602_Write_com(combuf); //调用忙检测函数
  119. }

  120. //---------------------------------------
  121. //名称:1602写数据函数(带忙检测)
  122. //---------------------------------------
  123. void LCD1602_Write_data_busy(unsigned char databuf)
  124. {
  125.      LCD1602_busy();      //调用忙检测函数
  126.      RS=1;                //选择数据寄存器
  127.      RW=0;                //选择写状态
  128.      P0=databuf;          //将命令字通过P0口送至DB
  129.      E=1;                 //E高电平将命令字写入1602液晶
  130.      E=0;                 //写完以后,恢复E的电平
  131. }

  132. //---------------------------------------
  133. //名称:1602液晶显示地址写函数
  134. //适用:给力者GL9单片机开发学习系统
  135. //公司:宁波芯动电子有限公司
  136. //网址:www.MovingChip.com
  137. //日期:20120914
  138. //---------------------------------------
  139. void LCD1602_Write_address(unsigned char x,unsigned char y)
  140. {
  141.      x&=0x0f;             //列地址限制在0-15间
  142.      y&=0x01;             //行地址限制在0-1间
  143.      if(y==0)             //如果是第一行
  144.          LCD1602_Write_com_busy(x|0x80);        //将列地址写入
  145.      else                 //如果是第二行
  146.          LCD1602_Write_com_busy((x+0x40)|0x80); //将列地址写入
  147. }

  148. //---------------------------------------
  149. //名称:1602液晶初始化函数
  150. //---------------------------------------
  151. void LCD1602_init(void)
  152. {
  153.      Delay1602(1500);               //调用延时函数
  154.      LCD1602_Write_com(0x38);       //8位数据总线,两行显示模式,5*7点阵显示
  155.      Delay1602(500);                //调用延时函数
  156.      LCD1602_Write_com(0x38);       //8位数据总线,两行显示模式,5*7点阵显示
  157.      Delay1602(500);                //调用延时函数
  158.      LCD1602_Write_com(0x38);       //8位数据总线,两行显示模式,5*7点阵显示
  159.      LCD1602_Write_com_busy(0x38);  //8位数据总线,两行显示模式,5*7点阵显示
  160.      LCD1602_Write_com_busy(0x08);  //显示功能关,无光标
  161.      LCD1602_Write_com_busy(0x01);  //清屏
  162.      //LCD1602_Write_com_busy(0x06);  //写入新的数据后,光标右移,显示屏不移动
  163.      LCD1602_Write_com_busy(0x0C);  //显示功能开,无光标
  164. }

  165. //---------------------------------------
  166. //名称:1602液晶指定地址显示函数
  167. //---------------------------------------
  168. void LCD1602_Disp(unsigned char x,unsigned char y,unsigned char buf)
  169. {
  170.      LCD1602_Write_address(x,y);    //先将地址信息写入
  171.      LCD1602_Write_data_busy(buf);  //再写入要显示的数据
  172. }

  173. //---------------------------------------
  174. //名称:1602液晶将字符输出到液晶显示
  175. //---------------------------------------
  176. void Print(unsigned char x,unsigned char y,unsigned char *str)
  177. {
  178.     LCD1602_Write_address(x,y);
  179.         while(*str!='\0')
  180.     {
  181.         LCD1602_Write_data_busy(*str);
  182.         str++;
  183.     }
  184. }
  185. //---------------------------------------
  186. //名称:Delay10ms延时10毫秒函数
  187. //---------------------------------------
  188. void Delay10ms(void)   //误差 0us
  189. {
  190.     unsigned char a,b,c;
  191.     for(c=1;c>0;c--)
  192.         for(b=38;b>0;b--)
  193.             for(a=130;a>0;a--);
  194. }
  195. void keyscan()
  196. {
  197.         if(key1==0)                //检测按键K1是否按下
  198.         {
  199.                 Delay10ms();        //消除抖动
  200.                 while(key1==0);
  201.                 menu++;
  202.                 if(menu==3)
  203.                         menu=1;
  204.                 Adjust=1;
  205.         }
  206.         if(menu==1)
  207.         {       
  208.                 Print(0,0,word2);
  209.                 DISbuf_bai=0;
  210.                 DISbuf_ge=0;
  211.                 LCD1602_Disp(2,1,DISbuf_bai/1000+'0');       //在第1行的第1列显示千位
  212.               LCD1602_Disp(3,1,(DISbuf_bai%1000)/100+'0'); //在第1行的第2列显示百位
  213.                   LCD1602_Disp(4,1,':');
  214.               LCD1602_Disp(5,1,(DISbuf_ge%100)/10+'0');   //在第1行的第3列显示十位
  215.                LCD1602_Disp(6,1,DISbuf_ge%10+'0');         //在第1行的第4列显示个位
  216.                 if(key2==0)                //检测按键K1是否按下
  217.                 {
  218.                         Delay10ms();        //消除抖动
  219.                         while(key2==0);
  220.                         Time_ge++;
  221.                         if(Time_ge>59)
  222.                         {
  223.                                 Time_ge=0;
  224.                                 Time_bai++;
  225.                         }       
  226.                 }
  227.                 if(key3==0)                //检测按键K1是否按下
  228.                 {
  229.                         Delay10ms();        //消除抖动
  230.                         while(key3==0);
  231.                         Time_ge--;
  232.                         if(Time_ge<0)
  233.                         {
  234.                                 Time_ge=59;
  235.                                 Time_bai--;
  236.                         }
  237.                
  238.                 }
  239.         }
  240.         if(menu==2)
  241.         {       
  242.                 if(key2==0)                //检测按键K1是否按下
  243.                 {
  244.                         Delay10ms();        //消除抖动
  245.                         while(key2==0);
  246.                         Print(0,0,word3);
  247.                         Adjust=0;       
  248.                 }
  249.                 if(key3==0)                //检测按键K1是否按下
  250.                 {
  251.                         Delay10ms();        //消除抖动
  252.                         while(key3==0);
  253.                         Print(0,0,word1);
  254.                         Adjust=1;
  255.                
  256.                 }
  257.                 if(Adjust==0)
  258.                 {
  259.                         Print(0,0,word3);       
  260.                 }
  261.                 else
  262.                 {
  263.                         Print(0,0,word1);
  264.                 }
  265.         }
  266.         LCD1602_Disp(9,1,Time_bai/10+'0');       //在第1行的第1列显示千位
  267.     LCD1602_Disp(10,1,Time_bai%10+'0'); //在第1行的第2列显示百位
  268.           LCD1602_Disp(11,1,':');
  269.     LCD1602_Disp(12,1,Time_ge/10+'0');   //在第1行的第3列显示十位
  270.     LCD1602_Disp(13,1,Time_ge%10+'0');         //在第1行的第4列显示个位
  271.         LCD1602_Disp(14,1,' ');
  272.         LCD1602_Disp(15,1,' ');       
  273. }
  274. void Display()
  275. {
  276.         LCD1602_Disp(2,1,DISbuf_bai/10+'0');       //在第1行的第1列显示千位
  277.            LCD1602_Disp(3,1,DISbuf_bai%10+'0'); //在第1行的第2列显示百位
  278.         LCD1602_Disp(4,1,':');
  279.            LCD1602_Disp(5,1,DISbuf_ge/10+'0');   //在第1行的第3列显示十位
  280.            LCD1602_Disp(6,1,DISbuf_ge%10+'0');         //在第1行的第4列显示个位
  281.         LCD1602_Disp(7,1,' ');
  282.         LCD1602_Disp(8,1,' ');
  283.         if(DISbuf_ge==Time_ge && DISbuf_bai==Time_bai)
  284.         {
  285.                                 Adjust=1;
  286.         }
  287. }
  288. //---------------------------------------
  289. //名称: 主函数
  290. //---------------------------------------
  291. void main(void)            //主函数,单片机开机后就是从这个函数开始运行
  292. {

  293.     LCD1602_init();        //调用1602液晶初始化函数

  294.     //***定时器Timer0初始化***
  295.     TMOD&=0xF0;            //将TMOD的低4位定时器0控制部分清零
  296.     TMOD|=0x01;            //设置定时器0为方式1
  297.     TL0=0xFF;              //设置定时器0初值低8位
  298.     TH0=0x4B;              //设置定时器0初值高8位
  299.     TR0=1;                 //启动定时器0
  300.     ET0=1;                 //Timer0中断允许
  301.     //**********************

  302.     //***开全局中断设置****
  303.     //定时器Timer0设置了中断允许,此处要开全局中断
  304.     EA=1;                  //开全局中断
  305.     //*********************
  306.         menu=2;
  307.         Adjust=1;
  308.         Time_bai=0;
  309.         Time_ge=10;
  310.         DISbuf_bai=0;
  311.         DISbuf_ge=0;
  312.         Print(0,0,word1);
  313.         LCD1602_Disp(2,1,DISbuf_bai/10+'0');       //在第1行的第1列显示千位
  314.            LCD1602_Disp(3,1,DISbuf_bai%10+'0'); //在第1行的第2列显示百位
  315.         LCD1602_Disp(4,1,':');
  316.     LCD1602_Disp(5,1,DISbuf_ge/10+'0');   //在第1行的第3列显示十位
  317.     LCD1602_Disp(6,1,DISbuf_ge%10+'0');         //在第1行的第4列显示个位
  318.         beep=1;
  319.         P0 = 0x01;
  320.     while(1)               //死循环,单片机初始化后,将一直运行这个死循环
  321.     {                  
  322.                 if(DISbuf_ge==Time_ge && DISbuf_bai==Time_bai && Adjust==1)
  323. ……………………

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

所有资料51hei提供下载:
Project.zip (52 KB, 下载次数: 14)
回复

使用道具 举报

ID:217754 发表于 2017-9-30 23:14 | 显示全部楼层
谢谢分享。下载看看
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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