stm32f412 SPI dma接收和UART dma发送问题解决
Posted 实业创业者
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了stm32f412 SPI dma接收和UART dma发送问题解决相关的知识,希望对你有一定的参考价值。
在做STM32F412和RT1052的SPI通信和UART通信时,遇到了一些问题,主要还是对STM的HAL库不熟悉,在这里做个记录
使用STM32F412的SPI1作为从机通过DMA方式接收RT1052的数据,STM32的程序通过CubeMX生成的。STM32F412其他的几路SPI准备用来驱动WS2812,公司以产品需要,大家可以看看如下产品链接:
https://item.taobao.com/item.htm?ft=t&id=591591168912
在调试过程中出了2个问题:
1、如果接收出错后,就是丢了字节后,DMA就不能正常接收了。一直停留在SPI_WaitFlagStateUntilTimeout()这个函数出不来。然后把DMA的模式从正常改为了循环模式后就好了
hdma_spi1_rx.Init.Mode = DMA_CIRCULAR ;//模式:外设流控模式,循环模式,普通模式
2、我直接在
void DMA2_Stream0_IRQHandler(void)
/* USER CODE BEGIN DMA2_Stream0_IRQn 0 */
/* USER CODE END DMA2_Stream0_IRQn 0 */
HAL_DMA_IRQHandler(&hdma_spi1_rx);
/* USER CODE BEGIN DMA2_Stream0_IRQn 1 */
/* USER CODE END DMA2_Stream0_IRQn 1 */
这个函数里面去处理SPI接收的中断,发现每帧数据过来后会进两次中断,第一次数据并没有完全接收,一直找不出问题来。后来看了: HAL_DMA_IRQHandler(&hdma_spi1_rx);这个函数里面的内容,发现对应了2种接收的处理,一种是:
/* Half Transfer Complete Interrupt management ******************************/
if ((tmpisr & (DMA_FLAG_HTIF0_4 << hdma->StreamIndex)) != RESET)
相当于接收一半后的中断。还有一个是:
/* Transfer Complete Interrupt management ***********************************/
if ((tmpisr & (DMA_FLAG_TCIF0_4 << hdma->StreamIndex)) != RESET)
完全接收后的中断,我需要的是第二种。然后在看下面的处理,实际上是对应的有对应的回调函数的:
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
这个函数会在完全接收以后被调用,这样就不用自己还去判断是否接收完毕了,实际上CubMX生成的程序已经给处理好了,只是我自己之前比较熟悉直接在中断函数里面直接进行处理,没有用回调函数的方式,这样就需要自己去写对应的寄存器的处理和判断了。
我用的STM32F412的uart1进行DMA的发送和接收,发现在调用
HAL_UART_Transmit_DMA(&huart1,tBuf,11);
发送以后怎么就不能再发送了,查找后发现发送把串口状态切换到busy,但是切回Ready状态的操作需要我们自己动手;在HAL_DMA_Start_IT()
函数里面会将DMA加锁但是没有解锁,同时函数会开启DMA 半传输、完成传输、传输错误、FIFO溢出错误中断位;这样一来,就需要自己手动来处理这个事情了。
//UART1 TX中断
void DMA2_Stream7_IRQHandler(void)
/* USER CODE BEGIN DMA2_Stream7_IRQn 0 */
/* USER CODE END DMA2_Stream7_IRQn 0 */
HAL_DMA_IRQHandler(&hdma_usart1_tx);
/* USER CODE BEGIN DMA2_Stream7_IRQn 1 */
//解决DMA发送发送几次就不能在发送了
// 1.建议开启DMA传输完成中断
// 2.在完成中断函数里面将串口状态切换到Ready状况;
// 3.将DMA解锁
// 4.Clear相应中断标志位
huart1.gState = HAL_UART_STATE_READY;
hdma_usart1_tx.State = HAL_DMA_STATE_READY;
__HAL_DMA_CLEAR_FLAG(&hdma_usart1_tx, DMA_FLAG_TCIF3_7);
__HAL_DMA_CLEAR_FLAG(&hdma_usart1_tx, DMA_FLAG_HTIF3_7);
__HAL_DMA_CLEAR_FLAG(&hdma_usart1_tx, DMA_FLAG_FEIF3_7 );
__HAL_UNLOCK(&hdma_usart1_tx);
/* USER CODE END DMA2_Stream7_IRQn 1 */
然后就可以正常一直发送了。
以上是关于stm32f412 SPI dma接收和UART dma发送问题解决的主要内容,如果未能解决你的问题,请参考以下文章
STM32F4 HAL SPI_Receive dma 只接收一次
stm32f4 dma + uart idle + double 调试小记