首页 > 其他分享 >WS2812b彩灯(DMA+PWM)

WS2812b彩灯(DMA+PWM)

时间:2024-07-06 14:31:25浏览次数:18  
标签:TIM2 DMA TIM DMA1 InitStructure WS2812b PWM WS2812B

一.WS2812B简介

        WS2812B是一种数字可编程的LED灯条,可以使用单个数据线进行通讯控制LED灯的颜色和亮度。每个WS2812B都有一个唯一的地址,可以通过单个数据线进行级联。

二.WS2812B参数简介 

三. WS2812B数据通讯简介

 1.级联电路

2.数据传输

        该芯片是通过数据传输的时间来判断数据是0码还是1码的。

 此时就会有PWM的频率计算:

3.级联的数据传输

第一个数据缓存

        ·第一个24位有第一个模块接收并缓存

        ·第二个24位会被第一个模块转发到第二个模块上并缓存

        ·第三个24位会被第一个和第二个转发到第三个模块上并缓存

        ·第四个24位......

        ·第N个24位......

复位信号

第二个数据缓存

        ·第一个24位有第一个模块接收并缓存

        ·第二个24位会被第一个模块转发到第二个模块上并缓存

        ·第三个24位会被第一个和第二个转发到第三个模块上并缓存

        ·第四个24位......

        ·第N个24位......

复位信号

............

四.WS2812B驱动程序简介 

        这里我们使用PWM+DMA的方式驱动WS2812B。这里我们用的江协科技的程序。

DMA驱动程序:

#include "stm32f10x.h"


void (*DMA1_Handler)(void);  //也要开中断   数据转运+DMA  没用ADC

void DMA1_Init(uint32_t MemoryBaseAddr)//MemoryBaseAddr是WS2812B_Bit数组地址
{
 	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
	
	DMA_DeInit(DMA1_Channel2);
	
	DMA_InitTypeDef DMA_InitStructure;
	DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&TIM2->CCR1);//起始地址
	DMA_InitStructure.DMA_MemoryBaseAddr = MemoryBaseAddr;//存放地址
	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;//传输方向:双向   存储点到外设
	DMA_InitStructure.DMA_BufferSize = 0;//缓存区大小,传输计数器大于0,触发源有触发信号,DMA使能
	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设是否自增
	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//存储器是否自增
	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//是否自增 以半字的形式传输16位
	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
	DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;//不使用自动重装
	DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
	DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//硬件触发
	DMA_Init(DMA1_Channel2, &DMA_InitStructure);
	
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
	
	DMA_ITConfig(DMA1_Channel2, DMA_IT_TC, ENABLE);//DMA中断
	
	DMA_Cmd(DMA1_Channel2, ENABLE);
}

void DMA1_SetIRQHandler(void (*IRQHandler)(void))
{
	DMA1_Handler=IRQHandler;
}

void DMA1_Start(uint16_t DataNumber)  //调运函数,连续转运
{
	DMA_Cmd(DMA1_Channel2,DISABLE);
	DMA_SetCurrDataCounter(DMA1_Channel2,DataNumber);
	DMA_Cmd(DMA1_Channel2,ENABLE);
}

void DMA1_Channel2_IRQHandler(void) //DMA开中断12
{
	if(DMA_GetFlagStatus(DMA1_FLAG_TC2))
	{
		DMA1_Handler();
		DMA_ClearFlag(DMA1_FLAG_TC2);
	}
}

这里我们通过定时器中断驱动pwm 

PWN TIM2驱动:

#include "stm32f10x.h" //哪个函数不认识看芯片手册

void TIM2_Init(void) //TIM2开PWM的发送到DMA  PA0输出
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE); //开启定时器2时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//开启复用引脚时钟

	GPIO_InitTypeDef GPIO_InitStructure;  //GPIO
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出   定时器控制引脚
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);

	TIM_DeInit(TIM2);    //初始化时基单元
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
	TIM_TimeBaseStructure.TIM_Period = 90-1; //ARR周期            32视频里定时中断讲过,搞懂   90公式试出来的,然后一算
	TIM_TimeBaseStructure.TIM_Prescaler = 0; //PSC预分频器
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
	
	TIM_OCInitTypeDef TIM_OCInitStructure; //初始化输出比较单元
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
	TIM_OCInitStructure.TIM_Pulse = 0; //CCR捕获比较器  运行中设置
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
	TIM_OC1Init(TIM2, &TIM_OCInitStructure);
	
	TIM_CtrlPWMOutputs(TIM2, ENABLE);
	
	TIM_DMAConfig(TIM2,TIM_DMABase_CCR1,TIM_DMABurstLength_1Transfer); //DMA请求传输
	TIM_DMACmd(TIM2,TIM_DMA_Update,ENABLE); //寄存器位传输对象
	
	TIM_Cmd(TIM2, DISABLE);
}

void TIM2_Cmd(FunctionalState NewState)
{
	TIM_Cmd(TIM2, NewState);
}

void TIM2_SetCompare1(uint16_t Value) //主输出使能,TM2为高级定时器,所以这里加上
{
	TIM_SetCompare1(TIM2,Value);
}

WS2812B驱动:

#include "stm32f10x.h"
#include "TIM2.h"
#include "DMA1.h"

//#define WS2812B_LED_QUANTITY	32  //灯珠数量
#define WS2812B_LED_QUANTITY 30 //灯珠数量

//定义数组 类型符 数组名[常量]
uint32_t WS2812B_Buf[WS2812B_LED_QUANTITY];	//0xGGRRBB    正常的数据口输入,然后配置就行,绿红蓝总共24位,只有32               
uint16_t WS2812B_Bit[24*WS2812B_LED_QUANTITY+1];//灯珠数量*24bit+1 颜色位数+复位信号 根据数据手册可知还要加复位信号0(正常的0),因此需要写入 num24+reset(reset=?自己调) 位。
uint8_t WS2812B_Flag;

void WS2812B_IRQHandler(void);

void WS2812B_Init(void)
{
	DMA1_SetIRQHandler(WS2812B_IRQHandler);//把WS2812B_IRQHandler赋给DMA1_Handler
	DMA1_Init((uint32_t) (&WS2812B_Bit));//灯位量的地址存放到DMA  这时DMA就是灯珠的量 强制类型转换 不足的高位补0
	TIM2_Init();//定时器
} //用TIM2开PWM 送给DMA

void WS2812B_ClearBuf(void)//把LED的RGB数组值清零,全部输出0码,变成黑色,即不发光
{
	uint8_t i;
	for(i=0;i<WS2812B_LED_QUANTITY;i++)  
	{
		WS2812B_Buf[i]=0x000000;//24位的二进制数    6位的16进制数
	}
}

void WS2812B_SetBuf(uint32_t Color)  //设置显示相同的颜色
{
	uint8_t i;
	for(i=0;i<WS2812B_LED_QUANTITY;i++)  
	{
		WS2812B_Buf[i]=Color;//BUF是颜色,设置成同一个颜色,初始统一设置成不发光
	}
}

void WS2812B_UpdateBuf(void) //30和60对应不同的高电平时间也对应了时序的0码和1码 占空比控制亮灭   CCR和AAR+1共同决定的
{
	uint8_t i,j;
	for(j=0;j<WS2812B_LED_QUANTITY;j++)  //遍历每个LED
	{
		for(i=0;i<24;i++)    //遍历每个LED的颜色数据的每一位   	10000000 00000000  00000000
		{
			if(WS2812B_Buf[j]&(0x800000>>i)){WS2812B_Bit[j*24+i+1]=60;}//0x800000为二进制的1加23个0,>>:右移  
			else{WS2812B_Bit[j*24+i+1]=30;} //每一位,取值范围是0到23,所以再加1
		}
	}
	DMA1_Start(24*WS2812B_LED_QUANTITY+1);
	TIM2_Cmd(ENABLE);
	while(WS2812B_Flag==0);
	WS2812B_Flag=0;
}

void WS2812B_IRQHandler(void)    //定时器2 开PWM  直接就是根据时序占空比设置控制灯条
{
	TIM2_SetCompare1(0);//pwm设置
	TIM2_Cmd(DISABLE);//关闭定时器   
	WS2812B_Flag=1;
}

 五.江协科技程序文件

程序代码 链接:https://pan.baidu.com/s/12t9pRkyJYpP5MXVNhYFELg 提取码:5gkc 

原来视频 链接[WS2812B] 七彩流水灯/呼吸灯/三级调光照明 *附赠程序*_哔哩哔哩_bilibili

视频讲解 链接:2ws2812b外设配置_哔哩哔哩_bilibili

标签:TIM2,DMA,TIM,DMA1,InitStructure,WS2812b,PWM,WS2812B
From: https://blog.csdn.net/m0_59247951/article/details/140227843

相关文章

  • IP核:XDMA学习
    知识:XDMA效率没有RIFFA高,最高似乎只支持1288位宽;输出的用户时钟是250MHZ;IP核配置:参考:https://docs.amd.com/r/zh-CN/pg195-pcie-dma/具体: 重要:PCIe:BARs标签页该标签页主要用于配置BAR,所谓的使能和配置各接口interface,其实质是配置不同的BAR,首先介绍下什么是BAR......
  • 基于STM32F103C8T6的同步电机驱动-PWM驱动代码以及SVPWM的实现
    基于STM32F103C8T6的同步电机驱动-PWM驱动代码以及SVPWM的实现本系列文章:基于STM32F103C8T6的同步电机驱动-CubeMX配置与IQmath调用基于STM32F103C8T6的同步电机驱动-PWM驱动代码以及SVPWM的实现一、PWM驱动代码的编写在系列文章的第一篇中已经对主定时器TIM1进行了P......
  • STM32-PWM配置流程及作用
    STM32F407ZET6单片机配置PWM(脉冲宽度调制)PWM配置流程STM32F407ZET6单片机配置PWM的流程通常包括以下几个步骤:时钟使能:首先,需要使能定时器和相关IO口的时钟。这通常通过调用RCC(ResetandClockControl)相关的函数来实现,比如RCC_APB1PeriphClockCmd()用于使能APB1总线上的定时......
  • WPF Image scalertransform translatetransform mvvm,custom delegate command Comman
    //xaml<Windowx:Class="WpfApp187.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.mi......
  • 【PWM太阳能控制器调光方案】5V升24V 6A大电流无频闪PWM调光升压恒流LED驱动芯片FP720
    目前led灯带产品应用越来越广泛,在节能环保的社会快速发展驱动下,太阳能照明产品越来越多。但是现有技术中,有些空间狭小,又长又窄的环境空间不适用于现有的太阳能灯使用,现有技术中的太阳能灯照明效果不佳且不能够实现智能化照明;因此迫切地需要重新设计一款新的太阳能led灯带以......
  • stm32学习笔记---DMA直接存储器存取(代码部分)DMA数据转运/DMA+AD多通道
    目录第一个代码:DMA数据转运扩展知识DMA的配置步骤DMA的库函数DMA_DeInitDMA初始化和DMA结构体初始化函数DMA_CmdDMA_ITConfigDMA_SetCurrDataCounterDMA_GetCurrDataCounter四个获取标志位状态函数代码实现MyDMA.c第一步,开启时钟第二步,初始化DMA第三步,开关控制......
  • stm32学习笔记---DMA直接存储器存取(理论部分)
    目录DMA的简介存储器映像DMA框图DMA基本结构图DMA请求数据宽度与对齐实例数据转运+DMAADC扫描模式+DMA位段嵌入式闪存启动配置声明:本专栏是本人跟着B站江科大的视频的学习过程中记录下来的笔记,我之所以记录下来是为了方便自己日后复习。如果你也是跟着江科大的视......
  • 基于CDMA的多用户水下无线光通信(2)——系统模型和基于子空间的延时估计
      本文首先介绍了基于CDMA的多用户UOWC系统模型,并给出了多用户收发信号的数学模型。然后介绍基于子空间的延时估计算法,该算法只需要已知所有用户的扩频码,然后根据扩频波形的循环移位在观测空间的信号子空间上的投影进行延时估计。1、基于CDMA的多用户UOWC系统模型  首......
  • 带你彻底弄清CDMA码分多址的原理
    1.作用:主要用于无线多址接入,且具有很强抗干扰能力2.基本概念(1)码片:一个短间隔叫一个码片,1bit时间划分m个短间隔,则称1bit时间有m个码片(2)码片序列:1bit时间有m个码片,也就是每m个码片就有1bit的信息(每个站点都有自己的码片序列)(3)码片内容:码片中0写为-1,码片中1写为+13.站点发送......
  • DMA学习笔记(天空星stmf4开发板)
    目录    #DMA介绍#相关数据传输方法介绍#DMA相关数据手册框图介绍#DMA相关涉及概念介绍  #软件实现DMA传输数据    #DMA介绍#相关数据传输方法介绍    DirectMemoryAccess 即DMA ,芯片开发板,片上外设的一种,相关作用:进行传输数据不......