問題描述:
使用ADC單獨連續模式,DMA循環模式運行,調試時發現,若設置ADC取樣時間很短將影響DMA傳輸中斷函數的進入,ADC取樣時間可選:3、15、28、56、84、112、144、480個時鍾周期,實驗發現,若選最低的3個或15個時鍾周期作為取樣時間,則DMA傳輸中斷函數不能進入,若選擇28個時鍾周期及以后的6種取樣時間,均可正常進入DMA傳輸中斷函數。
結論:
經仿真顯示,ADC狀態寄存器ADC_SR的OVE位置1,說明ADC數據丟失溢出,通過調試非循環模式DMA啟動經驗,將DMA初始化(啟動)置於ADC初始化(啟動)前,問題解決。所以ADC的溢出發生在ADC啟動后DMA配置過程中,若設置取樣時間長的話,問題被避開了,但取樣時間短的話,會造成溢出。
DMA按照需要啟動需注意事項:
1、DMA傳輸完成中斷函數里面對ADC的CR2寄存器DMA位置0,即關閉ADC的DMA傳輸;
void DMA2_Stream0_IRQHandler(void) //ADC3的DMA中斷服務函數
{
u8 k;
if ((DMA_GetITStatus(DMA2_Stream0, DMA_IT_TCIF0) != RESET)) //傳輸完成標志且數據轉移至緩存區后允許將數據存入緩沖區
{
ADC_DMACmd(ADC3, DISABLE); //關閉ADC的DMA傳輸
Disc_Times++; //記錄進入中斷的次數
for(k=0;k<16;k++) //將數據轉移,防止被下一輪寫入沖掉
{
PDChnl[2].SampleValue[k]=ADC3_ConvertedValue[k];
}
DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TCIF0); //清除傳輸中斷標志位
}
}
2、DMA啟動前對通道傳輸數據的數量重新加載 DMA2_Stream0->NDTR = 0X10;
3、ADC的DMA啟動前對ADC狀態寄存器ADC_SR的溢出位OVE置0,ADC3->SR &=~0X1<<5 ;確保程序長期穩定運行,取樣時間短時,容易發現問題;取樣時間長時,程序運行幾分鍾后才會出錯,容易忽視;
DMA2_Stream0->NDTR = 0X10; //重新裝填DMA需要傳輸的數據個數
DMA_Cmd(DMA2_Stream0, ENABLE); //先使能DMA通道
ADC3->SR &=~0X1<<5 ; //將由硬件置1的ADC狀態寄存器的溢出標志位清除,不然容易出錯
ADC_DMACmd(ADC3, ENABLE); //再使能ADC的DMA傳輸
另記:
1、printf函數不能放在DMA中斷函數里面,容易導致DMA中斷處理不完,如果非要放,放在清除中斷標志位處理函數后;
2、規則組轉換完成中斷不需要,因為用的是兩個規則組傳遞完成的DMA中斷,所以
“//ADC_ITConfig(ADC2,ADC_IT_EOC,ENABLE); //每個規則通道轉換結束時中斷 ” 刪除;
3、“ADC_DMARequestAfterLastTransferCmd(ADC3, ENABLE); ”控制DMA傳輸一組數據后發不發送DMA請求,與ADC轉換后發送DMA請求無關,每次 ADC轉換完成后即進行DMA傳輸,應該是在ADC_DMACmd(ADC3, ENABLE)時內部進行了實現,我們不用擔心不同步的問題。