(2025-4-10,zzl:本文基于STM32H7,其他型号,可能略有不同,但是核心原理应该是都成立的)
一、核心原理
1.不使用SPI的NSS,将NSS设置为EXTI输入
这一步是为了获得SPI完成信号。
STM32只有DMA收发全部完成后(达到收发设置的字节数),才会触发SPI完成中断,不定长数据没法使用这样的设置。
2.获得DMA收发数量
STM32的HAL库,是没有这个接口的,需要操作寄存器,从寄存器获取DMA已经传输的数据量。
二、代码实现
1.Cubemx设置
只需要启用DMA+EXIT即可,其他随便
2.EXIT中断(SPI完成数据处理,和开启新接收)
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
if(GPIO_Pin == ZZL_SPI_NSS_Pin)
{
if(HAL_GPIO_ReadPin(ZZL_SPI2_NSS_GPIO_Port, ZZL_SPI2_NSS_Pin) == GPIO_PIN_SET)
{
/* 先停止SPI-DMA */
HAL_SPI_DMAStop(&hspi2);
/* 计算接收到的长度 */
BDMA_Channel_TypeDef *bdma_rx = hspi2.hdmarx->Instance;
BDMA_Channel_TypeDef *bdma_tx = hspi2.hdmatx->Instance;
uint32_t len = BUFF_MAX- bdma_rx->CNDTR;
/* 处理数据和准备下一次发送的数据 */
// ... = buffer_rx,len
// buffer_tx = ...
/* 重新设置DMA */
bdma_rx->CM0AR = (uint32_t)buffer_rx;
bdma_rx->CNDTR = BUFF_MAX;
bdma_tx->CM0AR = (uint32_t)buffer_tx;
bdma_tx->CNDTR = BUFF_MAX;
/* 启动DMA */
HAL_SPI_TransmitReceive_DMA(&hspi2, buffer_tx, buffer_rx, BUFF_MAX);
}
}//if(GPIO_Pin == ZZL_SPI_NSS_Pin)
}