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

2023-11-17

1.软件准备

(1)编程平台:Keil5

(2)CubeMX

2.硬件准备

(1)某宝买的RGB模块(4个灯珠级联)

(2)F1的板子,本例使用经典F103C8T6

(3)ST-link 下载器

(4)杜邦线若干

3.模块资料

(1)模块简介:

没什么比手册讲得更加清楚了,模块中文数据手册:ws2812b中文资料_数据手册_参数

(2)驱动原理:

         以上这是数据手册中提到的,WS2812驱动用的是单线归零码的通讯方式。不同占空比的方波代表1码或者0码,这里不同的占空比就是  0码或1码高电平时间 / 方波周期时间 。对于本次例程,我们就是改变PWM的占空比实现0码或1码的传输。

(3)PWM+DMA原理:

        关于DMA的详细解析,我推荐这篇文章:DMA原理,步骤超细详解,一文看懂DMA

        PWM+DMA可以实现数量和占空比可控的脉冲,具体实现原理是在开启DMA的情况下,定时器在每次计数满后,会自动将DMA传输过来的数据作为新一轮的比较数值。如果DMA传输的数据每次不同,那么每次的方波占空比就不一样的。在本例程中,我们将数据存放在一个数组,通过DMA传输数组的内容,根据数组中数据的个数和每个数据的大小,就能实现数量和占空比可控的PWM。

4.CubeMX配置

(1)芯片选择

 (2)配置RCC、SYS、时钟树

配置RCC

配置SYS

配置时钟树

(3)配置定时器TIM1

         在定时器配置中,我们根据WS2812的最大传输速率800kbps,设置定时器不分频和计数周期为89+1,这样下来波形的频率为  72M /(89+1) = 800K  ,并且一个波形的周期为  1 / 800 = 1.25us

(4)开启DMA

 (5)设置路径、生成代码工程 

5、Keil5代码

(1)创建RGB.c和RGB.h文件

(2)添加上述的RGB.c文件进工程

——————上述两步参考之前系列教学步骤,在此不再赘述(点击跳转)

(3)RGB.c和RGB.h代码

 RGB.h

#ifndef __RGB_H
#define __RGB_H
#include "main.h"
#define Hight_Data            ( 64  )                           //1 码相对计数值
#define Low_Data              ( 36  )                           //0 码相对计数值
#define Reste_Data            ( 80  )                           //80 复位电平相对计数值
#define Led_Num               (  4  )                           //WS2812灯个数
#define Led_Data_Len          ( 24  )                           //WS2812数据长度,单个需要24个字节
#define WS2812_Data_Len   (Led_Num * Led_Data_Len)              //ws2812级联后需要的数组长度

//uint16_t RGB_buffur[Reste_Data + WS2812_Data_Len] = { 0 }; //数据缓存数组


void WS2812_Display_1(uint32_t Color, uint16_t num);
void WS2812_Display_2( uint8_t red, uint8_t green, uint8_t blue,uint16_t num);

void WS2812_Number_4(uint32_t Color1,uint32_t Color2,uint32_t Color3,uint32_t Color4);//封装好的四个灯函数,只需要分别输入四个灯的颜色即可


#endif


 RGB.c

#include "RGB.h"
#include "main.h"
#include "tim.h"

uint16_t RGB_buffur[Reste_Data + WS2812_Data_Len] = { 0 }; //数据缓存数组

void WS2812_Display_1(uint32_t Color, uint16_t num)
{
   
    //指针偏移:需要跳过复位信号的N个0
    uint16_t* p = (RGB_buffur + Reste_Data) + (num * Led_Data_Len);
    
    for (uint8_t i = 0; i < 8; ++i)         
	p[i+8]= (((Color << i) & 0X800000) ? Hight_Data :Low_Data);
    for (uint8_t i = 8; i < 16; ++i)
	p[i-8]= (((Color << i) & 0X800000) ? Hight_Data :Low_Data);
    for (uint8_t i = 16; i < 24; ++i)
	p[i]= (((Color << i) & 0X800000) ? Hight_Data :Low_Data);  
       
}


void WS2812_Display_2( uint8_t red, uint8_t green, uint8_t blue,uint16_t num)
{
            
            uint8_t i;
            uint32_t Color=(green << 16 | red << 8 | blue);//将2个8位数据合并转化为32位数据类型
    
            //指针偏移:需要跳过复位信号的N个0
            uint16_t* p = (RGB_buffur + Reste_Data) + (num * Led_Data_Len);
    
            for (i = 0; i < 24; ++i)    //对数组进行编辑
			p[i]= (((Color << i) & 0X800000) ? Hight_Data : Low_Data);	
                        
}


void WS2812_Number_4(uint32_t Color1,uint32_t Color2,uint32_t Color3,uint32_t Color4)
{
    
    uint16_t  RGB_Buff_4[Reste_Data + 4 * WS2812_Data_Len] = { 0 };
    uint16_t* p;
    uint32_t Color;
    
    for( uint8_t k=0;k<4;k++)
  {      
      switch (k)    //进行指针偏移
      {
        case 0: p= (RGB_Buff_4 + Reste_Data) + (0 * Led_Data_Len),Color=Color1;break;
        case 1: p= (RGB_Buff_4 + Reste_Data) + (1 * Led_Data_Len),Color=Color2;break;
        case 2: p= (RGB_Buff_4 + Reste_Data) + (2 * Led_Data_Len),Color=Color3;break;
        case 3: p= (RGB_Buff_4 + Reste_Data) + (3 * Led_Data_Len),Color=Color4;break;
        default : ;break;     
      }
      
     for (uint8_t i = 0; i < 8; ++i)   //对数组进行编辑
    {   
        for (uint8_t i = 0; i < 8; ++i)
        p[i+8]= (((Color << i) & 0X800000) ? Hight_Data :Low_Data);
        for (uint8_t i = 8; i < 16; ++i)
        p[i-8]= (((Color << i) & 0X800000) ? Hight_Data :Low_Data);
        for (uint8_t i = 16; i < 24; ++i)
        p[i]= (((Color << i) & 0X800000) ? Hight_Data :Low_Data);
    } 
   
 }   
  
    HAL_TIM_PWM_Start_DMA(&htim1,TIM_CHANNEL_1,(uint32_t *)RGB_Buff_4,(176));//启动DMA传输
    
}

 //  DMA 传输完成回调函数
void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
{
    HAL_TIM_PWM_Stop_DMA(&htim1,TIM_CHANNEL_1);
}



(4)main函数

#include "RGB.h"



int main(void)
{
 
  extern uint16_t RGB_buffur[Reste_Data + WS2812_Data_Len];
 
  HAL_Init();
 
  SystemClock_Config();

  MX_GPIO_Init();
  MX_DMA_Init();
  MX_TIM1_Init();
  /* USER CODE BEGIN 2 */

//        //点亮4个灯
//        WS2812_Display_1(0x180000, 0);
//        WS2812_Display_1(0x001800, 1);
//        WS2812_Display_1(0x000018, 2);
//        WS2812_Display_1(0x181818, 3);
//        HAL_TIM_PWM_Start_DMA(&htim1,TIM_CHANNEL_1,(uint32_t *)RGB_buffur,(176));//启动DMA传输        


//        //以下代码和上述效果一致,只是颜色数据表示形式不一样
//        WS2812_Display_2( 22 , 0 , 0, 0);
//        WS2812_Display_2(  0 , 22, 0, 1);
//        WS2812_Display_2(  0 , 0, 22, 2);
//        WS2812_Display_2( 22, 22 , 22, 3);
//        HAL_TIM_PWM_Start_DMA(&htim1,TIM_CHANNEL_1,(uint32_t *)RGB_buffur,(176));//启动DMA传输 

 
 
  while (1)
  {
      
      //流水效果
    WS2812_Number_4(0x180000,0x001800,0x000018,0);
    HAL_Delay(500);
    WS2812_Number_4(0,0x180000,0x001800,0x000018);
    HAL_Delay(500);
    WS2812_Number_4(0x000018,0,0x180000,0x001800);
    HAL_Delay(500);
    WS2812_Number_4(0x001800,0x000018,0,0x180000);
    HAL_Delay(500);
     
    
  }
 
}

        因时间问题,代码没有做过多注释。后续再补上。

6.接线图及效果

        关于接线:定时器1的通道1为PA8,将PA8和模块IN引脚连接,并注意供电充足即可。

  本例程源码下载:点击跳转 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STM32系列(HAL库)——F103C8T6驱动WS2812全彩RGB模块(PWM+DMA方式) 的相关文章

随机推荐

  • 会议OA项目----我的审批

    前言 上一篇博客我将我的会议的送审和会议排座这两个功能完成 送审之后就到了审批阶段 那么这次做的就是 我的审批 一 实现思路 根据产品原型图 见产品原型图 我的审批界面与我的会议界面大同小异 那么我们可以调用之前的写好的SQL语句 只不过将
  • 文件上传/下载接口(超简单的教程来了)

    前言 文件上传 下载接口与普通接口类似 但是有细微的区别 如果需要发送文件到服务器 例如 上传文档 图片 视频等 就需要发送二进制数据 上传文件一般使用的都是 Content Type multipart form data 数据类型 可以
  • java懒加载注解_一分钟学习Spring注解之懒加载@Lazy

    先声明 本篇文章非常简单属于一分钟学会使用系列 不深入讲解原理 如果要学习源码 可以看小编Spring源码解析系列 什么是懒加载 懒加载就是不使用不加载 使用的时候才去加载 Spring默认不是懒加载 而是启动加载 就在Spring上下文启
  • rac集群节点级联重启故障分析

    author skate time 2012 07 16 无意中发现以前处理故障写的一篇文章 记录下来以备查找 rac集群节点级联重启故障分析 环境 os linux db rac10g ocfs2 rac数据库环境实际包含两个集群 一个是
  • linux socket非阻塞之connect 函数

    1 connect原型 include
  • 联想E480安装MacOS苹果系统记录

    联想E480安装MacOS记录 联想E480安装黑苹果 自己有用IPad和Iphone 但Mac OS却没怎接触过 于是萌生了转用Mac OS的想法 用自用的联想E480装个黑果 为了方便软件上的互补 双系统优先 网上搜搜转转没发现有E48
  • 代码随想录算法训练营第三天 | 203.移除链表元素、707.设计链表、206.反转链表

    目录 知识点 链表 结点定义 单链表的初始化 判断一个链表是否为空 单链表的销毁 清空单链表 求链表表长 取单链表中第i个元素 按值查找 插入第i个结点 删除第i个结点 移除列表元素 没有采用虚拟头结点的方法 采用虚拟头结点的方法 设计链表
  • PHPExcel导出各种方法总结

    PHPExcel导出 方法一 https blog csdn net u014236259 article details 60601767 public function ExportExcelOrder data name vendor
  • ARM+Linux中断系统详细分析

    ULK第四章里明确讲到 Linux实现了一种没有优先级的中断模型 并且 Linux中断和异常都支持嵌套 这个我不太理解了 这两种说法都与我以前的理解刚好相反 核对了原书 翻译没有错 Linux中断系统到底是否支持优先级 可否嵌套 中断号又是
  • c# json解析(反序列化)、json规范化

    使用 NETFramework3 5 4 0中提供的System Web Script Serialization命名空间下的JavaScriptSerializer类进行对象的序列化与反序列化 很直接 要求当前的工程的TargetFram
  • Two Divisors【GCD数论】

    You are given nn integers a1 a2 ana1 a2 an For each aiai find its two divisors d1 gt 1d1 gt 1 and d2 gt 1d2 gt 1 such th
  • vue实现预览PDF、Excel、Docx、Txt、PPT文件的功能

    目录 一 实现步骤 二 实现效果 代码真实可用 一 实现步骤 1 使用的是vue和elementUI 假设有这些变量 attachment是附件的意思 data return previewDialog false attachmentSr
  • 交换机与路由器技术:静态NAT、动态NAT、PAT和端口镜像

    网络地址转换NAT 1 静态转换 2 动态转换 3 端口多路复用PAT 4 端口映射 服务器映射 目录 一 NAT基本概念 1 目的 2 出现背景 3 转换方式 二 静态NAT 三 动态NAT 三 PAT 总结 五 端口镜像 1 基本概念
  • 【unity】Shader.SetGlobalFloat/Vector/Texture 不生效

    Shader SetGlobalFloat Shader SetGlobalVector Shader SetGlobalTexture等等函数不生效是为什么 答 shader的properties要去掉对应的变量 也就是说shader获取
  • echarts的基本使用

    一 基本使用 1 导入echarts js 下载并导入 地址 https echarts apache org zh download html 使用 CDN 方法 https cdn staticfile org echarts 4 3
  • C++ private,public,protected的访问范围解析

    第一 private public protected的访问范围 private 只能由该类中的函数 其友元函数访问 不能被任何其他访问 该类的对象也不能访问 protected 可以被该类中的函数 子类的函数 以及其友元函数访问 但不能被
  • BuilderException: Error parsing SQL Mapper Configuration. Cause: java.lang.NullPointerException

    集成mybatis plus sqlSessionFactory改为MybatisSqlSessionFactoryBean后 项目无法启动
  • 团队新人多,稳定性经验不足,研发质量怎么保障?|TakinTalks论道

    一分钟精华速览 在研发和稳定性保障过程中 人与设备 程序 组织的交互是一个复杂的过程 虽然人们极少会恶意犯错 但由于受特定情景下的实际条件影响 人为失误也时有发生 那么 如何尽可能减少这些失误的发生 如何保障研发质量和系统稳定 TakinT
  • 读《大数据时代》有感

    大数据时代 读后感 大数据时代 这本书主要描述的是大数据时代到临人们生活 工作与思维各方面所遇到的重大变革 文中清晰的阐述了大数据的基本概念和特点 并列出明确的观点 不管对于产业实践者 还是对于政府和公众机构 都非常具有价值 作者将本书分为
  • STM32系列(HAL库)——F103C8T6驱动WS2812全彩RGB模块(PWM+DMA方式)

    1 软件准备 1 编程平台 Keil5 2 CubeMX 2 硬件准备 1 某宝买的RGB模块 4个灯珠级联 2 F1的板子 本例使用经典F103C8T6 3 ST link 下载器 4 杜邦线若干 3 模块资料 1 模块简介 没什么比手册