關于使能ADC1 使用DMA1 CH1 只能進一次中斷的問題

各位大佬?

? ? ? ?代碼目的? TIM4_CC4作為觸發(fā)單元? 周期性的觸發(fā)ADC1進行轉(zhuǎn)換? ?ADC1在觸發(fā)DMA1 把ADC1獲得的三個通道的數(shù)據(jù)送到一個數(shù)組中,傳送完成后觸發(fā)中斷。

? ? ? ?目前的進度和遇到的問題??

? ? ? ?1.TM4_CC4周期性的觸發(fā)ADC1進行轉(zhuǎn)換? 這一步已完成(開了ADC中斷,測試了下ADC中斷周期和TM4_CC4中斷周期同步)

? ? ? ?2.ADC1觸發(fā)DMA1_CH1傳輸數(shù)據(jù) 并觸發(fā)中斷(此步也完成 發(fā)送的三個通道adc數(shù)據(jù)也準確)

? ? ? ?3.雖然DMA1_CH1能進中斷? 但只能進一次? 具體代碼如下:

? ? ??

? ? ? ?TM4初始化

? ? ? ??

TIM4->CTLR1=1<<7;? ? ? ? ? ? //使能自動重裝載

TIM4->CTLR2=7<<4;? ? ? ? ? ? //比較通道4作為觸發(fā)輸出

TIM4->DMAINTENR=1<<8;? ? ? ? //允許比較4中斷

TIM4->PSC=4800;? ? ? ? ? ? ? //預分頻值

TIM4->ATRLR=400;? ? ? ? ? ? ?//20ms


TIM4->CTLR1|=1<<0;? ? ? ? ? ?//開啟定時器

TIM4->CCER=1<<12;? ? ? ? ? ? //開啟使能CC4輸出

TIM4->CHCTLR2=6<<12;? ? ? ? ?//翻轉(zhuǎn)REF4

TIM4->CH4CVR=200;

TIM4->DMAINTENR=1<<4;? ? ? ? //允許比較4中斷

? ? ? ?ADC初始化

? ? ? ??

? ? GPIO_InitTypeDef GPIO_InitStructure={0};

? ? ADC_InitTypeDef? ADC_InitStructure={0};


? ? RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1 , ENABLE ); //使能GPIOA時鐘和ADC

? ? RCC_ADCCLKConfig(RCC_PCLK2_Div8); //設置ADC時鐘分頻為6分頻


? ? GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_5|GPIO_Pin_7;? ?//

? ? GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //GPIO模式為模擬輸入

? ? GPIO_Init(GPIOA, &GPIO_InitStructure);


? ? ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;? //配置ADC為獨立模式

? ? ADC_InitStructure.ADC_ScanConvMode = ENABLE;? ? ? ? //多通道模式下開啟掃描模式

? ? ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;? //設置開啟連續(xù)轉(zhuǎn)換模式

? ? ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T4_CC4; //由T4_CC4觸發(fā)

? ? ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //設置ADC數(shù)據(jù)右對齊

? ? ADC_InitStructure.ADC_NbrOfChannel = 3;? ? ? ? ? ? ? ? //規(guī)則轉(zhuǎn)換的ADC通道的數(shù)目

? ? ADC_Init(ADC1, &ADC_InitStructure);? ? ? ? ? ? ? ? ? ? //根據(jù)ADC_InitStructure中指定的參數(shù)初始化ADC1寄存器

?

? ? ADC1->CTLR1|=1<<5;? ?//開啟ADC轉(zhuǎn)換結(jié)束中斷

? ? ADC1->CTLR2|=1<<20;? ? //開啟外部觸發(fā)功能

? ? ADC_Cmd(ADC1, ENABLE);? ? ? //使能ADC1


? ? ADC_ResetCalibration(ADC1); //重置ADC1校準寄存器。


? ? while(ADC_GetResetCalibrationStatus(ADC1)); //等待復位校準結(jié)束


? ? ADC_StartCalibration(ADC1); //開啟AD校準


? ? while(ADC_GetCalibrationStatus(ADC1));? ? ? //等待校準結(jié)束


? ? ADC_BufferCmd(ADC1, DISABLE); //disable buffer??


? ?DMA初始化

? ?

DMA_InitTypeDef DMA_InitStructure={0};

? ? RCC_AHBPeriphClockCmd( RCC_AHBPeriph_DMA1, ENABLE ); //使能開啟DMA時鐘


? ? DMA_DeInit(DMA1_Channel1); //復位DMA控制器


? ? DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&ADC1->RDATAR;? //配置外設地址為ADC數(shù)據(jù)寄存器地址

? ? DMA_InitStructure.DMA_MemoryBaseAddr = (u32)ADC_ConvertedValue; //配置存儲器地址為讀取ADC值地址

? ? DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;? ? ? ? ? ? ?//配置數(shù)據(jù)源為外設,即DMA傳輸方式為外設到存儲器

? ? DMA_InitStructure.DMA_BufferSize = 3;? ? ? ? ? ? ? ? ? ? ? //設置DMA數(shù)據(jù)緩沖區(qū)大小,此處設置為length

? ? DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//設置DMA外設遞增模式關閉

? ? DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;? ? ? ? ?//設置DMA存儲器遞增模式開啟

? ? DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //設置外設數(shù)據(jù)大小為半字,即兩個字節(jié)

? ? DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;? ? ? ? ?//設置存儲器數(shù)據(jù)大小為半字,即兩個字節(jié)

? ? DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;? ? ? ? ?//設置DMA模式為正常模式

? ? DMA_InitStructure.DMA_Priority = DMA_Priority_High; //設置DMA傳輸通道優(yōu)先級為高,當使用一 DMA通道時,優(yōu)先級設置不影響

? ? DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;? ? ? ? //因為此DMA傳輸方式為外設到存儲器,因此禁用存儲器到存儲器傳輸方式

? ? DMA_Init( DMA1_Channel1, &DMA_InitStructure );? ? ? //初始化DMA



? ? DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);? //使能DMA傳輸完成中斷

DMA_Cmd(DMA1_Channel1 , ENABLE);? //使能DMA


中斷配置部分

?

//NVIC->IENR[0]|=1<<27;? ? ? ? ? //開啟DMA中斷

? NVIC->IENR[1]|=1<<2;? ? ? ? ?//開啟ADC 34號中斷? ? ? ? ? ? ? ? ? ? ?DMA_CH1中斷號? 27? ?ADC1_2中斷號 34

? //NVIC->IENR[1]|=1<<14;? ? ? ? //允許TIM4中斷


DMA中斷處理部分

?

if(DMA_GetITStatus(DMA1_IT_TC1))

? ? ? ?{

? ? ? ? ? ?//printf("\r\n Enter DMA Interrupt \r\n");


?

? ? ? ? ? DMA_ClearITPendingBit(DMA1_IT_TC1); //清除全部中斷標志

? ?

? ? ? ?}


你好 你的DMA是單次模式


如果是循環(huán)模式? 就會一直循環(huán)進入中斷? 而需求是adc觸發(fā)dma只需要傳輸一次


搞定了? 主要是需要重置DMA的CNTR寄存器? 當DMA傳輸結(jié)束后 此寄存器為0??

DMA根據(jù)此寄存器的值來判斷是否傳輸結(jié)束? 以下是中斷處理的代碼

#define DMA1_CNTR1 (*(uint32_t *) 0x4002000C)? //在sdk中沒找到具體的寄存器定義 所以自己定義了一個

void DMA1_Channel1_IRQHandler(void)

{

?if(DMA_GetITStatus(DMA1_IT_TC1))

? {

? ? DMA_ClearITPendingBit(DMA1_IT_TC1);? ? ?//清除全部中斷標志0

? ? DMA1_CNTR1=3;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //關鍵? 必須重置? 否則只能傳輸一次

? ?TIM3->CTLR1|=1<<0;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//重啟定時器3? 原因為程序利用TIM3 產(chǎn)生單次TROG 觸發(fā)ADC3個通道的規(guī)則轉(zhuǎn)換? ADC轉(zhuǎn)換后在觸發(fā)DMA傳輸? 所以需要重啟TIM3

?

? }

}



只有登錄才能回復,可以選擇微信賬號登錄

国产91精品新入口,国产成人综合网在线播放,九热这里只有精品,本道在线观看,美女视频a美女视频,韩国美女激情视频,日本美女pvp视频