- void BOARD_InitPins(void)
- {
- GPIO_Init_Type gpio_init;
- /* PA3 - UART2_RX. */
- gpio_init.Pins = GPIO_PIN_3;
- gpio_init.PinMode = GPIO_PinMode_In_Floating;
- gpio_init.Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOA, &gpio_init);
- GPIO_PinAFConf(GPIOA, gpio_init.Pins, GPIO_AF_1);
- /* PA2 - UART2_TX. */
- gpio_init.Pins = GPIO_PIN_2;
- gpio_init.PinMode = GPIO_PinMode_AF_PushPull;
- gpio_init.Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOA, &gpio_init);
- GPIO_PinAFConf(GPIOA, gpio_init.Pins, GPIO_AF_1);
- /* PB14 - SPI2_MISO. */
- gpio_init.Pins = GPIO_PIN_14;
- gpio_init.PinMode = GPIO_PinMode_In_Floating;
- gpio_init.Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOB, &gpio_init);
- GPIO_PinAFConf(GPIOB, gpio_init.Pins, GPIO_AF_0);
- /* PB15 - SPI2_MOSI. */
- gpio_init.Pins = GPIO_PIN_15;
- gpio_init.PinMode = GPIO_PinMode_AF_PushPull;
- gpio_init.Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOB, &gpio_init);
- GPIO_PinAFConf(GPIOB, gpio_init.Pins, GPIO_AF_0);
- }
2.SPI外设初始化
- void SPI_1Lines_HalfDuplex_Init(void)
- {
- /* Setup SPI module. */
- SPI_Master_Init_Type spi_init;
- spi_init.ClockFreqHz = BOARD_LOOP_SPI_FREQ;//24MHZ
- spi_init.BaudRate = BOARD_LOOP_SPI_BAUDRATE;//8MHZ
- spi_init.XferMode = SPI_XferMode_TxRx;
- spi_init.PolPha = SPI_PolPha_Alt3;
- spi_init.DataWidth = SPI_DataWidth_8b;
- spi_init.LSB = false;
- spi_init.AutoCS = true;
- SPI_InitMaster(BOARD_LOOP_SPI_PORT, &spi_init);
- /* Enable SPI. */
- SPI_Enable(BOARD_LOOP_SPI_PORT, true);
- }
这里我们将SPI 频率设置为8Mhz从下图可以看出每bit占用125ns 一个byte是8x125=1000ns
根据时序我们将
1110 0000 即0xE0 表示为WS2812的0
1111 1000 即0xF8 表示为WS2812的1
这里5个bit的1 实际是5*125=625 实际是不符合850ns的但是可以用。试过设置SPI频率的6mhz的话也就是每bit 166.666ns 但是所有数据都被识别为1,ws2812全部亮了。
3.时钟初始化
- void BOARD_InitBootClocks(void)
- {
- CLOCK_ResetToDefault();
- CLOCK_BootToHSE48MHz();
- /* UART2. */
- RCC_EnableAPB1Periphs(RCC_APB1_PERIPH_UART2, true);
- RCC_ResetAPB1Periphs(RCC_APB1_PERIPH_UART2);
- /* SPI2. */
- RCC_EnableAPB1Periphs(RCC_APB1_PERIPH_SPI2, true);
- RCC_ResetAPB1Periphs(RCC_APB1_PERIPH_SPI2);
- /* GPIOA. */
- RCC_EnableAHBPeriphs(RCC_AHB_PERIPH_GPIOA, true);
- RCC_ResetAPB1Periphs(RCC_AHB_PERIPH_GPIOA);
- /* GPIOB. */
- RCC_EnableAHBPeriphs(RCC_AHB_PERIPH_GPIOB, true);
- RCC_ResetAPB1Periphs(RCC_AHB_PERIPH_GPIOB);
- }
4.WS2812驱动代码WS2812.C
- /*
- * WS2812.C
- *
- * Created on: 2021年10月9日
- * Author: Administrator
- */
- #include "board_init.h"
- #include "WS2812.H"
- /*******************************************************************************
- * Function Name : SPI_1Lines_HalfDuplex_Init
- * Description : Configuring the SPI for half-duplex communication.
- * Input : None
- * Return : None
- *******************************************************************************/
- u32 ws2812_led[led_cout]; //灯珠数量 一个存储24位rgb颜色
- void SPI_1Lines_HalfDuplex_Init(void)
- {
- /* Setup SPI module. */
- SPI_Master_Init_Type spi_init;
- spi_init.ClockFreqHz = BOARD_LOOP_SPI_FREQ;//24MHZ
- spi_init.BaudRate = BOARD_LOOP_SPI_BAUDRATE;//8MHZ
- spi_init.XferMode = SPI_XferMode_TxRx;
- spi_init.PolPha = SPI_PolPha_Alt3;
- spi_init.DataWidth = SPI_DataWidth_8b;
- spi_init.LSB = false;
- spi_init.AutoCS = true;
- SPI_InitMaster(BOARD_LOOP_SPI_PORT, &spi_init);
- /* Enable SPI. */
- SPI_Enable(BOARD_LOOP_SPI_PORT, true);
- }
- void WS2812_SET0(void)
- {
- while ( SPI_STATUS_TX_FULL & SPI_GetStatus(BOARD_LOOP_SPI_PORT) )
- {}
- SPI_PutData(BOARD_LOOP_SPI_PORT, 0xE0);//1110 0000
- }
- void WS2812_SET1(void)
- {
- while ( SPI_STATUS_TX_FULL & SPI_GetStatus(BOARD_LOOP_SPI_PORT) )
- {}
- SPI_PutData(BOARD_LOOP_SPI_PORT, 0xF8);//1111 1000
- }
- void Ws2812_Rest(void)
- {
- u8 i = 60;
- while (i) //0.444*200=88.8us
- {
- while ( SPI_STATUS_TX_FULL & SPI_GetStatus(BOARD_LOOP_SPI_PORT) )
- {}
- SPI_PutData(BOARD_LOOP_SPI_PORT, 0x00);
- i--;
- }
- }
- void ws2812_rgb(u8 ws_num, u8 r, u8 g, u8 b)
- {
- u32 grb = 0;
- grb = g;
- grb <<= 8;
- grb |= r;
- grb <<= 8;
- grb |= b;
- ws2812_led[ws_num] = grb;
- //ws2812_rx(64);
- }
- //填充LED
- void ws2812_rgb_all(u8 ws_count, u8 r, u8 g, u8 b)
- {
- u8 i;
- u32 grb = 0;
- grb = g;
- grb <<= 8;
- grb |= r;
- grb <<= 8;
- grb |= b;
- for (i = 0; i < ws_count; i++)
- {
- ws2812_led[i] = grb;
- }
-
- }
- void ws2812_save(u8 ws_number, u8 r, u8 g, u8 b)
- {
- u32 grb = 0;
- grb = g;
- grb <<= 8;
- grb |= r;
- grb <<= 8;
- grb |= b;
- ws2812_led[(ws_number - 1)] = grb;
- }
- /****************将保存的数组RGB数据发送到所有LED*******/
- /******************************************************/
- void ws2812_rx(u8 led_count)
- {
- u8 a, i;
- for (a = 0; a < led_count; a++)
- {
- for (i = 0; i < 24; i++)
- {
- if ((ws2812_led[a] & 0x800000) == 0)
- WS2812_SET0();
- else
- WS2812_SET1();
- ws2812_led[a] <<= 1;
- }
- }
- Ws2812_Rest();
- }
- void ws2812_clear_all(u8 ws_count)
- {
- u8 i;
- u32 grb = 0;
- for (i = 0; i < ws_count; i++)
- {
- ws2812_led[i] = grb;
- }
- }
- /*
- * WS2812.H
- *
- * Created on: 2021年10月9日
- * Author: Administrator
- */
- #ifndef USER_WS2812_H_
- #define USER_WS2812_H_
- #include "board_init.h"
- #define led_cout 64
- #define WS_ARRAY_SIZE (led_cout*3)
- typedef unsigned char u8;
- typedef unsigned int u32;
- void SPI_1Lines_HalfDuplex_Init(void);
- void WS2812_SET0(void);
- void WS2812_SET1(void);
- void Ws2812_Rest(void);
- //设置第ws_num个灯珠的颜色rgb
- void ws2812_rgb(u8 ws_num, u8 ws_r, u8 ws_g, u8 ws_b);
- //设置前ws_count个灯珠颜色为rgb
- void ws2812_rgb_all(u8 ws_count, u8 ws_r, u8 ws_g, u8 ws_b);
- //将最新的ws_data[]数组中的值发送至WS2812B模块
- //void ws2812_refresh(u8 ws_count);
- //将rgb颜色值保存到第ws_number位数组内
- void ws2812_save(u8 ws_number, u8 r, u8 g, u8 b);
- //数组中的值发送至WS2812B模块
- void ws2812_rx(u8 led_count);
- //关闭所有LED
- void ws2812_clear_all(u8 ws_count);
- #endif /* USER_WS2812_H_ */
main函数- /*
- * Copyright 2021 MindMotion Microelectronics Co., Ltd.
- * All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
- #include "board_init.h"
- #include "WS2812.H"
- #define APP_SPI_BUF_LEN 16u /* SPI buffer for SPI tx. */
- #define BOARD_DELAY_COUNT 10000u
- void app_delay(uint32_t delay)
- {
- for (uint32_t i = 0u; i < delay; i++)
- {
- for (uint32_t j = 0u; j < BOARD_DELAY_COUNT; j++)
- {
- __NOP();
- }
- }
- }
- int main(void)
- {
- BOARD_Init();
- printf("spi_master_basic example.\r\n");
- /* Setup spi. */
- SPI_1Lines_HalfDuplex_Init();
- Ws2812_Rest();
- ws2812_rgb_all(8,1,0,0);
- ws2812_rx(8);
- while (1)
- {
- ws2812_rgb_all(8,3,0,0);//将8颗LED的R,G,B的值写入缓存
- ws2812_rx(8);//发送LED数据并显示
- app_delay(80);
-
- ws2812_rgb_all(8,2,1,0);//橙
- ws2812_rx(8);
- app_delay(80);
-
- ws2812_rgb_all(8,2,2,0);//黄
- ws2812_rx(8);
- app_delay(80);
-
- ws2812_rgb_all(8,0,3,0);//绿
- ws2812_rx(8);
- app_delay(80);
-
- ws2812_rgb_all(8,0,3,3);//青
- ws2812_rx(8);
- app_delay(80);
-
- ws2812_rgb_all(8,0,0,3);//绿
- ws2812_rx(8);
- app_delay(80);
-
- ws2812_rgb_all(8,3,0,3);//绿
- ws2812_rx(8);
- app_delay(80);
-
-
- ws2812_rgb(0,3,0,0);
- ws2812_rgb(1,3,2,0);
- ws2812_rgb(2,2,3,0);
- ws2812_rgb(3,0,3,0);
- ws2812_rgb(4,0,3,2);
- ws2812_rgb(5,0,0,3);
- ws2812_rgb(6,3,0,3);
- ws2812_rgb(7,3,0,0);
- ws2812_rx(8);
- app_delay(1000);
-
- //printf("spi_master_basic example.\r\n");
- }
- }
显示效果,忽略中间有一个坏掉了
spi_master_basic.zip
(305 KB, 下载次数: 8)