【软件STM32cubeIDE下STM32F4xx使用DMA+定时器推PWM+灯带WS2812-进阶-综合汇总(讲解移植相关)】

(1)前言

做灯带ws2812其实有一段时间了,中间遇到很多问题,从开始的学习,到后来慢慢熟悉,再到后来尝试点很多灯带,做过非常多的实验了,自己新建工程,几乎尝试过很多条道路,并且每个选择都有尝试,这篇是一个汇总篇,将为给各位讲述移植时注意的函数,共享这些知识为其绕过一些坑。

写在前面,其实自己之前写过很多文章了,里面有很多“细节点”,对应新手而言,非常建议注意下这些点。

本次实验非常重要的两个表,你要是做相关实验,可能会反复看这两张表。
—DMA1请求映射表
在这里插入图片描述
—DMA2请求映射表
在这里插入图片描述

(2)环境

  • 软件环境:STM32cubeIDE 1.8.0
  • 硬件芯片:STM32F407ZGT6
  • HAL库版本:stm32cube_fw_f4_v1262
  • 灯带型号:WS2812

(3)综合汇总

(1)作为最基础的,这其实是我最早调试成功的,也是最先使用双缓存的,并且是最开始发现函数顺序的重要性的点,算是开始吧。
【关于STM32F4xx使用DMA+TIM3_PWM调试灯带WS2812过程记录】

(2)作为基础的,这篇讲述了使用TIM2点亮灯带,这里同时遇到最早的问题,32位寄存器与TIM3的16位寄存器
【软件STM32cubeIDE下STM32F4xx使用32位定时器2(TIM2)用DMA+PWM点亮灯带WS2812-基础样例

(3)如果你已经会了基本的点灯带,那么当你想让你的灯带颜色更漂亮些,那么可以推荐看下列文章。
【关于STM32F4xx使用DMA+PWM调试灯带WS2812过程记录+进阶】

(4)后来我做个其它尝试,希望可以复用同一数据流,其实这种方式不是很推荐,请教大佬后,才实现,但需要在回调函数不断初始化。
【关于STM32F4 使用DMA数据流-冲突下-复用输出PWM操作问题的记录以及解决办法】

(5)再后来,因为需求变更,自己也想知道一些边界的存在,所有尝试所有数据流点灯的。
【软件STM32cubeIDE下STM32F4xx使用DMA+定时器+推PWM+点亮灯带WS2812相关-进阶(全数据流版)】

(4)移植相关讲解

写在前面,我们看一些基础案例,最终希望能运用在我们自己的项目上的,而不是说以基础样例为基础,这就会涉及,弄明白了样例后,将相应代码添加到自己的工程里,同时不与现有自己项目工程冲突,而且移植时,一定是你自己基础样例能跑起来了,不要没跑起来,就移植,这样你都不知道基础样例问题还是移植中产生问题。

本次实验我将选取我以前一个样例,同时也会上传其代码,以此代码为样例,来说明要移植哪些代码。

(1)第一步:MX_GPIO_Init()与 MX_DMA_Init();

这两函数里面内容其实挺少的的,但是稍微不注意,灯带就可能跑不起来。
1)MX_GPIO_Init()内容如下,主要是RCC的使能。
在这里插入图片描述

2)MX_DMA_Init()内容如下,主要是数据流优先级以及中断使能。
在这里插入图片描述

(2)第二步:定时器组初始化函数,例如void MX_TIM2_Init(void);

(1)无论STM32cubeIDE软件还是STM32cubeMX软件,通过配置,软件都会为你自动生成好这些函数,只要你设置没错,但是移植时要注意有时候,我们不只是使用一组定时器,这里也用通道分配,只要你确定选择使用一下通道了,就不要随意更改,移植时,主要将里面内容复制。

  1. 注意函数顺序
  2. 移植目标要是有系统时,注意是否自动初始化,这样会打乱原本函数顺序
  3. 注意里面内容

如下图所示:
在这里插入图片描述

(3)第三步:在stm32f4xx_hal_msp.c文件下,一些函数以及结构体声明;

(1)主要是这几个函数,圈出来这几个,为啥不说是三个呢,因为我见过有些编译器生成出来的,不叫这个名字的,类似名字,但带base这样。
在这里插入图片描述
(2)加入结构体声明
在这里插入图片描述

(4)第四步:在stm32f4xx_it.c文件下,数据流函数加入中断函数以及结构体声明;

(1)有时候可能其他,比如串口,SPI占用了这个数据流,是不能共存的,我们要去掉相应使能,并且更换我们需要的。
在这里插入图片描述

(2)结构体声明
在这里插入图片描述

(5)第五步:灯带驱动编写以及移植。

(1)这块弄过很多次了,主要是功能是往数组里赛灯带数据的功能和一些声明


uint32_t tim2_ccr1_value[]={10,20,30,40,50,60,70,80,90};
uint16_t tim3_ccr1_value[]={10,20,30,40,50,60,70,80,90};
#define ONE_PULSE        (59)                           //1
#define ZERO_PULSE       (29)                           //0
#define RESET_PULSE      (48)                           //80 ¸
#define LED_NUMS         (22)                            //led ¸
#define LED_DATA_LEN     (24)                           //led
#define WS2812_DATA_LEN  (LED_NUMS*LED_DATA_LEN)        //ws2812

uint16_t  RGB_buffur[RESET_PULSE + WS2812_DATA_LEN] = { 0 };
uint32_t  RGB_buffur1[RESET_PULSE + WS2812_DATA_LEN] = { 0 };


void ws2812_set_RGB(uint8_t R, uint8_t G, uint8_t B, uint16_t num)
{

    uint16_t * p = (RGB_buffur + RESET_PULSE) + (num * LED_DATA_LEN);

    for (uint16_t i = 0;i < 8;i++)
    {

        p[i]      = (G << i) & (0x80)?ONE_PULSE:ZERO_PULSE;
        p[i + 8]  = (R << i) & (0x80)?ONE_PULSE:ZERO_PULSE;
        p[i + 16] = (B << i) & (0x80)?ONE_PULSE:ZERO_PULSE;
    }

}

void ws2812_set_RGB1(uint8_t R, uint8_t G, uint8_t B, uint16_t num)
{

    uint32_t * p = (RGB_buffur1 + RESET_PULSE) + (num * LED_DATA_LEN);

    for (uint16_t i = 0;i < 8;i++)
    {

        p[i]      = (G << i) & (0x80)?ONE_PULSE:ZERO_PULSE;
        p[i + 8]  = (R << i) & (0x80)?ONE_PULSE:ZERO_PULSE;
        p[i + 16] = (B << i) & (0x80)?ONE_PULSE:ZERO_PULSE;
    }

}



void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
{
	//if(htim)
 __HAL_TIM_SetCompare(htim, TIM_CHANNEL_1,0); //占空比清0,若不清会导致灯珠颜色不�???
    HAL_TIM_PWM_Stop_DMA(htim,TIM_CHANNEL_1);
    __HAL_TIM_SetCompare(htim, TIM_CHANNEL_2,0); //占空比清0,若不清会导致灯珠颜色不�???
       HAL_TIM_PWM_Stop_DMA(htim,TIM_CHANNEL_2);
       __HAL_TIM_SetCompare(htim, TIM_CHANNEL_3,0); //占空比清0,若不清会导致灯珠颜色不�???
          HAL_TIM_PWM_Stop_DMA(htim,TIM_CHANNEL_3);
          __HAL_TIM_SetCompare(htim, TIM_CHANNEL_4,0); //占空比清0,若不清会导致灯珠颜色不�???
             HAL_TIM_PWM_Stop_DMA(htim,TIM_CHANNEL_4);
}

(6)第六步:生成想要的灯带颜色。

(1)这部分,因为之前说过,如何生成好看的彩灯,这一步其实是可以单独列出一个部分
我这部分是找到网上资料,然后自己工程调优过的,细节也说了如下文章。

如果你已经会了基本的点灯带,那么当你想让你的灯带颜色更漂亮些,那么可以推荐看下列文章。
【关于STM32F4xx使用DMA+PWM调试灯带WS2812过程记录+进阶】

(7)第七步:函数输出。

(1)这块也比较明确,就一个函数,直接DMA推送,优点是不耗费CPU资源。
在这里插入图片描述

(6)实验代码

实验代码连接:https://download.csdn.net/download/qq_22146161/87383562

(7)细节点

细节点还是零零散散将一些的,这里有可能有之前说过的。

(1)移植目标为带有系统时,要注意函数初始化顺序。

个人案例真实写照,当时移植是RT-thread,虽然系统为我们带来方便,但是有时候调试是真摸不到头脑。
这块因为系统原因,定时器先初始化了,结果就是跑不起来,样例一上就行,一移植就废。

(2)一些容易误导名字,无法使用数据流-边界问题

这属于边界问题,当时为了探究F4边界,想把所有数据流都点灯带,结果16个通道,只是点了14个,想TIM_TRIG和TIM1_UP这种,是不能用的。另外TIM1_CH1N也尝试过,不能用
在这里插入图片描述

(9)总结

更多的测试,有些我可能无法传递,也许是我忘了,也许是文字表达有限,我这些文章是你的辅助,一定要动手自己尝试下,同时也非常欢迎讨论。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
STM32F4可以通过TIM PWM DMA来控制WS2812灯带。 在使用STM32F4来控制WS2812灯带之前,我们需要了解一些基本的原理。WS2812灯带是一种基于Neopixel技术的RGB LED灯带,它具有灯珠之间串行通信的特点。通过发送一系列的0和1的数据信号,可以控制每个灯珠的颜色与亮度。 首先,我们需要配置STM32F4的GPIO引脚作为TIM输出模式,选择PWM模式,并配置DMA进行数据传输。接着,我们需要设置TIM的周期和预分频系数,以控制PWM信号的频率和占空比。根据WS2812的通信协议,每个数据位以50%占空比的PWM信号来表示,其中逻辑0和逻辑1的时间分别为400ns和800ns。 然后,我们通过DMA传输具有正确占空比的PWM数据到GPIO引脚,以控制WS2812灯带。我们可以使用定时器计数器的更新事件作为触发源,通过TIM的DMA请求信号来触发DMA传输。 我们可以通过编写相应的代码来配置STM32F4定时器DMA。首先,我们需要定义一个数据缓冲区,将要传输的PWM数据写入缓冲区中。然后,我们配置DMA的传输长度、传输方向和传输模式。接着,我们配置定时器PWM模式、周期和预分频系数。最后,我们启动定时器DMA,并等待传输完成。 以上就是利用STM32F4的TIM PWM DMA来控制WS2812灯带的简要介绍。通过正确配置定时器DMA,我们可以实现高效、准确地控制WS2812灯带的颜色和亮度,从而实现丰富多彩的灯光效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

好奇龙猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值