![62bbc64bff7c3015197a3b3c414f5efc.png](https://i-blog.csdnimg.cn/blog_migrate/e6b116eb6b3912bc6626de9fc6e48683.png)
欢迎关注BUG记录知乎专栏和BUG记录公众号,关注BUG记录公众号回复2812获取本文的参考单片机程序以及STM32CubeMx的安装包和库文件
![755a390269dad7a9cb004cf43664e4a5.png](https://i-blog.csdnimg.cn/blog_migrate/f70a922fb13724f53e0ace6bb74abd8d.jpeg)
之前曾写过SPI协议的verilog实现,其实单片机也有很多地方用到了SPI,今天我们说一个比较冷门的SPI用法——控制WS2812灯带。
本文主要介绍STM32CubeMx的使用,WS2812灯带的控制。通过WS2812的例程,简单展示STM32CubeMx的方便,快捷
玩过单片机的人或多或少都知道STM32单片机,而STM32单片机因为其相对而言强大的性能,操作也变得较为复杂;为了让更多的人能够快速的上手STM32,减少各种外设内设寄存器操作的复杂干扰,官方推出了STM32CubeMx,能够以图形化界面,设置好相关的内部寄存器,使开发者不被底层操作束缚。
![22dde807b139b92016cf71dbe94a4393.png](https://i-blog.csdnimg.cn/blog_migrate/23bd3d9199315efd706604feefbd5f9f.png)
WS2812,如上图,它可以显示256级亮度,完成16777216种颜色的全真色彩显示。用它可以完成各种绚丽的色彩显示。但是,它的控制也有一点麻烦,通过一根线上占空比不同区别0-1,将色彩的RGB二进制代码发送到WS2812显示
![c5d6a1711995d5dcaa00308429d70859.png](https://i-blog.csdnimg.cn/blog_migrate/7b413f9bc05b730f407347a893a078df.png)
![6f26b0429f223e0378871c213ab25cf8.png](https://i-blog.csdnimg.cn/blog_migrate/1aa9d9e331173ba8a68d0d3990d1616f.png)
RGB一共要发24位,而输入码型却不是简单的高低电平,它有较为复杂的时序要求;为了解决这个问题,有人想到了“曲线实现”的方法,通过SPI输出不同的数据来实现对WS2812的控制。
举例来说,假设SPI发送速率为4.5MBit/s, 那么发送1bit所占的时间为1/4.5 us,大概为0.22us; 那么,我发送0xf0时,前4位数都是高电平,占时0.88us,满足了T1L的高电平时间,这时候有人会说你低4位都是低电平,没关系,满足条件后的低电平默认为空闲状态,实验证明这确实也不会影响最终效果。
同样,发送0xc0,满足T0L的时序要求,而现在,需要做的就是使用STM32CubeMx完成相关的寄存器设置;
![b074ed7a5ec41088a759af75c792a0bc.png](https://i-blog.csdnimg.cn/blog_migrate/6f5a2dc95edd23656ba9f1654b31ab6f.jpeg)
![a933cd4e6d92f5ba16a7ec54bb1a7ac3.png](https://i-blog.csdnimg.cn/blog_migrate/63a93a8589959f7dd9b21be38c94e581.jpeg)
![2c40a0bd459108afed91a40bbb84ecbd.png](https://i-blog.csdnimg.cn/blog_migrate/2ecb2097f06e0753649ee00386a3b118.jpeg)
![415d5ca937a3befcc78a979d33197ca1.png](https://i-blog.csdnimg.cn/blog_migrate/e9722448638ff98bbb8a5d38dce35fd8.jpeg)
这个地方需要注意,因为SPI的速率较高,内部的8MHz时钟可能无法满足,这个时候需要启用外部晶振,再经过PLL倍频,操作如下:
![0d5eaf98937730bf7bfc0ce757436a32.png](https://i-blog.csdnimg.cn/blog_migrate/ac9b89a7638366b6ee09447d1021a471.jpeg)
PLL的倍频操作如上图,可以适当做调整。
![2690c59381b2ea78cf42902b5f402571.png](https://i-blog.csdnimg.cn/blog_migrate/a9f52403cbcb14b9fba80712162fc83a.jpeg)
设置好Debug,否则没办法Debug代码;这个地方根据自己的调试器做选择;
![9b37431aeef6641e8e04319d7d5b320e.png](https://i-blog.csdnimg.cn/blog_migrate/3610d87debf4fa93957dcca77c2700d9.jpeg)
选用SPI1,模式选择仅主发送,然后在Parameter Setting里面,选择MSB First,上面的PLL设置倍频后,SPI的时钟为72MHz,经过预分频16后,SPI的波特率为4.5MBit/s,这个地方需要选择CPOL和CPHA,关于CPOL,CPHA的内容可以查看配置芯片寄存器的SPI通信协议的verilog实现(一)
![61bcef962e9fecb0d8d0e65bf31cc8d2.png](https://i-blog.csdnimg.cn/blog_migrate/7cd9e583310dcd19d84cb3606450a69b.jpeg)
这个地方,添加一个SPI1_TX的DMA,具体设置如上;
![a4110a9043e649e86a0157df14d6e626.png](https://i-blog.csdnimg.cn/blog_migrate/0d8cd2a33f2078a832679125abb148d4.jpeg)
点击Project Manager子标签,设置如同上面
![6e50a72016de4c86e26dea554f6a8261.png](https://i-blog.csdnimg.cn/blog_migrate/847e1387d0d9c63a3208610cca42abcf.jpeg)
注意选择正确的Toolchain,然后点击右上角“generate code”,就可以生成相关的工程文件啦;
![7fb605c9f8254520461240add68be843.png](https://i-blog.csdnimg.cn/blog_migrate/c976c1bf501ad8a2c30009fb4eb15d60.jpeg)
![f5a9f051700785107b36889013957b48.png](https://i-blog.csdnimg.cn/blog_migrate/3df677bc8f5af74fc5bda7e305c6adb5.png)
里面的通信控制主要是使用了HAL_SPI_Transmit_DMA函数,这是HAL库自带的库函数,使用这个库函数发送数据;
![b572448533154fbd4ff06865ebbcfcf9.png](https://i-blog.csdnimg.cn/blog_migrate/463ae88cf8e342166dff86d7d46eade9.jpeg)
这个是RGB转成SPI发送需要发送的数据;转换的过程比较简单粗暴,没想什么巧法子。
![0f4b9e2c95655dca06782d8187d307a7.png](https://i-blog.csdnimg.cn/blog_migrate/ee9e06e201cd884d4b0db08f04e1cac4.png)
这个是WS2812总的发送程序,其实也就是结合了上面的两个程序,到此WS2812驱动就基本写完了,具体细节可以关注BUG记录公众号回复2812获取本文的参考单片机程序以及STM32CubeMx的安装包和库文件
注意,STM32CubeMx生成的代码里想做修改,需要在“/* USER CODE END WHILE */”和“/* USER CODE BEGIN 3 */”中间写,这样如果使用STM32CubeMx重新修改设置,重新生成代码不会抹掉用户做的代码修改;
maxs-well/ws2812_by_SPI_DMA_STM32github.com![cc9821d120adb6f4c7360d1033a9087d.png](https://i-blog.csdnimg.cn/blog_migrate/730ca8415adc8d3f6913ec12c88eac75.png)
这是本文用到的代码,除去ws2812.c和ws2812.h,其他的源代码基本是STM32CubeMx生成,如果想看本文用到的STM32CubeMx工程,安装包和库文件,欢迎关注微信公众号BUG记录(BugRec),回复2812获取资源。
如果有更好的方法方案可以留言一起谈论,欢迎大家点赞收藏留言讨论交流。
万物皆可卷积:配置芯片寄存器的SPI通信协议的verilog实现(二)- Verilog实现讲解zhuanlan.zhihu.com
![e1dc2877631081bc7408712aeb39dffb.png](https://i-blog.csdnimg.cn/blog_migrate/1061c8555cdae9bbe781f75cf8e8b20d.png)
![12af3b9f8f2eec348bd3428e7c0ddfb3.png](https://i-blog.csdnimg.cn/blog_migrate/5a4a235b8d7feb00807598623b3b125e.jpeg)
![12af3b9f8f2eec348bd3428e7c0ddfb3.png](https://i-blog.csdnimg.cn/blog_migrate/5a4a235b8d7feb00807598623b3b125e.jpeg)