標題:
單片機ws2812程序無法用按鍵控制?
[打印本頁]
作者:
高低都不調(diào)
時間:
2024-1-2 12:22
標題:
單片機ws2812程序無法用按鍵控制?
這個是用別人的程序修改的,現(xiàn)在遇到幾個問題。外部中斷接的開機按鍵需要按幾次才能開機。按鍵左和按鍵右無法控制切換流水燈模式
單片機源程序如下:
#include<STC8Hxxx.h>
#include"intrins.h"
sbit WS2812 = P3^2;
sbit Power= P1^0;//ws2812電源開關(guān)
sbit key_left= P2^0;//按鍵左
sbit key_right= P2^1;//按鍵右
sbit key_ok= P2^2;//按鍵確認
sbit key_Return= P2^3;//按鍵返回
#define numLEDs 64 //燈的個數(shù)
unsigned char buf_R[numLEDs] = {0};//顏色緩存
unsigned char buf_G[numLEDs] = {0};
unsigned char buf_B[numLEDs] = {0};
unsigned char Timer0_cnt=0;//記錄定時器0中斷次數(shù)
unsigned char list=1;//播放列表
void RGB_Set_Up(); //送0碼
void RGB_Set_Down(); //送1碼
void Timer0_Init();//按鍵掃描定時器0初始化
void key_service();//按鍵服務(wù)程序
//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--);
}
//復(fù)位延時
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;
//經(jīng)過邏輯分析儀調(diào)試的的延時
_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;
//經(jīng)過邏輯分析儀調(diào)試的的延時
_nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();
WS2812 = 0;
}
//發(fā)送24位數(shù)據(jù)
void Send_2812_24bits(unsigned char G8,unsigned char R8,unsigned char B8)
{
unsigned int n = 0;
//發(fā)送G8位
for(n=0;n<8;n++)
{
G8<<=n;
if(G8&0x80 == 0x80)
{
RGB_Set_Up();
}
else
{
RGB_Set_Down();
}
}
//發(fā)送R8位
for(n=0;n<8;n++)
{
R8<<=n;
if(R8&0x80 == 0x80)
{
RGB_Set_Up();
}
else
{
RGB_Set_Down();
}
}
//發(fā)送B8位
for(n=0;n<8;n++)
{
B8<<=n;
if(B8&0x80 == 0x80)
{
RGB_Set_Up();
}
else
{
RGB_Set_Down();
}
}
}
//復(fù)位碼
void RGB_Rst()
{
WS2812 = 0;
Delay50us();
}
//顏色交換24位不拆分發(fā)
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]);
}
}
//復(fù)位
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個循環(huán)
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 在輪子上循環(huán)所有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 把每一個第三個像素關(guān)掉
}
}
}
}
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; //設(shè)置INT1的中斷類型 (1:僅下降沿 0:上升沿和下降沿)
EX1 = 1;//使能INT1中斷
INTCLKO|=0x10;//開啟外部中斷2
EA = 1; //開啟總中斷
Timer0_Init();//按鍵掃描定時器0初始化
while(1)
{
key_service();//按鍵服務(wù)程序
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; //設(shè)置定時器模式
TMOD |= 0x01; //設(shè)置定時器模式16位模式
TL0 = 0x00; //設(shè)置定時初始值
TH0 = 0x70; //設(shè)置定時初始值
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);
}
//按鍵掃描服務(wù)程序
void key_service()//按鍵服務(wù)程序
{
if(TF0==1)
{
TF0 = 0; //清除TF0標志
TL0 = 0x9A; //設(shè)置定時初始值
TH0 = 0xA9; //設(shè)置定時初始值
if(key_Return==0)//返回鍵掃描
{
Delay10ms(); //按鍵消抖延時@22.1184MHz
if(key_Return==1)
{
RGB_Rst();//復(fù)位
colorWipe(0xffffff,100); //白色
PCON=0x02;//進入掉電模式
_nop_();
_nop_();
}
while(!key_Return);//等待按鍵松開
}
if(key_ok == 0)//OK鍵掃描
{
Delay10ms(); //按鍵消抖延時@22.1184MHz
if(key_ok==0)
{
RGB_Rst();//復(fù)位
colorWipe(0xffff00,100); //黃色
PCON=0x02;//進入掉電模式
_nop_();
_nop_();
}
while(!key_ok);//等待按鍵松開
}
if( key_left == 0)//按鍵左鍵掃描
{
Delay10ms(); //按鍵消抖延時@22.1184MHz
if(key_left==0)
{
RGB_Rst();//復(fù)位
list--;
}
while(!key_left);//等待按鍵松開
}
if(key_right == 0)//按鍵右鍵掃描
{
Delay10ms(); //按鍵消抖延時@22.1184MHz
if(key_right==0)
{
RGB_Rst();//復(fù)位
list++;
}
while(!key_right);//等待按鍵松開
}
}
}
//中斷服務(wù)程序
void exint0() interrupt 2 //INT1中斷入口
{
colorWipe(0x00,100); //0ff
Power = 0; //關(guān)閉ws2812電源
P3M0 = 0x00; P3M1 = 0x04;//P3.2高阻輸入
PCON=0x02;//進入掉電模式
_nop_();
_nop_();
}
//-----------------------------------------
//中斷服務(wù)程序
void exint1() interrupt 10 //INT2中斷入口
{
EA = 0; //關(guān)閉總中斷
PCON=0x00;//取消掉電模式
P3M0 = 0x00; P3M1 = 0x00;//P3.2準雙向輸入
Power = 1; //開啟ws2812電源
EA = 1; //開啟總中斷
_nop_();
_nop_();
}
復(fù)制代碼
作者:
lkc8210
時間:
2024-1-2 16:05
按鍵左和按鍵右無法控制切換流水燈模式是因為其他地方用了大量長時間delay
全部時間都耗在顏色刷函數(shù)里
阻塞了按鍵掃描函數(shù)
放棄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();
}
}
復(fù)制代碼
作者:
高低都不調(diào)
時間:
2024-1-2 21:20
lkc8210 發(fā)表于 2024-1-2 16:05
按鍵左和按鍵右無法控制切換流水燈模式是因為其他地方用了大量長時間delay
全部時間都耗在顏色刷函數(shù)里
...
感謝熱情指導(dǎo),有空去掉延時函數(shù)試試。我試過用定時器中斷10ms掃描按鍵但是流水的會閃爍;蛘哂脙蓚定時器中斷一個負責(zé)刷新一個負責(zé)按鍵。
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1