STM32103 USART DMA发送完成判断方法分享

2019-12-14 13:33发布

<i class="pstatus"> 本帖最后由 shuen729 于 2018-4-28 11:57 编辑 </i><br> <br><p> 今天调代码的时候,遇到这个问题,USART在DMA模式下,进DMA发送完成中断后发现数据其实USART那边还没有真正的完成发送,论坛里面搜“DMA 发送完成”有一篇帖子,但是很遗憾不让看,要密码。</p><br><p> 然后不得已,看参考手册,找到下面的时序图</p><br> <p><img src="https://www.xiaopingtou.net/data/attach/1912/s7logd01cd1ixh2sli8xicabop2ykx9w.jpg" lazyloadthumb="1" border="0" alt=""></p><br><p> 然后在中断里面改了下,先把DMA禁止掉,然后等待TC置位,TC置位就可以确认所有数据已经送出。</p><br><p> void DMA1_Channel7_IRQHandler(void)</p><br><p> {</p><br><p> &nbsp; &nbsp; if(SET==DMA_GetITStatus(DMA1_IT_TC7))</p><br><p> &nbsp; &nbsp; {</p><br><p> &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;DMA_ClearITPendingBit(DMA1_IT_TC7);</p><br><p> &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;DMA_Cmd(DMA_USART2_TX, DISABLE);</p><br><p> &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;DMA_USART2_TX-&gt;CNDTR = 0;</p><br><p> &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;while(RESET == USART_GetFlagStatus(USART2,USART_FLAG_TC))</p><br><p> &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;{</p><br><p> &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;USART_ClearFlag(USART2,USART_FLAG_TC);</p><br><p> &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;}</p><br><p> &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;Usart2_TR_Sw(RS485_RX);</p><br><p> &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;return ;</p><br><p> &nbsp; &nbsp; }</p><br><p> }</p> <br> <p><img src="https://image.xiaopingtou.net/data/attach/191214/zbahRxQ9.png" alt="135857g95xy0xgxfpkfxmm"><br></p><p><br></p>
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
58条回答
stm32_bldc
1楼-- · 2019-12-19 02:41
 精彩回答 2  元偷偷看……
think_a_second
2楼-- · 2019-12-19 08:20
zchong 发表于 2018-5-2 20:28
开启TC中断,DMA传输完成(移位寄存器全部移出)前TC不会置位,当所有数据从串口的管脚移出后TC才会置位, ...

同意,其它接口的DMA发送,我也是这么操作的
梁皇山土匪
3楼-- · 2019-12-19 10:20
学习一下。。。
SCREA
4楼-- · 2019-12-19 12:03
本帖最后由 SCREA 于 2018-11-22 23:40 编辑

请教个问题,我的在DMA中断发送完成中 添加
  1. while ((USART2->SR & USART_SR_TC) == 0);
复制代码
不行,反倒是在DMA启动后添加这一句起作用,有没有人知道中断添加这句发送不起作用的原因?

PS:DMA中断添加这一局
  1. while ((uart_base->SR & USART_SR_TC) == 0);
复制代码CNDTR写一个字符还输出。若是CNDTR发送多个字符,则字符都不输出了,貌似DMA后续请求都失败了

==============
若是如我所说,每次启动发送DMA就等while ((uart_base->SR & USART_SR_TC) == 0); 那么这个发送DMA 意义在哪里?(CPU不干其他事,就等这个结束)
shuen729
5楼-- · 2019-12-19 17:32
SCREA 发表于 2018-11-22 23:07
请教个问题,我的在DMA中断发送完成中 添加

不行,反倒是在DMA启动后添加这一句起作用,有没有人知道中断 ...

首先,对你的问题我有个疑问USART2->SR和uart_base->SR到底是不是指向同一个地址?
第二,刚刚在f103上面测试,DMA中断中加入等待不影响DMA的后续发送,代码在下面:
/*usart1 TX DMA handle*/
void DMA1_Channel4_IRQHandler(void)
{
    if(RESET != DMA_GetITStatus(DMA1_IT_TC4))
    {
    while(0==(USART1->SR&USART_FLAG_TC));//**********这里加入等待(注意:实际工程中绝对不允许这么做)
    DMA_ClearITPendingBit(DMA1_IT_TC4);
    /*disable TC IT*/
    DMA_ITConfig(DMA1_Channel4,DMA_IT_TC,DISABLE);
    /*stop translation*/
    DMA_Cmd(DMA1_Channel4,DISABLE);
    }
}
第三,实际工程中绝对不允许在中断中做耗时的操作,更不要说等待外设
最后,你说的“DMA 意义在哪里”---------启动DMA之前肯定要看之前的操作是否已经完成,就跟写flash操作一样,write之后要等待操作完成。DMA的意义在于,假如你发1000个字节,那么你只需启动DMA就可以了,不需要你去往USART1->DR里面写入1000次数据,可以把节约的时间用来做别的操作。如果启动之前不检查上次的发送是否完成,而此时直接停掉DMA修改参数再次启动,那么前面发出去的数据就是不完整的,而我们不希望发生这种情况。
*************************************************************************
如果不希望等待,那么建议你这么做:
1.创建一个环形队列,
2.需要往串口打印数据的时候先写入队列里面,
3.真正发送的流程从队列获取数据启动DMA从USART发出去,
4.软件流程是这样:我要往串口打印数据---》先写入环形队列---》检查DMA是否正在用USART往外发送---》如果是则return。
                                                                                                                                  |
                                                                                                                                  /
                                                                                                                                 如果不是,则启动一次发送---》发送完成后进入USART的TC中断,中断中从队列获取数据再次启动发送。

SCREA
6楼-- · 2019-12-19 22:48
 精彩回答 2  元偷偷看……

一周热门 更多>