赞
踩
笔者使用的WS2812是淘宝买的灯环,如下图所示
留出来四个接口,分别是DOUT,DIN,VCC,GND
根据描述
我们使用到的仅为DIN,VCC,GND
推荐使用5V供电,即VCC连接至单片机的5V引脚
DIN作为数据接收端,需要连接至单片机SPI的MOSI引脚,笔者选择开启SPI1,因此连接到PA7
GND连接至单片机的GND引脚
时钟配置为48MHz
设置SPI
开启DMA
在数据包与数据包之间需要大于280us的延时,一个数据包有好几个数据帧,取决于想点亮几个灯珠
数据帧格式如上,G R B每种颜色用8bit,24位表示一个颜色,分给一个灯珠
当想表示0的时候,需要高电平持续200~300多ns,然后是580ns~1us的低电平
当想表示1的时候,需要高电平持续580ns~1us,然后是580ns~1us的低电平
笔者设置SPI为6MHz,一个时钟周期大概是160ns(1/6MHz)
那么想表示0,就需要大约2个时钟的高电平(160*2=320ns)紧接着6个时钟的低电平(6*160=960ns),就是由SPI发出0xC0
想表示1,就需要大约4个时钟的高电平(4*160=640ns)紧接着4个时钟的低电平(4*160=640ns),就是由SPI发出0xF0
定义结构体和存放信息的数组和宏定义
- #define WS2812_0 0xC0
- #define WS2812_1 0xF0
- #define WS2812_RST 0x00
- #define LED_NUMS 16
- #define RGB_BIT 24
-
- typedef struct
- {
- uint8_t R;
- uint8_t G;
- uint8_t B;
- }LEDType;
-
- volatile uint8_t RGB_BIT_Buffer[RGB_BIT];
- volatile uint8_t buffer[RGB_BIT*LED_NUMS];
- volatile LEDType LED[LED_NUMS];
这里的RGB_BIT_Buffer是一个含有24个字节的数组,用来存放一个LED灯的色彩信息
buffer用来存放笔者所用模块的16个灯珠的所有色彩信息
这个函数非常关键,用于将色彩转化为24位的数据
- /**
- create 24 byte sent by SPI using RGB values.
- */
- static static void WS2812_CreatData(uint8_t R,uint8_t G,uint8_t B)
- {
- uint8_t temp[RGB_BIT] = {0};
- for (uint8_t i=0;i<8;i++){
- temp[7-i] = (G & 0x01) ? WS2812_1 : WS2812_0;
- G = G >> 1;
- }
- for (uint8_t i=0;i<8;i++){
- temp[15-i] = (R & 0x01) ? WS2812_1 : WS2812_0;
- R = R >> 1;
- }
- for (uint8_t i=0;i<8;i++){
- temp[23-i] = (B & 0x01) ? WS2812_1 : WS2812_0;
- B = B >> 1;
- }
- memcpy(RGB_BIT_Buffer, temp, RGB_BIT);
- }
将16个灯珠的色彩进行处理,变成一个大的数组,存入buffer中
- /**
- cook the whole buffer made by many(16 pieces) RGB_BIT_Buffers.
- */
- void WS2812_MakeBuffer()
- {
- for(uint16_t i=0;i < LED_NUMS;i++)
- {
- WS2812_CreatData(LED[i].R,LED[i].G,LED[i].B);
- memcpy(buffer + i * RGB_BIT, RGB_BIT_Buffer, RGB_BIT);
- }
- }
- void WS2812_TurnOff()
- {
- for(uint16_t i=0;i<LED_NUMS*24;i++)
- {
- buffer[i]=WS2812_0;
- }
- }
这个函数用来使某个灯珠呈现出设定的色彩
- /**
- an led of position will bright with color value
- pos is [0 , max-1]
- */
- static void WS2812_Color_Pos(uint32_t color,uint16_t Pos)
- {
- uint8_t R,G,B;
- uint16_t i;
-
- R=(color >> 16 ) & 0x00FF;
- G=(color >> 8 ) & 0x0000FF;
- B=(color ) & 0x0000FF;
-
- WS2812_CreatData(R,G,B);
- if(Pos < LED_NUMS && Pos >=0)
- {
- memcpy(buffer + RGB_BIT * Pos, RGB_BIT_Buffer,RGB_BIT);
- }
- else
- {
- WS2812_TurnOff();
- }
- }
根据介绍里的描述,ws2812可以显示256*256*256种颜色,但常用的RGB值其实并不多,我们只需要显示其中一些就能呈现出RGB变幻的效果了
- void WS2812_Show_Wheel()
- {
- static uint16_t i=0;
- i++;
- WS2812_Color_Pos(0xFF0000,(i)%16);
- WS2812_Color_Pos(0XFF7F00,(i+1)%16);
- WS2812_Color_Pos(0XFFFF00,(i+2)%16);
- WS2812_Color_Pos(0X7FFF00,(i+3)%16);
- WS2812_Color_Pos(0X00FF00,(i+4)%16);
- WS2812_Color_Pos(0X00FF7F,(i+5)%16);
- WS2812_Color_Pos(0X00FFFF,(i+6)%16);
- WS2812_Color_Pos(0X007FFF,(i+7)%16);
- WS2812_Color_Pos(0X0000FF,(i+8)%16);
- WS2812_Color_Pos(0X7F00FF,(i+9)%16);
- WS2812_Color_Pos(0XFF00FF,(i+10)%16);
- WS2812_Color_Pos(0XFF007F,(i+11)%16);
- WS2812_Color_Pos(0XFF0000,(i+12)%16);
- WS2812_Color_Pos(0XFF7F00,(i+13)%16);
- WS2812_Color_Pos(0XFFFF00,(i+14)%16);
- WS2812_Color_Pos(0X7FFF00,(i+15)%16);
- WS2812_Update();
- }
- void WS2812_Update()
- {
- HAL_SPI_Transmit_DMA(&hspi1,buffer,RGB_BIT*LED_NUMS);
- }
- /**
- * @brief The application entry point.
- * @retval int
- */
- 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_SPI1_Init();
- /* USER CODE BEGIN 2 */
-
- /* USER CODE END 2 */
-
- /* Infinite loop */
- /* USER CODE BEGIN WHILE */
- while (1)
- {
- WS2812_Show_Wheel();
- HAL_Delay(30);
- /* USER CODE END WHILE */
-
- /* USER CODE BEGIN 3 */
- }
- /* USER CODE END 3 */
- }
-
- #include "ws2812.h"
-
- volatile uint8_t RGB_BIT_Buffer[RGB_BIT];
- volatile uint8_t buffer[RGB_BIT*LED_NUMS];
- volatile LEDType LED[LED_NUMS];
-
-
- void WS2812_Update()
- {
- HAL_SPI_Transmit_DMA(&hspi1,buffer,RGB_BIT*LED_NUMS);
- }
-
- /**
- create 24 byte sent by SPI using RGB values.
- */
- static void WS2812_CreatData(uint8_t R,uint8_t G,uint8_t B)
- {
- uint8_t temp[RGB_BIT] = {0};
- for (uint8_t i=0;i<8;i++){
- temp[7-i] = (G & 0x01) ? WS2812_1 : WS2812_0;
- G = G >> 1;
- }
- for (uint8_t i=0;i<8;i++){
- temp[15-i] = (R & 0x01) ? WS2812_1 : WS2812_0;
- R = R >> 1;
- }
- for (uint8_t i=0;i<8;i++){
- temp[23-i] = (B & 0x01) ? WS2812_1 : WS2812_0;
- B = B >> 1;
- }
- memcpy(RGB_BIT_Buffer, temp, RGB_BIT);
- }
-
- /**
- cook the whole buffer made by many(16 pieces) RGB_BIT_Buffers.
- */
- static void WS2812_MakeBuffer()
- {
- for(uint16_t i=0;i < LED_NUMS;i++)
- {
- WS2812_CreatData(LED[i].R,LED[i].G,LED[i].B);
- memcpy(buffer + i * RGB_BIT, RGB_BIT_Buffer, RGB_BIT);
- }
- }
-
-
-
- void WS2812_TurnOff()
- {
- for(uint16_t i=0;i<LED_NUMS*24;i++)
- {
- buffer[i]=WS2812_0;
- }
- }
-
-
- /**
- an led of position will bright with color value
- pos is [0 , max-1]
- */
- static void WS2812_Color_Pos(uint32_t color,uint16_t Pos)
- {
- uint8_t R,G,B;
- uint16_t i;
-
- R=(color >> 16 ) & 0x00FF;
- G=(color >> 8 ) & 0x0000FF;
- B=(color ) & 0x0000FF;
-
- WS2812_CreatData(R,G,B);
- if(Pos < LED_NUMS && Pos >=0)
- {
- memcpy(buffer + RGB_BIT * Pos, RGB_BIT_Buffer,RGB_BIT);
- }
- else
- {
- WS2812_TurnOff();
- }
- }
-
-
-
- void WS2812_Show_Wheel()
- {
- static uint16_t i=0;
- i++;
- WS2812_Color_Pos(0xFF0000,(i)%16);
- WS2812_Color_Pos(0XFF7F00,(i+1)%16);
- WS2812_Color_Pos(0XFFFF00,(i+2)%16);
- WS2812_Color_Pos(0X7FFF00,(i+3)%16);
- WS2812_Color_Pos(0X00FF00,(i+4)%16);
- WS2812_Color_Pos(0X00FF7F,(i+5)%16);
- WS2812_Color_Pos(0X00FFFF,(i+6)%16);
- WS2812_Color_Pos(0X007FFF,(i+7)%16);
- WS2812_Color_Pos(0X0000FF,(i+8)%16);
- WS2812_Color_Pos(0X7F00FF,(i+9)%16);
- WS2812_Color_Pos(0XFF00FF,(i+10)%16);
- WS2812_Color_Pos(0XFF007F,(i+11)%16);
- WS2812_Color_Pos(0XFF0000,(i+12)%16);
- WS2812_Color_Pos(0XFF7F00,(i+13)%16);
- WS2812_Color_Pos(0XFFFF00,(i+14)%16);
- WS2812_Color_Pos(0X7FFF00,(i+15)%16);
- WS2812_Update();
- }
-
- #ifndef WS2812_H
- #define WS2812_H
-
- #include "string.h"
- #include "main.h"
- #include "spi.h"
-
- #define WS2812_0 0xC0
- #define WS2812_1 0xF0
- #define WS2812_RST 0x00
- #define LED_NUMS 16
- #define RGB_BIT 24
-
- typedef struct
- {
- uint8_t R;
- uint8_t G;
- uint8_t B;
- }LEDType;
-
-
- /**
- turn off all leds
- */
- void WS2812_TurnOff();
- void WS2812_Show_Wheel();
- void WS2812_Update();
- #endif
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。