<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>
if(SET==DMA_GetITStatus(DMA1_IT_TC7))</p><br><p>
{</p><br><p>
DMA_ClearITPendingBit(DMA1_IT_TC7);</p><br><p>
DMA_Cmd(DMA_USART2_TX, DISABLE);</p><br><p>
DMA_USART2_TX->CNDTR = 0;</p><br><p>
while(RESET == USART_GetFlagStatus(USART2,USART_FLAG_TC))</p><br><p>
{</p><br><p>
USART_ClearFlag(USART2,USART_FLAG_TC);</p><br><p>
}</p><br><p>
Usart2_TR_Sw(RS485_RX);</p><br><p>
return ;</p><br><p>
}</p><br><p>
}</p>
<br>
<p><img src="https://image.xiaopingtou.net/data/attach/191214/zbahRxQ9.png" alt="135857g95xy0xgxfpkfxmm"><br></p><p><br></p>
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
首先,对你的问题我有个疑问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中断,中断中从队列获取数据再次启动发送。
一周热门 更多>