chen 发表于 2023-12-10 19:17:45

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    //灯珠数量

chen 发表于 2023-12-10 19:39:04

代码乱码了,我再发一下后面的
#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刷新显示

神农鼎 发表于 2023-12-10 19:42:33

驱动 WS2812B?

//硬件SPI模拟WS2811时序(用SPI的8位数据模拟WS281x的一位数据)
//_____
// |      |____|   11110000high level
//__
// |   |_______|   11000000low level

chen 发表于 2023-12-10 19:50:57

神农鼎 发表于 2023-12-10 19:42
驱动 WS2812B?

是的

社区闲人 发表于 2023-12-11 07:57:08

该方案可行。就是把两个字节的空闲位做为高电平处理。一个字节只传输一个bit.

suncat0504 发表于 2023-12-15 23:17:03

谢谢分享处理代码。

lzl1okOK 发表于 2023-12-18 09:35:01

还没用过库开发,看版主的程序有点像STM32的的HAL库!

HJJDSTC 发表于 2023-12-18 17:22:06

有完完整的代码吗?

chen 发表于 2023-12-20 20:25:29

HJJDSTC 发表于 2023-12-18 17:22
有完完整的代码吗?

这代码算是比较完整的了,整个工程这里不方便发出来

HJJDSTC 发表于 2023-12-22 09:16:12

chen 发表于 2023-12-20 20:25
这代码算是比较完整的了,整个工程这里不方便发出来

感谢分享
页: [1] 2
查看完整版本: SPI-DMA, 驱动全彩LED,无需反相,灯带数量只受xdata大小限制@STC32F12K54