zoukankan      html  css  js  c++  java
  • STM32的USART DMA传输(转)

    源:STM32的USART DMA传输

    问题描述:

         我有一个需求,AD采得一定数目的数据之后,由串口DMA发出,由于AD使用双缓冲,所以每次开始DMA的时候都需要重新设置开始的内存地址以及传输的数目(这些都是理所当然的),但是在开始调试的时候,遇到了一些问题,问题如下:当第一次DMA传输完毕,关闭DMA以设置内存地址等,再开启DMA,发现不启动了。

          开始是参考了《STM32中文参考手册REV10》,里面的发送步骤如下:

    1. 在DMA控制寄存器上将USART_DR寄存器地址配置成DMA传输的目的地址。在每个TXE事件后,数据将被传送到这个地址。
    2. 在DMA控制寄存器上将存储器地址配置成DMA传输的源地址。在每个TXE事件后,将从此存储器区读出数据并传送到USART_DR寄存器。
    3. 在DMA控制寄存器中配置要传输的总的字节数。
    4. 在DMA寄存器上配置通道优先级。
    5. 根据应用程序的要求,配置在传输完成一半还是全部完成时产生DMA中断。
    6. 在DMA寄存器上激活该通道。

    检查代码,发现没问题,但是问题还是解决不了,就找了英文的参考手册(REV14),发现上面的步骤有了些修改:

    1. Write the USART_DR register address in the DMA control register to configure it as the
    destination of the transfer. The data will be moved to this address from memory after
    each TXE event.
    2. Write the memory address in the DMA control register to configure it as the source of
    the transfer. The data will be loaded into the USART_DR register from this memory
    area after each TXE event.
    3. Configure the total number of bytes to be transferred to the DMA control register.
    4. Configure the channel priority in the DMA register
    5. Configure DMA interrupt generation after half/ full transfer as required by the
    application.
    6. Clear the TC bit in the SR register by writing 0 to it.
    7. Activate the channel in the DMA register.
    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标志位清除

    一个诡异的问题:

    发现即使上面提到的两个条件都不满足,但是下面的代码依然可以正常传输:

    //ENBALE 之前USART1的TC,DMA1 对应USART TX的DMA通道TC标志都已经置位,没有清除
                    DMA_Cmd(USART1_Tx_DMA_Channel, ENABLE);
                    while((USART1->SR & USART_FLAG_TC) == 0x00);

    这样也可以。但是只要换成:

                    DMA_Cmd(USART1_Tx_DMA_Channel, ENABLE);
                    
                    /* Wait until USARTy TX DMA1 Channel Transfer Complete */
                    while (DMA_GetFlagStatus(USART1_Tx_DMA_FLAG ) == RESET) {
                    }

    就不行了。比较奇怪。

    结论:

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

  • 相关阅读:
    上下文调用(call , apply , bind)
    源码学习第七天(水滴石穿)
    学习源码第六天(加油别放弃)
    学习源码第五天(难得可贵)
    学习源码第四天(昨天只看了一点正则,发现正则真的水很深,但很有魅力)
    简单谈谈$.merge()
    学习源码第三天(短暂的坚持)
    学习源码第二天(渐入佳境)
    jquery源码学习第一天
    经典面试题简单分析
  • 原文地址:https://www.cnblogs.com/LittleTiger/p/4730339.html
Copyright © 2011-2022 走看看