打印

GD32F303 SPI DMA 条件下如何配置8位的CRC

[复制链接]
5896|7
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
chuancqc|  楼主 | 2024-8-8 17:25 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
如题 GD32F303 SPI DMA 条件下如何配置8位的CRC,我的配置如下
void Spi1_init()
{
    spi_parameter_struct spi_init_struct;

        /* deinitilize SPI and the parameters */
    spi_i2s_deinit(SPI1);
        spi_struct_para_init(&spi_init_struct);
       
    rcu_periph_clock_enable(RCU_GPIOB);
    rcu_periph_clock_enable(RCU_SPI1);
    rcu_periph_clock_enable(RCU_AF);
        /* configure SPI1 GPIO: NSS/PB12, SCK/PB13, MISO/PB14, MOSI/PB15 */
    gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_13 | GPIO_PIN_15);    /* SPI1 GPIO config: SCK/PB13, MOSI/PB15 */
    gpio_init(GPIOB, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_MAX, GPIO_PIN_14);            /* SPI1 GPIO config: MISO/PB14 */
    gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_MAX, GPIO_PIN_12);                 /* PB12 as CS */
       
        SPI1_CS_H;
       
    spi_init_struct.trans_mode              = SPI_TRANSMODE_FULLDUPLEX;
    spi_init_struct.device_mode             = SPI_MASTER;
    spi_init_struct.frame_size              = SPI_FRAMESIZE_8BIT;
    spi_init_struct.clock_polarity_phase    = SPI_CK_PL_LOW_PH_1EDGE;// SPI 接口逻辑在时钟极性 (CPOL) = 0 和时钟相位 (CPHA) = 0 的情况下运行
    spi_init_struct.nss                     = SPI_NSS_SOFT; //注意 SPI_NSS_HARD是指外部的CS 也就是说对从机有效 主机应该使用SPI_NSS_SOFT
    spi_init_struct.prescale                = SPI_PSC_32;
    spi_init_struct.endian                  = SPI_ENDIAN_MSB;//大端
    spi_init(SPI1,&spi_init_struct);
       

    /* set crc polynomial */
    spi_crc_polynomial_set(SPI1,7);
    spi_crc_on(SPI1);
       
    /* enable SPI1 */
    spi_enable(SPI1);
}


我使用了,可是实际上示波器没有监测到下发的正常校验结果
spi_crc_polynomial_set(SPI1,7);
spi_crc_on(SPI1);


发送数据填充
{
        Afex->Spi_Txbuf[0] = Afex->Aevaddr;
        Afex->Spi_Txbuf[1] = 0xFF;
        //Afex->Spi_Txbuf[2] = CRC8(Afex->Spi_Txbuf, 2);
        AFE1_CS_L;
        SPI1_TransmitReceiveDma(Afex->Spi_Txbuf, Afex->Afe_Rxbuf, 2);
        AFE1_CS_H;
}



//DMA数据填充和发送使能等这里用了个信号量阻塞
uint8_t SPI1_TransmitReceiveDma(const uint8_t * data_tx, uint8_t * data_rx,const uint8_t length)
{
    uint8_t result = 0;
        taskENTER_CRITICAL();
       
        dma_memory_address_config(DMA0,DMA_CH4,(uint32_t)data_tx);
        dma_transfer_number_config(DMA0,DMA_CH4,length);
       
        dma_memory_address_config(DMA0,DMA_CH3,(uint32_t)data_rx);
        dma_transfer_number_config(DMA0,DMA_CH3,length+1);


        spi_enable(SPI1);
       
    dma_channel_enable(DMA0, DMA_CH4);
    dma_channel_enable(DMA0, DMA_CH3);     /* 使能 DMA 数据流 */

    spi_dma_enable(SPI1, SPI_DMA_TRANSMIT);
    spi_dma_enable(SPI1, SPI_DMA_RECEIVE); /* 使能 SPI DMA 请求 */
       
        taskEXIT_CRITICAL();
        result = (xSemaphoreTake(spi1_txComplete, 50) == pdTRUE) &&
          (xSemaphoreTake(spi1_rxComplete, 50) == pdTRUE); /* 等待传输完成 */

        taskENTER_CRITICAL();
        spi_disable(SPI1);
        taskEXIT_CRITICAL();
       
        return result;
}

//中断监测函数监测到发送或接收完毕后释放信号量接触发送现场阻塞

void  spi1TxDmaIsr(void)
{
        if(dma_interrupt_flag_get(DMA0,DMA_CH4,DMA_INT_FLAG_FTF)){
                dma_interrupt_flag_clear(DMA0, DMA_CH4, DMA_INT_FLAG_G);            /* 清除中断标志位 */
                portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;

//                dma_interrupt_disable(DMA0, DMA_CH4, DMA_INT_FTF);
                dma_flag_clear(DMA0, DMA_CH4, DMA_FLAG_FTF);                        /*停止并清除 DMA 数据流 */
                spi_dma_disable(SPI1, SPI_DMA_TRANSMIT);                            /* 关闭 SPI DMA 请求 */
                dma_channel_disable(DMA0, DMA_CH4);                                 /* 关闭数据流 */
               
                xSemaphoreGiveFromISR(spi1_txComplete, &xHigherPriorityTaskWoken);  /* 释放信号量 */
                portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
        }
}

void spi1RxDmaIsr(void)
{
        if(dma_interrupt_flag_get(DMA0,DMA_CH3,DMA_INT_FLAG_FTF)){
                dma_interrupt_flag_clear(DMA0, DMA_CH3, DMA_INT_FLAG_G);            /* 清除中断标志位 */
               
                portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;

//                dma_interrupt_disable(DMA0, DMA_CH3, DMA_INT_FTF);
                dma_flag_clear(DMA0, DMA_CH3, DMA_FLAG_FTF);                        /* 停止并清除 DMA 数据流 */
                spi_dma_disable(SPI1, SPI_DMA_RECEIVE);                             /* 关闭 SPI DMA 请求 */
                dma_channel_disable(DMA0, DMA_CH3);                                 /* 关闭数据流 */

                xSemaphoreGiveFromISR(spi1_rxComplete, &xHigherPriorityTaskWoken);  /* 释放信号量 */
                portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
        }
}
以上是SPI 驱动收发相关的配置,实际上并没有发出正确的校验值。
认为硬件crc会自动填充一位8bit数据到末尾的缓存区,官方文档对此说明很少。


使用特权

评论回复
沙发
两只袜子| | 2024-8-9 19:37 | 只看该作者
在GD32F303系列单片机中配置SPI DMA以及8位的CRC校验,需要分别进行SPI DMA的配置和CRC校验的配置。

使用特权

评论回复
板凳
tpgf| | 2024-8-10 14:10 | 只看该作者
需要正确设置SPI和DMA的相关参数,并启用硬件CRC计算功能。

使用特权

评论回复
地板
wowu| | 2024-8-18 07:18 | 只看该作者
通过spi_parameter_struct结构体,将SPI设置为“主模式”

使用特权

评论回复
5
wakayi| | 2024-8-18 11:13 | 只看该作者
将SPI的SCK、MOSI、MISO引脚配置为复用推挽输出,并将NSS引脚配置为推挽输出

使用特权

评论回复
6
xiaoqizi| | 2024-8-18 16:16 | 只看该作者
GD32支持32位CRC计算,但对于8位CRC,可能需要自定义实现或采用特定于应用的方法

使用特权

评论回复
7
木木guainv| | 2024-8-18 20:15 | 只看该作者
在内存中设置一个缓冲区用于存放待发送的数据,并初始化DMA传输所需的相关参数

使用特权

评论回复
8
磨砂| | 2024-8-18 21:03 | 只看该作者
通过DMA将缓冲区中的数据发送到SPI的数据传输寄存器中,实现自动传输

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

16

帖子

1

粉丝