STM32的USART DMA傳輸(轉)
問題描述:
我有一個需求,AD采得一定數目的數據之后,由串口DMA發(fā)出,由于AD使用雙緩沖,所以每次開始DMA的時候都需要重新設置開始的內存地址以及傳輸的數目(這些都是理所當然的),但是在開始調試的時候,遇到了一些問題,問題如下:當第一次DMA傳輸完畢,關閉DMA以設置內存地址等,再開啟DMA,發(fā)現(xiàn)不啟動了。
本文引用地址:http://www.ex-cimer.com/article/201611/318101.htm開始是參考了《STM32中文參考手冊REV10》,里面的發(fā)送步驟如下:
1. 在DMA控制寄存器上將USART_DR寄存器地址配置成DMA傳輸的目的地址。在每個TXE事件后,數據將被傳送到這個地址。2. 在DMA控制寄存器上將存儲器地址配置成DMA傳輸的源地址。在每個TXE事件后,將從此存儲器區(qū)讀出數據并傳送到USART_DR寄存器。3. 在DMA控制寄存器中配置要傳輸的總的字節(jié)數。4. 在DMA寄存器上配置通道優(yōu)先級。5. 根據應用程序的要求,配置在傳輸完成一半還是全部完成時產生DMA中斷。6. 在DMA寄存器上激活該通道。
檢查代碼,發(fā)現(xiàn)沒問題,但是問題還是解決不了,就找了英文的參考手冊(REV14),發(fā)現(xiàn)上面的步驟有了些修改:
1. Write the USART_DR register address in the DMA control register to configure it as thedestination of the transfer. The data will be moved to this address from memory aftereach TXE event.2. Write the memory address in the DMA control register to configure it as the source ofthe transfer. The data will be loaded into the USART_DR register from this memoryarea 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 register5. Configure DMA interrupt generation after half/ full transfer as required by theapplication.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傳輸成功的條件:
后來,又做了其他一些測試,發(fā)現(xiàn)即使不清除TC標志位,只要把對應DMA通道的TCIF標志(傳輸完成標志,DMA_ISR寄存器里面)清除,同樣也可以正常重啟傳輸。所以,要重啟傳輸,保證在重新ENABLE DMA之前,滿足以下兩個條件之一即可:
- DMA_ISR 對應的TCIF標志清除
- USART_SR 的TC標志位清除
一個詭異的問題:
發(fā)現(xiàn)即使上面提到的兩個條件都不滿足,但是下面的代碼依然可以正常傳輸:
//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簡單些。
評論