WS2812b彩灯(DMA+PWM)

一.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;
}

 幻影的程序

        定时器驱动

#include "timer.h"
#include "led.h"

//通用定时器中断初始化
//这里时钟选择为APB1的2倍,而APB1为36M
//arr:自动重装值。
//psc:时钟预分频数
//这里使用的是定时器3!
void TIM3_Int_Init(u16 arr,u16 psc)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能

	TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值	 计数到5000为500ms
	TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值  10Khz的计数频率  
	TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
 
	TIM_ITConfig(  //使能或者失能指定的TIM中断
		TIM3, //TIM2
		TIM_IT_Update ,
		ENABLE  //使能
		);
	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级0级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //从优先级3级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
	NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器

	TIM_Cmd(TIM3, ENABLE);  //使能TIMx外设
							 
}


        DMA驱动程序

#include "dma.h"

u16 SendBuff[24*16+220]={
	
	10,10,10,10,10,10,10,10,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,		//1
    10,10,10,10,10,10,10,10,3,3,10,3,10,3,10,10,3,3,3,3,3,3,3,3,	//2
    10,10,10,10,10,10,10,10,3,10,3,10,10,10,3,3,3,3,3,3,3,3,3,3,	//3
    10,10,10,10,10,10,10,10,10,3,3,3,3,10,10,3,3,3,3,3,3,3,3,3,		//4
    10,10,10,10,10,10,10,10,10,3,10,10,3,10,10,3,3,3,3,3,3,3,3,3,	//5 
    10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,3,3,3,3,3,3,3,3,//6
    10,10,10,10,10,3,3,10,10,10,10,10,10,10,10,10,3,3,3,3,3,3,3,3,	//7
    10,10,3,3,10,3,3,10,10,10,10,10,10,10,10,10,3,3,3,3,3,3,3,3,	//8	
    10,3,3,10,10,10,10,3,10,10,10,10,10,10,10,10,3,3,3,3,3,3,3,3,	//9
    3,10,10,3,10,10,10,3,10,10,10,10,10,10,10,10,3,3,3,3,3,3,3,3,	//10    
    3,10,3,3,3,10,3,3,10,10,10,10,10,10,10,10,3,3,3,3,3,3,3,3,		//11
    3,3,3,10,3,3,10,10,10,10,10,10,10,10,10,10,3,3,3,3,3,3,3,3,		//12
    3,3,3,3,3,3,3,3,10,10,10,10,10,10,10,10,3,3,3,3,3,3,3,3,		//13
    10,10,10,10,10,10,10,10,3,3,3,10,3,3,10,10,3,3,3,3,3,3,3,3,		//14
    10,10,10,10,10,10,10,10,3,10,3,3,3,10,3,3,3,3,3,3,3,3,3,3,		//15    
    10,10,10,10,10,10,10,10,3,10,10,3,10,10,10,3,3,3,3,3,3,3,3,3,	//16
//    3,3,3,3,3,3,3,3,10,10,10,10,10,10,10,10,3,3,3,3,3,3,3,3,
//    3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,10,10,10,10,10,10,10,10,
//    10,10,10,10,10,10,10,10,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
//    3,3,3,3,3,3,3,3,10,10,10,10,10,10,10,10,3,3,3,3,3,3,3,3,
//    3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,10,10,10,10,10,10,10,10,
//    10,10,10,10,10,10,10,10,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
//    3,3,3,3,3,3,3,3,10,10,10,10,10,10,10,10,3,3,3,3,3,3,3,3,
//    3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,10,10,10,10,10,10,10,10,
//    10,10,10,10,10,10,10,10,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
    
    
    
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};
u16 DMA1_MEM_LEN = 24*16+220;// 保存DMA每次数据传送的长度 

void DMA_Config(void)
{
    DMA_InitTypeDef DMA_InitStructure;
    
    // 使能DMA时钟
 	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);	// 使能DMA传输
	
    // 初始化通道参数
    DMA_DeInit(DMA1_Channel2); // 将DMA的通道2寄存器重设为缺省值
	DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&TIM1->CCR1); // DMA外设TIM1的CCR1基地址
	DMA_InitStructure.DMA_MemoryBaseAddr = (u32)SendBuff;  // DMA内存基地址
	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;  // 数据传输方向,从内存读取发送到外设
	DMA_InitStructure.DMA_BufferSize = DMA1_MEM_LEN;  //DMA通道的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; //数据宽度为16位
	DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;  // 循环发送
	DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //DMA通道 x拥有中优先级 
	DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  //DMA通道x没有设置为内存到内存传输
	DMA_Init(DMA1_Channel2, &DMA_InitStructure);  //根据DMA_InitStruct中指定的参数初始化DMA的通道寄存器
    
    // 使能TIME的DMA
    TIM_DMACmd(TIM1,TIM_DMA_CC1,ENABLE);

    // 开始DMA
    DMA_SetCurrDataCounter(DMA1_Channel2,DMA1_MEM_LEN);//DMA通道的DMA缓存的大小
    DMA_Cmd(DMA1_Channel2, ENABLE);  //使能USART1 TX DMA1 所指示的通道 
} 
 


//让LED全灭
void WS2812B_ClearBuf(void)
{
	uint16_t i;
	for(i=0;i<384;i++)  
	{
		SendBuff[i]=3;
	}
}
#ifndef __DMA_H
#define __DMA_H	 
#include "sys.h"

void DMA_Config(void);

void WS2812B_ClearBuf(void);



#endif

PWM驱动程序

#include "pwm.h"
#include "led.h"
//	 
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK Mini STM32开发板
//PWM  驱动代码			   
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//修改日期:2010/12/03
//版本:V1.0
//版权所有,盗版必究。
//Copyright(C) 正点原子 2009-2019
//All rights reserved
// 	  


//PWM输出初始化
//arr:自动重装值
//psc:时钟预分频数
void delay_ms(u16 nms);
void TIM1_PWM_Init(u16 arr,u16 psc)
{  
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_OCInitTypeDef  TIM_OCInitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);// 定时器1
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE);  //使能GPIO外设时钟使能         

    //设置该引脚为复用输出功能,输出TIM1 CH1的PWM脉冲波形
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //TIM_CH1
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);  

	TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值	 80K
	TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值  不分频
	TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
	TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位

 
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式1
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
	TIM_OCInitStructure.TIM_Pulse = 0; //设置待装入捕获比较寄存器的脉冲值
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
	TIM_OC1Init(TIM1, &TIM_OCInitStructure);  //根据TIM_OCInitStruct中指定的参数初始化外设TIMx

    TIM_CtrlPWMOutputs(TIM1,ENABLE);	//MOE 主输出使能	

	TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);  //CH1预装载使能	 
	
	TIM_ARRPreloadConfig(TIM1, ENABLE); //使能TIMx在ARR上的预装载寄存器
	
	TIM_Cmd(TIM1, ENABLE);  //使能TIM1
 
   
}
#ifndef __PWM_H
#define __PWM_H
#include "sys.h"

void TIM1_PWM_Init(u16 arr,u16 psc);

#endif

 要初始化io口不初始化会出现错误

#include "led.h"

//初始化PB5和PE5为输出口.并使能这两个口的时钟		    
//LED IO初始化
void LED_Init(void)
{
 
	GPIO_InitTypeDef  GPIO_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	 // 使能PA端口时钟

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;				 // LED0-->PA.8 端口配置
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 // 推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 // IO口速度为50MHz
	GPIO_Init(GPIOA, &GPIO_InitStructure);					 // 根据设定参数初始化GPIOA.8
	GPIO_SetBits(GPIOA,GPIO_Pin_8);						 	 // PA.8 输出高
}
 
#ifndef __LED_H
#define __LED_H	 
#include "sys.h"

#define LED0 PAout(8)	// PA8
#define LED1 PDout(2)	// PD2	

void LED_Init(void);//初始化

		 				    
#endif

 主程序

#include "led.h"
#include "delay.h"
#include "sys.h"
#include "timer.h"
#include "pwm.h"
#include "dma.h"

extern u16 SendBuff[20]; // 
extern u16 DMA1_MEM_LEN; // 保存DMA每次数据传送的长度 

void TIM3_IRQHandler(void)   //TIM3中断
{
	if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源 
    {
        TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  //清除TIMx的中断待处理位:TIM 中断源 
        
        // 用户逻辑
    }
}

 int main(void)
 {	
    // 延时函数初始化
	delay_init();	   
 	 
    // IO初始化
    LED_Init();
     
    // DMA控制PWM输出
    TIM1_PWM_Init(13-1,7-1); // 72/7=10.285MHz  1.26us
    DMA_Config();
     
    // 定时器任务
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组2
    TIM3_Int_Init(10-1,72-1); // 72分频,10us
     
    
   	while(1)
    {
//        TIM1->CCR1 = 3; // 0
//        TIM1->CCR1 = 10; // 1      
    }
}
 

 五.江协科技程序文件

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

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

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

  • 24
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值