CH58xSPI0中断DMA

发布时间 2023-08-28 16:04:40作者: SweetTea_lllpc

前言:

本文针对不常使用的SPI方式使用提供参考,结合SPI中断/DMA/首字节命令模式。

流程:

  1. 主机发送数据时首字节配置为待发送数据的长度;
  2. 从机使能SPI中断;
  3. 在进入中断后配置DMA接收数据。

代码:

主机发送代码参考:

#if 1
    /* SPI 0 */
    GPIOA_SetBits(GPIO_Pin_12);
    GPIOA_ModeCfg(GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14, GPIO_ModeOut_PP_5mA);
    SPI0_MasterDefInit();

    tx_playload[0] = sizeof(string);
    for (i=0; i<sizeof(string); i++)
    {
        tx_playload[1+i] = string[i];
    }
    printf("sizeof(string):%d\n", sizeof(string));
    GPIOA_ResetBits(GPIO_Pin_12);
    SPI0_MasterTrans(tx_playload, (1+sizeof(string)));
    GPIOA_SetBits(GPIO_Pin_12);

    PRINT("END ...\n");
    while(1);
#endif

从机接收代码参考:

int main()
{
    SetSysClock(CLK_SOURCE_PLL_60MHz);

    /* 配置串口调试 */
    DebugInit();
    PRINT("Start @ChipID=%02X\n", R8_CHIP_ID);

    /* 设备模式 */
    PRINT("spi0 mul slave mode \n");
    GPIOA_ModeCfg(GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15, GPIO_ModeIN_PU);
    R8_SPI0_CLOCK_DIV = 4;                      //主频时钟4分频
    R8_SPI0_CTRL_MOD = RB_SPI_ALL_CLEAR;        //SPI 的 FIFO/计数器/中断标志清零
    R8_SPI0_CTRL_MOD = RB_SPI_MODE_SLAVE;       //SPI0从机模式
    R8_SPI0_CTRL_MOD |= RB_SPI_SLV_CMD_MOD;     //首字节命令模式
    R8_SPI0_CTRL_MOD |= RB_SPI_FIFO_DIR;        //输入模式,接收数据
    R8_SPI0_CTRL_MOD &= ~(RB_SPI_MOSI_OE | RB_SPI_SCK_OE);
    R8_SPI0_CTRL_MOD |= RB_SPI_MISO_OE ;

    R8_SPI0_INTER_EN |= RB_SPI_IE_FST_BYTE;
    PFIC_EnableIRQ(SPI0_IRQn);

    while(1);
}
__attribute__((interrupt("WCH-Interrupt-fast")))
__attribute__((section(".highcode")))
void SPI0_IRQHandler(void)
{
    uint8_t len = 0;
    if (R8_SPI0_INT_FLAG & RB_SPI_IF_FST_BYTE){ //已接收到首字节
        R8_SPI0_CTRL_CFG |= RB_SPI_AUTO_IF;
        R8_SPI0_INT_FLAG |= RB_SPI_IF_BYTE_END; //清除单字节传输完成标志位,
        len = R8_SPI0_FIFO;
        R16_SPI0_DMA_BEG = (UINT32)(rx_buff);
        R16_SPI0_DMA_END = (UINT32)((rx_buff)+len);
        R8_SPI0_INTER_EN |= RB_SPI_IE_DMA_END;
        R8_SPI0_CTRL_CFG |= RB_SPI_DMA_ENABLE;
        PRINT("Len:%d\n", len);
    }

    if(R8_SPI0_INT_FLAG & RB_SPI_IF_DMA_END)
    {
        R8_SPI0_INT_FLAG |= RB_SPI_IF_DMA_END;  //清除DMA完成标志位
        PRINT("SPI_Rec:%s\n", rx_buff);
        R16_SPI0_DMA_BEG = 10;                  //更改DMA地址,出中断
        R16_SPI0_DMA_END = 11;
        R8_SPI0_CTRL_CFG &= ~RB_SPI_DMA_ENABLE;
    }
    R8_SPI0_INT_FLAG |= 0xff;
//    PRINT("..................\n");
}