You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

STM32F407 SPI带CRC与DMA传输:如何检测CRC传输结束?

STM32F407 SPI CRC传输后NSS释放的解决方案

针对你遇到的CRC传输完成后无法触发NSS拉高的问题,核心是利用SPI内置的状态标志和中断机制精准判断CRC传输结束时机,以下是具体实现方法:

关键触发信号与判断逻辑

CRC传输完成的核心标志是SPI状态寄存器(SPI_SR)中的RXNE(接收缓冲区非空)位,结合CRCERR(CRC错误)位可同时完成校验结果判断。当DMA完成数据传输后启动CRC交互,待对方的CRC值被接收后,RXNE会自动置位,此时即可安全拉高NSS。

配置与执行流程

  1. 预配置SPI寄存器

    • 确保SPI_CR1.CRCEN位置1,开启CRC功能;
    • 开启SPI的RXNE中断(SPI_CR2.RXNEIE置1),确保CRC接收完成后能触发中断。
  2. DMA+SPI中断协同处理

    • DMA数据传输完成触发DMA中断:在中断函数中置位SPI_CR1.CRCNEXT,启动CRC传输,保持NSS低电平;
    • SPI中断响应RXNE事件:
      • 读取SPI_DR获取对方发送的CRC值;
      • 检查SPI_SR.CRCERR位判断校验是否通过;
      • 确认后操作GPIO拉高NSS;
      • 清除CRCERR标志(通过向SPI_SR对应位写入0)。

寄存器级代码示例

// DMA传输完成中断服务函数(以SPI1_TX_DMA为例)
void DMA2_Stream3_IRQHandler(void) {
    // 清除DMA传输完成标志
    DMA2->IFCR |= DMA_IFCR_CTCIF3;
    // 启动CRC传输
    SPI1->CR1 |= SPI_CR1_CRCNEXT;
}

// SPI1中断服务函数
void SPI1_IRQHandler(void) {
    if (SPI1->SR & SPI_SR_RXNE) {
        // 读取接收的CRC值
        uint16_t received_crc = SPI1->DR;
        
        // 处理CRC校验结果
        if (SPI1->SR & SPI_SR_CRCERR) {
            // CRC校验失败,执行错误处理
        } else {
            // CRC校验通过,拉高NSS引脚(假设NSS接PA4)
            GPIOA->BSRR = GPIO_BSRR_BS4;
        }
        
        // 清除CRC错误标志
        SPI1->SR &= ~SPI_SR_CRCERR;
    }
}

注意事项

  • 调整中断优先级:确保SPI中断优先级高于DMA中断,避免CRC传输启动后无法及时响应RXNE中断;
  • 从机端逻辑:若从机需参与NSS控制,需在自身TXE(CRC已发送)和RXNE(主机CRC已接收)均置位后再处理NSS;
  • 时序匹配:严格遵循RM0090中CRC传输的时序要求,NSS低电平需覆盖数据传输、CRC发送、CRC接收的全流程,直到RXNE置位后再释放。

内容的提问来源于stack exchange,提问作者user1771706

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 19:18:39