WS2812控制时序如下
纯软件的开发,如果没有测时序的工具真的很麻烦。
对于WS2812的应用已经非常熟练,但是程序执行起来之后,现象一直不正常,
用了逻辑分析仪发现占空比等时间不对,发现函数莫名的被优化,写了多种延时方法都没实现
加了关键字修饰变量,起到点效果
void delay_250ns(void)
{
volatile unsigned int i;
for(i=0; i<1; i++);
}
用的系统函数延时1us实测有1.3us左右。
最终,经过不断调整时序,效果出来了,还算不错的。
用的PA0作为时序输出端
整体代码如下
#include "debug.h"
/* Global define */
/* Global Variable */
void delay_250ns(void)
{
volatile unsigned int i;
for(i=0; i<1; i++);
}
void WS_Reset() //复位
{
GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_RESET);
Delay_Ms(1);
}
void WS_Set_One(unsigned long dat)
{
unsigned char i;
for(i=0; i<24; i++)
{
if(0x800000 == (dat & 0x800000) ) {GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET); Delay_Us(1); GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_RESET); delay_250ns();}
else {GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET); delay_250ns(); GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_RESET); Delay_Us(1);}
dat <<= 1;
}
}
void WS_SetAll(unsigned long dat, unsigned char led_num)
{
unsigned char j;
for(j=0; j<led_num; j++)
{
WS_Set_One(dat);
}
WS_Reset();
}
void Led_Cycle_Run(void)
{
unsigned char i;
for(i = 0; i < 30; i++)
{
WS_SetAll(0xFFFFFF, i);
Delay_Ms(50);
}
}
/*********************************************************************
* @fn GPIO_Toggle_INIT
*
* @brief Initializes GPIOA.0
*
* @return none
*/
void GPIO_Toggle_INIT(void)
{
GPIO_InitTypeDef GPIO_InitStructure = {0};
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
/*********************************************************************
* @fn main
*
* @brief Main program.
*
* @return none
*/
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
Delay_Init();
USART_Printf_Init(115200);
printf("SystemClk:%d\r\n", SystemCoreClock);
printf("GPIO Toggle TEST\r\n");
GPIO_Toggle_INIT();
while(1)
{
Delay_Ms(250);
Led_Cycle_Run();
WS_SetAll(0x00, 30);
}
}
时钟切换为144MHz
#define SYSCLK_FREQ_144MHz 144000000
ws2812
|