> 技术文档 > STM32-十二行代码,实现DMA+SPI从机+不定长,接收数据_stm32h7 spi dma

STM32-十二行代码,实现DMA+SPI从机+不定长,接收数据_stm32h7 spi dma


(2025-4-10,zzl:本文基于STM32H7,其他型号,可能略有不同,但是核心原理应该是都成立的)

 

一、核心原理

1.不使用SPI的NSS,将NSS设置为EXTI输入

这一步是为了获得SPI完成信号。

STM32只有DMA收发全部完成后(达到收发设置的字节数),才会触发SPI完成中断,不定长数据没法使用这样的设置。

2.获得DMA收发数量

STM32的HAL库,是没有这个接口的,需要操作寄存器,从寄存器获取DMA已经传输的数据量。

 

二、代码实现

1.Cubemx设置

只需要启用DMA+EXIT即可,其他随便

STM32-十二行代码,实现DMA+SPI从机+不定长,接收数据_stm32h7 spi dma

STM32-十二行代码,实现DMA+SPI从机+不定长,接收数据_stm32h7 spi dma

 

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)}