请选择 进入手机版 | 继续访问电脑版

你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32的USART DMA传输

[复制链接]
STMCU小助手 发布时间:2022-1-14 23:02
问题描述:
     我有一个需求,AD采得一定数目的数据之后,由串口DMA发出,由于AD使用双缓冲,所以每次开始DMA的时候都需要重新设置开始的内存地址以及传输的数目(这些都是理所当然的),但是在开始调试的时候,遇到了一些问题,问题如下:当第一次DMA传输完毕,关闭DMA以设置内存地址等,再开启DMA,发现不启动了。
      开始是参考了《STM32中文参考手册REV10》,里面的发送步骤如下:
  1. 1. 在DMA控制寄存器上将USART_DR寄存器地址配置成DMA传输的目的地址。在每个TXE事件后,数据将被传送到这个地址。
  2. 2. 在DMA控制寄存器上将存储器地址配置成DMA传输的源地址。在每个TXE事件后,将从此存储器区读出数据并传送到USART_DR寄存器。
  3. 3. 在DMA控制寄存器中配置要传输的总的字节数。
  4. 4. 在DMA寄存器上配置通道优先级。
  5. 5. 根据应用程序的要求,配置在传输完成一半还是全部完成时产生DMA中断。
  6. 6. 在DMA寄存器上激活该通道。
复制代码

检查代码,发现没问题,但是问题还是解决不了,就找了英文的参考手册(REV14),发现上面的步骤有了些修改:
  1. 1. Write the USART_DR register address in the DMA control register to configure it as the
  2. destination of the transfer. The data will be moved to this address from memory after
  3. each TXE event.
  4. 2. Write the memory address in the DMA control register to configure it as the source of
  5. the transfer. The data will be loaded into the USART_DR register from this memory
  6. area after each TXE event.
  7. 3. Configure the total number of bytes to be transferred to the DMA control register.
  8. 4. Configure the channel priority in the DMA register
  9. 5. Configure DMA interrupt generation after half/ full transfer as required by the
  10. application.
  11. 6. Clear the TC bit in the SR register by writing 0 to it.
  12. 7. Activate the channel in the DMA register.
  13. When the number of data transfers programmed
复制代码

多了一步,即第6步,清除SR寄存器的TC标志位。照做,ok了。

重启DMA传输成功的条件:
后来,又做了其他一些测试,发现即使不清除TC标志位,只要把对应DMA通道的TCIF标志(传输完成标志,DMA_ISR寄存器里面)清除,同样也可以正常重启传输。所以,要重启传输,保证在重新ENABLE DMA之前,满足以下两个条件之一即可:
  • DMA_ISR 对应的TCIF标志清除
  • USART_SR 的TC标志位清除
一个诡异的问题:
发现即使上面提到的两个条件都不满足,但是下面的代码依然可以正常传输:
  1. //ENBALE 之前USART1的TC,DMA1 对应USART TX的DMA通道TC标志都已经置位,没有清除
  2.                 DMA_Cmd(USART1_Tx_DMA_Channel, ENABLE);
  3.                 while((USART1->SR & USART_FLAG_TC) == 0x00);
复制代码

这样也可以。但是只要换成:
  1.                 DMA_Cmd(USART1_Tx_DMA_Channel, ENABLE);
  2.                
  3.                 /* Wait until USARTy TX DMA1 Channel Transfer Complete */
  4.                 while (DMA_GetFlagStatus(USART1_Tx_DMA_FLAG ) == RESET) {
  5.                 }
复制代码

就不行了。比较奇怪。

结论:
不管那些诡异的问题了,以后重启DMA之前,清除串口的TC或者DMA的TC。不过根据使用的感觉,清除DMA的TC简单些。

收藏 评论0 发布时间:2022-1-14 23:02

举报

0个回答
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版