• STM32G0 定时器PWM DMA输出驱动WS2812配置 LL库


    通过DMA方式输出PWM模拟LED数据信号

    优点:不消耗CPU资源
    缺点:占用内存较大

    STM32CUBEMX配置

    定时器配置

    定时器通道:TIM3 CH2
    分频:0
    重装值:79,芯片主频64Mhz,因此PWM输出频率:64Mhz/79 ≈ 800Khz,满足芯片要求。
    auto-reload preload 要关闭
    output compare preload 要打开
    在这里插入图片描述

    DMA配置

    外设一定要选择TIM3_UP,不要选TIM_CHx
    方向是内存到外设,和ADC是反的
    模式选择Circular,也可以选择Normal,每次要写的时候才发送,这里为了方便选Circular。
    重要:数据宽度,外设选择half word,内存选择byte,可以省空间
    在这里插入图片描述

    添加初始化代码

    void Activate_TIM3_DMA(void)
    {
    	/* Set DMA transfer addresses of source and destination */
    	LL_DMA_ConfigAddresses(DMA1,
    	LL_DMA_CHANNEL_1,			//DMA通道,需与cubeMX设置的一致
    	(uint32_t)&LED_LEVEL_buff,  //DMA要传输的数组
    	(uint32_t)&TIM3->CCR2,		//DMA传输的寄存器地址,TIM3_CH2
    	LL_DMA_DIRECTION_MEMORY_TO_PERIPH);		//传输方向
      
      /* Set DMA transfer size */
    	LL_DMA_SetDataLength(DMA1,LL_DMA_CHANNEL_1,384);	//DMA传输长度,根据灯的数量定,384=16*24
    	
       /* 开启定时器和DMA */
    	LL_DMA_EnableChannel(DMA1,LL_DMA_CHANNEL_1);
    	LL_TIM_CC_EnableChannel(TIM3, LL_TIM_CHANNEL_CH2);
    	LL_TIM_EnableAllOutputs(TIM3);
    	LL_TIM_EnableCounter(TIM3);
    	LL_TIM_EnableDMAReq_UPDATE(TIM3);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    添加LED电平代码

    #define TL    20 		//写0电平占空比= 20/(79+1) 79为定时器重装值
    #define TH    55 		//写1电平时间
    
    /*LED数据传输电平数组*/ /*多余的4个数组是RESET信号,需大于80us*/
    vu8 LED_LEVEL_buff[16][24] = {
    TL, TL, TL, TL, TL, TL, TL, TL,   TL, TL, TL, TL, TL, TL, TL, TL,   TL, TL, TL, TL, TL, TL, TL, TL,/*led0*/
    TL, TL, TL, TL, TL, TL, TL, TL,   TL, TL, TL, TL, TL, TL, TL, TL,   TL, TL, TL, TL, TL, TL, TL, TL,/*led1*/
    TL, TL, TL, TL, TL, TL, TL, TL,   TL, TL, TL, TL, TL, TL, TL, TL,   TL, TL, TL, TL, TL, TL, TL, TL,/*led2*/
    TL, TL, TL, TL, TL, TL, TL, TL,   TL, TL, TL, TL, TL, TL, TL, TL,   TL, TL, TL, TL, TL, TL, TL, TL,/*led3*/
    TL, TL, TL, TL, TL, TL, TL, TL,   TL, TL, TL, TL, TL, TL, TL, TL,   TL, TL, TL, TL, TL, TL, TL, TL,/*led4*/
    TL, TL, TL, TL, TL, TL, TL, TL,   TL, TL, TL, TL, TL, TL, TL, TL,   TL, TL, TL, TL, TL, TL, TL, TL,/*led5*/
    TL, TL, TL, TL, TL, TL, TL, TL,   TL, TL, TL, TL, TL, TL, TL, TL,   TL, TL, TL, TL, TL, TL, TL, TL,/*led6*/
    TL, TL, TL, TL, TL, TL, TL, TL,   TL, TL, TL, TL, TL, TL, TL, TL,   TL, TL, TL, TL, TL, TL, TL, TL,/*led7*/
    TL, TL, TL, TL, TL, TL, TL, TL,   TL, TL, TL, TL, TL, TL, TL, TL,   TL, TL, TL, TL, TL, TL, TL, TL,/*led8*/
    TL, TL, TL, TL, TL, TL, TL, TL,   TL, TL, TL, TL, TL, TL, TL, TL,   TL, TL, TL, TL, TL, TL, TL, TL,/*led9*/
    TL, TL, TL, TL, TL, TL, TL, TL,   TL, TL, TL, TL, TL, TL, TL, TL,   TL, TL, TL, TL, TL, TL, TL, TL,/*led10*/
    TL, TL, TL, TL, TL, TL, TL, TL,   TL, TL, TL, TL, TL, TL, TL, TL,   TL, TL, TL, TL, TL, TL, TL, TL,/*led11*/
    0};
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    这里一共12个灯,每个灯需24bit,定义16组数据是因为WS2812发送完所有数据后需要80us的低电平信号,剩下4组数据为80us的低电平信号。
    已知每个信号宽度为1.25us,算下来为800Khz,这个非常重要,因此TIM重装值必须为79。
    计算0码的长度,也就是占空比,占空比= 20/(79+1),时间大概为0.31us,满足需求
    计算1码的长度,也就是占空比,占空比= 55/(79+1),时间大概为0.86us,满足需求
    在这里插入图片描述
    在这里插入图片描述
    当要更改灯光颜色的时候,修改LED_LEVEL_buff就行了,效率很高,缺点是需要占用较大的内存空间,由于CPU主频很低,重装值不会超过79,因此数组用8位就够了,32位纯属浪费空间,所以DMA内存长度一定要和数组匹配,否则会出现波形混乱。

  • 相关阅读:
    hutool工具使用JWT.verify进行token验证,解析token,JWTUtil.parseToken
    day03-拉取在线用户&无异常退出功能
    IPsec协议
    Java集合中常见的面试题
    python 日志处理(基础篇)
    K8s: 在Pod中将configmap数据注入容器
    CCF- CSP 202009-2风险人群筛查 满分题解
    【App自动化测试】(十七)遍历测试工具——Android Maxim
    计算机毕业论文内容参考|基于深度学习的交通标识智能识别系统的设计与维护
    TypeScript 学习笔记(四):装饰器与高级编程技巧
  • 原文地址:https://blog.csdn.net/otto1230/article/details/132581314