打印
[AT32F403/403A]

看了该芯片的例程,串口的DMA如何使用??

[复制链接]
2115|13
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
在AT32F403A的例程中,找到了USART文件下,关于DMA的有两个,在DMA_interrupt这个例程中,只有初始化的时候有一些DMA的操作,然后中断都是收到数据中断也没见有接着操作DMA的相关操作,在DMA_Polling例程中,我理解的意思是在
/* Wait until USART3 RX DMA1 Channel Transfer Complete */
  while (DMA_GetFlagStatus(DMA1_FLAG_TC3) == RESET)
  {
  }

  /* Check the received data with the send ones */
  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 (177.17 KB )

1.png

使用特权

评论回复
地板
mark一江水| | 2021-5-6 11:13 | 只看该作者
chenyuanjiyi 发表于 2021-5-6 10:43
地址如图片,基本是仿照DMA_polling例程,就改了串口1,我用CH340和上位机连,通过了那个接收的while,但 ...

串口1的基地址不对哦

使用特权

评论回复
5
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
if(done_flag)//收到数据
  {
    USART_SendBuff_DMA(USART1,DMA1_Channel4,RxBuffer1,RX_len);
    memset(RxBuffer1,0,sizeof(RxBuffer1));
    done_flag=0;

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

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

  }
清空下就可以实现收到什么数据,发送什么数据 a123456789

使用特权

评论回复
6
mark一江水| | 2021-5-6 17:24 | 只看该作者
chenyuanjiyi 发表于 2021-5-6 17:02
现在将基地址改成这个了(uint32_t)&USART1->DT,他这个基地址的在文档上也没看到具体对应什么地址啊?
另 ...

基地址在文档第一章就有。你后面是说接收前有丢数据吗,要先使能接收dma再使能发送才行。

使用特权

评论回复
7
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的通道发送了。
现在改成这样了
void USART_SendBuff_DMA(USART_Type* USARTx,DMA_Channel_Type* DMA_CHx, uint8_t *buff, uint32_t size)
{
  <font color="#ff0000"><b>memcpy(TxBuffer1,buff,size);</b></font>
  DMA_ChannelEnable(DMA_CHx,DISABLE);  //关闭USARTx TX DMA1 所指示的通道  
  DMA_SetCurrDataCounter(DMA_CHx,size);//DMA通道的DMA缓存的大小
         DMA_ChannelEnable(DMA_CHx, ENABLE);  //使能USARTx TX DMA1 所指示的通道
  
  USART_DMACmd(USARTx,USART_DMAReq_Tx,ENABLE);//使能串口的DMA发送
  while(1)
  {
    if( DMA_GetFlagStatus(DMA1_FLAG_TC4) != RESET)//传输完成
    {
      DMA_ClearFlag(DMA1_FLAG_TC4);//清除通道4传输完成标志
      DMA_ChannelEnable(DMA1_Channel4, DISABLE);//传输完,要关闭DMA的通道
       break;
    }
  }
}

使用特权

评论回复
8
admvip| | 2021-5-7 06:11 | 只看该作者
感觉使用DMA还在死等传输完成,就失去了DMA的意义了。还是放在DMA完成中断里处理比较好。

使用特权

评论回复
9
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

使用特权

评论回复
10
单片小菜| | 2021-5-7 22:41 | 只看该作者
感谢楼主的分享,不错的东东。

使用特权

评论回复
11
嵌入小菜菜| | 2021-5-7 23:37 | 只看该作者
二楼正解,不错的帖子。

使用特权

评论回复
12
admvip| | 2021-5-10 11:05 | 只看该作者
提供一个已经实际使用的DMA串口空闲驱动代码
串口及DMA初始化代码就不提供了,自行调通。
接收DMA设置为单次,不要用循环模式。

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

void UART_DMARx_IDLECallback(void)
{
        #if RX_Enable
        //串口DMA空闲中断数据处理
        uint32_t temp;

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

        #endif
}


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



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

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


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





使用特权

评论回复
13
zhangtiegang| | 2022-2-17 16:40 | 只看该作者
chenyuanjiyi 发表于 2021-5-6 17:59
发现那个问题根本原因了,我封装的那个USART_SendBuff_DMA函数中,将收到的数据给了USART->DT,然后又开启 ...

您好,可以请教您一下关于雅特力MCU的问题吗

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

16

主题

134

帖子

3

粉丝