搜索
bottom↓
回复: 16

stm32使用dma传输串口数据时,当dma中断发送完成

[复制链接]

出0入0汤圆

发表于 2019-3-18 12:25:53 来自手机 | 显示全部楼层 |阅读模式
stm32使用dma传输串口数据时,当dma中断发送完成时,是串口发送完成了,还是dma到串口完成了?谢谢

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入475汤圆

发表于 2019-3-18 12:34:32 来自手机 | 显示全部楼层
如果你是马不停蹄的又会接着发串口那么就有问题,如果你要做其他事情就无所谓了,反正等你再次发的时候串口本身也发完了。  实际上串口脉冲还没有发完,应该是后者。这个我在spi上面验证过的,供你参考

出0入0汤圆

 楼主| 发表于 2019-3-18 12:41:33 来自手机 | 显示全部楼层
我也是现在才发现有这个问题,就是还没有去验证是哪个,因为用485要转接收,才发现要2ms才能把数据正常发送出去,所以估计有这个问题。能不能再结合串口发送完成中断来确保发送完成了

出0入0汤圆

发表于 2019-3-18 13:01:31 | 显示全部楼层
DMA中断时,只表示需要传送的所有数据字节全部传送到串口的发送数据寄存器中了。
此时串口实际上还有2个字节并未发送完成,数据寄存器和移位寄存器中的2个字节还需要发送,并不能关闭串口发送。
同理,如果是485切换方向,必须要等到发送完成,也就是移位寄存器发送完成-TC标志置位。

出870入263汤圆

发表于 2019-3-18 13:01:35 | 显示全部楼层
jaky80000 发表于 2019-3-18 12:41
我也是现在才发现有这个问题,就是还没有去验证是哪个,因为用485要转接收,才发现要2ms才能把数据正常发送 ...

ST官方都有APPNOTE指导的(对于UART没有RS485功能的单片机型号而言):
1、启动DMA前,先关闭UART发送完成中断,并清除发送完成中断标志;
2、在DMA传输完成中断函数中,开启UART发送完成中断;
3、在UART发送完成中断函数中,切换RS485为接收态;

出0入0汤圆

 楼主| 发表于 2019-3-18 22:00:12 | 显示全部楼层
楼上的3位分析的透彻,谢谢你们的关键点指明,谢谢!

出5入4汤圆

发表于 2019-3-18 22:07:56 来自手机 | 显示全部楼层
lingdianhao 发表于 2019-3-18 13:01
DMA中断时,只表示需要传送的所有数据字节全部传送到串口的发送数据寄存器中了。
此时串口实际上还有2个字 ...

有个疑问请教,dma每次搬运一个字节到串口的寄存器,最后一次搬运完之后发生dma发送完成中断,这个时候串口应该只有1个字节没发完吧,为什么是2字节呢?

出0入475汤圆

发表于 2019-3-18 22:32:54 来自手机 | 显示全部楼层
tim4146 发表于 2019-3-18 22:07
有个疑问请教,dma每次搬运一个字节到串口的寄存器,最后一次搬运完之后发生dma发送完成中断,这个时候串 ...

我测试的是一个不止,两个不到。简单粗暴的就是直接上示波器什么都清楚了,中断时候找个io脚改变个电平与发送的信号对着看啥都明白了

出5入4汤圆

发表于 2019-3-18 23:06:13 | 显示全部楼层
1a2b3c 发表于 2019-3-18 22:32
我测试的是一个不止,两个不到。简单粗暴的就是直接上示波器什么都清楚了,中断时候找个io脚改变个电平与 ...

好的,学习了,我也只是想当然的以为是1字节,没测过
5L的办法确实不错,我们项目上之前用的都是延时的办法做的,强行做了个间隔时间之后再改变485芯片的收发状态

出0入31汤圆

发表于 2019-3-19 07:49:07 来自手机 | 显示全部楼层
用uart的tc中断

出0入0汤圆

发表于 2019-3-19 08:23:11 | 显示全部楼层
辅助TC完成中断

出0入0汤圆

发表于 2019-3-19 09:06:19 | 显示全部楼层
tim4146 发表于 2019-3-18 22:07
有个疑问请教,dma每次搬运一个字节到串口的寄存器,最后一次搬运完之后发生dma发送完成中断,这个时候串 ...

你看串口的硬件结构就明白了,TXE指的是发送缓冲器DR空,TC指的是SHIFT移位寄存器空。
DMA完成只是代表把最后一个字节送到DR寄存器里面了,此时SHIFT移位寄存器有1个字节正在开始发送,
DR寄存器里面有一个字节等待发送,所以就是2个字节未发送完成。

出0入0汤圆

发表于 2019-3-19 09:24:46 | 显示全部楼层
你搜一下DMA+空闲中断接收不定长数据完整例程里有发送的处理方式,或都可以看一下cubemx生成DMA发送函数处理,里面是官方处理机制,可以参考

出0入0汤圆

发表于 2019-3-19 10:05:01 | 显示全部楼层
DMA发送,是把数据倒到USART的DR中,
如果你是使能的DMA传送完成中断,那一定是只是送到串口中了
建议,在DMA中断完成后,可以判断下串口发送完成标志,然后再启动下一次发送

出0入0汤圆

 楼主| 发表于 2019-3-20 07:33:58 来自手机 | 显示全部楼层
armstrong 发表于 2019-3-18 13:01
ST官方都有APPNOTE指导的(对于UART没有RS485功能的单片机型号而言):
1、启动DMA前,先关闭UART发送完 ...

我在实际测试过程中有这个现象,初始化时并没有开启发送完成中断,在dma传输完成中断里开启发送完成中断,在串口发送完成中断由发送转接收,然后清除发送完成标志(SR &= 0XFFBF),然后关闭发送完成中断。这个流程会发现发送出去的字节数会比设定的少两个字节。
分析,按理论上说在开启发送完成中断时,串口数据寄存器和移位寄存器中都还有数据,也就是在如果在串口发送完成中断里如果不关闭发送完成中断,会产生两次中断。但在实际测试过程中发现并没有产生两次中断,而且如果发送完成中断函数只添加发转收,却能正确传输所有数据,并且再下次发起dma传输时也并不会发送完一个字节产生一次发送完成中断,没搞太明白,请帮忙想想,谢谢。

出870入263汤圆

发表于 2019-3-20 08:20:38 | 显示全部楼层
jaky80000 发表于 2019-3-20 07:33
我在实际测试过程中有这个现象,初始化时并没有开启发送完成中断,在dma传输完成中断里开启发送完成中断 ...

正应了IT界那句名言,“Talk is cheap, show me the code!”,这是我用在STM32F1XX的串口发送代码,USART2用DMA1_Channel7通道发送,你看看:
  1. void Drv_Usart2TxStream(uint8_t const data[], uint32_t num)
  2. {
  3.   if(!data || !num){
  4.     return;
  5.   }

  6.   if(is_tx_busy){
  7.     return;
  8.   }

  9.   /* 设置发送忙标志,表示占用硬件 */
  10.   is_tx_busy = TRUE;
  11.   
  12.   /* 清除串口发送完成中断标志 */
  13.   USART_ITConfig(USART2, USART_IT_TC, DISABLE);
  14.   USART_ClearFlag(USART2, USART_FLAG_TC);

  15.   /* 启动DMA发送 */
  16.   DMA1->IFCR = DMA_IFCR_CGIF7;
  17.   DMA1_Channel7->CCR   = ((0<<12)|(0<<8)|DMA_CCR7_MINC|DMA_CCR7_DIR);
  18.   DMA1_Channel7->CCR  |= (DMA_CCR7_TCIE|DMA_CCR7_TEIE);
  19.   DMA1_Channel7->CPAR  = (uint32_t)&USART2->DR;
  20.   DMA1_Channel7->CMAR  = (uint32_t)data;
  21.   DMA1_Channel7->CNDTR = (uint16_t)num;
  22.   DMA1_Channel7->CCR  |= DMA_CCR7_EN;
  23. }

  24. void DMA1_Channel7_IRQHandler(void)
  25. {
  26.   uint32_t isr = DMA1->ISR;
  27.   DMA1->IFCR = DMA_IFCR_CGIF7;
  28.   if(isr & (DMA_ISR_TEIF7|DMA_ISR_TCIF7)){
  29.     DMA1_Channel7->CCR = 0;
  30.     USART_ITConfig(USART2, USART_IT_TC, ENABLE);
  31.   }
  32. }

  33. void USART2_IRQHandler(void)
  34. {
  35.   // 最后一字节发送完成中断
  36.   if((USART2->CR1 & USART_CR1_TCIE) && (USART2->SR & USART_SR_TC)){
  37.     USART_ITConfig(USART2, USART_IT_TC, DISABLE);
  38.     is_tx_busy = 0;
  39.     // 至此,最后一字节也发送完成了
  40.   }
  41. }
复制代码

代码中更新is_tx_busy变量的地方,对应某些应用种RS485切换方向的地方。

出0入0汤圆

 楼主| 发表于 2019-3-20 08:42:03 来自手机 | 显示全部楼层
armstrong 发表于 2019-3-20 08:20
正应了IT界那句名言,“Talk is cheap, show me the code!”,这是我用在STM32F1XX的串口发送代码,USART ...

代码确实是这样写的。请问下,你实际有没有用在485上啊。如果是在串口上这个代码完全没有问题。我现在测出来的现象是我上楼所说的所以才没有太明白。tc中断指发送完成后产生的,而不是dma发送完成后终中断后,这时串口的dr和移位寄存器中都还有数据,当移位寄存器发送完后按理就应该产生tc中断的(此中断并没有说dr中没有数据才产生的),所以是不是会产生两次tc中断(理论上)?
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-25 08:30

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表