跟据示波波形,反复调试,同时优化程序,使高电平最小时间接近0.5us,如示波器图所示,这时可利用程序驱动WS2812,否则会因程序运行速度过慢而无法驱动。
为了简化程序,加快代码运行速度,采用汇编与C语言混合编程
#pragma ASM
SETB P2.5
CLR P2.5
CLR P2.5
#pragma ENDASM
因单片机时钟周期限制,在仿真的调试过程中加入for,while循环会使ws2812的驱动波形出现长时间的低电平,导致不能正常点亮led,故此程序没有使用for循环,而是多条语句重复使用,造成了代码量很大,因本人能力有限,没有精力进行简化,望使用的大佬能进一步完善。
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
单片机源程序如下:
- #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();
- }
- }
复制代码
Keil代码与Proteus8.8版本仿真51hei下载:
本人初学,仅供参考,存在错误和不足之处,请大家回帖多多指教,切勿照搬,文件下载:
WS2812.zip
(1.56 MB, 下载次数: 151)
|