找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1980|回复: 14
收起左侧

关于单片机按键控制LED流水程序问题 非常感谢

[复制链接]
ID:877522 发表于 2021-8-13 16:17 | 显示全部楼层 |阅读模式
大家好:
   我写一个 2种LED流水的方式,想通过K1按键进行切换,怎么按下一次,能开启一种模式,按下K1第二次,怎么也不能开启,帮忙看下,谢谢!

1.png

单片机源程序如下:
  1. #include <reg52.h>
  2. #include <intrins.h>
  3. #define uint unsigned int
  4. #define uchar unsigned char
  5. uchar temp,num,aa,flag;

  6. sbit D1=P1^0;
  7. sbit D2=P1^1;
  8. sbit D3=P1^2;
  9. sbit D4=P1^3;
  10. sbit D5=P1^4;
  11. sbit D6=P1^5;
  12. sbit D7=P1^6;
  13. sbit D8=P1^7;

  14. void delay(uint z);
  15. void LEDInit();
  16. void LED1_Stys();
  17. void LED2_Stys();
  18. void key1();

  19. void delay1(uchar z)
  20. {
  21.         uchar x,y;
  22.         for(x=z;x>0;x--)
  23.         for(y=110;y>0;y--);        
  24. }

  25. sbit K1          = P3^0;        //启动模式1
  26. sbit K2   =        P3^1;        //启动模式2


  27. void LEDInit()
  28. {

  29.         TMOD=0x01;  //确定定时器0 的工作方式为1,16 位定时器
  30.         TH0=0XFC;   //设定1000us(1MS) 的定时器初值 65536-1000=64536 ,64536 的16进制为FC18
  31.         TL0=0X18;     
  32.         EA=1;//开总中断
  33.         ET0=1;//开启定时器0中断
  34.         TR0=1;//启动定时器0
  35. }

  36. void LED1_Stys()
  37. {
  38.        LEDInit();
  39.         while(1)
  40.         {}
  41. }

  42. void LED2_Stys()
  43. {
  44.     temp=0x01;
  45.     P1=temp;        
  46.     while(1)
  47.     {
  48.     delay(1000);
  49.     temp=_crol_(temp,1);
  50.     P1=temp;
  51.     }
  52. }

  53. void key1()   
  54. {

  55. if(K1==0)
  56.         {
  57.                 delay1(5);         
  58.                 if(K1==0)        
  59.                 {
  60.                         num++;            
  61.                         while(!K1);               
  62.                         if(num==1)         
  63.                         {
  64.                         LED1_Stys();
  65.                         }
  66.             
  67.             if(num==2)         
  68.                         {
  69.             num=0;
  70.                         LED2_Stys();
  71.                         }

  72.         }
  73.     }

  74. }
  75.    



  76. void main()
  77. {
  78. key1();  
  79. }   
  80.   
  81.    


  82. void Time0() interrupt 1
  83. {
  84.     uint i;
  85.     TH0=0XFC;   //设定1000us 的定时器初值 65536-1000=64536 ,64536 的16进制为FC18
  86.     TL0=0X18;
  87.     i++;
  88.     if(i==40)  // 40*1000us=40000us=40MS
  89.     {
  90.      D1=~D1;
  91.     }
  92.    
  93.     if(i==80)  
  94.     {
  95.      D2=~D2;
  96.     }
  97.    
  98.     if(i==120)  
  99.     {
  100.      D3=~D3;
  101.     }
  102.    
  103.     if(i==160)  
  104.     {
  105.      D4=~D4;
  106.     }
  107.    
  108.     if(i==200)  
  109.     {
  110.      D5=~D5;
  111.     }
  112.    
  113.     if(i==240)  
  114.     {
  115.      D6=~D6;
  116.     }
  117.    
  118.     if(i==280)  
  119.     {
  120.      D7=~D7;
  121.     }
  122.    
  123.     if(i==320)
  124.     {   
  125.      D8=~D8;
  126.     }
  127.    
  128.     if(i==360)
  129.     {
  130.      i=0;
  131.      P1=~P1;
  132.     }
  133.       
  134. }

  135. void  delay(uint z)
  136. {
  137.                 uint x,y;
  138.                 for(x=z;x>0;x--);
  139.                 for(y=35000;y>0;y--);        
  140. }

  141. // 用按键 切换 2 种LED 流水模式
复制代码
LED-2种流水-独立按键切换.rar (14.23 KB, 下载次数: 10)
回复

使用道具 举报

ID:849376 发表于 2021-8-13 16:44 | 显示全部楼层
用定时器中断比较好实现,延时就别用了
回复

使用道具 举报

ID:849376 发表于 2021-8-13 16:46 | 显示全部楼层
你的main里面没有定时器初始化和while
回复

使用道具 举报

ID:849376 发表于 2021-8-13 16:48 | 显示全部楼层
LED1_Stys()和LED2_Stys()里面的while也会卡死在里面
回复

使用道具 举报

ID:161164 发表于 2021-8-13 17:45 | 显示全部楼层
本帖最后由 lkc8210 于 2021-8-13 22:47 编辑

好可怕的代码
四点建议
1.不要在大循环以外的其它地方用while(1)
2.就算很有需要,也要加离开条件
3.编程尽量模组化,一个函数负责按键扫描,另一个函数负责流水灯控制,他们之间用标致位交流
4.中断内不要干太多情,有机会超时

现在最简单的改法,就是建议2:
  1. void LED1_Stys()
  2. {
  3.     LEDInit();
  4.     while(1)
  5.     {
  6.         if(!K1) {
  7.             TR0=0;
  8.             P1=0xFF;
  9.             break;
  10.         }
  11.     }
  12. }

  13. void LED2_Stys()
  14. {
  15.     temp=0x01;
  16.     P1=temp;
  17.     while(1)
  18.     {
  19.         delay(1000);
  20.         temp=_crol_(temp,1);
  21.         P1=temp;
  22.         if(!K1) {
  23.             P1=0xFF;
  24.             break;
  25.         }
  26.     }
  27. }
  28. void main()
  29. {
  30.         while (1)
  31.   {
  32.     key1();
  33.   }
  34. }
复制代码







回复

使用道具 举报

ID:332444 发表于 2021-8-13 17:55 | 显示全部楼层
其一8个流水灯不用逐一定义,只有单一使用才逐一定义如定义的2个按键是应该的,其二中断代码尽量少否则日后也这样写估计被人看到不会用这样的人.其三有了定时器可不用死循环延时否则日后也这样写估计被人看到会被人议论的.
回复

使用道具 举报

ID:877522 发表于 2021-8-13 18:10 | 显示全部楼层
lkc8210 发表于 2021-8-13 17:45
好可怕的代码
四点建议
1.不要在大循环以外的其它地方用while(1)

谢谢 你的建议  能否帮忙修改一下  感谢
回复

使用道具 举报

ID:877522 发表于 2021-8-13 20:55 来自手机 | 显示全部楼层
Letitia 发表于 2021-8-13 16:48
LED1_Stys()和LED2_Stys()里面的while也会卡死在里面

是的,只能进去一个,不能切换,能否指点一下怎么修改
回复

使用道具 举报

ID:914633 发表于 2021-8-13 21:20 | 显示全部楼层
1.LED1_Stys()和LED2_Stys()这两个随便进一个就一直在while循环里了出不来了,按键不起作用了
2.你第一种状态是用定时器中断做的吧,切换至第二个状态时,你没关定时器中断,第一个状态仍然会存在,第二个状态会受影响
回复

使用道具 举报

ID:877522 发表于 2021-8-16 08:23 | 显示全部楼层
lkc8210 发表于 2021-8-13 17:45
好可怕的代码
四点建议
1.不要在大循环以外的其它地方用while(1)

非常感谢 !用你写的代码可以了正常切换了
回复

使用道具 举报

ID:877522 发表于 2021-8-16 08:24 | 显示全部楼层
hoodieboi 发表于 2021-8-13 21:20
1.LED1_Stys()和LED2_Stys()这两个随便进一个就一直在while循环里了出不来了,按键不起作用了
2.你第一种 ...

是的,谢谢提醒,
回复

使用道具 举报

ID:877522 发表于 2021-8-16 12:30 | 显示全部楼层
lkc8210 发表于 2021-8-13 17:45
好可怕的代码
四点建议
1.不要在大循环以外的其它地方用while(1)

您好,现在可以切换了,按下K1 先是LED 按照方式1 流水,然后按下K1 按照方式2流水,然后在按下还是按照方式1 流水,可是这时的流水跟第一次不一致了,效果有差异,我在LED 初始化增加了 P1=0xff  还是一样的,能否帮忙在分析一下,非常感谢!代码如下



  1. #include <reg52.h>
  2. #include <intrins.h>
  3. #define uint unsigned int
  4. #define uchar unsigned char
  5. uchar temp,num,aa,flag;


  6. sbit D1=P1^0;
  7. sbit D2=P1^1;
  8. sbit D3=P1^2;
  9. sbit D4=P1^3;
  10. sbit D5=P1^4;
  11. sbit D6=P1^5;
  12. sbit D7=P1^6;
  13. sbit D8=P1^7;

  14. void delay(uint z);

  15. void LEDInit();
  16. void LED_2Init();
  17. void LED1_Stys();
  18. void LED2_Stys();
  19. void key1();

  20. void delay1(uchar z)
  21. {
  22.         uchar x,y;
  23.         for(x=z;x>0;x--)
  24.         for(y=110;y>0;y--);       
  25. }

  26. sbit K1          = P3^0;        //启动模式1
  27. sbit K2   =        P3^1;        //启动模式2

  28. void LEDInit()    //内部定时器0初始化程序  (序号1)
  29. {

  30.         TMOD=0x01;  //确定定时器0 的工作方式为1,16 位定时器
  31.         TH0=0XFC;   //设定1000us(1MS) 的定时器初值 65536-1000=64536 ,64536 的16进制为FC18
  32.         TL0=0X18;     
  33.         EA=1;//开总中断
  34.         ET0=1;//开启定时器0中断
  35.         TR0=1;//启动定时器0
  36.         P1=0xFF;
  37. }

  38. void LED1_Stys()     //LED 流水方式1
  39. {
  40.    
  41.        LEDInit();
  42.         while(1)
  43.         {
  44.         if(!K1)
  45.         {
  46.             TR0=0;
  47.             P1=0xFF;
  48.             break;
  49.         }
  50.         }
  51.         
  52.      
  53. }

  54. void LED2_Stys()   //LED 流水方式2
  55. {
  56.    
  57.     temp=0x01;
  58.     P1=temp;        
  59.     while(1)
  60.     {
  61.     delay(1000);
  62.     temp=_crol_(temp,1);
  63.     P1=temp;
  64.       
  65.         if(!K1)
  66.         {
  67.        P1=0xff;
  68.        break;
  69.         }
  70.          
  71.       
  72.     }
  73. }

  74. void key1()   
  75. {

  76.    if(K1==0)
  77.         {
  78.                 delay1(5);          
  79.                 if(K1==0)       
  80.                 {
  81.                         num++;             
  82.                         while(!K1);               
  83.                         if(num==1)         
  84.                         {
  85.                         LED1_Stys();
  86.                         }
  87.             
  88.             if(num==2)         
  89.                         {
  90.             num=0;
  91.                         LED2_Stys();
  92.                         }
  93.    
  94.         }
  95.     }

  96.       
  97.      
  98. }
  99.    

  100. void main()
  101. {
  102. while(1)
  103. {
  104. key1();
  105. }   
  106. }   
  107.   
  108.   
  109. void Time0() interrupt 1
  110. {
  111.     uint i;
  112.     TH0=0XFC;   //设定1000us 的定时器初值 65536-1000=64536 ,64536 的16进制为FC18
  113.     TL0=0X18;
  114.     i++;
  115.     if(i==40)  // 40*1000us=40000us=40MS
  116.     {
  117.      D1=~D1;
  118.     }
  119.    
  120.     if(i==80)  
  121.     {
  122.      D2=~D2;
  123.     }
  124.    
  125.     if(i==120)  
  126.     {
  127.      D3=~D3;
  128.     }
  129.    
  130.     if(i==160)  
  131.     {
  132.      D4=~D4;
  133.     }
  134.    
  135.     if(i==200)  
  136.     {
  137.      D5=~D5;
  138.     }
  139.    
  140.     if(i==240)  
  141.     {
  142.      D6=~D6;
  143.     }
  144.    
  145.     if(i==280)  
  146.     {
  147.      D7=~D7;
  148.     }
  149.    
  150.     if(i==320)
  151.     {   
  152.      D8=~D8;
  153.     }
  154.    
  155.     if(i==360)
  156.     {
  157.      i=0;
  158.      P1=~P1;
  159.     }
  160.       
  161. }

  162. void  delay(uint z)
  163. {
  164.                 uint x,y;
  165.                 for(x=z;x>0;x--);
  166.                 for(y=35000;y>0;y--);       
  167. }

  168. // 用按键 切换 2 种LED 流水模式

  169. //void LED_2Init()  //外部定时器0初始化程序 (序号0)

  170. //{
  171. //EA=1;
  172. //EX0=1;
  173. //IT0=1;
  174. //}
  175. //  


  176. // void Time1() interrupt 0
  177. // {
  178. // LED2_Stys();
  179. //
  180. // }
  181. //     
  182. //LED_2Init();
  183. //while(1);
复制代码
回复

使用道具 举报

ID:161164 发表于 2021-8-16 13:53 | 显示全部楼层
SGW2020 发表于 2021-8-16 12:30
您好,现在可以切换了,按下K1 先是LED 按照方式1 流水,然后按下K1 按照方式2流水,然后在按下还是按照 ...

把中断内的uint i; 移到顶
  1. #include <reg52.h>
  2. #include <intrins.h>
  3. #define uint unsigned int
  4. #define uchar unsigned char
  5. uchar temp,num,aa,flag;

  6.     uint i;//<<<<<<<<<<<<<<<<<<<<<<<<<<
复制代码

在LED 初始化里再加i=0;
  1. void LEDInit()    //内部定时器0初始化程序  (序号1)
  2. {

  3.     TMOD=0x01;  //确定定时器0 的工作方式为1,16 位定时器
  4.     TH0=0XFC;   //设定1000us(1MS) 的定时器初值 65536-1000=64536 ,64536 的16进制为FC18
  5.     TL0=0X18;
  6.     EA=1;//开总中断
  7.     ET0=1;//开启定时器0中断
  8.     TR0=1;//启动定时器0
  9.     P1=0xFF;
  10.                 i=0;//<<<<<<<<<<<<<<<<<<<<<
  11. }
复制代码
回复

使用道具 举报

ID:877522 发表于 2021-8-17 08:30 | 显示全部楼层
lkc8210 发表于 2021-8-16 13:53
把中断内的uint i; 移到顶

在LED 初始化里再加i=0;

好的 ,非常感谢,我把中断里面的 非 改为,P1=0XFe 之类的 也可以了,谢谢!
  1. #include <reg52.h>
  2. #include <intrins.h>
  3. #define uint unsigned int
  4. #define uchar unsigned char
  5. uchar temp,num,aa,flag;

  6. void delay(uint z);

  7. void LEDInit();
  8. void LED_2Init();
  9. void LED1_Stys();
  10. void LED2_Stys();
  11. void key1();

  12. void delay1(uchar z)
  13. {
  14.         uchar x,y;
  15.         for(x=z;x>0;x--)
  16.         for(y=110;y>0;y--);       
  17. }

  18. sbit K1          = P3^0;        //启动模式1
  19. sbit K2   =        P3^1;        //启动模式2

  20. void LEDInit()    //内部定时器0初始化程序  (序号1)
  21. {

  22.         TMOD=0x01;  //确定定时器0 的工作方式为1,16 位定时器
  23.         TH0=0XFC;   //设定1000us(1MS) 的定时器初值 65536-1000=64536 ,64536 的16进制为FC18
  24.         TL0=0X18;     
  25.         EA=1;//开总中断
  26.         ET0=1;//开启定时器0中断
  27.         TR0=1;//启动定时器0

  28. }

  29. void LED1_Stys()     //LED 流水方式1 通过定时器中断 流水
  30. {
  31.    
  32.        LEDInit();
  33.         while(1)
  34.         {
  35.         if(!K1)
  36.         {
  37.             TR0=0;
  38.             P1=0xFF;
  39.             break;
  40.         }
  41.         }
  42.         
  43.      
  44. }

  45. void LED2_Stys()   //LED 流水方式2  通过程序定时逐一流水
  46. {
  47.    
  48.     temp=0x01;
  49.     P1=temp;        
  50.     while(1)
  51.     {
  52.     delay(1000);
  53.     temp=_crol_(temp,1);
  54.     P1=temp;
  55.       
  56.         if(!K1)
  57.         {
  58.        P1=0xff;
  59.        break;
  60.         }
  61.          
  62.       
  63.     }
  64. }

  65. void key1()     // 键盘 扫描程序
  66. {

  67.    if(K1==0)
  68.         {
  69.                 delay1(5);          
  70.                 if(K1==0)       
  71.                 {
  72.                         num++;             
  73.                         while(!K1);               
  74.                         if(num==1)         
  75.                         {
  76.                         LED1_Stys();
  77.                         }
  78.             
  79.             if(num==2)         
  80.                         {         
  81.                         LED2_Stys();
  82.                         }
  83.            if(num==3)         
  84.                         {
  85.             num=0;
  86.                         P1=0X0;
  87.                         }
  88.                        
  89.         }
  90.     }
  91.    
  92. }


  93. void main()    // 主程序
  94. {
  95. while(1)
  96. {
  97. key1();
  98. }   
  99. }   
  100.   
  101.   
  102. void Time0() interrupt 1   //内部定时器0 (序号为1)
  103. {
  104.     uint i;
  105.     TH0=0XFC;   //设定1000us 的定时器初值 65536-1000=64536 ,64536 的16进制为FC18
  106.     TL0=0X18;
  107.     i++;
  108.     if(i==40)  // 40*1000us=40000us=40MS
  109.     {
  110.      P1=0xfe;
  111.     }
  112.    
  113.     if(i==80)  
  114.     {
  115.      P1=0xfc;
  116.     }
  117.    
  118.     if(i==120)  
  119.     {
  120.      P1=0xf8;
  121.     }
  122.    
  123.     if(i==160)  
  124.     {
  125.      P1=0xf0;
  126.     }
  127.    
  128.     if(i==200)  
  129.     {
  130.      P1=0xe0;
  131.     }
  132.    
  133.     if(i==240)  
  134.     {
  135.      P1=0xc0;
  136.     }
  137.    
  138.     if(i==280)  
  139.     {
  140.      P1=0x80;
  141.     }
  142.    
  143.     if(i==320)
  144.     {   
  145.      P1=0x00;
  146.     }
  147.    
  148.     if(i==360)
  149.     {
  150.      i=0;
  151.      P1=0xff;
  152.     }
  153.       
  154. }

  155. void  delay(uint z)
  156. {
  157.                 uint x,y;
  158.                 for(x=z;x>0;x--);
  159.                 for(y=35000;y>0;y--);       
  160. }

  161. // 用按键 切换 2 种LED 流水模式 程序OK


复制代码
回复

使用道具 举报

ID:401564 发表于 2021-8-17 16:53 | 显示全部楼层
我感觉一个流水灯程序是没有必要问的
有学习板也没有必要仿真的
我学了十来天的C语言,到现在,BMP280,ADXL345,OLED(SH1106驱动)都写过了,暂时还没有遇上一定要发帖问的问题,自己解决问题可能用的时间久一点,但印象更加深刻
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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