#申请原创#@21小跑堂 今天给大家带来的是SPI+DMA驱动WS2812,其实WS2812是一种常见的LED灯珠,通常用于制作RGB全彩LED矩阵。它由三个引脚组成:VCC(电源)、GND(接地)和数据信号。每个灯珠包含一个红色、绿色和蓝色LED,可以通过不同的顺序和亮度控制来产生千变万化的颜色。在电子电路中,WS2812模块通常通过SPI接口与微控制器连接,用于驱动和编程。
具体如何驱动时序和逻辑其实可以参考以下文章,我觉得写的非常好,这里也谢谢作者的分享,感谢@二狗正在赶来路上。
https://blog.csdn.net/xia233233/ ... 1001.2014.3001.5502
我主要讲讲如何配置cubemx和移植Adafruit_NeoPixel来玩耍WS2812吧。
首先根据上次的操作,打开cubemx,选择好对应型号,其实也可以用上次的cubemx工程继续配置,这个就看个人习惯了,我是重新配置了一下。
首先进入到cubemx中要配置外部时钟晶振,这里选择外部时钟晶振。
接下来是配置SWD,主要是为了方便后续的下载与调试。
接下来是配置我们需要的SPI,本次我选择的是SPI1,然后由于需要SPI的速度在5.52——9.41MHz范围内,并且SPI发送一个字节时间长度等于一个编码的时间长度。因此,我们后续需要配置MCU的时钟树。
下面是针对SPI的DMA配置。
这是针对时钟树进行的配置,其实使用cubemx来配置APM32F11的话,主频最高让设置100MHz,不过就单独驱动WS2812的话,我觉得主频设置成72MHz也是可以的,设置成72MHz的话可以让SPI的速率达到9MHz。
以上就是外设的配置,已经操作完成,接下来就是配置输出工程方面。第一步是选择代码生成,设置如下:
主要设置了复制仅用到的库,这样是为了让工程小一些,还有就是将外围设备初始化为每个外围设备生成一对“.c/.h”文件,这样方便移植和修改。
接下来就是可以生成工程了,设置好工程名称、工程存储位置和编译链/IDE既可。
至此,针对于cubemx方面的操作就完成了,将生成的工程打开。
WS2812的C和H文件是从这里下载,https://gitee.com/xia-wang-666/ws2812_-led需要注意的是,请按照原作者的规则去使用该文件,毕竟开源不易,请大家珍惜。
如果就是需要点亮WS2812的话,可以将WS2812的C和H文件放入到刚刚生成好的工程中,并配置好头文件,编译不报错,就可以使用了。如果想要测试代码是否OK,可以在主函数调用以下函数中的一个/多个均可。其中LEN是代表要电量的LED灯个数。
//常用颜色的点亮测试函数
void RGB_RED(uint16_t RGB_LEN)
{
uint8_t i;
for(i = 0; i < RGB_LEN; i++)
{
RGB_Set_Color(i, RED);
}
RGB_Reflash(RGB_LEN);
}
void RGB_GREEN(uint16_t RGB_LEN)
{
uint8_t i;
for(i = 0; i < RGB_LEN; i++)
{
RGB_Set_Color(i, GREEN);
}
RGB_Reflash(RGB_LEN);
}
void RGB_BLUE(uint16_t RGB_LEN)
{
uint8_t i;
for(i = 0; i < RGB_LEN; i++)
{
RGB_Set_Color(i, BLUE);
}
RGB_Reflash(RGB_LEN);
}
void RGB_YELLOW(uint16_t RGB_LEN)
{
uint8_t i;
for(i = 0; i < RGB_LEN; i++)
{
RGB_Set_Color(i, YELLOW);
}
RGB_Reflash(RGB_LEN);
}
void RGB_WHITE(uint16_t RGB_LEN)
{
uint8_t i;
for(i = 0; i < RGB_LEN; i++)
{
RGB_Set_Color(i, WHITE);
}
RGB_Reflash(RGB_LEN);
}
值得注意的是:以上代码如果按照此文章或者链接文章操作,均可以实现WS2812的正确驱动操作。当然了,点亮不是目的,目的是玩起来。之前有了解的是,WS2812的C语言方面的库,可以使用Adafruit_NeoPixel,AdafruitNeoPixel是一个开源的Arduino库,用于控制基于WS2811、WS2812或APA102(又称DotStar)等LED驱动芯片的RGB LED像素串。
void setAllPixelColor(uint8_t r, uint8_t g, uint8_t b)//设置所有LED的颜色
{
uint8_t i = 0;
RGB_RST();
for(i = 0; i < PIXEL_MAX; i++)
{
RGB_DAT[i].R = r;
RGB_DAT[i].G = g;
RGB_DAT[i].B = b;
}
for(i = 0; i < PIXEL_MAX; i++)
{
RGB_Reflash(i);
}
}
void setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b)//设置单个LED颜色
{
uint8_t i = 0;
RGB_RST();
RGB_DAT[n].G = r;
RGB_DAT[n].R = g;
RGB_DAT[n].B = b;
for(i = 0; i < PIXEL_MAX; i++)
{
RGB_Reflash(i);
}
}
void SetPixelColor(uint16_t n, uint32_t c)
{
RGB_RST();
RGB_DAT[n].R = ((uint8_t)(c >> 16));
RGB_DAT[n].G = (uint8_t)(c >> 8);
RGB_DAT[n].B = (uint8_t)c;
RGB_Reflash(n);
}
以上代码可以放在WS2812中,PIXEL_MAX可以用RGB_NUM替代,函数的头文件我就不发了,其实就把void以及这行放到ws2812.h中既可。
void rainbowCycle(uint16_t wait)//彩虹特效,放在主函数while(1)中运行
{
uint16_t i, j;
for(j = 0; j < 256 * 5; j++)
{
// 5 cycles of all colors on wheel
for(i = 0; i < PIXEL_MAX; i++)
{
SetPixelColor(i, Wheel(((i * 256 / PIXEL_MAX) + j) & 255));
}
HAL_Delay (wait);
}
}
以下是彩虹特效,哈哈,还是很漂亮的嘛
到此,针对于WS2812的SPI+DMA驱动WS2812并且加入了一些特效效果就告一段落了,总的来说,SPI与DMA是比较常用的MCU的外设之一,本次的应用可以很由浅入深的了解SPI与DMA的工作流程,并且可以将WS2812驱动起来,实现一些灯效,在一些LED项目中具有参考意义。
|