学习驱动ws2821灯珠(基于STM32HAl库)

1.原理学习

        1.1ws2821的手册内容

        

 

 

 

注:VDD接5V

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

        若不使用PWM驱动,则将DIN与PA9引脚连接,PA9设置如下

        

 

        DOUT接下一个LED的DIN引脚

 

        1.2.1通过NOP延时函数

        选择72MHZ,然后一个NOP=(1/72MhZ)=0.0138us

        T0L: 0.0138*50=0.69us    50代表nop的个数

        T0H: 0.0138*20=0.276us   20代表nop的个数

        

        T1L: 0.0138*20=0.276us   20代表nop的个数

        T1H: 0.0138*50=0.69us     50代表nop的个数

        1.2.2通过pwm+dma的方式

        

通过控制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)

1码PWM占空比:

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

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

2.Cube配置

配置时钟

 

 定时器配置

配置DMA 

 

 

 

3.驱动代码编写

ws2821.h

#ifndef __RGB_H__
#define __RGB_H__
 
#include "main.h"
 
/*这里是上文计算所得CCR的宏定义*/
#define CODE_1       (58)       //1码定时器计数次数
#define CODE_0       (28)       //0码定时器计数次数
 

 
#define Pixel_NUM 24 //LED数量宏定义
 

void Reset_Load(void); //该函数用于将数组最后24个数据变为0,代表RESET_code
void RGB_SendArray(void);          //发送最终数组
void RGB_RED_while(uint16_t Pixel_Len);
void RGB_Change(uint16_t Pixel_Len);
void RGB_Set(uint8_t LedId,uint32_t color_temp);
void RGB_test(uint16_t Pixel_Len);
void RGB_Bit1(void);
void RGB_Bit0(void);
void RGB_RESET(void);
#endif

ws2821.c

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

uint32_t Pixel_Buf[Pixel_NUM+1][24];       

/*
功能:设定单个RGB LED的颜色,把结构体中RGB的24BIT转换为0码和1码
参数:LedId为LED序号,Color:定义的颜色结构体
*/

void RGB_Bit0(void)
{
	HAL_GPIO_WritePin(GPIOA,GPIO_PIN_9,GPIO_PIN_SET);
	__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
	__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
	
	
		HAL_GPIO_WritePin(GPIOA,GPIO_PIN_9,GPIO_PIN_RESET);
	__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
	__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
	__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
	__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
	__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();


}

void RGB_Bit1(void)
{
	
	HAL_GPIO_WritePin(GPIOA,GPIO_PIN_9,GPIO_PIN_SET);
		__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
	__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
	__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
	__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
	__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
	
	HAL_GPIO_WritePin(GPIOA,GPIO_PIN_9,GPIO_PIN_RESET);
__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
	__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();


}

void RGB_RESET(void)
{
		HAL_GPIO_WritePin(GPIOA,GPIO_PIN_9,GPIO_PIN_RESET);
	for(int i=0;i<10;i++)
	{
		__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
		__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
		__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
		__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
	}
	
}



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);
}
 


void RGB_RED_while(uint16_t Pixel_Len)
{
	uint16_t i;
	for(i=0;i<Pixel_Len;i++)//给对应个数LED写入白色
	{
		RGB_SetColor(i,GREEN);
	//Reset_Load();
		
	
	
		RGB_SendArray();
	
	}
	
	
}


void RGB_Change(uint16_t Pixel_Len)
{
	int i;
		for(i=Pixel_Len;i>=0;i--)//给对应个数LED写入白色
	{
		//RGB_SetColor(i,RED);
		RGB_Set(i,0xff0000);
		Reset_Load();
		RGB_SendArray();
		HAL_Delay(100);
	}
}


void RGB_Set(uint8_t LedId,uint32_t color_temp)
{
		uint16_t i; 
	if(LedId > Pixel_NUM)return; //avoid overflow 防止写入ID大于LED总数
	
	for(i=0;i<8;i++)
	{
		//Pixel_Buf[LedId][i] = (((color_temp>>8)&(1<<i))?(CODE_1):(CODE_0));
		Pixel_Buf[LedId][i] = (((color_temp>>8)&(1<<i)));
		if((Pixel_Buf[LedId][i]&(1<<i))==0)
		{
				RGB_Bit0();
		}
		else
		{
				RGB_Bit1();
		}
	}
	for(i=8;i<16;i++)
	{
		//Pixel_Buf[LedId][i] = (((color_temp>>16)&(1<<(i-8)))?(CODE_1):(CODE_0));
		Pixel_Buf[LedId][i] = (((color_temp>>16)&(1<<(i-8))));
		if((Pixel_Buf[LedId][i]&(1<<(i-8)))==0)
		{
				RGB_Bit0();
		}
		else
		{
				RGB_Bit1();
		}
	}
	for(i=16;i<24;i++)
	{
		//Pixel_Buf[LedId][i] = (((color_temp)&(1<<(i-16)))?(CODE_1):(CODE_0));
		Pixel_Buf[LedId][i] = (((color_temp)&(1<<(i-16))));
		if((Pixel_Buf[LedId][i]&(1<<(i-16)))==0)
		{
				RGB_Bit0();
		}
		else
		{
				RGB_Bit1();
		}
	}
}

void RGB_test(uint16_t Pixel_Len)
{
	uint16_t i;
		for(i=0;i<24;i++)
		{
	
		RGB_Set(i,0x00ff00);
		//Reset_Load();	
		//RGB_SendArray();
		
		}
	
}
	

        3.1通过NOP延时函数

void RGB_Bit0(void)
{
	HAL_GPIO_WritePin(GPIOA,GPIO_PIN_9,GPIO_PIN_SET);
	__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
	__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
	
	
		HAL_GPIO_WritePin(GPIOA,GPIO_PIN_9,GPIO_PIN_RESET);
	__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
	__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
	__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
	__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
	__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();


}

void RGB_Bit1(void)
{
	
	HAL_GPIO_WritePin(GPIOA,GPIO_PIN_9,GPIO_PIN_SET);
		__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
	__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
	__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
	__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
	__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
	
	HAL_GPIO_WritePin(GPIOA,GPIO_PIN_9,GPIO_PIN_RESET);
__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
	__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();


}

   设置颜色

void RGB_Set(uint8_t LedId,uint32_t color_temp)
{
		uint16_t i; 
	if(LedId > Pixel_NUM)return; //avoid overflow 防止写入ID大于LED总数
	
	for(i=0;i<8;i++)
	{
		
		Pixel_Buf[LedId][i] = (((color_temp>>8)&(1<<i)));
		if((Pixel_Buf[LedId][i]&(1<<i))==0)
		{
				RGB_Bit0();
		}
		else
		{
				RGB_Bit1();
		}
	}
	for(i=8;i<16;i++)
	{
		
		Pixel_Buf[LedId][i] = (((color_temp>>16)&(1<<(i-8))));
		if((Pixel_Buf[LedId][i]&(1<<(i-8)))==0)
		{
				RGB_Bit0();
		}
		else
		{
				RGB_Bit1();
		}
	}
	for(i=16;i<24;i++)
	{
		
		Pixel_Buf[LedId][i] = (((color_temp)&(1<<(i-16))));
		if((Pixel_Buf[LedId][i]&(1<<(i-16)))==0)
		{
				RGB_Bit0();
		}
		else
		{
				RGB_Bit1();
		}
	}
}

测试函数

void RGB_test(uint16_t Pixel_Len)
{
	uint16_t i;
		for(i=0;i<24;i++)
		{
	
		RGB_Set(i,0x00ff00);
		//Reset_Load();	
		//RGB_SendArray();
		
		}
	
}

直接在main 调用

int main(void)
{
  /* USER CODE BEGIN 1 */
		
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_TIM1_Init();
  MX_RTC_Init();
  /* USER CODE BEGIN 2 */
	
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */		
		RGB_test(24);
		
		
  }
  /* USER CODE END 3 */
}

        3.2通过pwm+dma的方式

通过先前提到的,取0码高电平数28,取1码高电平数58,这种方法与上面的区别在于驱动和设置颜色

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

设置颜色

void RGB_Set(uint8_t LedId,uint32_t color_temp)
{
		uint16_t i; 
	if(LedId > Pixel_NUM)return; //avoid overflow 防止写入ID大于LED总数
	
	for(i=0;i<8;i++)
	{
		Pixel_Buf[LedId][i] = (((color_temp>>8)&(1<<i))?(CODE_1):(CODE_0));
		
	}
	for(i=8;i<16;i++)
	{
		Pixel_Buf[LedId][i] = (((color_temp>>16)&(1<<(i-8)))?(CODE_1):(CODE_0));
		
	}
	for(i=16;i<24;i++)
	{
		Pixel_Buf[LedId][i] = (((color_temp)&(1<<(i-16)))?(CODE_1):(CODE_0));
		
	}
}

发送数组

void RGB_SendArray(void)
{
	HAL_TIM_PWM_Start_DMA(&htim1, TIM_CHANNEL_1, (uint32_t *)Pixel_Buf,(Pixel_NUM+1)*24);
}

测试函数

void RGB_test(uint16_t Pixel_Len)
{
	uint16_t i;
		for(i=0;i<24;i++)
		{
	
		RGB_Set(i,0xff0000);
		Reset_Load();	
		RGB_SendArray();
		
		}
	
}

在main中直接调用

int main(void)
{
  /* USER CODE BEGIN 1 */
		
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_TIM1_Init();
  MX_RTC_Init();
  /* USER CODE BEGIN 2 */
	
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */		
		RGB_test(24);
		
		
  }
  /* USER CODE END 3 */
}

4.演示 

4.1方法一:

4.2方法二:

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值