找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机ws2812程序无法用按键控制?

[复制链接]
ID:190152 发表于 2024-1-2 12:22 | 显示全部楼层 |阅读模式
这个是用别人的程序修改的,现在遇到几个问题。外部中断接的开机按键需要按几次才能开机。按键左和按键右无法控制切换流水灯模式

单片机源程序如下:
  1. #include<STC8Hxxx.h>
  2. #include"intrins.h"

  3. sbit WS2812 = P3^2;
  4. sbit Power= P1^0;//ws2812电源开关
  5. sbit key_left= P2^0;//按键左
  6. sbit key_right= P2^1;//按键右
  7. sbit key_ok= P2^2;//按键确认
  8. sbit key_Return= P2^3;//按键返回



  9. #define numLEDs 64  //灯的个数

  10. unsigned char buf_R[numLEDs] = {0};//颜色缓存
  11. unsigned char buf_G[numLEDs] = {0};
  12. unsigned char buf_B[numLEDs] = {0};
  13. unsigned char Timer0_cnt=0;//记录定时器0中断次数
  14. unsigned char list=1;//播放列表

  15. void RGB_Set_Up();  //送0码
  16. void RGB_Set_Down(); //送1码
  17. void Timer0_Init();//按键扫描定时器0初始化
  18. void key_service();//按键服务程序
  19. //void playlist(unsigned char list);



  20. //真对 STC8系列 IO口初始化 准双向
  21. void IO_init(void)
  22. {

  23.   P0M0 = 0X00;
  24.   P0M1 = 0X00;

  25.   P1M0 = 0X01;
  26.   P1M1 = 0X00;

  27.   P2M0 = 0X00;
  28.   P2M1 = 0X00;

  29.   P3M0 = 0X00;
  30.   P3M1 = 0X00;

  31.   P4M0 = 0X00;
  32.   P4M1 = 0X00;

  33.   P5M0 = 0X00;
  34.   P5M1 = 0X00;
  35. }


  36. void HAL_Delay(unsigned long t)
  37. {
  38.                   unsigned int x,y;
  39.                   for(x=114;x>0;x--)
  40.           for(y=t;y>0;y--);
  41. }

  42.    //复位延时
  43. void Delay50us()                //@22.1184MHz
  44. {
  45.         unsigned char i, j;

  46.         _nop_();
  47.         _nop_();
  48.         i = 2;
  49.         j = 15;
  50.         do
  51.         {
  52.                 while (--j);
  53.         } while (--i);
  54. }
  55. //1码,高电平850ns 低电平400ns 误差正负150ns
  56. void RGB_Set_Up()
  57. {
  58.                 WS2812 = 1;
  59.           //经过逻辑分析仪调试的的延时
  60.                 _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();
  61.           _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();
  62.                 WS2812 = 0;
  63. }
  64. //1码,高电平400ns 低电平850ns 误差正负150ns
  65. void RGB_Set_Down()
  66. {
  67.    WS2812 = 1;
  68.           //经过逻辑分析仪调试的的延时
  69.                 _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();  
  70.                 WS2812 = 0;
  71. }

  72. //发送24位数据
  73. void Send_2812_24bits(unsigned char G8,unsigned char R8,unsigned char B8)
  74. {
  75.                    unsigned int n = 0;
  76.                    //发送G8位
  77.                   for(n=0;n<8;n++)
  78.                   {
  79.                       G8<<=n;
  80.                           if(G8&0x80 == 0x80)
  81.                           {
  82.                              RGB_Set_Up();
  83.                           }
  84.                           else
  85.                           {
  86.                             RGB_Set_Down();
  87.                           }
  88.                   }
  89.                   //发送R8位
  90.                   for(n=0;n<8;n++)
  91.                   {
  92.                       R8<<=n;
  93.                           if(R8&0x80 == 0x80)
  94.                           {
  95.                              RGB_Set_Up();
  96.                           }
  97.                           else
  98.                           {
  99.                             RGB_Set_Down();
  100.                           }
  101.                   }
  102.                         //发送B8位
  103.                     for(n=0;n<8;n++)
  104.                   {
  105.                       B8<<=n;
  106.                           if(B8&0x80 == 0x80)
  107.                           {
  108.                              RGB_Set_Up();
  109.                           }
  110.                           else
  111.                           {
  112.                             RGB_Set_Down();
  113.                            }
  114.                   }
  115.                   
  116.                   
  117.          
  118. }                 
  119. //复位码
  120. void RGB_Rst()
  121. {
  122.             WS2812 = 0;
  123.           Delay50us();
  124. }

  125. //颜色交换24位不拆分发

  126. void SetPixelColor(unsigned char num,unsigned long c)
  127. {
  128.            unsigned char i;
  129.        for(i=0;i<numLEDs;i++)
  130.            {
  131.               buf_R[num] = (unsigned char)(c>>16);
  132.                           buf_G[num] = (unsigned char)(c>>8);
  133.                           buf_B[num] = (unsigned char)(c);
  134.            }

  135.                  for(i=0;i<numLEDs;i++)
  136.                 {
  137.                         Send_2812_24bits(buf_G[i],buf_R[i],buf_B[i]);
  138.                 }

  139. }

  140. //复位
  141. void PixelUpdate()
  142. {
  143.         RGB_Rst();
  144. }


  145. // Fill the dots one after the other with a color
  146. //用一种颜色填充这些圆点
  147. void colorWipe(unsigned long c, unsigned int wait)
  148. {
  149.   unsigned char i=0;
  150.   for( i=0; i<numLEDs; i++)
  151.         {
  152.     SetPixelColor(i, c);
  153.     PixelUpdate();
  154.     HAL_Delay(wait*5);
  155.   }

  156. }
  157. void Watercolor(unsigned long c, unsigned int wait)
  158. {
  159.   unsigned char i=0;
  160.   for( i=0; i<numLEDs; i++)
  161.         {
  162.     SetPixelColor(i, c);
  163.          PixelUpdate();
  164.     HAL_Delay(wait*5);
  165.         SetPixelColor(i, 0);
  166.    PixelUpdate();
  167.     HAL_Delay(wait);
  168.   }

  169. }

  170. //颜色
  171. unsigned long Color(unsigned char r, unsigned char g, unsigned char b)
  172. {
  173.   return ((unsigned long)r << 16) | ((unsigned long)g <<  8) | b;
  174. }

  175. //颜色算法
  176. unsigned long Wheel(unsigned char WheelPos)
  177. {
  178.   WheelPos = 255 - WheelPos;
  179.   if(WheelPos < 85)
  180.         {
  181.     return Color(255 - WheelPos * 3, 0, WheelPos * 3);
  182.   }
  183.   if(WheelPos < 170) {
  184.     WheelPos -= 85;
  185.     return Color(0, WheelPos * 3, 255 - WheelPos * 3);
  186.   }
  187.   WheelPos -= 170;
  188.   return Color(WheelPos * 3, 255 - WheelPos * 3, 0);
  189. }

  190. //彩虹
  191. void rainbow(unsigned int wait)
  192. {
  193.   unsigned int i, j;

  194.   for(j=0; j<256; j++)
  195.         {
  196.             for(i=0; i<numLEDs; i++)
  197.                 {
  198.                                       SetPixelColor(i, Wheel((i+j) & 255));
  199.                             }
  200.                 PixelUpdate();
  201.                             HAL_Delay(wait);
  202.                   }
  203. }

  204. //稍微不同的是,这使得彩虹均匀分布
  205. void rainbowCycle(unsigned int wait)
  206. {
  207.   unsigned int i, j;

  208.   for(j=0;j<256*5;j++)
  209.         { // 5 cycles of all colors on wheel  车轮上所有颜色的5个循环
  210.     for(i=0;i<numLEDs;i++)
  211.          {
  212.      SetPixelColor(i, Wheel(((i * 256 / numLEDs) + j) & 255));
  213.     }
  214.           PixelUpdate();
  215.     HAL_Delay (wait);
  216.   }
  217. }


  218. //Theatre-style crawling lights with rainbow effect
  219. //带有彩虹效果的戏剧式爬行灯
  220. void theaterChaseRainbow(unsigned int wait)
  221. {
  222.         int j,q;
  223.         unsigned int i;
  224.   for (j=0; j < 256; j++)
  225.         {     // cycle all 256 colors in the wheel 在轮子上循环所有256色
  226.     for (q=0; q < 3; q++)
  227.                 {
  228.       for (i=0; i < numLEDs; i=i+3)
  229.                         {
  230.         SetPixelColor(i+q, Wheel( (i+j) % 255));    //turn every third pixel off 把每一个第三个像素
  231.       }
  232.       PixelUpdate();

  233.       HAL_Delay(wait);

  234.       for (i=0; i < numLEDs; i=i+3)
  235.                         {
  236.         SetPixelColor(i+q, 0);        //turn every third pixel off  把每一个第三个像素关掉
  237.       }
  238.     }
  239.   }
  240. }

  241. void colorWipe_1()//颜色刷1
  242.         {
  243.                                     colorWipe(0xff0000,1);        //红色
  244.                                          HAL_Delay(10000);
  245.                                    colorWipe(0xff00,1);         //绿色
  246.                                         HAL_Delay(10000);
  247.                                    colorWipe(0xff,1);//蓝色
  248.                                         HAL_Delay(10000);
  249.                                    colorWipe(0xffff00,1);        //黄色
  250.                                          HAL_Delay(10000);
  251.                                    colorWipe(0xffff,1);        //青色
  252.                                          HAL_Delay(10000);
  253.                                    colorWipe(0xff00ff,1);        //紫色
  254.                                          HAL_Delay(10000);
  255.                                    colorWipe(0xffffff,1);        //白色
  256.                                          HAL_Delay(10000);
  257.                                    colorWipe(0x00,1);        //off
  258.                                          HAL_Delay(10000);
  259.         }

  260. void colorWipe_2()//颜色刷2
  261.         {
  262.                             Watercolor(0xff0000, 100);//红色
  263.                                          HAL_Delay(1000);
  264.                                         Watercolor(0xff00, 100);//绿色
  265.                                          HAL_Delay(1000);
  266.                                         Watercolor(0xff, 100);//蓝色
  267.                                          HAL_Delay(1000);
  268.                                         Watercolor(0xffff00, 100);        //黄色
  269.                                          HAL_Delay(1000);
  270.                                         Watercolor(0xffff, 100);//青色
  271.                                          HAL_Delay(1000);
  272.                                         Watercolor(0xff00ff, 100);        //紫色
  273.                                          HAL_Delay(1000);
  274.                                         Watercolor(0xffffff, 100);        //白色
  275.                                          HAL_Delay(1000);        
  276.                                         colorWipe(0x00,1);        //off
  277.                                          HAL_Delay(10000);
  278.         }

  279. void colorWipe_3()//颜色刷3
  280.         {
  281.                                          colorWipe(0xff0000,100);        //红色
  282.                                          HAL_Delay(1000);
  283.                                         colorWipe(0x00,100);        //0ff
  284.                                          HAL_Delay(1000);
  285.                                         colorWipe(0xff00,100);         //绿色
  286.                                          HAL_Delay(1000);
  287.                                         colorWipe(0x00,100);        //0ff
  288.                                          HAL_Delay(1000);
  289.                                         colorWipe(0xff,100);//蓝色
  290.                                          HAL_Delay(1000);
  291.                                     colorWipe(0x00,100);        //0ff
  292.                                          HAL_Delay(1000);
  293.                                     colorWipe(0xffff00,100);        //黄色
  294.                                          HAL_Delay(1000);
  295.                                         colorWipe(0x00,100);        //0ff
  296.                                          HAL_Delay(1000);
  297.                                         colorWipe(0xffff,100);        //青色
  298.                                          HAL_Delay(1000);
  299.                                         colorWipe(0x00,100);        //0ff
  300.                                          HAL_Delay(1000);
  301.                                         colorWipe(0xff00ff,100);        //紫色
  302.                                          HAL_Delay(1000);
  303.                                          colorWipe(0x00,100);        //0ff
  304.                                          HAL_Delay(1000);
  305.                                            colorWipe(0xffffff,100);        //白色
  306.                                          HAL_Delay(1000);
  307.                                         colorWipe(0x00,100);        //0ff
  308.                                           HAL_Delay(1000);
  309.         }


  310. void main()
  311. {               
  312.                 IO_init();        //io口初始化
  313.                 IT1 = 1; //设置INT1的中断类型 (1:仅下降沿 0:上升沿和下降沿)
  314.                 EX1 = 1;//使能INT1中断
  315.                 INTCLKO|=0x10;//开启外部中断2
  316.             EA = 1;                //开启总中断
  317.                 Timer0_Init();//按键扫描定时器0初始化
  318.                 while(1)
  319.                 {        
  320.                 key_service();//按键服务程序  
  321.                 switch(list)
  322.                                 {
  323.                                 case 1: colorWipe_1(); break;//颜色刷1
  324.                                 case 2: colorWipe_2(); break;//颜色刷2
  325.                                 case 3: colorWipe_3(); break;//颜色刷3
  326.                                 case 4: rainbow(10); break;//彩虹
  327.                                 case 5: rainbowCycle(10); break;//彩虹2
  328.                                 case 6:        theaterChaseRainbow(10); break;//彩虹升级
  329.                                 default:break;
  330.                                 }                 
  331.                
  332.            
  333.                 }
  334. }

  335. //-----------------------------------------
  336. //按键定时器初始化程序
  337. void Timer0_Init(void)                //20毫秒@22.1184MHz
  338. {
  339.         AUXR &= 0x7F;                        //定时器时钟12T模式
  340.         TMOD &= 0xF0;                        //设置定时器模式
  341.         TMOD |= 0x01;                        //设置定时器模式16位模式
  342.         TL0 = 0x00;                                //设置定时初始值
  343.         TH0 = 0x70;                                //设置定时初始值
  344.         TF0 = 0;                                //清除TF0标志
  345.         //ET0 = 1;                //定时器0中断开启
  346.         TR0 = 1;                                //定时器0开始计时
  347. }

  348. void Delay10ms()                //@22.1184MHz 按键消抖10ms延时
  349. {
  350.         unsigned char i, j, k;

  351.         i = 2;
  352.         j = 32;
  353.         k = 60;
  354.         do
  355.         {
  356.                 do
  357.                 {
  358.                         while (--k);
  359.                 } while (--j);
  360.         } while (--i);
  361. }


  362. //按键扫描服务程序
  363. void key_service()//按键服务程序
  364.         {
  365.         if(TF0==1)
  366.                 {
  367.                          TF0 = 0;                                //清除TF0标志
  368.                         TL0 = 0x9A;                                //设置定时初始值
  369.                         TH0 = 0xA9;                                //设置定时初始值

  370.                         if(key_Return==0)//返回键扫描
  371.                                 {
  372.                                  Delay10ms();                //按键消抖延时@22.1184MHz
  373.                                  if(key_Return==1)
  374.                                          {
  375.                                                 RGB_Rst();//复位
  376.                                                 colorWipe(0xffffff,100);        //白色
  377.                                                  PCON=0x02;//进入掉电模式
  378.                                                  _nop_();
  379.                                                     _nop_();
  380.                                         }
  381.                                         while(!key_Return);//等待按键松开
  382.                                 }

  383.                         if(key_ok == 0)//OK键扫描
  384.                                  {
  385.                                         Delay10ms();                //按键消抖延时@22.1184MHz
  386.                                         if(key_ok==0)
  387.                                                 {
  388.                                                         RGB_Rst();//复位
  389.                                                         colorWipe(0xffff00,100);        //黄色
  390.                                                         PCON=0x02;//进入掉电模式
  391.                                                          _nop_();
  392.                                                             _nop_();
  393.                                                 }
  394.                                 while(!key_ok);//等待按键松开
  395.                                 }

  396.                         if( key_left == 0)//按键左键扫描
  397.                                  {
  398.                                         Delay10ms();                //按键消抖延时@22.1184MHz
  399.                                         if(key_left==0)
  400.                                                 {
  401.                                                 RGB_Rst();//复位
  402.                                                 list--;
  403.                                                 }
  404.                                 while(!key_left);//等待按键松开
  405.                                 }
  406.                         if(key_right == 0)//按键右键扫描
  407.                                  {
  408.                                         Delay10ms();                //按键消抖延时@22.1184MHz
  409.                                         if(key_right==0)
  410.                                                 {
  411.                                                 RGB_Rst();//复位
  412.                                                 list++;
  413.                                                 }
  414.                                 while(!key_right);//等待按键松开
  415.                                 }
  416.                                        
  417.                 }
  418.         }


  419. //中断服务程序
  420. void exint0() interrupt 2       //INT1中断入口
  421. {
  422.         colorWipe(0x00,100);        //0ff
  423.         Power = 0;        //关闭ws2812电源
  424.     P3M0 = 0x00; P3M1 = 0x04;//P3.2高阻输入
  425.         PCON=0x02;//进入掉电模式
  426.         _nop_();
  427.     _nop_();
  428. }


  429. //-----------------------------------------
  430. //中断服务程序
  431. void exint1() interrupt 10      //INT2中断入口
  432. {
  433.     EA = 0;                //关闭总中断
  434.         PCON=0x00;//取消掉电模式
  435.         P3M0 = 0x00; P3M1 = 0x00;//P3.2准双向输入
  436.         Power = 1;        //开启ws2812电源
  437.           EA = 1;                //开启总中断
  438.         _nop_();
  439.     _nop_();
  440. }

复制代码
回复

使用道具 举报

ID:161164 发表于 2024-1-2 16:05 | 显示全部楼层
按键左和按键右无法控制切换流水灯模式是因为其他地方用了大量长时间delay
全部时间都耗在颜色刷函数里
阻塞了按键扫描函数
放弃delay(10000)吧
给你一个思路
  1. #include <reg52.h>
  2. typedef         unsigned char        u8;  //0 to 255
  3. typedef         unsigned int        u16;  //0 to 65535
  4. sbit Led = P1^0;
  5. void Delay1ms(void)        //@11.0592MHz
  6. {
  7.         unsigned char data i, j;

  8.         i = 2;
  9.         j = 199;
  10.         do
  11.         {
  12.                 while (--j);
  13.         } while (--i);
  14. }
  15. u16 Delay = 0;
  16. void main()
  17. {
  18.         P1 = 0xFE;
  19.     while (1)
  20.     {
  21.                 if(++Delay>=500)
  22.                 {
  23.                         Delay = 0;
  24.                         Led = !Led;
  25.                 }
  26.                 Delay1ms();
  27.     }
  28. }
复制代码
回复

使用道具 举报

ID:190152 发表于 2024-1-2 21:20 | 显示全部楼层
lkc8210 发表于 2024-1-2 16:05
按键左和按键右无法控制切换流水灯模式是因为其他地方用了大量长时间delay
全部时间都耗在颜色刷函数里
...

感谢热情指导,有空去掉延时函数试试。我试过用定时器中断10ms扫描按键但是流水的会闪烁。或者用两个定时器中断一个负责刷新一个负责按键。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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