WS2812灯珠(一)-- STM32 普通IO方式驱动

2019-04-15 18:21发布

      相信大家在看到这篇文章的时候一定对WS2812芯片的时序有了一定的了解,这里对于WS2812硬件通信方面就不做过多的介绍了。驱动WS2812需要的实现纳秒级别的电平翻转,像一般主频较低的MCU很难实现这种级别的电平翻转。我在这里使用的MCU是STM32F103系列主频为72M,恰好可以通过延时翻转高低电平模拟WS2812的通信时序进而实现对WS2812灯珠的驱动。 STM32通过普通IO方式驱动WS2812灯珠首先我们要初始化IO端口。 /** * @brief 初始化IO控制口 * @param * @retval None */ void ws2811_init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能PA端口时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //WS2811-->PA.0 端口配置 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz GPIO_Init(GPIOA, &GPIO_InitStructure); //根据设定参数初始化GPIOA.0 GPIO_ResetBits(GPIOA,GPIO_Pin_0); //PA.0 输出低电平 } 接下来便要实现合适的延时函数: /** * @brief ws281x模块用到的延时函数 * @param delay_num :延时数 (示波器测量延时时间 = delay_num * 440ns ) * @retval None */ void ws281X_delay(unsigned int delay_num) { while(delay_num--); } 通过示波器测量出的该延时函数的延时时间为delay_num x 440ns,恰好可以实现纳秒级别的延时。因此可用此来模拟WS281x的通信时序。 /** * @brief 根据WS281x芯片时序图编写的发送0码,1码RESET码的函数 * @param * @retval None */ void ws281x_sendLow(void) //发送0码 { PAout(0) = 1; ws281x_delay(1); //示波器测试约为440ns PAout(0) = 0; ws281x_delay(2); } void ws281x_sendHigh(void) //发送1码 { PAout(0) = 1; ws281x_delay(2); PAout(0) = 0; ws281x_delay(1); } void ws2811_Reset(void) //发送RESET码 { PAout(0) = 0; delay_us(60); PAout(0) = 1; PAout(0) = 0; } 接下来根据这些通信时序我们便可以实现点亮WS2812灯珠的函数了 /** * @brief 发送点亮一个灯的数据(即24bit) * @param dat:颜 {MOD}的24位编码 * @retval None */ void ws281x_sendOne(uint32_t dat) { uint8_t i; unsigned char byte; for(i = 24; i > 0; i--) { byte = ((dat>>i) & 0x01); //位操作,读取dat数据的第i位 if(byte == 1) { ws281x_sendHigh(); } else { ws281x_sendLow(); } } } 如在主函数中调用ws281x_sendOne(0XFF0000)即可点亮一个绿灯。 如果需要控制多个WS2812灯珠可以定义一个缓冲区pixelBuffer[PIXEL_NUM]的数组,首先将颜 {MOD}数据依次填入缓冲区,再通过发送函数将颜 {MOD}数据依次发出即可。若想实现多种炫酷效果还可以移植Adafruit_NeoPixel库函数。