跟據示波波形,反復調試,同時優化程序,使高電平最小時間接近0.5us,如示波器圖所示,這時可利用程序驅動WS2812,否則會因程序運行速度過慢而無法驅動。
為了簡化程序,加快代碼運行速度,采用匯編與C語言混合編程
#pragma ASM
SETB P2.5
CLR P2.5
CLR P2.5
#pragma ENDASM
因單片機時鐘周期限制,在仿真的調試過程中加入for,while循環會使ws2812的驅動波形出現長時間的低電平,導致不能正常點亮led,故此程序沒有使用for循環,而是多條語句重復使用,造成了代碼量很大,因本人能力有限,沒有精力進行簡化,望使用的大佬能進一步完善。
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
51hei.gif (86.87 KB, 下載次數: 42)
下載附件
2022-9-1 13:54 上傳
單片機源程序如下:
- #include <reg51.h>
- #include <LCD1602.h>
- #include <GY25.h>
- #include <WS2812.h>
- #include <stdio.h>
- #define PIXEL_COUNT 16
- sbit led1=P2^3;
- sbit led2=P2^4;
- int flag_now=0,flag_last=0;
- char strTemp[10]= {'0','1','2','3','4','5','6','7','8','9'};
- int RR,GG,BB;
- int i;
- int US100;
- int MS1;
- void display()
- {
- LCD_set_position(0);
- LCD_printc(strTemp[YPR/1000]);
- LCD_printc(strTemp[YPR/100%10]);
- LCD_printc(strTemp[YPR/10%10]);
- LCD_printc(strTemp[YPR%10]);
- }
- void led_init()
- {
- led1=1;
- led2=1;
- }
- void delay10ms(void) //誤差 0.000000000000us
- {
- unsigned char a,b;
- for(b=235;b>0;b--)
- for(a=57;a>0;a--);
- }
- int count=0;
- void control()
- {
- if(YPR<10&&YPR>-10)
- flag_now=1;
- else
- flag_now=2;
- if(flag_now==1)
- {
- led1=0;
- led2=1;
- }
- if(flag_now==2)
- {
- led1=1;
- led2=0;
- }
- if(flag_last!=flag_now)
- {
-
- if(flag_now==1)
- for(count=1;count<=32;count++)
- {
- ws2812_led(count);
- delay10ms();
- }
- if(flag_now==2)
- for(count=32;count>0;count--)
- {
- ws2812_led(count);
- delay10ms();
- }
- ws2812_led(0);
- }
-
- flag_last=flag_now;
- }
- void main(void)
- {
- InitUART();
- led_init();
- SBUF = 0XA5;
- while(!TI);
- SBUF = 0X52;
- while(!TI);
- delay10ms();
- while(1)
- {
- control();
- }
- }
復制代碼
51hei.png (4.5 KB, 下載次數: 73)
下載附件
2021-1-7 17:49 上傳
Keil代碼與Proteus8.8版本仿真51hei下載:
本人初學,僅供參考,存在錯誤和不足之處,請大家回帖多多指教,切勿照搬,文件下載:
WS2812.zip
(1.56 MB, 下載次數: 151)
2021-1-7 17:34 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|