文章目录

  • STM32CubeMX-SPI+DMA 驱动 2812 灯带
    • 一、初始准备
      • 1.硬件平台
    • 二、操作步骤
      • 1.CubeMX生成初始化代码
        • 1.1 建立工程(通用步骤)
        • 1.2配置SPI和DMA外设
        • 1.3生成代码(通用步骤)
      • 2.编写代码
      • 3.程序下载,观察现象(通用步骤)
    • 三、实验现象

STM32CubeMX-SPI+DMA 驱动 2812 灯带

本章内容使用 STM32CubeMX 软件配置 STM32F407ZGT6 开发板,使用 SPI + DMA 方式来驱动 WS2812 彩灯

教程包含通用步骤以及专用步骤,其中,通用步骤为STM32CubeMX配置其他外设工程的通用操作,STM32CubeMX系列教程基本通用,专用操作则是针对当前工程进行的配置

一、初始准备

1.硬件平台

主控使用正点原子STM32F4探索者:

WS2812 灯环:

WS2812 是一个单总线控制的 RGB 彩灯,,通过单根总线向其写入数据,通过写入的数据控制 RGB 颜色,因为是单总线,所以通过总线上高低电平时间长短的不同来区分 0 和 1,手册中关于 0 和 1 的区分如下:

具体时间对应如下:

数据发送速度可达 800Kbps,就是 1.25us 发送一位数据,因为协议有一定的兼容性,所以实际上一个位的周期在1.25us±300ns之间都能识别到,因为是 us 级延时,所以时间要控制精准很难,因此我们借助 SPI 来控制 WS2812,我们用 SPI 的 MOSI 接口的一个 Byte(8位)模拟 WS2812 的一个位,比如下面的 SPI 我 设置的 5.25M 速率,一个字节约为 1.5us,所以可以通过发送了一个字节的数据控制电平时间,然后模拟 0 和 1 到 WS2812,比如下面发送的 0xF8

高电平时间 950ns,低电平时间我们不用管,只要整体传输速率在 2812 范围内就行就行,2812 识别 0 和 1 主要还是看高电平时间,所以下面这个 SPI 发的数据是 0xF8 代表的就是 2812 的 1

同理,当发送的数据是 0xC0 时这代表 0

到此,我们就可以通过 SPI 发送的不同数据来发送 0 和 1 到 WS2812,SPI 数据发送 0 和 1的原理明白了,WS2812 控制等的颜色需要 24 位,分别对应 G、R、B 的三个颜色的值,当我们发完一个灯的 RGB 值后,继续发送就会切换到下一个灯的 RGB 色彩控制,循环下去,所以 WS2812 可以无线套娃,可 DIY 性很高

但我们仔细想想,发送 24 位控制 1 个灯,相当于 SPI 要发送 24 个字节去控制一个灯,这对资源的占用太大了,严重占用 CPU 资源,所以我们一般用 SPI 控制灯的时候顺便加上 DMA,减小 CPU 压力

二、操作步骤

1.CubeMX生成初始化代码

1.1 建立工程(通用步骤)

  • 芯片选择

打开cube软件,选择从芯片来创建工程,一般开发都是使用这个来开发,有的时候也可能使用另外两个,但不多,第二个基于ST提供的开发板创建工程,针对性高,第三个则选择ST提供的例程来创建工程

F4探索者的主控为STM32F407ZGT6,所以在搜索框找到STM32F407ZG后点击具体芯片,再开始工程

  • 配置时钟源

我们点开SystemCore(系统内核设置),再点击RCC配置HSE和LSE时钟源,这里我都选择使用外部时钟,配置后,我们可以看到右边芯片引脚分配图的两个时钟源引脚点亮,表示时钟配置为外部源

  • 配置时钟树

我们进入ClockConfiguration配置时钟树,使时钟的输入路径和大小符合我们预期,探索者的晶振和时钟倍频如下

一般配置正确时颜色蓝白为主,配置错误时则会出现紫色,提示我们要修改值

具体时钟树的了解可以看我很久之前的文章,有做一些分析

CSDN文章链接-时钟树分析

1.2配置SPI和DMA外设

  • 开启 SPI1,配置为只有主机发送,然后配置 SPI 为 5.25M 跳变沿选第二个(2Edge)

因为跳变沿为 1 的话,MOSI 的空闲电平为高电平,为 2 的话则会延续上次发送的最后电平,我们发送数据的末尾都是低电平,这样 WS2812 不会误判

  • 开启 DMA,参数保持默认

1.3生成代码(通用步骤)

点击进入Project Manager 配置生成工程的名字,存储路径**(不要有中文)**以及编译器,这里我们选MDK-ARM(Keil被收购后改名)

配置生成选项,主要为下面三大块,第一个我们选择只拷贝必要的库,第二个选择为每个外设生成.c和.h文件,保存之前的用户代码,以及删除之前的生成代码,第三个不选择

PS:用户代码段是一下注释之间的代码,只有原始的用户代码段注释才有效,用户自己添加的无效

/* USER CODE BEGIN 1 *//* USER CODE END 1 */

最后点击生成代码

2.编写代码

在工程目录创建 Hardware 文件夹,下面在创建个 ws2812 文件夹,里面放上如下文件

在 MDK 工程里面导入文件和其路径

然后编写驱动代码,这里我参考了这篇文章,在其基础上进行修改,改动的挺多,完善内存使用,同时将刷新和设置隔离,方便我们可以在 RTOS 中使用

WS2812b幻彩ARGB灯珠的STM32F103的CPU-SPI方式驱动-作者:爱莎女王

先写头文件代码

#ifndef __WS2812_H
#define __WS2812_H#include "main.h"typedef struct             //颜色结构体
{uint8_t R;uint8_t G;uint8_t B;
}RGBColor_TypeDef;#define RGB_NUM    24 // RGB数量// 复位函数
void RGB_RST(void);
// 颜色设置函数
void RGB_Set_Color(uint8_t LedId, RGBColor_TypeDef Color);
// RGB 刷新函数
void RGB_Reflash(uint8_t reflash_num);// 各种颜色测试
void RGB_RED(uint16_t RGB_LEN);     //红
void RGB_GREEN(uint16_t RGB_LEN);       //绿
void RGB_BLUE(uint16_t RGB_LEN);        //蓝
void RGB_YELLOW(uint16_t RGB_LEN);      //黄
void RGB_MAGENTA(uint16_t RGB_LEN); //紫
void RGB_BLACK(uint16_t RGB_LEN);       //黑
void RGB_WHITE(uint16_t RGB_LEN);       //白#endif /* __WS2812_H */

然后写源文件代码

#include "ws2812.h"
#include "spi.h"
#include "dma.h"// 常用的颜色,亮度调的比较低
const RGBColor_TypeDef RED      = {30 ,0  ,  0};
const RGBColor_TypeDef GREEN    = {0  , 30,  0};
const RGBColor_TypeDef BLUE     = {0  ,  0, 30};
const RGBColor_TypeDef YELLOW   = { 30, 30,  0};
const RGBColor_TypeDef MAGENTA  = { 30,  0, 30};
const RGBColor_TypeDef BLACK    = {  0,  0,  0};
const RGBColor_TypeDef WHITE    = { 30, 30, 30};//模拟bit码:0xC0 为 0,0xF8 为 1
const uint8_t code[]={0xC0,0xF8};
//灯颜色缓存区
RGBColor_TypeDef RGB_DAT[RGB_NUM];//SPI底层发送接口,一次发24个字节,相当于1个灯
extern DMA_HandleTypeDef hdma_spi1_tx;
static void SPI_Send(uint8_t *SPI_RGB_BUFFER)
{/* 判断上次DMA有没有传输完成 */while(HAL_DMA_GetState(&hdma_spi1_tx) != HAL_DMA_STATE_READY);/* 发送一个(24bit)的 RGB 数据到 2812 */HAL_SPI_Transmit_DMA(&hspi1,SPI_RGB_BUFFER,24);
}
//颜色设置函数,传入 ID 和 颜色,进而设置缓存区
void RGB_Set_Color(uint8_t LedId, RGBColor_TypeDef Color)
{if(LedId < RGB_NUM){RGB_DAT[LedId].G = Color.G;RGB_DAT[LedId].R = Color.R;RGB_DAT[LedId].B = Color.B;}
}
//刷新函数,将颜色缓存区刷新到WS2812,输入参数是指定的刷新长度
void RGB_Reflash(uint8_t reflash_num)
{static uint8_t RGB_BUFFER[24]={0};uint8_t dat_b,dat_r,dat_g;//将数组颜色转化为 24 个要发送的字节数据if(reflash_num>0 && reflash_num<=RGB_NUM){for(int i=0;i<reflash_num;i++){dat_g = RGB_DAT[i].G;dat_r = RGB_DAT[i].R;dat_b = RGB_DAT[i].B;for(int j=0;j<8;j++){RGB_BUFFER[7-j] =code[dat_g & 0x01];RGB_BUFFER[15-j]=code[dat_r & 0x01];RGB_BUFFER[23-j]=code[dat_b & 0x01];dat_g >>=1;dat_r >>=1;dat_b >>=1;}SPI_Send(RGB_BUFFER);}}
}
//复位函数
void RGB_RST(void)
{uint8_t dat[100] = {0};/* 判断上次DMA有没有传输完成 */while(HAL_DMA_GetState(&hdma_spi1_tx) != HAL_DMA_STATE_READY);/* RGB RESET */HAL_SPI_Transmit_DMA(&hspi1,dat,100); HAL_Delay(10);
}//常用颜色的点亮测试函数
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);
}
//.........其他测试函数省略...........//

代码把刷新和设置隔离,方便在 RTOS 中调用,其实可以进一步修改,让不同硬件的颜色buffer和刷新进一步隔离,通过指针传递共用底层,我后面有时间再修改,可以关注我的仓库链接,后面更新了会推到上面

JeckXu Gitee

3.程序下载,观察现象(通用步骤)

程序下载我一般用两种方式:

第一种是使用MDK自带的下载环境下载程序,我们给单片机连接ST-Link后配置下载,点击魔术棒,选择debug

选择ST-link后,点击setting

添加对应F4的Flash

keil界面点击下载

第二种是使用Stm32Programmer下载软件,该下载软件下载方式多,下载快,下面我使用st-link下载

打开软件,点击connect左边选择stlink后再点击connect连接下载器

点击open file,找到工程路径下MDK文件夹下工程生成的hex文件

之后点击downlod下载,下载结果如下

三、实验现象

灯环刷新

STM32CubeMX-SPI+DMA 驱动 2812 灯带相关推荐

  1. PWM+DMA驱动SK6812MINI灯带

    SK6812MINI是一款常见的RGB灯带,它的工作状态稳定,驱动简单,通过简单的代码即可实现流动彩虹灯的功能.下面让我们来看一下它的具体实现流程吧! 1.硬件配置 PWM配置: 选择对应IO口的TI ...

  2. 【基于 STM32CubeMX + PWM + DMA驱动SW2812b全彩RGB灯】

    基于 STM32CubeMX + PWM + DMA驱动SW2812b全彩RGB灯 STM32CubeMX配置: 工程源码: END 以上就是相关配置,最需要注意的就是时钟以及pre数值以及芯片时钟频 ...

  3. [SPI+DMA] 驱动WS2812B显示时钟

    [SPI+DMA] 驱动WS2812B显示时钟 实现原理 本人一个大学萌新,偶然间发现RGB时钟这神奇的玩意,就想试试.目前初步实现时钟显示,第一次写博客,只是为了记录自己的学习成果方便以后查看,大家 ...

  4. 驱动RGB灯带MCU阐述

    驱动RGB灯带MCU推荐 本文仅分享个人工作中积累的经验,无任何商业行为,若有更好的方案欢迎交流共同进步. 一.RGB灯带驱动IC简介 市面上存在多种RGB驱动IC,比如:WS2812,YX1903B ...

  5. FPGA驱动RGB灯带WS2812B

    记录一下短学期做的东西 -- FPGA驱动RGB灯带WS2812B 设计目标 1.有多种模式,按键调节模式等参数: 2.模式1:红绿蓝白四色循环显示,速度.亮度可调: 3.模式2:7彩虹+白色,闪烁, ...

  6. STM32F427库函数PWM+DMA控制ws2812b灯带

    STM32F427IIHx库函数PWM+DMA控制ws2812b灯带 一.参考资料 查看ws2812b用户手册可知: 二.代码部分 添加文件ws2812b.c,ws2812b.h 配置的F427IIH ...

  7. 小熊派 FreeRTOS+SPI+DMA 驱动 TFT-LCD

    文章目录 小熊派 FreeRTOS+SPI+DMA 驱动 TFT-LCD 一.文章前言 二.SPI+DMA 配置 三.FreeRTOS 配置 四.代码编写 五.实验现象 小熊派 FreeRTOS+SP ...

  8. 【STM32】基于STM32CubeIDE SPI+DMA驱动WS2812

    [STM32]基于STM32CubeIDE SPI+DMA驱动WS2812 ✨申明:本文章仅发表在CSDN网站,任何其他网见此内容均为盗链和爬取,请多多尊重和支持原创!

  9. [HAL]STM32 SPI+DMA驱动WS2812

    该程序是纯手敲,非Cube生成!所有代码均注释. 源码在文章后面获取 WS2818 简介 Keyword: 单线通讯.归零码.Reset.RGB顺序 RGB一共有24bit位 ->相当于驱动一个 ...

  10. STM32 SPI+DMA 驱动 SRAM LY68L6400SLIT 应用笔记

    关键词:库函数,STM32F407,SPI+DMA ,SPI-DMA,SRAM , LY68L6400SLIT,STM32CubeMX 编 辑:大黄蜂 说明:本笔记记录 基于 STM32F407 + ...

最新文章

  1. Exchange日常管理之二十二:配置保留策略
  2. jQuery的jquery-1.10.2.min.map触发404(未找到)
  3. 成都python培训比较好的机构-成都Python培训班哪个好,怎样才能不走弯路学习
  4. TLSNotary中心化预言机(2) 核心功能
  5. c 语言epc编码如何解开,EPC编码结构
  6. 读tomcat源码,随笔类图
  7. .NET 6 使用 Obfuscar 进行代码混淆
  8. Software Construction Series(1)
  9. python-kafka多线程快速读取consumer消费者数据,同时使用批读取与无限流读取改进
  10. 5G( 9)---开发者:你如何迎接5G时代的到来?
  11. Linux进程管理:进程和线程基础知识
  12. Jenkins学习总结(4)——持续集成,持续交付,持续部署之间的区别
  13. css基础知识汇总9
  14. inster into java_SELECT INTO 和 INSERT INTO SELECT 两种表复制语句
  15. 3dmax2022新功能特性-3ds max2022中文版安装包安装教程
  16. 视频播放设计测试用例
  17. 【区块链】以太坊Solidity编程:智能合约实现之基本语法
  18. 夜深了,最好喝点咖啡
  19. 利用开放的isbn查询Api接口录入图书信息,工作效率倍增
  20. Leetcode——至多包含K个不同字符的最长子串

热门文章

  1. 滚滚长江东逝水(三国演义插曲)铃声 滚滚长江东逝水(三国演义插...
  2. 第一次学游泳技巧_包你第一次下水就能学会游泳的方法
  3. Fireshot——很棒的的网页截图扩展
  4. 软件图形用户界面设计
  5. 如何分辨HDD/SSD硬盘接口?
  6. SOT23(Small Outline Transistor)
  7. 课程预约小程序开发需要哪些功能?
  8. 西瓜书读书笔记(一)-绪论
  9. 眼球图像处理-视网膜血管管径比与高血压
  10. Labview实现信号频域分析