精华内容
下载资源
问答
  • WS2812_STM32 用于STM32F上具有SPI的WS2812b控制的库 基本要求:SPI速度约为4.5Mb / S。 以HAL风格编写。 使用来自以下位置的colorspa对话: :
  • STM32驱动WS2812

    2018-10-12 22:11:15
    STM32驱动WS2812,基于STM32CubeMX,输出90个串联的WS2812 LED
  • Manik的STM32F4xx WS2812B库 描述 STM32F4xx-WS2812B-lib是一个非常易于使用的库,可使用STM32F4xx处理WS2812B可编程LED。 整个库旨在尽可能简单地使用。 它只需要一个命令即可进行初始化,并且只需要一个命令即可...
  • 此代码包含一个非常简单的 WS2812B RGB LED 驱动程序。 它适用于 STM32F4 微控制器并使用 libopencm3。 该代码使用硬件定时器来生成位时序,并使用 DMA 将“位”加载到定时器捕获比较寄存器中。 这让 CPU 同时可以...
  • STM32F030 DMX512 WS2812B 驱动 此代码基于馈送到 USART1 的 DMX512 数据包驱动八个并行的 WS2812B LED 串(连接到 GPIOA 引脚 0-7)。 WS2812B 库是一个位于的 Elia 代码的端口
  • STM32控制WS2812灯带【含完整代码】

    千次阅读 2021-01-12 11:02:51
    目录STM32控制WS2812灯带灯带信息实现代码引脚对应寄存器信息大全注意点参考资料 STM32控制WS2812灯带 用STM32控制WS2812 RGB灯带的代码资料不多。这里的代码是通过示波器一点一点调整得到的。本着开源原则,和大家...


    STM32控制WS2812灯带【含完整代码】

    用STM32控制WS2812 RGB灯带的代码资料不多。这里的代码是通过示波器一点一点调整得到的。本着开源原则,和大家分享学习。


    灯带信息

    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述
    点击查看完整文档


    实现代码

    核心代码如下:

    // 引脚对应的寄存器(更多信息见下文)
    #define A0_HIGH  GPIOA->BSRR = 1           // A low electrical level. (GPIO_PIN_0: 1)
    #define A0_LOW   GPIOA->BSRR = 65536u      // A high electrical level.(GPIO_PIN_0: 1 << 16u)
    #define A1_HIGH  GPIOA->BSRR = 2           // A low electrical level. (GPIO_PIN_1: 2)
    #define A1_LOW   GPIOA->BSRR = 131072u     // A high electrical level.(GPIO_PIN_1: 2 << 16u)
    #define B12_HIGH GPIOB->BSRR = 4096        // A low electrical level. (GPIO_PIN_12: 4096)
    #define B12_LOW  GPIOB->BSRR = 268435456u  // A high electrical level.(GPIO_PIN_12: 4096 << 16u)
    
    #define HIGH     B12_HIGH   // 持续一个很短时间的高电平
    #define LOW      B12_LOW    // 持续一个很短时间的低电平
    
    // 连续多个HIGH/LOW == 一个HIGH/LOW + delay函数 (卡示波器得到的)
    #define SIG1()     HIGH;HIGH;HIGH; HIGH;HIGH;LOW    // 一个 signal 1.
    #define SIG0()     HIGH;HIGH;LOW;	 LOW;LOW;LOW    // 一个 signal 0.
    
    // 示例颜色 (注意这里的颜色顺序是:高位->低位 —— G->R->B)
    #define RED    0x00ff00
    #define GREEN  0xff0000
    #define BLUE   0x0000ff
    
    #define LED_LEN       144  // 灯带长度
    #define BIT_LEN       24   // 每颗灯对应24位 0/1 signal
    
    uint32_t led_buf[LED_LEN] = { 0 };  // 存储每颗灯的颜色值,范围:[0, 0xffffff].
    
    void sync() {
    	uint32_t bit_buf[LED_LEN * BIT_LEN] = { 0 }; // 将要传输的bit数组
    	
    	for (uint32_t i = 0; i < LED_LEN; ++i) {
    		for (uint32_t j = 0; j < BIT_LEN; ++j) {
    			bit_buf[i * BIT_LEN + j] = (led_buf[i] >> (BIT_LEN - 1 - j)) & 1;  // 高位先传
    		}
    	}
    	
    	__disable_irq();  // 关闭中断
    	
    	for (uint32_t i = 0; i < LED_LEN * BIT_LEN; ++i) {
    		if (bit_buf[i]) {
    			SIG1();
    		} else {
    			SIG0();
    		}
    	}
    	
    	__enable_irq();  // 开启中断
    }
    

    引脚对应寄存器信息大全

    #define GPIO_PIN_0                 ((uint16_t)0x0001)  /* Pin 0 selected    */
    #define GPIO_PIN_1                 ((uint16_t)0x0002)  /* Pin 1 selected    */
    #define GPIO_PIN_2                 ((uint16_t)0x0004)  /* Pin 2 selected    */
    #define GPIO_PIN_3                 ((uint16_t)0x0008)  /* Pin 3 selected    */
    #define GPIO_PIN_4                 ((uint16_t)0x0010)  /* Pin 4 selected    */
    #define GPIO_PIN_5                 ((uint16_t)0x0020)  /* Pin 5 selected    */
    #define GPIO_PIN_6                 ((uint16_t)0x0040)  /* Pin 6 selected    */
    #define GPIO_PIN_7                 ((uint16_t)0x0080)  /* Pin 7 selected    */
    #define GPIO_PIN_8                 ((uint16_t)0x0100)  /* Pin 8 selected    */
    #define GPIO_PIN_9                 ((uint16_t)0x0200)  /* Pin 9 selected    */
    #define GPIO_PIN_10                ((uint16_t)0x0400)  /* Pin 10 selected   */
    #define GPIO_PIN_11                ((uint16_t)0x0800)  /* Pin 11 selected   */
    #define GPIO_PIN_12                ((uint16_t)0x1000)  /* Pin 12 selected   */
    #define GPIO_PIN_13                ((uint16_t)0x2000)  /* Pin 13 selected   */
    #define GPIO_PIN_14                ((uint16_t)0x4000)  /* Pin 14 selected   */
    #define GPIO_PIN_15                ((uint16_t)0x8000)  /* Pin 15 selected   */
    #define GPIO_PIN_All               ((uint16_t)0xFFFF)  /* All pins selected */
    
    GPIOx->BSRR = GPIO_Pin_x;  // 高电平
    GPIOx->BSRR = (uint32_t)GPIO_Pin << 16u;  // 低电平
    

    注意点

    1. 如果不在传输数据过程中停止中断,数据传输会因为被打断而出现误差,导致灯带闪烁,颜色变得离谱。
    2. 传输bit时应该高位先传(详见代码sync()函数),颜色顺序为:高位->低位 —— G->R->B

    完整例程代码下载链接

    点击下载

    参考资料

    WS2812手册
    个人经验

    展开全文
  • STM32F103 例程 包括 基本功能 WS2812真彩LED灯 驱动程序 软件开发工具 KEIL4
  • 基于STM32开发板平台,经过RCT6和ZET6不同芯片测试可用。 WS2812全彩LED流水灯,颜色可调,性能稳定。
  • STM32-WS2812B-RGBLED灯.zip

    2019-11-15 14:59:51
    STM32控制WS2812B全彩LED灯闪烁,这个灯对时序要求比较严格,所以针对不同芯片需要调整,我这边还有CC2530和F4系列的程序资料,需要的可以私聊我。
  • STM32驱动WS2812D全彩LED

    万次阅读 多人点赞 2018-09-08 16:34:32
    2.2 24bit 数据结构 2.3 电路连接 图出处:天际智联STM32F103开源四轴 3.软件实现 头文件: #define RGB_LED GPIO_Pin_9 #define RGB_LED_HIGH (GPIO_SetBits(GPIOB,RGB_LED)) #define RGB_LED_LOW (GPIO_ResetBits...

    前言:

    为了方便查看博客,特意申请了一个公众号,附上二维码,有兴趣的朋友可以关注,和我一起讨论学习,一起享受技术,一起成长。

    在这里插入图片描述


    1.简介

    一个集控制电路与发光电路于一体的智能外控 LED 光源。 其外型与一个 SMD5050 侧发光 LED 灯珠相同, 每个元件即为一个像素点。 像素点内部包含了智能数字接口数据锁存信号整形放大驱动电路, 电源稳压电路, 内置恒流电路, 高精度 RC 振荡器, 输出驱动采用 PWM 技术, 有效保证了像素点内光的颜色高一致性。

    ● IC控制电路与LED点光源共用一个电源。

    ● 控制电路与RGB芯片集成在一个5mm直径的圆头四脚直插封装的灯珠中, 构成一个完整的外控像素点。

    ● 内置信号整形电路, 任何一个像素点收到信号后经过波形整形再输出, 保证线路波形畸变不会累加。

    ● 内置上电复位和掉电复位电路。

    ● 每个像素点的三基色颜色可实现256级亮度显示, 完成16777216种颜色的全真色彩显示。

    ● 扫描频率 2kHz/s。

    ● 串行级联接口, 能通过一根信号线完成数据的接收与解码。

    ● 任意两点传传输距离在不超过 2 米时无需增加任何电路。

    ● 当刷新速率 30 帧/秒时, 级联数不小于 2048 点。

    ● 数据发送速度可达 800Kbps

    2.通讯协议

    数据协议采用单线归零码的通讯方式, 像素点在上电复位以后, DIN端接受从控制器传输过来的数据, 首先送过来的24bit数据被第一个像素点提取后, 送到像素点内部的数据锁存器, 剩余的数据经过内部整形处理电路整形放大后通过DO端口开始转发输出给下一个级联的像素点, 每经过一个像素点的传输, 信号减少24bit。 像素点采用自动整形转发技术, 使得该像素点的级联个数不受信号传送的限制, 仅仅受限信号传输速度要求。

    这里写图片描述

    2.1 数据传输

    这里写图片描述

    对于 ns 延时,这里采用__nop() 实现,用 KEIL 调试了一下,发现几处的__nop()的延时不太一样,对于 72M主频,最小延时应该是:1/72000000=13.9ns,查询了一些资料,比较精确的延时还是得用示波器看一看。

    2.2 24bit 数据结构

    这里写图片描述

    2.3 电路连接

    这里写图片描述

    图出处:天际智联STM32F103开源四轴

    3.软件实现

    头文件:

    #define 	RGB_LED 	GPIO_Pin_9
    #define		RGB_LED_HIGH	(GPIO_SetBits(GPIOB,RGB_LED))
    #define 	RGB_LED_LOW		(GPIO_ResetBits(GPIOB,RGB_LED))
    
    void RGB_LED_Init(void)
    {
    	GPIO_InitTypeDef  GPIO_InitStructure;
     	
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	 
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;				 
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		
    	GPIO_Init(GPIOB, &GPIO_InitStructure);					
    	GPIO_SetBits(GPIOB,GPIO_Pin_9);						 
    }
    
    /********************************************************/
    //
    /********************************************************/
    void RGB_LED_Write0(void)
    {
    	RGB_LED_HIGH;
    	__nop();__nop();__nop();__nop();__nop();__nop();
    	RGB_LED_LOW;
    	__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_LED_Write1(void)
    {
    	RGB_LED_HIGH;
    	__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
    	__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
    	__nop();__nop();
    	RGB_LED_LOW;
    	__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
    	__nop();__nop();
    }
    
    void RGB_LED_Reset(void)
    {
    	RGB_LED_LOW;
    	delay_us(80);
    }
    
    void RGB_LED_Write_Byte(uint8_t byte)
    {
    	uint8_t i;
    
    	for(i=0;i<8;i++)
    		{
    			if(byte&0x80)
    				{
    					RGB_LED_Write1();
    			}
    			else
    				{
    					RGB_LED_Write0();
    			}
    		byte <<= 1;
    	}
    }
    
    void RGB_LED_Write_24Bits(uint8_t green,uint8_t red,uint8_t blue)
    {
    	RGB_LED_Write_Byte(green);
    	RGB_LED_Write_Byte(red);
    	RGB_LED_Write_Byte(blue);
    }
    
    //亮灯颜色设定,其他颜色以此类推
    void RGB_LED_Red(void)
    {
    	 uint8_t i;
    	//4个LED全彩灯
    	for(i=0;i<4;i++)
    		{
    			RGB_LED_Write_24Bits(0, 0xff, 0);
    	}
    }
    
    void RGB_LED_Green(void)
    {
    	uint8_t i;
    
    	for(i=0;i<4;i++)
    		{
    			RGB_LED_Write_24Bits(0xff, 0, 0);
    	}
    }
    
    void RGB_LED_Blue(void)
    {
    	uint8_t i;
    
    	for(i=0;i<4;i++)
    		{
    			RGB_LED_Write_24Bits(0, 0, 0xff);
    	}
    }
    

    RGB颜色的数值可从此链接查询:http://www.sioe.cn/yingyong/yanse-rgb-16/


    参考:

    1.单总线led驱动芯片WS2811在linux下的驱动

    2.RGB灯WS2812B

    展开全文
  • STM32单片机WS2812B驱动程序灯效程序

    热门讨论 2017-06-06 17:13:31
    代码主要是基于stm32开发,包括两路ws2812b初始化代码,以及呼吸灯、跑马灯、彩虹灯等灯效程序,均是用pwm+dma的方式发送数据,不占用内存,本程序已用在项目中,可稳定运行。
  • 基于stm32f103c8t6最小系统板,ws2812灯带,六种模式,由按键或蓝牙app调模式,电位器ad采集互动,0.96寸OLED显示屏显示模式及参数。
  • STM32 cubemx驱动ws2812b灯条

    千次阅读 2021-01-10 17:06:30
    ws2812 程序设计与应用(1)DMA 控制 PWM 占空比原理及实现(STM32ws2812b原理 WS2812 内部集成了处理芯片和3颗不同颜色的led灯(红,绿,蓝),通过单总线协议分别控制三个灯的亮度强弱,达到全彩的效果,每一...

    参考链接

    ws2812 程序设计与应用(1)DMA 控制 PWM 占空比原理及实现(STM32)

    ws2812b原理

    • WS2812 内部集成了处理芯片和3颗不同颜色的led灯(红,绿,蓝),通过单总线协议分别控制三个灯的亮度强弱,达到全彩的效果,每一个灯需要 8 bits(1 byte) 的数据,所以一颗 ws2812 共需要24 bits(3 bytes) 的数据。
    • ws2812 采用 PWM方式来编码,即每个PWM的周期固定为1.25us(800k),占空比为 1/3 时为 0 码,占空比为 2/3 为 1 码。另外,ws2812 复位信号为一个 不低于50us的低电平:
    • 时序
    • 在这里插入图片描述

    在这里插入图片描述

    ws2812传输原理

    ws2812 的特点是可以多个灯珠串联起来,这样就可以通过一个总线控制多个灯珠:
    在这里插入图片描述
    ws2812 可以将第一个24字节的时序留下,余下的往下一位传递:
    在这里插入图片描述
    可以结合波逻辑分析仪捕获的波形来理解:
    在这里插入图片描述

    上图是4个led的驱动时序,首先是一个100us的低电平复位来ws2812,接着是第一个led灯的数据,它有24个周期,分为3个部分,每一个部分是8个周期分别对应不同颜色的灯,可以看到,第一个部分都是宽占空比,所以全是1,第二个部分都是窄占空比,所以全是0,第三个部分和第一个部分同。所以第一颗led灯,是绿色和蓝色一起亮,视觉效果为青色,其它同理。

    时序的数据结构是,高位到低位:
    在这里插入图片描述

    基本信息

    芯片型号 系统时钟 定时器 高速总线 引脚
    STM32F427IIH 180Mhz TIM8_CH2 APB2 PI6

    CubeMx配置

    时钟

    TIM8_CH2

    在这里插入图片描述
    周期计算:
    ws2812b需要800kb的周期,系统时钟是180Mhz,TIM8是挂在APB2总线上的,它的时钟也是180Mhz,
    因此,有:180 * 1000 / 800 = 225 (224+1),因此自动装载值设为 224 ;
    #####
    cubemx的配置到此结束。

    代码部分

    tim.c里添加

    void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
    {
        HAL_TIM_PWM_Stop_DMA(&htim8,TIM_CHANNEL_2);
    }
    

    ws2812.c里添加
    参数说明:

    ONE_PULSE ZERO_PULSE WS2812_DATA_LEN
    149 74 334
    149 =(224+1)* 2/3 74 = (224+1)* 2/3 80 + led_nums * 24
    #include "ws2812b.h"
    #include "tim.h"
    
    #define ONE_PULSE        (149)                           //1 码
    #define ZERO_PULSE       (74)                           //0 码
    #define RESET_PULSE      (80)                           //80 ,复位信号
    #define LED_NUMS         (11)                            //led 数量
    #define LED_DATA_LEN     (24)                           //led 长度,单个需要24bits
    #define WS2812_DATA_LEN  (LED_NUMS*LED_DATA_LEN)        //ws2812灯条需要的数组长度
    
    uint16_t static RGB_buffur[RESET_PULSE + WS2812_DATA_LEN] = { 0 };
    
    void ws2812_set_RGB(uint8_t R, uint8_t G, uint8_t B, uint16_t num)
    {
        //
        uint16_t* p = (RGB_buffur + RESET_PULSE) + (num * LED_DATA_LEN);
        
        for (uint16_t i = 0;i < 8;i++)
        {
            //
            p[i]      = (G << i) & (0x80)?ONE_PULSE:ZERO_PULSE;
            p[i + 8]  = (R << i) & (0x80)?ONE_PULSE:ZERO_PULSE;
            p[i + 16] = (B << i) & (0x80)?ONE_PULSE:ZERO_PULSE;
    
        }
    }
    /*ws2812 初始化*/
    void ws2812_init(uint8_t led_nums)
    {
    	uint16_t num_data;
    	num_data = 80 + led_nums * 24;
    	for(uint8_t i = 0; i < led_nums; i++)
    	{
    		ws2812_set_RGB(0x00, 0x00, 0x00, i);
    	}
    	 HAL_TIM_PWM_Start_DMA(&htim8,TIM_CHANNEL_2,(uint32_t *)RGB_buffur,(num_data)); 
    }
    /*全亮蓝灯*/
    void ws2812_blue(uint8_t led_nums)
    {
    	uint16_t num_data;
    	num_data = 80 + led_nums * 24;
    	for(uint8_t i = 0; i < led_nums; i++)
    	{
    		ws2812_set_RGB(0x00, 0x00, 0x22, i);
    	}
    	 HAL_TIM_PWM_Start_DMA(&htim8,TIM_CHANNEL_2,(uint32_t *)RGB_buffur,(num_data));
    }
    /*全亮红灯*/
    void ws2812_red(uint8_t led_nums)
    {
    	uint16_t num_data;
    	num_data = 80 + led_nums * 24;
    	for(uint8_t i = 0; i < led_nums; i++)
    	{
    		ws2812_set_RGB(0x22, 0x00, 0x00, i);
    	}
    	 HAL_TIM_PWM_Start_DMA(&htim8,TIM_CHANNEL_2,(uint32_t *)RGB_buffur,(num_data));
    }
    /*全亮绿灯*/
    void ws2812_green(uint8_t led_nums)
    {
    	uint16_t num_data;
    	num_data = 80 + led_nums * 24;
    	for(uint8_t i = 0; i < led_nums; i++)
    	{
    		ws2812_set_RGB(0x00, 0x22, 0x00, i);
    	}
    	 HAL_TIM_PWM_Start_DMA(&htim8,TIM_CHANNEL_2,(uint32_t *)RGB_buffur,(num_data));
    }
    
    void ws2812_example(void)
    {		
    	  ws2812_set_RGB(0x00, 0x00, 0x22, 0);
        ws2812_set_RGB(0x00, 0x00, 0x22, 1);
        ws2812_set_RGB(0x00, 0x00, 0x22, 2);
        ws2812_set_RGB(0x00, 0x00, 0x22, 3);
        ws2812_set_RGB(0x00, 0x00, 0x22, 6);
        ws2812_set_RGB(0x00, 0x00, 0x22, 7);
    		ws2812_set_RGB(0x00, 0x00, 0x22, 8);
        ws2812_set_RGB(0x00, 0x00, 0x22, 10);
        HAL_TIM_PWM_Start_DMA(&htim8,TIM_CHANNEL_2,(uint32_t *)RGB_buffur,(344)); //344 = 80 + 24 * LED_NUMS(11)
    
        HAL_Delay(500);
    }
    
    

    ws2812b.h 里加入

    #ifndef  WS2812B_H
    #define WS2812B_H
    #include "type.h"
    #include "stdint.h"
    
    void ws2812_set_RGB(uint8_t R, uint8_t G, uint8_t B, uint16_t num);
    
    void ws2812_example(void);
    extern void ws2812_blue(uint8_t led_nums);
    extern void ws2812_red(uint8_t led_nums);
    extern void ws2812_green(uint8_t led_nums);
    
    #endif
    

    main.c里加入

    	...
    	ws2812_init(11);
    	 while (1)
       	{
    		ws2812_blue(8);
    		HAL_Delay(500);
    		ws2812_red(8);
    		HAL_Delay(500);
    		ws2812_green(8);
    		HAL_Delay(500);
    	}
    	...
    

    演示效果:
    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述

    更新

    type.h

    #ifndef _TYPE_H
    #define _TYPE_H
    
    #include "stm32f4xx_hal.h"
    #include <stdlib.h>
    #include <stdarg.h>
    #include <string.h>
    #include <stdbool.h>
    
    
    typedef uint8_t 	u8;
    typedef uint16_t 	u16;
    typedef uint32_t 	u32;
    
    typedef int8_t 		s8;
    typedef int16_t 	s16;
    typedef int32_t		s32;
    
    typedef volatile uint8_t 	vu8;
    typedef volatile uint16_t 	vu16;
    typedef volatile uint32_t 	vu32;
    
    typedef volatile int8_t 	vs8;
    typedef volatile int16_t 	vs16;
    typedef volatile int32_t	vs32;
    
    typedef union{
    	s8 		s8_fmt[8];	//for angle and omega
    	u8 		u8_fmt[8];	//for angle and omega
    	char 	ch_fmt[8];	//
    	s16		s16_fmt[4];
    	u16		u16_fmt[4];
    	s32 	s32_fmt[2];
    	u32 	u32_fmt[2];
    	float 	f32_fmt[2];
    	double 	d64_fmt;
    }data_convert_ut;	//for diaobi gyro
    
    #endif
    
    
    
    
    展开全文
  • stm32-WS2812 PWM+DMA(自己写库函数)

    热门讨论 2021-02-25 19:32:06
    stm32-WS2812 HAL PWM+DMA库函数 查看Github项目 CubeMx配置如下: 1、选择72M时钟 2、选择外部晶振 3、选择调试方式 4、选择定时器3 PWM 通道1输出 (记住接线:PA6--->WS2812_DATA_IN)DMA配置:...

    stm32-WS2812 HAL PWM+DMA库函数

    查看Github项目

    CubeMx配置如下:

    1、选择72M时钟

    2、选择外部晶振

    3、选择调试方式

    4、选择定时器3 PWM 通道1输出 (记住接线:PA6--->WS2812_DATA_IN)DMA配置:内存到外设,内存地址自增加,(数据为Byte)

    5、根据上面选择进行修改配置头文件:

    文件:mylib_ws28xx.h

    #ifndef MYLIB_WS28XX
    #define MYLIB_WS28XX
    
    /****************************************
    *Include
    ****************************************/
    #include "tim.h"			//定时器句柄
    //如果需要移植,更改这个 __show() 驱动以及对应的数据结构即可
    
    /****************************************
    *Config
    ****************************************/
    #define BIT_1                   61 			//1比较值为61-->850us
    #define BIT_0                   28 			//0比较值为28-->400us
    
    #define PIXEL_SIZE							6
    #define WS28xx_PWM_hTIMER				htim3
    #define WS28xx_PWM_Chaneel      TIM_CHANNEL_1		
    
    
    /****************************************
    *数据结构
    ****************************************/
    
    #define HSV_H_MAX 				360
    #define HSV_H_MIN 				1
    
    #define HSV_S_MAX 				1
    #define HSV_S_MIN 				0.6				//0.6保证能显示基本颜色(而不会变白色失真)
    
    #define HSV_V_MAX 				1
    #define HSV_V_MIN 				0.005
    //整个WS28xx_DataTypeStruct结构体将被以PWM方式发送
    typedef struct
    {
    						//3个0等待PWM稳定
    	unsigned char ColorStartData[3];
    						//实际GRB数据(已经转换为PWM对应的值)
    	unsigned char ColorRealData[24*PIXEL_SIZE*8];
    						//结束位为0
    	unsigned char ColorEndData;
    }WS28xx_DataTypeStruct;
    
    /****************************************
    *对象化编程
    ****************************************/
    typedef struct 
    {
    	//实际发送的数据
    	WS28xx_DataTypeStruct WS28xx_Data;
    	//灯数量
    	unsigned short int Pixel_size;
    	
    	
    //单独设置index的RGB颜色
    void (*SetPixelColor_RGB)(unsigned short int index,unsigned char r,unsigned char g,unsigned char b);
    //从RGB数据读出:设置index的RGB颜色
    void (*SetPixelColor_From_RGB_Buffer)( unsigned short int pixelIndex,unsigned char pRGB_Buffer[][3],unsigned short int DataCount);
    //设置所有为RGB颜色
    void (*SetALLColor_RGB)(unsigned char r,unsigned char g,unsigned char b);
    //获取某个位置的RGB
    void (*GetPixelColor_RGB)(unsigned short int index,unsigned char *r,unsigned char *g,unsigned char *b);
    	
    
    	
    // **************************************** HSV空间设置 ****************************************
    //单独设置index的HSV颜色																									--->>改变HSV
    void (*SetPixelColor_HSV)(unsigned short int index,unsigned short int h,float s,float v);
    	
    //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!以下操作在原来颜色基础上做改变
    //设置某个位置的HSV色相(Hue)(1~~360)																		--->>也就是颜色(逆时针)
    //SetPixelColor_HSV_H注意该函数,如果一开始
    void (*SetPixelColor_HSV_H)(unsigned short int pixelIndex,unsigned short int light);
    //设置某个位置的HSV饱和度(Saturation)(0.6~~1)													--->>色彩纯净度
    void (*SetPixelColor_HSV_S)(unsigned short int pixelIndex,float light);
    //设置某个位置的HSV明度(Value)(0.005~~1)																--->>也就是亮度
    void (*SetPixelColor_HSV_V)(unsigned short int pixelIndex,float light);
    
    //设置所有HSV色相(1~~360)			       																			--->>也就是颜色(逆时针)
    void (*SetALLColor_HSV_H)(unsigned short int setH);
    //设置所有HSV饱和度(0.01~~1)																			   			--->>色彩纯净度
    void (*SetALLColor_HSV_S)(float setS);
    //设置所有明度/亮度(0.01~~1)																							--->>也就是亮度
    void (*SetALLColor_HSV_V)(float setV);
    //显示(发出数据)
    void (*show)(void);
    }WS28xx_TypeStruct;
    
    extern WS28xx_TypeStruct WS28xx;
    
    
    void	WS28xx_TypeStructInit(void);
    
    
    /*
    *工具函数
    */
    #define LIMIT(x,max,min) ((x<max )? ((x>min )? x:min):max)
    #define MAX(a,b,c) (a>b?a:b>c?b:c)
    #define MIN(a,b,c) (a<b?a:b<c?b:c)
    void RGB2HSV(unsigned char r, unsigned char g, unsigned char b, float *h, float *s, float *v);
    void HSV2RGB(float h, float s, float v, unsigned char *r, unsigned char *g, unsigned char *b);
    #endif
    

    文件:mylib_ws28xx.c

    #include "../Inc/mylib_ws28xx.h"
    
    WS28xx_TypeStruct WS28xx;
    //如果需要移植官方库函数,更改这个 __show() 驱动即可
    void __show()
    {
    	HAL_TIM_PWM_Start_DMA(&WS28xx_PWM_hTIMER,WS28xx_PWM_Chaneel,(uint32_t *)(&WS28xx.WS28xx_Data),sizeof(WS28xx.WS28xx_Data));
    }
    
    		
    //设置index的颜色
    void __SetPixelColor_RGB(unsigned short int index,unsigned char r,unsigned char g,unsigned char b)
    {
    	unsigned char j;
    	if(index > WS28xx.Pixel_size)
    		return;
    	for(j = 0; j < 8; j++)
    	{
    		//G
    		WS28xx.WS28xx_Data.ColorRealData [24 * index + j]     = (g & (0x80 >> j)) ? BIT_1 : BIT_0; //将高位先发
    		//R
    		WS28xx.WS28xx_Data.ColorRealData [24 * index + j + 8]     = (r & (0x80 >> j)) ? BIT_1 : BIT_0; //将高位先发
    		//B
    		WS28xx.WS28xx_Data.ColorRealData [24 * index + j + 16]     = (b & (0x80 >> j)) ? BIT_1 : BIT_0; //将高位先发
    	}
    }
    //获取某个位置的RGB
    void __GetPixelColor_RGB(unsigned short int index,unsigned char *r,unsigned char *g,unsigned char *b)
    {
    	unsigned char j;
    	*r=0;
    	*g=0;
    	*b=0;
    	if(index > WS28xx.Pixel_size)
    		return;
    	for(j = 0; j <8; j++)
    	{
    		//G
    		(*g)|=((WS28xx.WS28xx_Data.ColorRealData [24 * index + j] >=BIT_1)?  0x80>>j:0);
    		//R
    		(*r)|=((WS28xx.WS28xx_Data.ColorRealData [24 * index + j + 8] >=BIT_1)? 0x80>>j:0);
    		//B
    		(*b)|=((WS28xx.WS28xx_Data.ColorRealData [24 * index + j + 16] >=BIT_1)? 0x80>>j:0);
    	}
    }
    //读取RGB缓存数据,并且设置颜色例如下面数据
    /*unsigned char RGB[x][3]={
    {r1,g1,b2},
    {r1,g1,b2},
    {r1,g1,b2}};
    */
    void __SetPixelColor_From_RGB_Buffer( unsigned short int pixelIndex,unsigned char pRGB_Buffer[][3],unsigned short int DataCount)
    {
    	unsigned short int Index,j=0;
    	for(Index=pixelIndex;Index < WS28xx.Pixel_size; Index++)
    	{
    			WS28xx.SetPixelColor_RGB(Index,pRGB_Buffer[j][0],pRGB_Buffer[j][1],pRGB_Buffer[j][2]);
    			j++;
    			if(j>DataCount)
    				return;
    	}
    }
    
    //设置所有颜色
    void __SetALLColor_RGB(unsigned char r,unsigned char g,unsigned char b)
    {
    	unsigned short int Index;
    	for(Index=0;Index < WS28xx.Pixel_size; Index++)
    	{
    		WS28xx.SetPixelColor_RGB(Index,r,g,b);
    	}
    }
    
    void RGB2HSV(unsigned char r, unsigned char g, unsigned char b, float *h, float *s, float *v)
    {
      float red, green ,blue;
      float cmax, cmin, delta;
      
      red = (float)r / 255;
      green = (float)g / 255;
      blue = (float)b / 255;
      
      cmax = MAX(red, green, blue);
      cmin = MIN(red, green, blue);
      delta = cmax - cmin;
    
      /* H */
      if(delta != 0)
      {
        if(cmax == red)
        {
    			*h= green >= blue ? 60 * ((green - blue) / delta): 60 * ((green - blue) / delta) + 360;
        }
        else if(cmax == green)
        {
          *h = 60 * ((blue - red) / delta + 2);
        }
        else if(cmax == blue) 
        {
          *h = 60 * ((red - green) / delta + 4);
        }
      }else
      {
        *h = 0;
      }
      /* S */
    	*s=cmax?delta / cmax:0;
      /* V */
      *v = cmax;
    }
      
    void HSV2RGB(float h, float s, float v, unsigned char *r, unsigned char *g, unsigned char *b)
    {
        int hi = ((int)h / 60) % 6;
        float f = h * 1.0 / 60 - hi;
        float p = v * (1 - s);
        float q = v * (1 - f * s);
        float t = v * (1- (1 - f) * s);
        switch (hi){
            case 0:
                *r = 255 * v;
                *g = 255 * t;
                *b = 255 * p;
                break;
            case 1:
                *r = 255 * q;
                *g = 255 * v;
                *b = 255 * p;
                break;
            case 2:
                *r = 255 * p;
                *g = 255 * v;
                *b = 255 * t;
                break;
            case 3:
                *r = 255 * p;
                *g = 255 * q;
                *b = 255 * v;
                break;
            case 4:
                *r = 255 * t;
                *g = 255 * p;
                *b = 255 * v;
                break;
            case 5:
                *r = 255 * v;
                *g = 255 * p;
                *b = 255 * q;
                break;
        }
    }
    //单独设置index的RGB颜色
    void __SetPixelColor_HSV(unsigned short int pixelIndex,unsigned short int h,float s,float v)
    {
    	unsigned char r,g,b;
    	h = LIMIT(h,HSV_H_MAX,HSV_H_MIN);
    	s = LIMIT(s,HSV_S_MAX,HSV_S_MIN);
    	v = LIMIT(v,HSV_V_MAX,HSV_V_MIN);
    	HSV2RGB(h, s, v, &r, &g, &b);
    	WS28xx.SetPixelColor_RGB(pixelIndex,r,g,b);
    }
    void __SetPixelColor_HSV_H(unsigned short int pixelIndex,unsigned short int setH)
    {
    	unsigned char r,g,b;
    	float h,s,v;
    	WS28xx.GetPixelColor_RGB(pixelIndex,&r,&g,&b);
    	RGB2HSV(r,g,b, &h, &s, &v);
    	h = LIMIT(setH,HSV_H_MAX,HSV_H_MIN);
    	s = LIMIT(s,HSV_S_MAX,HSV_S_MIN);
    	v = LIMIT(v,HSV_V_MAX,HSV_V_MIN);
    	HSV2RGB(h, s, v, &r, &g, &b);
    	WS28xx.SetPixelColor_RGB(pixelIndex,r,g,b);
    }
    
    
    void __SetPixelColor_HSV_S(unsigned short int pixelIndex,float setS)
    {
    	unsigned char r,g,b;
    	float h,s,v;
    	WS28xx.GetPixelColor_RGB(pixelIndex,&r,&g,&b);
    	RGB2HSV(r,g,b, &h, &s, &v);
    	h = LIMIT(h,HSV_H_MAX,HSV_H_MIN);
    	s = LIMIT(setS,HSV_S_MAX,HSV_S_MIN);
    	v = LIMIT(v,HSV_V_MAX,HSV_V_MIN);
    	HSV2RGB(h, s, v, &r, &g, &b);
    	WS28xx.SetPixelColor_RGB(pixelIndex,r,g,b);
    }
    void __SetPixelColor_HSV_V(unsigned short int pixelIndex,float setV)
    {
    	unsigned char r,g,b;
    	float h,s,v;
    	WS28xx.GetPixelColor_RGB(pixelIndex,&r,&g,&b);
    	RGB2HSV(r,g,b, &h, &s, &v);
    	h = LIMIT(h,HSV_H_MAX,HSV_H_MIN);
    	s = LIMIT(s,HSV_S_MAX,HSV_S_MIN);
    	v = LIMIT(setV,HSV_V_MAX,HSV_V_MIN);
    	HSV2RGB(h, s, v, &r, &g, &b);
    	WS28xx.SetPixelColor_RGB(pixelIndex,r,g,b);
    }
    
    
    void __SetALLColor_HSV_H(unsigned short int setH)
    {
    	unsigned short int Index;
    	for(Index=0;Index < WS28xx.Pixel_size; Index++)
    	{
    		WS28xx.SetPixelColor_HSV_H(Index,setH);
    	}
    }
    void __SetALLColor_HSV_S(float setS)
    {
    	unsigned short int Index;
    	for(Index=0;Index < WS28xx.Pixel_size; Index++)
    	{
    		WS28xx.SetPixelColor_HSV_S(Index,setS);
    	}
    }
    void __SetALLColor_HSV_V(float setV)
    {
    	unsigned short int Index;
    	for(Index=0;Index < WS28xx.Pixel_size; Index++)
    	{
    		WS28xx.SetPixelColor_HSV_V(Index,setV);
    	}
    }
    
    void	WS28xx_TypeStructInit()
    {
    	WS28xx.Pixel_size=PIXEL_SIZE;
    	WS28xx.GetPixelColor_RGB=__GetPixelColor_RGB;
    	WS28xx.SetPixelColor_From_RGB_Buffer=__SetPixelColor_From_RGB_Buffer;
    	WS28xx.SetPixelColor_RGB=__SetPixelColor_RGB;
    	WS28xx.SetALLColor_RGB=__SetALLColor_RGB;
    	//HSV空间设置
    	WS28xx.SetPixelColor_HSV=__SetPixelColor_HSV;
    	WS28xx.SetPixelColor_HSV_H=__SetPixelColor_HSV_H;
    	WS28xx.SetPixelColor_HSV_S=__SetPixelColor_HSV_S;
    	WS28xx.SetPixelColor_HSV_V=__SetPixelColor_HSV_V;
    	WS28xx.SetALLColor_HSV_H=__SetALLColor_HSV_H;
    	WS28xx.SetALLColor_HSV_S=__SetALLColor_HSV_S;
    	WS28xx.SetALLColor_HSV_V=__SetALLColor_HSV_V;
    	WS28xx.show=__show;
    }
    

    引入头文件:

    #include "../mylib/Inc/mylib_ws28xx.h"

    在main初始化调用:

    #include "../Inc/mylib_ws28xx_test.h"
    
    void read_RGB_Buffer()
    {
    	uint8_t rgb[][3]={
    	{0xFF,0,0},
    	{0,0xFF,0},
    	{0,0,0xFF},
    	{0,0,0xFF},
    	{0,0xFF,0},
    	{0xFF,0,0},
    	};
    	uint8_t r,g,b;
    	WS28xx.SetPixelColor_From_RGB_Buffer(0,rgb,6);
    	WS28xx.show();
    	HAL_Delay(500);
    	WS28xx.GetPixelColor_RGB(1,&r,&g,&b);
    	WS28xx.SetPixelColor_RGB(3,r,g,b);
    	WS28xx.show();
    	HAL_Delay(500);
    }
    void HSV_test()
    {
    	uint16_t h=0,index=0;
    	float v=0,s=0;
    	
    	WS28xx.SetALLColor_HSV_V(0.4);
    	for(h=0;h<360;h+=20)
    	{
    		WS28xx.SetPixelColor_HSV_H(index++%WS28xx.Pixel_size,h);
    		WS28xx.show();
    		HAL_Delay(300);
    	}
    	
    	for(s=0.6;s<1;s+=0.05)
    	{
    		WS28xx.SetALLColor_HSV_S(s);
    		WS28xx.show();
    		HAL_Delay(200);
    	}
    	for(v=0;v<1;v+=0.05)
    	{
    		WS28xx.SetALLColor_HSV_V(v);
    		WS28xx.show();
    		HAL_Delay(200);
    	}
    }
    
    void WS2812_test()
    {
    	read_RGB_Buffer();
    	HSV_test();
    }
    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_TIM3_Init();
      /* USER CODE BEGIN 2 */
    	WS28xx_TypeStructInit();//初始化
    
      /* USER CODE END 2 */
    
      /* Infinite loop */
      /* USER CODE BEGIN WHILE */
      while (1)
      { 
         WS2812_test();
        /* USER CODE END WHILE */
        /* USER CODE BEGIN 3 */
      }
      /* USER CODE END 3 */
    }

    最终目录文件:

    效果图如下:


    GitHub项目链接:https://github.com/Jim-Chenming/stm32-WB2812

     

     

     

     

    展开全文
  • STM32控制WS2812D全彩LED

    千次阅读 2020-07-25 09:59:06
    WS2812D-F8是一个集控制电路与发光电路于一体的智能外控LED光源。其外型与一个F8 LED灯珠相同,每 个元件即为一个像素点。像素点内部包含了智能数字接口数据锁存信号整形放大驱动电路,还包含有高精度的内 部振荡...
  • stm32驱动的ws2812智能灯_yuanam.zip
  • 利用第三方云平台机智云智能设备,简单3步打造了基于Nucleo-L496ZG驱动WS2812全彩LED的智能灯,可手机APP远程控制。 接线图: esp8266模块 TX-----àD0 RX-----àD1 WS2812LED Din-----àD11 实物连接头: 视频演示: ...
  • 源码为stm32F030C8t6 控制WS2812 RGB灯,但适应于stm32f0主频48MHz系列单片机。stm32F103可按主频比例减少延时指令
  • STM32F103dmapwm驱动ws2812,已经可以使用,超级好用,然后已经用在项目中
  • STM32F1控制WS2812,TIM+DMA控制波形数据,波形任意可调,串口编辑波形,AD采集R,G,B电流,完整应用系统
  • STM32L051_WS2812.zip

    2020-04-13 16:37:43
    STM32L051C8T6驱动WS2812工程文件,采用HAL库,PWM+DMA方式驱动,可实现流水灯,常亮、闪亮、RGB颜色渐变等效果。
  • STM32F103控制WS2812B

    万次阅读 2018-08-24 18:04:00
    #include "...stm32f10x_tim.h" #include "stm32f10x_dma.h"  #include "stm32f10x_gpio.h"  #include "misc.h"   uint16_t WS_SendBuff[(LED_NUM*24) + 58] =
  • 该示例旨在作为 stm32f4 发现板项目的起点。 目标是演示如何组织项目。 即使它被设置为使用 stm32f4 发现板作为目标,它也应该很容易适应您自己的平台。 用法 您必须通过运行来获取 libopencm3 子模块: git ...
  • STM32F103C8+WS2812B.rar

    2020-03-13 09:35:40
    包括keil工程和cubeMX工程的源码,stm32f103c8+spi驱动WS2812B,经过测试和验证,几乎没有色差
  • 这篇要使用到SPI+DMA,需要了解的话,可以参考我另两篇博客 时钟:https://www.cnblogs.com/PureHeart/p/11330967.html SPI+DMA通信:... 文章前半会先介绍WS2812通信方式,文章后半才是SPI+DMA ...WS2812...
  • 0xWS2812 STM32 driver for WS2812(B) RGB LEDs 0xWS2812 pronounced "hex-WS2812" This code aims at providing a basic interface to the WS2812(B) individually addressable RGB LEDs by WorldSemi. The code...

空空如也

空空如也

1 2 3 4 5 ... 12
收藏数 229
精华内容 91
关键字:

stm32ws2812