文章目录

  • 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. 【Spring】基于xml实现事务控制(银行转账)
  2. java 多线程共享数据_Java多线程学习:多个线程间共享数据
  3. 第十六课、Qt对象间的父子关系------------------狄泰软件学院
  4. Rethink Technology预测看好VVC
  5. 关于低代码自定义表单的思路和想法
  6. 韦冬雪计算机应用,捕获效应下RFID防碰撞算法的研究与应用
  7. 2020年共享汽车发展趋势研究报告
  8. 【Python】小练习
  9. 聊聊数据权限哪些事儿
  10. Python实现微信朋友签名云图项目
  11. 织梦5.7 10万新闻文章 生成测试
  12. matlab 8fsk,MFSK蒙特卡洛仿真与理论误码率的对比
  13. CSDN新手机号绑定不成功,提示已存在账号,CSDN换绑手机号的相关问题
  14. hexo+next 给博客添加网易云音乐外链接
  15. 区块链+保险的概述和发展现状
  16. Centos7 kvm环境制作qcow2 格式镜像
  17. DNS 缓存查看以及清除(转载)
  18. 微信小程序实现身份证识别功能
  19. 计算机课屏幕以锁定,电脑无限宝锁定课堂怎么办
  20. 通过CTFShow例题掌握爆破方法

热门文章

  1. 3种CSS3实现的网页过度效果代码,可独立用于网页设计展示
  2. “由于这台计算机没有远程桌面客户端访问许可证,远程会话被中断“的解决方案
  3. 苹果怎样用小米云服务器,小米云服务ios版
  4. 青岛大学计算机专业春考,青岛大学春季高考分数线2020
  5. 权游谁将领盒饭?AI告诉你
  6. 机智云(esp8266)与74hc595控制16路继电器
  7. Browser-Solidity的本地安装及使用介绍
  8. 此情可待的伤感爱情日志分享:失去你的那一刻,我的世界不再光明
  9. CI/CD---使用新版云效流水线自动部署Java项目
  10. python解析FreeMind思维导图