WS2812B彩灯 STM32HAL库开发:PWM+DMA(stm32f103c8t6)

news2024/12/26 23:16:07

目录

一、摘要

二、WS2812B介绍

三、CUBEMX配置

四、程序介绍(KEIL编译器)

五、数据手册


一、摘要

        1、本文使用示例单片机型号为stm32f103c8t6,RGB型号为WS2812B

        2、主要实现功能是实现用PWM+DMA使RGB_LED亮起不同颜色的灯光;

        3、目的:简单调通该型号RGB_LED,方便后续改编使用,希望各位读者可以依次做出更炫酷的效果。为了便于更好理解数据手册和单片机配置的关联,第二部分也放入了CUBEMX的部分配置图片

        4、优点:DMA转运,硬件自动数据搬运(由内存到外设),减少CPU资源占用,第一次使用DMA可以先大致看一下DMA相关知识,这会让你很容易理解下面的一些配置

二、WS2812B介绍

       ( 为了便于更好理解数据手册和单片机配置的关联,第二部分也放入了CUBEMX的部分)

 依据方向标识与单片机接好线路

注:VDD接5V

        DIN接单片机PWM输出引脚(本文中接PA8引脚,即TIM1_PWM输出通道1)

        DOUT接下一个LED的DIN引脚

此处重装值就是定时器一个周期从0计到89计90个数(后面介绍为什么是89)                                                          

通过控制PWM占空比发送0码和1码,额定周期为1.25us,则频率为800Khz

0码PWM占空比:

(0码高电平时间)/(周期)--->  0.4 / 1.25 = 0.32 

  用占空比乘以定时器重装值加一就是0码的CCR值(代表PWM高电平计数个数)--->

  0.32 * (89+1) = 28.8(取28,实测不可以高于28,但23到28都可以)

1码PWM占空比:

同理计算:(1码高电平时间)/ (周期)---> 0.8 / 1.25 = 0.64

(占空比)*(重置值+1)= CCR ---> 0.64 * 1.25 = 57.6(取58)

每一个LED的R、G、B分别由八位数据控制颜色浓度,(每种颜色浓度有0~255档,理论上RGB就可以组成256的3次方中颜色组合)即每个LED需要24BIT数据,那么需要发送数据的总长度则为(要控制LED数量 n)*(24),每个LED保存24BIT将剩余位传给后面LED。全部数据发送完成后要继续发送大于24us的低电平作为RESET_CODE等才可以点亮。

三、CUBEMX配置

 

时钟树配置

  

定时器配置

PWM频率:

Fpwm =Tclk / ((arr+1)*(psc+1))(单位:Hz)

上面提到数据传送频率为800Khz,Tclk为72Mhz,我们这里设置psc = 0,arr= 89,得到频率刚好为800Khz。

占空比:

duty circle = TIM3->CCR1 / arr(单位:%)

TIM3->CCR1  用户设定值(即上述0码和1码占空比计算所得CCR)

PWM-DMA配置

 1:DMA配置

 2:添加一个DMA

 3:选择定时器1的通道一外设

四、程序介绍(KEIL编译器)

RGB.H

#ifndef __RGB_H__
#define __RGB_H__

#include "main.h"

/*这里是上文计算所得CCR的宏定义*/
#define CODE_1       (58)       //1码定时器计数次数
#define CODE_0       (25)       //0码定时器计数次数

/*建立一个定义单个LED三原色值大小的结构体*/
typedef struct
{
	uint8_t R;
	uint8_t G;
	uint8_t B;
}RGB_Color_TypeDef;

#define Pixel_NUM 1  //LED数量宏定义,这里我使用一个LED,(单词pixel为像素的意思)

void RGB_SetColor(uint8_t LedId,RGB_Color_TypeDef Color);//给一个LED装载24个颜色数据码(0码和1码)
void Reset_Load(void); //该函数用于将数组最后24个数据变为0,代表RESET_code
void RGB_SendArray(void);          //发送最终数组
void RGB_RED(uint16_t Pixel_Len);  //显示红灯
void RGB_GREEN(uint16_t Pixel_Len);//显示绿灯
void RGB_BLUE(uint16_t Pixel_Len); //显示蓝灯
void RGB_WHITE(uint16_t Pixel_Len);//显示白灯


#endif

 RGB.C

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

/*Some Static Colors------------------------------*/
const RGB_Color_TypeDef RED      = {255,0,0};   //显示红色RGB数据
const RGB_Color_TypeDef GREEN    = {0,255,0};
const RGB_Color_TypeDef BLUE     = {0,0,255};
const RGB_Color_TypeDef SKY      = {0,255,255};
const RGB_Color_TypeDef MAGENTA  = {255,0,220};
const RGB_Color_TypeDef YELLOW   = {127,216,0};
const RGB_Color_TypeDef OEANGE   = {127,106,0};
const RGB_Color_TypeDef BLACK    = {0,0,0};
const RGB_Color_TypeDef WHITE    = {255,255,255};

/*二维数组存放最终PWM输出数组,每一行24个
数据代表一个LED,最后一行24个0代表RESET码*/
uint32_t Pixel_Buf[Pixel_NUM+1][24];       

/*
功能:设定单个RGB LED的颜色,把结构体中RGB的24BIT转换为0码和1码
参数:LedId为LED序号,Color:定义的颜色结构体
*/
void RGB_SetColor(uint8_t LedId,RGB_Color_TypeDef Color)
{
	uint8_t i; 
	if(LedId > Pixel_NUM)return; //avoid overflow 防止写入ID大于LED总数
	
	for(i=0;i<8;i++) Pixel_Buf[LedId][i]   = ( (Color.G & (1 << (7 -i)))? (CODE_1):CODE_0 );//数组某一行0~7转化存放G
	for(i=8;i<16;i++) Pixel_Buf[LedId][i]  = ( (Color.R & (1 << (15-i)))? (CODE_1):CODE_0 );//数组某一行8~15转化存放R
	for(i=16;i<24;i++) Pixel_Buf[LedId][i] = ( (Color.B & (1 << (23-i)))? (CODE_1):CODE_0 );//数组某一行16~23转化存放B
}

/*
功能:最后一行装在24个0,输出24个周期占空比为0的PWM波,作为最后reset延时,这里总时长为24*1.2=30us > 24us(要求大于24us)
*/
void Reset_Load(void)
{
	uint8_t i;
	for(i=0;i<24;i++)
	{
		Pixel_Buf[Pixel_NUM][i] = 0;
	}
}

/*
功能:发送数组
参数:(&htim1)定时器1,(TIM_CHANNEL_1)通道1,((uint32_t *)Pixel_Buf)待发送数组,
			(Pixel_NUM+1)*24)发送个数,数组行列相乘
*/
void RGB_SendArray(void)
{
	HAL_TIM_PWM_Start_DMA(&htim1, TIM_CHANNEL_1, (uint32_t *)Pixel_Buf,(Pixel_NUM+1)*24);
}

/*
功能:显示红色
参数:Pixel_Len为显示LED个数
*/
void RGB_RED(uint16_t Pixel_Len)
{
	uint16_t i;
	for(i=0;i<Pixel_Len;i++)//给对应个数LED写入红色
	{
		RGB_SetColor(i,RED);
	}
	Reset_Load();
	RGB_SendArray();
}

/*
功能:显示绿色
参数:Pixel_Len为显示LED个数
*/
void RGB_GREEN(uint16_t Pixel_Len)
{
	uint16_t i;
	for(i=0;i<Pixel_Len;i++)//给对应个数LED写入绿色
	{
		RGB_SetColor(i,GREEN);
	}
	Reset_Load();
	RGB_SendArray();
}

/*
功能:显示蓝色
参数:Pixel_Len为显示LED个数
*/
void RGB_BLUE(uint16_t Pixel_Len)
{
	uint16_t i;
	for(i=0;i<Pixel_Len;i++)//给对应个数LED写入蓝色
	{
		RGB_SetColor(i,BLUE);
	}
	Reset_Load();
	RGB_SendArray();
}

/*
功能:显示白色
参数:Pixel_Len为显示LED个数
*/
void RGB_WHITE(uint16_t Pixel_Len)
{
	uint16_t i;
	for(i=0;i<Pixel_Len;i++)//给对应个数LED写入白色
	{
		RGB_SetColor(i,WHITE);
	}
	Reset_Load();
	RGB_SendArray();
}

//也可以继续添加其他颜色,和颜色变化函数等

 main.c

( 在此处调用RGB头文件)

( 在while(1)里写入想要的颜色变化,这里现象为红绿蓝白四种颜色1秒变化一次)

五、数据手册

百度云盘 WS2812B

阿里云盘 WS2812B

ok,简单讲到这里,希望你可以以次添加更多功能复杂的函数,做出更炫酷更有趣的LED颜色变幻,如果有什么地方感觉说的不清晰可以留言评论


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1202998.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

暖手宝上架亚马逊美国站UL499报告测试标准要求

暖手宝是运用物理及化学原理研制的自动取暖保健用品。该产品以其自动生热&#xff0c;有趣&#xff0c;实用等新颖独特的优势&#xff0c;深受欢迎——暖手宝具有自动取暖&#xff0c;理疗保健等多种功能。只要插上电源等上10分钟左右就能发热&#xff0c;最后一种是通过锂电池…

thinkphp6 只有默认页能访问 其他404 其他模块404

1.只有默认页能访问 其他页404 同时隐藏index.php 在 public/.htaccess 中添加如下配置&#xff0c;后重启服务 <IfModule mod_rewrite.c>Options FollowSymlinks -MultiviewsRewriteEngine OnRewriteCond %{REQUEST_FILENAME} !-dRewriteCond %{REQUEST_FILENAME} !-f…

活跃类指标

活跃类指标反映了用户的真实使用情况。本节我们深入探讨活跃类指标的核心逻辑。 1&#xff0e; UV UV ( Unique Visitor &#xff0c;独立访客&#xff09;&#xff0c;是所有活跃类指标的基础。 既然叫独立访客&#xff0c;何谓之独立&#xff1f; APP 产品界定独立访客相对…

算法的复杂性

通常情况下&#xff0c;一个问题可能对应有多种解决方案&#xff0c;每种解决方案都是一种算法。因此&#xff0c;我们可能经常需要做一件事&#xff1a;从众多算法中挑选出一个最好的算法。所谓“最好”的算法&#xff0c;即最适合当前场景使用的算法。 不同的应用场景&#x…

IT 基础架构管理需要了解的信息

各行各业的现代组织不断面临创新和扩展的压力。就在十多年前&#xff0c;一个组织可以争取时间&#xff0c;在投资新技术时保持保守&#xff0c;同时仍然保持竞争优势&#xff0c;快进到今天&#xff0c;随着商业实践的变化和新技术的不断涌现&#xff0c;商业和技术领域变得更…

瑞利长度(Rayleigh length)

瑞利长度 Rayleigh length 在光学&#xff0c;特别是激光学中&#xff0c;我们设鞍腰部&#xff08;如图中所示的最低处&#xff09;为A&#xff0c;其横截面面积为a&#xff0c;沿光的传播方向&#xff0c;当横截面面积因为散射达到2a时&#xff0c;我们设此处为B&#xff0c;…

Mysql-表的结构操作

1.创建表 CREATE TABLE table_name ( field1 datatype, field2 datatype, field3 datatype ) character set 字符集 collate 校验规则 engine 存储引擎 ; 说明&#xff1a; field 表示列名 datatype 表示列的类型 character set 字符集&#xff0c;如果没有指定字…

从0到0.01入门React | 003.精选 React 面试题

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云课上架的前后端实战课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入…

天津火爆python培训机构从哪里入手?

Python不仅被应用在职场办公中&#xff0c;还被大型互联网公司应用于大型后端开发&#xff0c;随着大数据领域的高速发展&#xff0c;这门高效的编程语言逐渐成为处理数据的最佳编程语言之一。 Python培训班优势 系统性学习&#xff1a;Python培训班会提供结构化的课程体系&a…

SAP系统供应商预付款请求和预付账款业务

最近搞清帐&#xff01; 在SAP中处理客户或供应商的预收/预付款相关业务流程操作说明, 首先由业务部门(销售或采购)下达销售/采购订单,同时基于订单提交预收/预付申请,客户/供应商款项到账时,由财务部门在SAP中勾选申请单来收付款;最后在财务转应收/应付转发票时自动核销。预付…

Notepad++,搜索窗口独立后,恢复

双击一下find result框&#xff0c;恢复到原来的模式。

腾讯待办停运后怎么办呢?导出的ics文件怎么打开查看

待办类工具在日常工作中的应用是比较广泛的&#xff0c;很多人会选择使用待办软件记录备忘事项&#xff0c;其中一些提醒类的工具是比较广泛使用的。腾讯待办属于一款待办事项和日程管理工具&#xff0c;它通常是以微信小程序的形式&#xff0c;为大家提供时间管理规划&#xf…

做一个Springboot文章分类模块

目录 文章分类 1、新增文章分类 前言 代码编写 测试 2、 文章分类列表 前言 代码编写 测试 3、获取文章列表详情 前言 代码实现 测试 4、更新文章分类 前言 代码实现 测试 5、删除文章分类 前言 代码实现 测试 分页查询 文章列表条件分页 前言 代码编…

晶圆代工产能利用率下降,降价大战一触即发 | 百能云芯

晶圆代工行业正面临产能利用率的重大挑战&#xff0c;据悉&#xff0c;联电、世界先进和力积电等主要代工厂纷纷降低明年首季的报价&#xff0c;幅度高达两位数百分比&#xff0c;项目客户降幅更高达15%至20%&#xff0c;各大晶圆代工厂深陷产能利用率六成保卫战。 晶圆代工降价…

Outlook关闭过去事件的提醒

Outlook关闭过去事件的提醒 故障现象 最近Outlook中推出的新功能让我们可以选择自动关闭过去事件的提醒。 目前这个功能暂时只向当月通道的Office 365 订阅者发布。 这些用户升级到1810版本后&#xff0c;可以在不想收到已发生事件提醒的时候通过下面的步骤自动忽略过去事件…

将按键放到输入框内:

如何将将Button放到输入框内&#xff1f; 效果图&#xff1a; 步骤如下&#xff1a; button 外围用template 包裹一层 <template #suffix v-if"row.WorkerRole TPM"> <el-inputtype"text"v-model"row.JobNumber"placeholder"…

期中成绩这样发

数字化时代&#xff0c;成绩查询系统已经成为学校里不可或缺的一部分。老师们需要一种方便、快捷、准确的方式来发布和查询成绩&#xff0c;而学生们则需要一种安全、可靠的方式来获取自己的成绩。那么&#xff0c;如何实现这一目标呢&#xff1f;我来给大家介绍几种简单实用的…

【STM32】定时器+基本定时器

一、定时器的基本概述 1.软件定时器原理 原来我们使用51单片机的时候&#xff0c;是通过一个__nop()__来进行延时 我们通过软件的方式来进行延时功能是不准确的&#xff0c;受到很多不确定因素。 2.定时器原理&#xff1a;计数之间的比值 因为使用软件延时受到影响&#xff0c…

RK3568驱动指南|第七期-设备树-第66章of操作函数实验:获取设备树节点

瑞芯微RK3568芯片是一款定位中高端的通用型SOC&#xff0c;采用22nm制程工艺&#xff0c;搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码&#xff0c;支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU&#xff0c;可用于轻量级人工…

正点原子嵌入式linux驱动开发——Linux ADC驱动

在之前的笔记中&#xff0c;学习了如何给ICM20608编写IIO驱动&#xff0c;ICM20608本质就是ADC&#xff0c;因此纯粹的ADC驱动也是IIO驱动框架的。本章就学习一下如何使用STM32MP1内部的ADC&#xff0c;并且在学习巩固一下IIO驱动。 ADC简介 ADC ADC&#xff0c;Analog to D…