SPI-DMA, 驱动全彩LED,无需反相,灯带数量只受xdata大小限制@STC32F12K54
SPI-DMA, 驱动全彩LED,猜猜驱动的谁SPI-DMA@STC32F12K54驱动全彩LED,无需反相,灯带数量只受xdata大小限制
===STC32F12K54, 8K edata
===STC32F12K54, 4K xdata, xdata 可以做 DMA-SPI 的缓冲区
时钟:默认的52Mhz,基于库函数的初始化
初始化部分:spi
void SPI_config(void)
{
SPI_InitTypeDef SPI_InitStructure;
SPI_InitStructure.SPI_Enable = ENABLE; //SPI启动 ENABLE, DISABLE
SPI_InitStructure.SPI_SSIG = DISABLE; //片选位 ENABLE, DISABLE
SPI_InitStructure.SPI_FirstBit= SPI_MSB; //移位方向 SPI_MSB, SPI_LSB
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //主从选择 SPI_Mode_Master, SPI_Mode_Slave
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //时钟相位 SPI_CPOL_High, SPI_CPOL_Low
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //数据边沿 SPI_CPHA_1Edge,SPI_CPHA_2Edge
SPI_InitStructure.SPI_Speed = SPI_Speed_2; //SPI速度 SPI_Speed_4, SPI_Speed_8, SPI_Speed_16, SPI_Speed_2
SPI_Init(&SPI_InitStructure);
NVIC_SPI_Init(DISABLE,Priority_0); //中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
// HSPllClkConfig(MCLKSEL_HIRC,PLL_96M,4); //系统时钟选择,PLL时钟选择,时钟分频系数
HSSPI_Enable();
}
初始化部分:DMA
void DMA_config(void)
{
DMA_SPI_InitTypeDef DMA_SPI_InitStructure; //结构定义
//----------------------------------------------
DMA_SPI_InitStructure.DMA_Enable = DISABLE; //DMA使能 ENABLE,DISABLE
DMA_SPI_InitStructure.DMA_Tx_Enable = ENABLE; //DMA发送数据使能 ENABLE,DISABLE
DMA_SPI_InitStructure.DMA_Rx_Enable = ENABLE; //DMA接收数据使能 ENABLE,DISABLE
DMA_SPI_InitStructure.DMA_Length = BUF_LENGTH; //DMA传输总字节数 (0~65535) + 1
DMA_SPI_InitStructure.DMA_Tx_Buffer = (u16)SpiTxBuffer; //发送数据存储地址
DMA_SPI_InitStructure.DMA_Rx_Buffer = (u16)SpiRxBuffer; //接收数据存储地址
DMA_SPI_InitStructure.DMA_SS_Sel = SPI_SS_P35; //自动控制SS脚选择 SPI_SS_P12,SPI_SS_P22,SPI_SS_P74,SPI_SS_P35
DMA_SPI_InitStructure.DMA_AUTO_SS = DISABLE; //自动控制SS脚使能 ENABLE,DISABLE
DMA_SPI_Inilize(&DMA_SPI_InitStructure); //初始化
SET_DMA_SPI_CR(DMA_ENABLE| CLR_FIFO); //bit7 1:使能 SPI_DMA, bit5 1:开始 SPI_DMA 从机模式, bit0 1:清除 SPI_DMA FIFO
NVIC_DMA_SPI_Init(ENABLE,Priority_3,Priority_3); //中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0~Priority_3; 总线优先级(低到高) Priority_0~Priority_3
}
初始化部分:灯带
void init_led()
{
u16 i;
P2_SPEED_HIGH(GPIO_Pin_3);
P24=0;//MISO置0
P23=1;//MOSI
//SpiTxBuffer=0xf0;//f0 0
delay_ms(1);
P23=0;
SPI_config();
DMA_config();
SpiTxFlag=1;
delay_ms(1);
for(i=0;i<LED_COUNT;i++)
set_led(i,0x00,0x00,0x00);//这里必须先发送一次spi,要保证最后一字节的最后一bit为0,这里为了方便就直接调用了灯带函数
updata_led();
delay_ms(10);
}设置led缓存,更新led<blockquote>#define<span style="white-space:pre"> </span>LED_COUNT<span style="white-space:pre"> </span> 30 //灯珠数量
代码乱码了,我再发一下后面的
#define LED_COUNT 30//灯带数量
#define BUF_LENGTH LED_COUNT*24 //n+1
extern u8 xdata SpiTxBuffer;
extern u8 xdata SpiRxBuffer;
void set_led(u16 cnt,u8 red,u8 green,u8 blue)//cnt:第几个灯,red 红,green 绿,blue:蓝
{
u16 i;
if(cnt>=LED_COUNT) return;
for(i=cnt*24;i<cnt*24+8;i++)
{
if((green&0x80)==0x80)//1
SpiTxBuffer=0xfe;
else
SpiTxBuffer=0xe0;//0
green<<=1;
}
for(i=cnt*24+8;i<cnt*24+16;i++)
{
if((red&0x80)==0x80)//1
SpiTxBuffer=0xfe;
else
SpiTxBuffer=0xe0;//0
red<<=1;
}
for(i=cnt*24+16;i<cnt*24+24;i++)
{
if((blue&0x80)==0x80)//1
SpiTxBuffer=0xfe;
else
SpiTxBuffer=0xe0;//0
blue<<=1;
}
}
void updata_led()
{
if(SpiTxFlag==1)
{
SpiTxFlag=0;
SET_DMA_SPI_CR(DMA_ENABLE | SPI_TRIG_M);
//delay_ms(1);
}
}
使用方法:先调用set_led设置缓存,然后调用updata_led刷新显示 驱动 WS2812B?
//硬件SPI模拟WS2811时序(用SPI的8位数据模拟WS281x的一位数据)
//_____
// | |____| 11110000high level
//__
// | |_______| 11000000low level
神农鼎 发表于 2023-12-10 19:42
驱动 WS2812B?
是的 该方案可行。就是把两个字节的空闲位做为高电平处理。一个字节只传输一个bit. 谢谢分享处理代码。 还没用过库开发,看版主的程序有点像STM32的的HAL库! 有完完整的代码吗?
HJJDSTC 发表于 2023-12-18 17:22
有完完整的代码吗?
这代码算是比较完整的了,整个工程这里不方便发出来 chen 发表于 2023-12-20 20:25
这代码算是比较完整的了,整个工程这里不方便发出来
感谢分享
页:
[1]
2