[AT32F403/403A] 看了该芯片的例程,串口的DMA如何使用??

[复制链接]
2699|13
 楼主| chenyuanjiyi 发表于 2021-5-5 19:38 | 显示全部楼层 |阅读模式
在AT32F403A的例程中,找到了USART文件下,关于DMA的有两个,在DMA_interrupt这个例程中,只有初始化的时候有一些DMA的操作,然后中断都是收到数据中断也没见有接着操作DMA的相关操作,在DMA_Polling例程中,我理解的意思是在
  1. /* Wait until USART3 RX DMA1 Channel Transfer Complete */
  2.   while (DMA_GetFlagStatus(DMA1_FLAG_TC3) == RESET)
  3.   {
  4.   }

  5.   /* Check the received data with the send ones */
  6.   TransferStatus1 = Buffercmp(TxBuffer2, RxBuffer1, TxBufferSize2);
初始化后就收到数据,然后放到RxBuffer1中,然后再判断收到的数据和TxBuffer2中的数据是否一样,我仿照例程使用串口1来收数据,但是我调试的时候,while是通过去了,加断点,查看RxBuffer1,这里根本就没有数据,希望大佬指点指点! 谢谢!


mark一江水 发表于 2021-5-6 10:02 来自手机 | 显示全部楼层
while能过,感觉串口是通了的,buffer没数据,你看一下dma配置的源地址和目的地址是否正确。
 楼主| chenyuanjiyi 发表于 2021-5-6 10:43 | 显示全部楼层
mark一江水 发表于 2021-5-6 10:02
while能过,感觉串口是通了的,buffer没数据,你看一下dma配置的源地址和目的地址是否正确。 ...

地址如图片,基本是仿照DMA_polling例程,就改了串口1,我用CH340和上位机连,通过了那个接收的while,但是rxbuff里面是没有数据的....
1.png
mark一江水 发表于 2021-5-6 11:13 来自手机 | 显示全部楼层
chenyuanjiyi 发表于 2021-5-6 10:43
地址如图片,基本是仿照DMA_polling例程,就改了串口1,我用CH340和上位机连,通过了那个接收的while,但 ...

串口1的基地址不对哦
 楼主| chenyuanjiyi 发表于 2021-5-6 17:02 | 显示全部楼层
本帖最后由 chenyuanjiyi 于 2021-5-6 17:17 编辑
mark一江水 发表于 2021-5-6 11:13
串口1的基地址不对哦

现在将基地址改成这个了(uint32_t)&USART1->DT,他这个基地址的在文档上也没看到具体对应什么地址啊?
另外我这样写的时候
TxBuffer1[] = "USART DMA Polling: USART2 -> USART3 using DMA\r\n";//这是我定义的数组
然后我想实现串口收到什么数据,发送什么数据,结果收到的 a123456789
串口发送的数据为 USART DMA Polling: Ua123456789
  1. if(done_flag)//收到数据
  2.   {
  3.     USART_SendBuff_DMA(USART1,DMA1_Channel4,RxBuffer1,RX_len);
  4.     memset(RxBuffer1,0,sizeof(RxBuffer1));
  5.     done_flag=0;

  6.   }
这是刚开始出现 USART DMA Polling: Ua123456789 这个现象的代码,然后修改后

  1.   if(done_flag)//收到数据
  2.   {
  3. <b><font color="#ff0000">    memset(TxBuffer1,0,sizeof(TxBuffer1));//清空TXbuff</font></b>
  4.     USART_SendBuff_DMA(USART1,DMA1_Channel4,RxBuffer1,RX_len);
  5.     memset(RxBuffer1,0,sizeof(RxBuffer1));
  6.     done_flag=0;

  7.   }
清空下就可以实现收到什么数据,发送什么数据 a123456789
mark一江水 发表于 2021-5-6 17:24 来自手机 | 显示全部楼层
chenyuanjiyi 发表于 2021-5-6 17:02
现在将基地址改成这个了(uint32_t)&USART1->DT,他这个基地址的在文档上也没看到具体对应什么地址啊?
另 ...

基地址在文档第一章就有。你后面是说接收前有丢数据吗,要先使能接收dma再使能发送才行。
 楼主| chenyuanjiyi 发表于 2021-5-6 17:59 | 显示全部楼层
本帖最后由 chenyuanjiyi 于 2021-5-6 18:05 编辑
mark一江水 发表于 2021-5-6 17:24
基地址在文档第一章就有。你后面是说接收前有丢数据吗,要先使能接收dma再使能发送才行。 ...

发现那个问题根本原因了,我封装的那个USART_SendBuff_DMA函数中,将收到的数据给了USART->DT,然后又开启DMA的通道发送了。
现在改成这样了
  1. void USART_SendBuff_DMA(USART_Type* USARTx,DMA_Channel_Type* DMA_CHx, uint8_t *buff, uint32_t size)
  2. {
  3.   <font color="#ff0000"><b>memcpy(TxBuffer1,buff,size);</b></font>
  4.   DMA_ChannelEnable(DMA_CHx,DISABLE);  //关闭USARTx TX DMA1 所指示的通道  
  5.   DMA_SetCurrDataCounter(DMA_CHx,size);//DMA通道的DMA缓存的大小
  6.          DMA_ChannelEnable(DMA_CHx, ENABLE);  //使能USARTx TX DMA1 所指示的通道
  7.   
  8.   USART_DMACmd(USARTx,USART_DMAReq_Tx,ENABLE);//使能串口的DMA发送
  9.   while(1)
  10.   {
  11.     if( DMA_GetFlagStatus(DMA1_FLAG_TC4) != RESET)//传输完成
  12.     {
  13.       DMA_ClearFlag(DMA1_FLAG_TC4);//清除通道4传输完成标志
  14.       DMA_ChannelEnable(DMA1_Channel4, DISABLE);//传输完,要关闭DMA的通道
  15.        break;
  16.     }
  17.   }
  18. }
admvip 发表于 2021-5-7 06:11 | 显示全部楼层
感觉使用DMA还在死等传输完成,就失去了DMA的意义了。还是放在DMA完成中断里处理比较好。
 楼主| chenyuanjiyi 发表于 2021-5-7 09:12 | 显示全部楼层
admvip 发表于 2021-5-7 06:11
感觉使用DMA还在死等传输完成,就失去了DMA的意义了。还是放在DMA完成中断里处理比较好。 ...

那个等待是参考正点原子DMA标准库的实验例程写的,找到一个你说的关于DMA发送完成中断的介绍,到时去试试:https://blog.csdn.net/u010001130/article/details/77816020
单片小菜 发表于 2021-5-7 22:41 | 显示全部楼层
感谢楼主的分享,不错的东东。
嵌入小菜菜 发表于 2021-5-7 23:37 | 显示全部楼层
二楼正解,不错的帖子。
admvip 发表于 2021-5-10 11:05 | 显示全部楼层
提供一个已经实际使用的DMA串口空闲驱动代码
串口及DMA初始化代码就不提供了,自行调通。
接收DMA设置为单次,不要用循环模式。

这个是串口空闲中断接收的回调函数
  1. /*************************************
  2. *函数名称:UART_DMARx_IDLECallback
  3. *函数说明:串口DMA空闲中断数据处理函数
  4. *入口参数:无
  5. *
  6. *返回参数:无
  7. *************************************/

  8. void UART_DMARx_IDLECallback(void)
  9. {
  10.         #if RX_Enable
  11.         //串口DMA空闲中断数据处理
  12.         uint32_t temp;

  13.         DMA_ChannelEnable(DMA1_Channel4, DISABLE);                        //DMA通道禁止
  14.         temp = DMA_GetCurrDataCounter(DMA1_Channel4);                //获取DMA剩余字节数
  15.         Rxbuffer_index = RX_Buffer_Size - temp;                                        //计算接收到的数据数量
  16.         USART_Rx_OK = 1;                                                                                                                                //接收完成标志置位

  17.         #endif
  18. }


在串口中断里的调用
  1. void USART1_IRQHandler(void)
  2. {
  3.         uint8_t clearTag;
  4.         if(USART_GetITStatus(USART1, USART_INT_IDLEF) != RESET)
  5.         {
  6. //                USART_ClearITPendingBit(USART1, USART_INT_IDLEF);                //清除中断标志位
  7.                 clearTag += USART1->DT;                                                                //读一次数据寄存器,作用是清除中断标志位
  8.                 UART_DMARx_IDLECallback();                                                //串口DMA空闲中断回调函数
  9.         }
  10. }



接收到的数据在用户程序里进行处理,处理完毕记得调用串口DMA接收恢复函数,恢复DMA接收
代码如下:
  1. /*************************************
  2. *函数名称:UART_DMARx_IDLEResume
  3. *函数说明:串口DMA空闲中断数据处理完成
  4. *后的DMA状态恢复函数
  5. *入口参数:无
  6. *
  7. *返回参数:无
  8. *************************************/

  9. void UART_DMARx_IDLEResume(void)
  10. {
  11.         memset(Rxbuffer, 0, RX_Buffer_Size);                                                //清空接收缓冲区
  12.         Rxbuffer_index = 0;                        //接收缓冲区索引清零
  13.         USART_Rx_OK = 0;                                //接收完成标志清零
  14.         DMA_ChannelEnable(DMA1_Channel4, DISABLE);                        //DMA通道禁止
  15.         DMA_SetCurrDataCounter(DMA1_Channel4, RX_Buffer_Size);        //重新设置DMA数据计数器参数
  16.         DMA_ChannelEnable(DMA1_Channel4, ENABLE);                                //DMA通道使能,开始空闲中断DMA传输
  17. }


就这么多代码,就可以实现串口DMA空闲中断的数据接收,比较适合一帧一帧的数据传输。





zhangtiegang 发表于 2022-2-17 16:40 | 显示全部楼层
chenyuanjiyi 发表于 2021-5-6 17:59
发现那个问题根本原因了,我封装的那个USART_SendBuff_DMA函数中,将收到的数据给了USART->DT,然后又开启 ...

您好,可以请教您一下关于雅特力MCU的问题吗
您需要登录后才可以回帖 登录 | 注册

本版积分规则

16

主题

134

帖子

3

粉丝
快速回复 在线客服 返回列表 返回顶部