STM32C6T6,SPI+DMA驱动WSP2812B炫彩灯带
目录
硬件选型
芯片类型:STM32C6T6开发板、WS2812B类型灯带、5V电源
驱动方式
SPI+DMA传输
GPIO初始化
这里使用SPI1的单工通信,MOSI引脚为GPIOA_7
void ws2812_GPIO_Init(void){
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
SPI初始化
void ws2812_SPI_Init(void){
SPI_InitTypeDef SPI_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_Tx;//设置SPI单向或者双向的数据模式
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;//设置SPI工作模式:设置为主SPI
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;//设置SPI的数据大小:SPI发送接收8位帧结构,
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;//选择了串行时钟的稳态:时钟悬空低
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;//数据捕获于第二个时钟沿
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;//NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8; /* 48MHz / 8 = 6MHz 定义波特率预分频的值*/
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;//指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
SPI_InitStructure.SPI_CRCPolynomial = 7;//CRC值计算的多项式
SPI_Init(SPI1, &SPI_InitStructure);//根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器
SPI_Cmd(SPI1, ENABLE);//根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器
SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, ENABLE);//使能SPI,DMA功能
}
DMA初始化
void ws2812_DMA_Init(void){
DMA_InitTypeDef DMA_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
DMA_DeInit(DMA1_Channel3);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) &(SPI1 -> DR);//外设地址寄存器
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ws2812_data_buffer;//内存地址寄存器
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;//数据传输方向,从内存读取发送到外设
DMA_InitStructure.DMA_BufferSize = WS2812_LED_NUM * 24;//传输数据长度
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设地址寄存器不变
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//内存地址寄存器递增
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//数据宽度为8位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//数据宽度为8位
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;//工作在正常缓存模式
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel3, &DMA_InitStructure);
}
将颜色转换为0码和1码,储存到闪存中
#define WS2812_LED_NUM 144
uint8_t ws2812_data_buffer[WS2812_LED_NUM][24] ;
// 11111000 SIG_1 5/8 = 62.5%
// 11100000 SIG_0 3/8 = 37.5%
#define SIG_1 0XF8
#define SIG_0 0XC0
void ws2812_Set_one_LED_Color(uint16_t LED_index ,uint32_t GRB_color){
uint8_t i = 0;
uint32_t cnt = 0x800000;
if(LED_index < WS2812_LED_NUM){
for(i = 0; i < 24; ++i){
if(GRB_color & cnt){
ws2812_data_buffer[LED_index][i] = SIG_1;
}
else{
ws2812_data_buffer[LED_index][i] = SIG_0;
}
cnt >>= 1;
}
}
}
启动传输
void ws2812_Send_Data(void){
DMA_Cmd(DMA1_Channel3, DISABLE );
DMA_ClearFlag(DMA1_FLAG_TC3);
DMA_SetCurrDataCounter(DMA1_Channel3,24 * WS2812_LED_NUM );
DMA_Cmd(DMA1_Channel3, ENABLE);
}
关灯操作
void ws2812_AllShutOff(void){
uint16_t i;
uint8_t j;
for(i = 0; i < WS2812_LED_NUM; i++)
{
for(j = 0; j < 24; j++)
{
ws2812_data_buffer[i][j] = SIG_0;
}
}
ws2812_Send_Data();
}
按数量和颜色点灯函数
void ws2812_number_LED_one_Color_breath(uint16_t interval_number, uint32_t GRB_color)
{
uint8_t i = 0;
uint16_t j = 0;
rgb_color.G = GRB_color>>16;
rgb_color.R = GRB_color>>8;
rgb_color.B = GRB_color;
for(i=1;i<=100;i++)
{
for(j=0;j<interval_number;j++){
ws2812_Set_one_LED_Color(j, ((rgb_color.G<<16) | (rgb_color.R<<8) | (rgb_color.B)));
}
ws2812_Send_Data();
}
}
主函数
int main(void){
ws2812_GPIO_Init();
ws2812_SPI_Init();
ws2812_DMA_Init();
ws2812_AllShutOff();
while(1){
ws2812_number_LED_one_Color_breath(20,0xFF0000);
}
}