【STM32F4系列】【HAL库】【自制库】WS2812(软件部分)(PWM+DMA)

这篇具有很好参考价值的文章主要介绍了【STM32F4系列】【HAL库】【自制库】WS2812(软件部分)(PWM+DMA)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

相关链接

硬件介绍(PCB设计方案)

模拟时序发送

协议

WS2812是一种异步串行通信,它每一位数据时间是ns级别的

ws2812数据手册,模块介绍,基础知识,STM32_HAL库,stm32,单片机,arm

ws2812数据手册,模块介绍,基础知识,STM32_HAL库,stm32,单片机,arm

默认是高电平状态

0码:220-380ns高电平+580-1600ns低电平

1码:580-1600ns高电平+220-380ns低电平

复位码:>280us低电平

ws2812数据手册,模块介绍,基础知识,STM32_HAL库,stm32,单片机,arm

ws2812数据手册,模块介绍,基础知识,STM32_HAL库,stm32,单片机,arm

24Bit数据来代表GRB的亮度值

从高位到低位发送,分别按照G->R->B的顺序发送

先发送第一个灯的数据(离Dat输入直连的那个灯)

例子:
分别发送红绿蓝三色的数据给3个ws2812

ws2812数据手册,模块介绍,基础知识,STM32_HAL库,stm32,单片机,arm

外设设置

硬件PWM

分析

STM32F4系列的系统频率为84MHz

定时器的最高频率(不改动时钟设置的情况下)为84MHz,也就是11ns左右,

完全可足以驱动WS2812(几百ns级的)

设系统频率为 f 单位是MHz

则0码.1码的高电平占空比 n0 n1(0码高电平取370ns左右,1码高电平取850ns左右)

重载值 n 分别为

n 0 = 0.37 f , n 1 = 0.85 f , n = 1.25 f n_{0}=0.37f,n_{1}=0.85f,n=1.25f n0=0.37f,n1=0.85f,n=1.25f

四舍五入一下,取n=105,n0=32,n1=71

HAL设置

ws2812数据手册,模块介绍,基础知识,STM32_HAL库,stm32,单片机,arm

PWM输出,不分频,重载值设为105

其他不需要改动

ws2812数据手册,模块介绍,基础知识,STM32_HAL库,stm32,单片机,arm

PWM的输出GPIO设置为开漏浮空输出(外接5V上拉)

DMA

分析

DMA是外设直接访问内存的一个手段,可以快速的传递数据

我们在这个例子里用到的是

将内存里的关于占空比的数据发送给定时器的比较值

让其发送具有编码含义的脉冲

PWM+DMA的一些问题:

使用HAL库DMA给定时器发送比较值时,会一次性发送多个(数组地址和长度)

定时器每当发送一个脉冲后,更改为下一个比较值,直到数组被发送完成,触发一次DMA中断

这样我们就可以利用这个特点发送WS2812的数据

HAL设置

ws2812数据手册,模块介绍,基础知识,STM32_HAL库,stm32,单片机,arm

设置PWM的输出通道为响应通道

从内存到外设模式(Direction的设置)

普通模式(Mode)

数据宽度(Data Width)为字(32bit)

方案设计

设置两个缓冲区,每个长度为25个uint32(其中前24个是发送的数据码,第25个是保持占空比为0)

缓冲区的第25个数据为0是确保DMA中断响应时是低电平(码字的低电平时间稍长,3-4us无所谓,但是不能出现而外的高电平)

发送复位码时则使用单独划分好的,在Flash里的静态数组

在DMA中断响应时,计算下次发送的数据给到缓冲区
这样只需要3个变量数组(2个缓冲区,1个存放灯带颜色数据),1个常量数组(复位码)

操作流程:

  1. 更改颜色信息给颜色数组
  2. 发送复位码,开启PWM+DMA
  3. 解码第一位颜色数据给到缓冲区0
  4. (DMA中断)发送缓冲区0给定时器
  5. (DMA中断)计算第二位颜色数据给缓冲区1
  6. (下一个)(DMA中断)发送缓冲区1给定时器
  7. (DMA中断)计算第三位颜色数据给缓冲区0

以此类推,直到发送完成

ws2812数据手册,模块介绍,基础知识,STM32_HAL库,stm32,单片机,arm

代码实现

解码函数

/**
 * @brief 将uint32转为发送的数据
 * @param Data:颜色数据
 * @param Ret:解码后的数据(PWM占空比)
 * @return
 * @author HZ12138
 * @date 2022-10-03 18:03:17
 */
void WS2812_uint32ToData(uint32_t Data, uint32_t *Ret)
{
    uint32_t zj = Data;
    uint8_t *p = (uint8_t *)&zj;
    uint8_t R = 0, G = 0, B = 0;
    B = *(p);     // B
    G = *(p + 1); // G
    R = *(p + 2); // R
    zj = (G << 16) | (R << 8) | B;
    for (int i = 0; i < 24; i++)
    {
        if (zj & (1 << 23))
            Ret[i] = WS2812_Code_1;
        else
            Ret[i] = WS2812_Code_0;
        zj <<= 1;
    }
    Ret[24] = 0;
}

用一个指针p,将数据中的RGB数据解码出来

然后使用一个循环,将数据存入缓冲区中

开始发送和复位

const uint32_t WS2812_Rst[240] = {0}; //复位码缓冲区
/**
 * @brief 开始发送颜色数据
 * @param 无
 * @return 无
 * @author HZ12138
 * @date 2022-10-03 18:05:13
 */
void WS2812_Start(void)
{
    HAL_TIM_PWM_Start_DMA(&WS2812_TIM, WS2812_TIM_Channel, (uint32_t *)WS2812_Rst, 240);
    WS2812_uint32ToData(WS2812_Data[0], WS2812_SendBuf0);
    WS2812_En = 1;
}
/**
 * @brief 发送复位码
 * @param 无
 * @return 无
 * @author HZ12138
 * @date 2022-10-03 18:05:33
 */
void WS2812_Code_Reast(void)
{
    HAL_TIM_PWM_Start_DMA(&WS2812_TIM, WS2812_TIM_Channel, (uint32_t *)WS2812_Rst, 240);
    WS2812_En = 0;
}

复位码缓冲区是常量数组,开始发送和单独复位码的区别WS2812_En的标志

WS2812_En为1时才执行交替发送缓冲区0和1

发送函数

/**
 * @brief 发送函数(DMA中断调用)
 * @param 无
 * @return 无
 * @author HZ12138
 * @date 2022-10-03 18:04:50
 */
void WS2812_Send(void)
{
    static uint32_t j = 0;
    static uint32_t ins = 0;
    if (WS2812_En == 1)
    {
        if (j == WS2812_Num)
        {
            j = 0;
            HAL_TIM_PWM_Stop_DMA(&WS2812_TIM, WS2812_TIM_Channel);
            WS2812_En = 0;
            return;
        }
        j++;
        if (ins == 0)
        {
            HAL_TIM_PWM_Start_DMA(&WS2812_TIM, WS2812_TIM_Channel, WS2812_SendBuf0, 25);
            WS2812_uint32ToData(WS2812_Data[j], WS2812_SendBuf1);
            ins = 1;
        }
        else
        {
            HAL_TIM_PWM_Start_DMA(&WS2812_TIM, WS2812_TIM_Channel, WS2812_SendBuf1, 25);
            WS2812_uint32ToData(WS2812_Data[j], WS2812_SendBuf0);
            ins = 0;
        }
    }
}

这个函数是在DMA中断中调用

思路如同前面所说

波形

ws2812数据手册,模块介绍,基础知识,STM32_HAL库,stm32,单片机,arm

整个波形全貌↑

ws2812数据手册,模块介绍,基础知识,STM32_HAL库,stm32,单片机,arm

两次发送的间隔(DMA中断中导致的)↑

ws2812数据手册,模块介绍,基础知识,STM32_HAL库,stm32,单片机,arm

1码↑

ws2812数据手册,模块介绍,基础知识,STM32_HAL库,stm32,单片机,arm

0码↑

成品

GitHub

百度网盘文章来源地址https://www.toymoban.com/news/detail-612332.html

到了这里,关于【STM32F4系列】【HAL库】【自制库】WS2812(软件部分)(PWM+DMA)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STM32系列(HAL库)——F103C8T6驱动WS2812全彩RGB模块(PWM+DMA方式)

    (1)编程平台:Keil5 (2)CubeMX (1)某宝买的RGB模块(4个灯珠级联) (2)F1的板子,本例使用经典F103C8T6 (3)ST-link 下载器 (4)杜邦线若干 (1)模块简介: 没什么比手册讲得更加清楚了,模块中文数据手册:ws2812b中文资料_数据手册_参数 (2)驱动原理:          以上这是数据手册中提到

    2023年04月11日
    浏览(16)
  • 【STM32F4系列】【HAL库】【模块介绍】MPU6050设置与DMP库使用

    MPU6050是一个3轴陀螺仪(测角加速度)和3轴加速度计(测量线加速度)的测量芯片 内部自带运算单元(DMP),可以输出经姿态融合计算后的 四元数 (一种表示旋转的方法) 而且MPU6050的价格较低(10r以下),常被用于精度不高的场合作为姿态感知的芯片 如经典项目平衡车,某年电赛题目风力摆

    2024年02月05日
    浏览(18)
  • [HAL]STM32 SPI+DMA驱动WS2812

    该程序是纯手敲,非Cube生成!所有代码均注释。 源码在文章后面获取 Keyword: 单线通讯、归零码、Reset、RGB顺序 RGB一共有24bit位 -相当于驱动一个灯要24bit位 -驱动若干个灯要24* n bit位,通过Reset码决定数据终止(保持) 24bit位应该如何发送? 可见: 表示低电平需要 T0H和T0L的配

    2024年02月09日
    浏览(17)
  • 心跳跟随的心形灯(STM32(HAL)+WS2812+MAX30102)

    在好几年前,我好像就看到了焊武帝 jiripraus在纪念结婚五周年时,制作的一个心跳跟随心形灯,感觉太浪漫了,于是在假期的时候,我也仿照做了一个,虽然还有很多需要完善的地方,但是大致功能已经实现了,下面开源讲讲开源的项目。 心脏的外壳采用紫铜丝或黄铜丝焊

    2024年02月14日
    浏览(18)
  • 使用STM32F103的SPI+DMA驱动ws2812 LED

    目录 前言 一、WS2812协议 1.1 数据传输编码方式:  1.2 传输的数据结构 二、驱动方式:SPI+DMA 2.1 原理介绍 2.2 SPI+DMA操作  2.3 编写代码 2.4 使用 三 总结 参考文章 主要使用的STM32F103C8T6芯片的SPI+DMA方式实现WS2812的驱动协议,总体可以看作是使用SPI来实现一种通信协议来发送信号。

    2024年02月09日
    浏览(31)
  • 【stm32开发笔记】基于HAL库的STM32F4添加DSP库

    本文分两种方法添加DSP库:1.CubeMX直接配置ioc添加; 2.KEIL内添加; 简述:补齐全部lib库-添加DSP包-使能DSP勾选-添加头文件及魔术棒配置-测试 1.补齐lib库。( 如果使用直接默认添加的库,是不支持FPU的,所以需要补齐后找到所需的lib文件进行替换,在MX的工程管理栏,选择复制所

    2024年02月16日
    浏览(19)
  • MPU6050(读取原数据、移植DMP、stm32f4、HAL库、KEIL5)

    记录一下自己遇到的问题及解决方法,希望能帮助到一些人。 第一步,读取芯片的原始数据。需要注意两点:1、对HAL库提供的IIC读取写入函数进行再包装。(千万不要觉的这步多此一举,后面移植DMP时用得到) 2、芯片的地址(这里面有俩坑)第一就是,芯片的 I2C 设备地址

    2023年04月08日
    浏览(13)
  • STM32F4系列单片机库函数模板工程创建

    目录 一、工程配置 1、新建工程 2、芯片选择 3、工程子文件夹创建 (1)FWLIB文件夹添加文件 (2)CORE文件夹添加文件 (3)USER文件夹添加文件 4、工程设置 (1)工程中添加文件夹 (2)工程文件夹中添加配置文件 ①FWLIB文件夹添加文件 ②CORE文件夹添加文件 ③USER文件夹添加

    2024年01月25日
    浏览(19)
  • 单片机:STM32F4x HAL库软硬SPI驱动ST7735s 1.8寸LCD屏幕

    说明:此篇为学习记录。可能存在错误或者不足。如有问题请指出。 主控芯片:STM32F411CEU6 主控开发板:WeAct STM32F411CEU6最小系统板 TFT-LCD屏幕:合宙1.8寸TFT-LCD,驱动为ST7735s MDK版本:5,32 HAL库版本:1.27.1 STM32CubeMX版本:6.7.0 ST7735s支持8080并口,3线和4线串行接口,模块的驱动方

    2024年02月03日
    浏览(22)
  • 关于STM32F4系列中printf重定向问题详解

    前言 关于 printf函数 和 fputc函数 联系和区别 联系: 1.共同目标: printf 函数和 fputc 函数都用于将字符 输出到指定的输出流中 。 2.字符输出: 两个函数都可以用于输出一个字符,但在实际使用时, printf 函数 通常用于输出 格式化的数据 ,而 fputc 函数 更常用于 单个字符的直

    2024年02月03日
    浏览(19)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包