第二十三节:独立按键控制跑马灯的速度。(上)

开场白:
上一节讲了独立按键控制跑马灯的方向。这一节继续要教会大家一个知识点:如何通过一个中间变量把按键跟跑马灯的速度有效关联起来。
具体内容,请看源代码讲解。

(1)硬件平台:基于朱兆祺51单片机学习板。在上一节的基础上,增加一个加速按键和一个减速按键,用矩阵键盘中的S5键作为加速独立按键,用矩阵键盘中的S9键作为减速独立按键,记得把输出线P0.4一直输出低电平,模拟独立按键的触发地GND。

(2)实现功能:
在上一节的基础上,第1个至第8个LED灯一直不亮。在第9个至第16个LED灯,依次逐个亮灯并且每次只能亮一个灯。每按一次独立按键S5,速度都会加快。每按一次独立按键S9,速度都会减慢。跟上一节一样,用S1来改变方向。

(3)源代码讲解如下: 

  1. #include "REG52.H"  
  2.   
  3. #define const_voice_short  40   //蜂鸣器短叫的持续时间  
  4.   
  5. #define const_key_time1  20    //按键去抖动延时的时间  
  6. #define const_key_time2  20    //按键去抖动延时的时间  
  7. #define const_key_time3  20    //按键去抖动延时的时间  
  8.   
  9. void initial_myself();      
  10. void initial_peripheral();  
  11. void delay_short(unsigned int uiDelayShort);   
  12. void delay_long(unsigned int uiDelaylong);  
  13.   
  14. void led_flicker_09_16(); //第9个至第16个LED的跑马灯程序,逐个亮并且每次只能亮一个.  
  15. void hc595_drive(unsigned char ucLedStatusTemp16_09,unsigned char ucLedStatusTemp08_01);  
  16. void led_update();  //LED更新函数  
  17. void T0_time();  //定时中断函数  
  18.   
  19. void key_service(); //按键服务的应用程序  
  20. void key_scan(); //按键扫描函数 放在定时中断里  
  21.   
  22. sbit hc595_sh_dr=P2^3;      
  23. sbit hc595_st_dr=P2^4;    
  24. sbit hc595_ds_dr=P2^5;    
  25.   
  26. sbit beep_dr=P2^7; //蜂鸣器的驱动IO口  
  27. sbit key_sr1=P0^0; //对应朱兆祺学习板的S1键  
  28. sbit key_sr2=P0^1; //对应朱兆祺学习板的S5键  
  29. sbit key_sr3=P0^2; //对应朱兆祺学习板的S9键  
  30.   
  31. sbit key_gnd_dr=P0^4; //模拟独立按键的地GND,因此必须一直输出低电平  
  32.   
  33. unsigned char ucKeySec=0;   //被触发的按键编号  
  34.   
  35. unsigned int  uiKeyTimeCnt1=0; //按键去抖动延时计数器  
  36. unsigned char ucKeyLock1=0; //按键触发后自锁的变量标志  
  37.   
  38. unsigned int  uiKeyTimeCnt2=0; //按键去抖动延时计数器  
  39. unsigned char ucKeyLock2=0; //按键触发后自锁的变量标志  
  40.   
  41. unsigned int  uiKeyTimeCnt3=0; //按键去抖动延时计数器  
  42. unsigned char ucKeyLock3=0; //按键触发后自锁的变量标志  
  43.   
  44. unsigned int  uiVoiceCnt=0;  //蜂鸣器鸣叫的持续时间计数器  
  45.   
  46. unsigned char ucLed_dr1=0;   //代表16个灯的亮灭状态,0代表灭,1代表亮  
  47. unsigned char ucLed_dr2=0;  
  48. unsigned char ucLed_dr3=0;  
  49. unsigned char ucLed_dr4=0;  
  50. unsigned char ucLed_dr5=0;  
  51. unsigned char ucLed_dr6=0;  
  52. unsigned char ucLed_dr7=0;  
  53. unsigned char ucLed_dr8=0;  
  54. unsigned char ucLed_dr9=0;  
  55. unsigned char ucLed_dr10=0;  
  56. unsigned char ucLed_dr11=0;  
  57. unsigned char ucLed_dr12=0;  
  58. unsigned char ucLed_dr13=0;  
  59. unsigned char ucLed_dr14=0;  
  60. unsigned char ucLed_dr15=0;  
  61. unsigned char ucLed_dr16=0;  
  62.   
  63. unsigned char ucLed_update=0;  //刷新变量。每次更改LED灯的状态都要更新一次。  
  64.   
  65.   
  66. unsigned char ucLedStep_09_16=0; //第9个至第16个LED跑马灯的步骤变量  
  67. unsigned int  uiTimeCnt_09_16=0; //第9个至第16个LED跑马灯的统计定时中断次数的延时计数器  
  68.   
  69. unsigned char ucLedStatus16_09=0;   //代表底层74HC595输出状态的中间变量  
  70. unsigned char ucLedStatus08_01=0;   //代表底层74HC595输出状态的中间变量  
  71.   
  72. unsigned char ucLedDirFlag=0;   //方向变量,把按键与跑马灯关联起来的核心变量,0代表正方向,1代表反方向  
  73. unsigned int  uiSetTimeLevel_09_16=300;  //速度变量,此数值越大速度越慢,此数值越小速度越快。  
  74.   
  75. void main()   
  76.   {  
  77.    initial_myself();    
  78.    delay_long(100);     
  79.    initial_peripheral();   
  80.    while(1)     
  81.    {  
  82.       led_flicker_09_16(); //第9个至第16个LED的跑马灯程序,逐个亮并且每次只能亮一个.  
  83.           led_update();  //LED更新函数  
  84.       key_service(); //按键服务的应用程序  
  85.    }  
  86.   
  87. }  
  88.   
  89.   
  90. void key_scan()//按键扫描函数 放在定时中断里  
  91. {    
  92.   
  93.   if(key_sr1==1)//IO是高电平,说明按键没有被按下,这时要及时清零一些标志位  
  94.   {  
  95.      ucKeyLock1=0; //按键自锁标志清零  
  96.      uiKeyTimeCnt1=0;//按键去抖动延时计数器清零,此行非常巧妙,是我实战中摸索出来的。        
  97.   }  
  98.   else if(ucKeyLock1==0)//有按键按下,且是第一次被按下  
  99.   {  
  100.      uiKeyTimeCnt1++; //累加定时中断次数  
  101.      if(uiKeyTimeCnt1>const_key_time1)  
  102.      {  
  103.         uiKeyTimeCnt1=0;   
  104.         ucKeyLock1=1;  //自锁按键置位,避免一直触发  
  105.         ucKeySec=1;    //触发1号键  
  106.      }  
  107.   }  
  108.   
  109.   if(key_sr2==1)//IO是高电平,说明按键没有被按下,这时要及时清零一些标志位  
  110.   {  
  111.      ucKeyLock2=0; //按键自锁标志清零  
  112.      uiKeyTimeCnt2=0;//按键去抖动延时计数器清零,此行非常巧妙,是我实战中摸索出来的。        
  113.   }  
  114.   else if(ucKeyLock2==0)//有按键按下,且是第一次被按下  
  115.   {  
  116.      uiKeyTimeCnt2++; //累加定时中断次数  
  117.      if(uiKeyTimeCnt2>const_key_time2)  
  118.      {  
  119.         uiKeyTimeCnt2=0;   
  120.         ucKeyLock2=1;  //自锁按键置位,避免一直触发  
  121.         ucKeySec=2;    //触发2号键  
  122.      }  
  123.   }  
  124.   
  125.   if(key_sr3==1)//IO是高电平,说明按键没有被按下,这时要及时清零一些标志位  
  126.   {  
  127.      ucKeyLock3=0; //按键自锁标志清零  
  128.      uiKeyTimeCnt3=0;//按键去抖动延时计数器清零,此行非常巧妙,是我实战中摸索出来的。        
  129.   }  
  130.   else if(ucKeyLock3==0)//有按键按下,且是第一次被按下  
  131.   {  
  132.      uiKeyTimeCnt3++; //累加定时中断次数  
  133.      if(uiKeyTimeCnt3>const_key_time3)  
  134.      {  
  135.         uiKeyTimeCnt3=0;   
  136.         ucKeyLock3=1;  //自锁按键置位,避免一直触发  
  137.         ucKeySec=3;    //触发3号键  
  138.      }  
  139.   }  
  140.   
  141. }  
  142.   
  143.   
  144. void key_service() //按键服务的应用程序  
  145. {  
  146.   switch(ucKeySec) //按键服务状态切换  
  147.   {  
  148.     case 1:// 改变跑马灯方向的按键 对应朱兆祺学习板的S1键   
  149.   
  150.           if(ucLedDirFlag==0) //通过中间变量改变跑马灯的方向  
  151.                   {  
  152.                      ucLedDirFlag=1;  
  153.                   }  
  154.                   else  
  155.                   {  
  156.                            ucLedDirFlag=0;  
  157.                   }  
  158.   
  159.           uiVoiceCnt=const_voice_short; //按键声音触发,滴一声就停。  
  160.           ucKeySec=0;  //响应按键服务处理程序后,按键编号清零,避免一致触发  
  161.           break;      
  162.       
  163.     case 2:// 加速按键 对应朱兆祺学习板的S5键 uiSetTimeLevel_09_16越小速度越快  
  164.           uiSetTimeLevel_09_16=uiSetTimeLevel_09_16-10;  
  165.                   if(uiSetTimeLevel_09_16<50)  //最快限定在50  
  166.                   {  
  167.                       uiSetTimeLevel_09_16=50;  
  168.                   }  
  169.   
  170.           uiVoiceCnt=const_voice_short; //按键声音触发,滴一声就停。  
  171.           ucKeySec=0;  //响应按键服务处理程序后,按键编号清零,避免一致触发  
  172.           break;    
  173.   
  174.     case 3:// 减速按键 对应朱兆祺学习板的S9键  uiSetTimeLevel_09_16越大速度越慢  
  175.           uiSetTimeLevel_09_16=uiSetTimeLevel_09_16+10;  
  176.                   if(uiSetTimeLevel_09_16>550)  //最慢限定在550  
  177.                   {  
  178.                       uiSetTimeLevel_09_16=550;  
  179.                   }  
  180.   
  181.           uiVoiceCnt=const_voice_short; //按键声音触发,滴一声就停。  
  182.           ucKeySec=0;  //响应按键服务处理程序后,按键编号清零,避免一致触发  
  183.           break;                    
  184.   }                  
  185. }  
  186.   
  187.   
  188.   
  189.   
  190. void led_update()  //LED更新函数  
  191. {  
  192.   
  193.    if(ucLed_update==1)  
  194.    {  
  195.        ucLed_update=0;   //及时清零,让它产生只更新一次的效果,避免一直更新。  
  196.   
  197.        if(ucLed_dr1==1)  
  198.            {  
  199.               ucLedStatus08_01=ucLedStatus08_01|0x01;  
  200.            }  
  201.            else  
  202.            {  
  203.               ucLedStatus08_01=ucLedStatus08_01&0xfe;  
  204.            }  
  205.   
  206.        if(ucLed_dr2==1)  
  207.            {  
  208.               ucLedStatus08_01=ucLedStatus08_01|0x02;  
  209.            }  
  210.            else  
  211.            {  
  212.               ucLedStatus08_01=ucLedStatus08_01&0xfd;  
  213.            }  
  214.   
  215.        if(ucLed_dr3==1)  
  216.            {  
  217.               ucLedStatus08_01=ucLedStatus08_01|0x04;  
  218.            }  
  219.            else  
  220.            {  
  221.               ucLedStatus08_01=ucLedStatus08_01&0xfb;  
  222.            }  
  223.   
  224.        if(ucLed_dr4==1)  
  225.            {  
  226.               ucLedStatus08_01=ucLedStatus08_01|0x08;  
  227.            }  
  228.            else  
  229.            {  
  230.               ucLedStatus08_01=ucLedStatus08_01&0xf7;  
  231.            }  
  232.   
  233.   
  234.        if(ucLed_dr5==1)  
  235.            {  
  236.               ucLedStatus08_01=ucLedStatus08_01|0x10;  
  237.            }  
  238.            else  
  239.            {  
  240.               ucLedStatus08_01=ucLedStatus08_01&0xef;  
  241.            }  
  242.   
  243.   
  244.        if(ucLed_dr6==1)  
  245.            {  
  246.               ucLedStatus08_01=ucLedStatus08_01|0x20;  
  247.            }  
  248.            else  
  249.            {  
  250.               ucLedStatus08_01=ucLedStatus08_01&0xdf;  
  251.            }  
  252.   
  253.   
  254.        if(ucLed_dr7==1)  
  255.            {  
  256.               ucLedStatus08_01=ucLedStatus08_01|0x40;  
  257.            }  
  258.            else  
  259.            {  
  260.               ucLedStatus08_01=ucLedStatus08_01&0xbf;  
  261.            }  
  262.   
  263.   
  264.        if(ucLed_dr8==1)  
  265.            {  
  266.               ucLedStatus08_01=ucLedStatus08_01|0x80;  
  267.            }  
  268.            else  
  269.            {  
  270.               ucLedStatus08_01=ucLedStatus08_01&0x7f;  
  271.            }  
  272.   
  273.        if(ucLed_dr9==1)  
  274.            {  
  275.               ucLedStatus16_09=ucLedStatus16_09|0x01;  
  276.            }  
  277.            else  
  278.            {  
  279.               ucLedStatus16_09=ucLedStatus16_09&0xfe;  
  280.            }  
  281.   
  282.        if(ucLed_dr10==1)  
  283.            {  
  284.               ucLedStatus16_09=ucLedStatus16_09|0x02;  
  285.            }  
  286.            else  
  287.            {  
  288.               ucLedStatus16_09=ucLedStatus16_09&0xfd;  
  289.            }  
  290.   
  291.        if(ucLed_dr11==1)  
  292.            {  
  293.               ucLedStatus16_09=ucLedStatus16_09|0x04;  
  294.            }  
  295.            else  
  296.            {  
  297.               ucLedStatus16_09=ucLedStatus16_09&0xfb;  
  298.            }  
  299.   
  300.        if(ucLed_dr12==1)  
  301.            {  
  302.               ucLedStatus16_09=ucLedStatus16_09|0x08;  
  303.            }  
  304.            else  
  305.            {  
  306.               ucLedStatus16_09=ucLedStatus16_09&0xf7;  
  307.            }  
  308.   
  309.   

(中http://www.eeskill.com/group/topic_scan/id/509

(下http://www.eeskill.com/group/topic_scan/id/510

永不止步步 发表于11-20 15:42 浏览65535次
分享到:

已有0条评论

暂时还没有回复哟,快来抢沙发吧

添加一条新评论

只有登录用户才能评论,请先登录注册哦!

话题作者

永不止步步
金币:67417个|学分:363741个
立即注册
畅学电子网,带你进入电子开发学习世界
专业电子工程技术学习交流社区,加入畅学一起充电加油吧!

x

畅学电子网订阅号