标题:
单片机ws2812程序无法用按键控制?
[打印本页]
作者:
高低都不调
时间:
2024-1-2 12:22
标题:
单片机ws2812程序无法用按键控制?
这个是用别人的程序修改的,现在遇到几个问题。外部中断接的开机按键需要按几次才能开机。按键左和按键右无法控制切换流水灯模式
单片机源程序如下:
#include<STC8Hxxx.h>
#include"intrins.h"
sbit WS2812 = P3^2;
sbit Power= P1^0;//ws2812电源开关
sbit key_left= P2^0;//按键左
sbit key_right= P2^1;//按键右
sbit key_ok= P2^2;//按键确认
sbit key_Return= P2^3;//按键返回
#define numLEDs 64 //灯的个数
unsigned char buf_R[numLEDs] = {0};//颜色缓存
unsigned char buf_G[numLEDs] = {0};
unsigned char buf_B[numLEDs] = {0};
unsigned char Timer0_cnt=0;//记录定时器0中断次数
unsigned char list=1;//播放列表
void RGB_Set_Up(); //送0码
void RGB_Set_Down(); //送1码
void Timer0_Init();//按键扫描定时器0初始化
void key_service();//按键服务程序
//void playlist(unsigned char list);
//真对 STC8系列 IO口初始化 准双向
void IO_init(void)
{
P0M0 = 0X00;
P0M1 = 0X00;
P1M0 = 0X01;
P1M1 = 0X00;
P2M0 = 0X00;
P2M1 = 0X00;
P3M0 = 0X00;
P3M1 = 0X00;
P4M0 = 0X00;
P4M1 = 0X00;
P5M0 = 0X00;
P5M1 = 0X00;
}
void HAL_Delay(unsigned long t)
{
unsigned int x,y;
for(x=114;x>0;x--)
for(y=t;y>0;y--);
}
//复位延时
void Delay50us() //@22.1184MHz
{
unsigned char i, j;
_nop_();
_nop_();
i = 2;
j = 15;
do
{
while (--j);
} while (--i);
}
//1码,高电平850ns 低电平400ns 误差正负150ns
void RGB_Set_Up()
{
WS2812 = 1;
//经过逻辑分析仪调试的的延时
_nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();
_nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();
WS2812 = 0;
}
//1码,高电平400ns 低电平850ns 误差正负150ns
void RGB_Set_Down()
{
WS2812 = 1;
//经过逻辑分析仪调试的的延时
_nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();
WS2812 = 0;
}
//发送24位数据
void Send_2812_24bits(unsigned char G8,unsigned char R8,unsigned char B8)
{
unsigned int n = 0;
//发送G8位
for(n=0;n<8;n++)
{
G8<<=n;
if(G8&0x80 == 0x80)
{
RGB_Set_Up();
}
else
{
RGB_Set_Down();
}
}
//发送R8位
for(n=0;n<8;n++)
{
R8<<=n;
if(R8&0x80 == 0x80)
{
RGB_Set_Up();
}
else
{
RGB_Set_Down();
}
}
//发送B8位
for(n=0;n<8;n++)
{
B8<<=n;
if(B8&0x80 == 0x80)
{
RGB_Set_Up();
}
else
{
RGB_Set_Down();
}
}
}
//复位码
void RGB_Rst()
{
WS2812 = 0;
Delay50us();
}
//颜色交换24位不拆分发
void SetPixelColor(unsigned char num,unsigned long c)
{
unsigned char i;
for(i=0;i<numLEDs;i++)
{
buf_R[num] = (unsigned char)(c>>16);
buf_G[num] = (unsigned char)(c>>8);
buf_B[num] = (unsigned char)(c);
}
for(i=0;i<numLEDs;i++)
{
Send_2812_24bits(buf_G[i],buf_R[i],buf_B[i]);
}
}
//复位
void PixelUpdate()
{
RGB_Rst();
}
// Fill the dots one after the other with a color
//用一种颜色填充这些圆点
void colorWipe(unsigned long c, unsigned int wait)
{
unsigned char i=0;
for( i=0; i<numLEDs; i++)
{
SetPixelColor(i, c);
PixelUpdate();
HAL_Delay(wait*5);
}
}
void Watercolor(unsigned long c, unsigned int wait)
{
unsigned char i=0;
for( i=0; i<numLEDs; i++)
{
SetPixelColor(i, c);
PixelUpdate();
HAL_Delay(wait*5);
SetPixelColor(i, 0);
PixelUpdate();
HAL_Delay(wait);
}
}
//颜色
unsigned long Color(unsigned char r, unsigned char g, unsigned char b)
{
return ((unsigned long)r << 16) | ((unsigned long)g << 8) | b;
}
//颜色算法
unsigned long Wheel(unsigned char WheelPos)
{
WheelPos = 255 - WheelPos;
if(WheelPos < 85)
{
return Color(255 - WheelPos * 3, 0, WheelPos * 3);
}
if(WheelPos < 170) {
WheelPos -= 85;
return Color(0, WheelPos * 3, 255 - WheelPos * 3);
}
WheelPos -= 170;
return Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}
//彩虹
void rainbow(unsigned int wait)
{
unsigned int i, j;
for(j=0; j<256; j++)
{
for(i=0; i<numLEDs; i++)
{
SetPixelColor(i, Wheel((i+j) & 255));
}
PixelUpdate();
HAL_Delay(wait);
}
}
//稍微不同的是,这使得彩虹均匀分布
void rainbowCycle(unsigned int wait)
{
unsigned int i, j;
for(j=0;j<256*5;j++)
{ // 5 cycles of all colors on wheel 车轮上所有颜色的5个循环
for(i=0;i<numLEDs;i++)
{
SetPixelColor(i, Wheel(((i * 256 / numLEDs) + j) & 255));
}
PixelUpdate();
HAL_Delay (wait);
}
}
//Theatre-style crawling lights with rainbow effect
//带有彩虹效果的戏剧式爬行灯
void theaterChaseRainbow(unsigned int wait)
{
int j,q;
unsigned int i;
for (j=0; j < 256; j++)
{ // cycle all 256 colors in the wheel 在轮子上循环所有256色
for (q=0; q < 3; q++)
{
for (i=0; i < numLEDs; i=i+3)
{
SetPixelColor(i+q, Wheel( (i+j) % 255)); //turn every third pixel off 把每一个第三个像素
}
PixelUpdate();
HAL_Delay(wait);
for (i=0; i < numLEDs; i=i+3)
{
SetPixelColor(i+q, 0); //turn every third pixel off 把每一个第三个像素关掉
}
}
}
}
void colorWipe_1()//颜色刷1
{
colorWipe(0xff0000,1); //红色
HAL_Delay(10000);
colorWipe(0xff00,1); //绿色
HAL_Delay(10000);
colorWipe(0xff,1);//蓝色
HAL_Delay(10000);
colorWipe(0xffff00,1); //黄色
HAL_Delay(10000);
colorWipe(0xffff,1); //青色
HAL_Delay(10000);
colorWipe(0xff00ff,1); //紫色
HAL_Delay(10000);
colorWipe(0xffffff,1); //白色
HAL_Delay(10000);
colorWipe(0x00,1); //off
HAL_Delay(10000);
}
void colorWipe_2()//颜色刷2
{
Watercolor(0xff0000, 100);//红色
HAL_Delay(1000);
Watercolor(0xff00, 100);//绿色
HAL_Delay(1000);
Watercolor(0xff, 100);//蓝色
HAL_Delay(1000);
Watercolor(0xffff00, 100); //黄色
HAL_Delay(1000);
Watercolor(0xffff, 100);//青色
HAL_Delay(1000);
Watercolor(0xff00ff, 100); //紫色
HAL_Delay(1000);
Watercolor(0xffffff, 100); //白色
HAL_Delay(1000);
colorWipe(0x00,1); //off
HAL_Delay(10000);
}
void colorWipe_3()//颜色刷3
{
colorWipe(0xff0000,100); //红色
HAL_Delay(1000);
colorWipe(0x00,100); //0ff
HAL_Delay(1000);
colorWipe(0xff00,100); //绿色
HAL_Delay(1000);
colorWipe(0x00,100); //0ff
HAL_Delay(1000);
colorWipe(0xff,100);//蓝色
HAL_Delay(1000);
colorWipe(0x00,100); //0ff
HAL_Delay(1000);
colorWipe(0xffff00,100); //黄色
HAL_Delay(1000);
colorWipe(0x00,100); //0ff
HAL_Delay(1000);
colorWipe(0xffff,100); //青色
HAL_Delay(1000);
colorWipe(0x00,100); //0ff
HAL_Delay(1000);
colorWipe(0xff00ff,100); //紫色
HAL_Delay(1000);
colorWipe(0x00,100); //0ff
HAL_Delay(1000);
colorWipe(0xffffff,100); //白色
HAL_Delay(1000);
colorWipe(0x00,100); //0ff
HAL_Delay(1000);
}
void main()
{
IO_init(); //io口初始化
IT1 = 1; //设置INT1的中断类型 (1:仅下降沿 0:上升沿和下降沿)
EX1 = 1;//使能INT1中断
INTCLKO|=0x10;//开启外部中断2
EA = 1; //开启总中断
Timer0_Init();//按键扫描定时器0初始化
while(1)
{
key_service();//按键服务程序
switch(list)
{
case 1: colorWipe_1(); break;//颜色刷1
case 2: colorWipe_2(); break;//颜色刷2
case 3: colorWipe_3(); break;//颜色刷3
case 4: rainbow(10); break;//彩虹
case 5: rainbowCycle(10); break;//彩虹2
case 6: theaterChaseRainbow(10); break;//彩虹升级
default:break;
}
}
}
//-----------------------------------------
//按键定时器初始化程序
void Timer0_Init(void) //20毫秒@22.1184MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式16位模式
TL0 = 0x00; //设置定时初始值
TH0 = 0x70; //设置定时初始值
TF0 = 0; //清除TF0标志
//ET0 = 1; //定时器0中断开启
TR0 = 1; //定时器0开始计时
}
void Delay10ms() //@22.1184MHz 按键消抖10ms延时
{
unsigned char i, j, k;
i = 2;
j = 32;
k = 60;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
//按键扫描服务程序
void key_service()//按键服务程序
{
if(TF0==1)
{
TF0 = 0; //清除TF0标志
TL0 = 0x9A; //设置定时初始值
TH0 = 0xA9; //设置定时初始值
if(key_Return==0)//返回键扫描
{
Delay10ms(); //按键消抖延时@22.1184MHz
if(key_Return==1)
{
RGB_Rst();//复位
colorWipe(0xffffff,100); //白色
PCON=0x02;//进入掉电模式
_nop_();
_nop_();
}
while(!key_Return);//等待按键松开
}
if(key_ok == 0)//OK键扫描
{
Delay10ms(); //按键消抖延时@22.1184MHz
if(key_ok==0)
{
RGB_Rst();//复位
colorWipe(0xffff00,100); //黄色
PCON=0x02;//进入掉电模式
_nop_();
_nop_();
}
while(!key_ok);//等待按键松开
}
if( key_left == 0)//按键左键扫描
{
Delay10ms(); //按键消抖延时@22.1184MHz
if(key_left==0)
{
RGB_Rst();//复位
list--;
}
while(!key_left);//等待按键松开
}
if(key_right == 0)//按键右键扫描
{
Delay10ms(); //按键消抖延时@22.1184MHz
if(key_right==0)
{
RGB_Rst();//复位
list++;
}
while(!key_right);//等待按键松开
}
}
}
//中断服务程序
void exint0() interrupt 2 //INT1中断入口
{
colorWipe(0x00,100); //0ff
Power = 0; //关闭ws2812电源
P3M0 = 0x00; P3M1 = 0x04;//P3.2高阻输入
PCON=0x02;//进入掉电模式
_nop_();
_nop_();
}
//-----------------------------------------
//中断服务程序
void exint1() interrupt 10 //INT2中断入口
{
EA = 0; //关闭总中断
PCON=0x00;//取消掉电模式
P3M0 = 0x00; P3M1 = 0x00;//P3.2准双向输入
Power = 1; //开启ws2812电源
EA = 1; //开启总中断
_nop_();
_nop_();
}
复制代码
作者:
lkc8210
时间:
2024-1-2 16:05
按键左和按键右无法控制切换流水灯模式是因为其他地方用了大量长时间delay
全部时间都耗在颜色刷函数里
阻塞了按键扫描函数
放弃delay(10000)吧
给你一个思路
#include <reg52.h>
typedef unsigned char u8; //0 to 255
typedef unsigned int u16; //0 to 65535
sbit Led = P1^0;
void Delay1ms(void) //@11.0592MHz
{
unsigned char data i, j;
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
}
u16 Delay = 0;
void main()
{
P1 = 0xFE;
while (1)
{
if(++Delay>=500)
{
Delay = 0;
Led = !Led;
}
Delay1ms();
}
}
复制代码
作者:
高低都不调
时间:
2024-1-2 21:20
lkc8210 发表于 2024-1-2 16:05
按键左和按键右无法控制切换流水灯模式是因为其他地方用了大量长时间delay
全部时间都耗在颜色刷函数里
...
感谢热情指导,有空去掉延时函数试试。我试过用定时器中断10ms扫描按键但是流水的会闪烁。或者用两个定时器中断一个负责刷新一个负责按键。
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1