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

2019-12-12 18:17发布

stm32使用dma传输串口数据时,当dma中断发送完成时,是串口发送完成了,还是dma到串口完成了?谢谢
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
16条回答
go2deathward
1楼-- · 2019-12-14 12:51
DMA发送,是把数据倒到USART的DR中,
如果你是使能的DMA传送完成中断,那一定是只是送到串口中了
建议,在DMA中断完成后,可以判断下串口发送完成标志,然后再启动下一次发送
jaky80000
2楼-- · 2019-12-14 15:03
love_ourdev 发表于 2019-3-18 13:01
ST官方都有APPNOTE指导的(对于UART没有RS485功能的单片机型号而言):
1、启动DMA前,先关闭UART发送完 ...

我在实际测试过程中有这个现象,初始化时并没有开启发送完成中断,在dma传输完成中断里开启发送完成中断,在串口发送完成中断由发送转接收,然后清除发送完成标志(SR &= 0XFFBF),然后关闭发送完成中断。这个流程会发现发送出去的字节数会比设定的少两个字节。
分析,按理论上说在开启发送完成中断时,串口数据寄存器和移位寄存器中都还有数据,也就是在如果在串口发送完成中断里如果不关闭发送完成中断,会产生两次中断。但在实际测试过程中发现并没有产生两次中断,而且如果发送完成中断函数只添加发转收,却能正确传输所有数据,并且再下次发起dma传输时也并不会发送完一个字节产生一次发送完成中断,没搞太明白,请帮忙想想,谢谢。
love_ourdev
3楼-- · 2019-12-14 19:53
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切换方向的地方。
jaky80000
4楼-- · 2019-12-14 21:56
 精彩回答 2  元偷偷看……

一周热门 更多>