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 */
}

然后就可以正常一直发送了。

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STM32F205是意法半导体(STMicroelectronics)推出的一款高性能32位ARM Cortex-M3处理器系列单片机。 串口是一种常用的通信方式,用于实现数据在两个设备之间的传输。STM32F205通过提供多个串口接口,方便用户进行通信。DMA(Direct Memory Access)是一种直接内存访问技术,可以在不占用CPU资源的情况下实现数据的高效传输。 STM32F205提供了多个串口接口,包括USART、UARTSPI等通信接口,用户可以根据实际需求选择合适的接口进行数据通信。对于串口的数据传输,STM32F205支持使用DMA进行数据的发送接收。 在使用DMA进行串口发送时,用户可以通过设置相应的寄存器来配置DMA传输的参数,如源地址、目的地址和数据长度等。然后,可以使用HAL库提供的函数来启动DMA传输,如HAL_UART_Transmit_DMA()函数。通过启动DMA传输,数据将从内存中的源地址传输到串口的数据寄存器中,然后通过串口发送出去。在传输完成后,可以通过检查相应的中断标志位来判断传输是否成功。 在使用DMA进行串口接收时,用户可以通过设置相应的寄存器来配置DMA传输的参数,如源地址、目的地址和数据长度等。然后,可以使用HAL库提供的函数来启动DMA传输,如HAL_UART_Receive_DMA()函数。通过启动DMA传输,数据将从串口的数据寄存器中传输到内存中的目的地址中,然后可以通过检查相应的中断标志位来判断接收是否成功。 总结而言,STM32F205可以通过配置寄存器和使用DMA来实现串口的高效发送接收。使用DMA可以减轻CPU的负担,提高数据传输的效率,为用户提供更好的开发性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值