什么是ADC?
ADC模塊是一種12位的逐次逼近型模擬數字轉換器。它有多達19個通道,可測量16個外部和3個內部信號源。各通道的A/D轉換可以單次、連續、掃描或間斷模式執行。 ADC的結果可以左對齊或右對齊方式存儲在16位數據寄存器中。
ADC的任務就是:將連續變化的模擬信號轉換為離散的數字信號,以便于我們的數字系統進行計算、處理、存儲、控制、顯示。
ADC重要指標:ADC模塊的位數和ADC模塊的模擬通道
ADC模塊的位數:是指數字量的位數,其實和分辨率有著密切的聯系。
ADC模塊的模擬通道:有幾個模擬量采集路口,也就是說可以對多少個模擬量進行轉換。
stm32的ADC特點
STM32的ADC有單次轉換和連續轉換2種模式,這兩種模式又可以選擇是否結合掃描模式。
CONT=0,SCAN=0 單次轉換模式(Single conversion mode)單次掃描1通道
CONT=1,SCAN=0 連續轉換模式(Continuous conversion mode) 連續掃描1通道
CONT=0,SCAN=1 掃描轉換模式(Scan mode):所有ADC_SQR序列通道轉換一次后停止。(單次掃描組)
CONT=1,SCAN=1 掃描轉換模式(Scan mode):所有ADC_SQR序列通道轉換一次后,再從第一個通道循環。連續掃描一組
需要注意的是,如果你的轉換序列當中有超過一個通道需要轉換的話,那么必須要開啟掃描模式,否則的話,始終只轉換第一通道。
用ADC1,Regular通道的順序為Ch0,Ch1,Ch2,Ch3,啟動Scan模式
在單次轉換模式下: 啟動ADC1,則
1. 開始轉換Ch0
2. 轉換完成后自動開始轉換Ch1
3. 轉換完成后自動開始轉換Ch2
4. 轉換完成后自動開始轉換Ch3
5. 轉換完成后停止,等待ADC的下一次啟動。下一次ADC啟動從第一步開始
在連續轉換模式下: 啟動ADC1,則
1. 開始轉換Ch0
2. 轉換完成后自動開始轉換Ch1
3. 轉換完成后自動開始轉換Ch2
4. 轉換完成后自動開始轉換Ch3
5. 轉換完成后回到第一步
如果沒啟動Sacn模式則上述過程中沒有2、3、4這三個步驟 上述前提是Discontinuous模式沒有啟用。
如何使stm32定時器觸發adc
STM32 ADC的常規通道可以由以上圖6個信號觸發任何一個,我們以使用TIM2_CH2觸發ADC1,獨立模式,每次僅測一條通道,則ADC的配置如下:(以下代碼使用STM32固件庫V3.5)
void ADC_Configuration(void)
{
ADC_InitTypeDef ADC_InitStructure;
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = DISABLE; //關閉通道掃描模式
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //注意不要使用持續轉換模式,否則只要觸發一次,//后續的轉換就會永不停歇(除非CONT清0),這樣第一次以后的ADC,就不是由TIM2_CC2來觸發了
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_CC2;//配置TIM2_CC2為觸發源
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 1;
ADC_Init(ADC1, &ADC_InitStructure);
RCC_ADCCLKConfig(RCC_PCLK2_Div6);//配置時鐘(12MHz),在RCC里面還應配置APB2=AHB時鐘72MHz,
ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 1, ADC_SampleTime_1Cycles5);
ADC_Cmd(ADC1,ENABLE);
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1); //Start Calibration register
while(ADC_GetCalibrationStatus(ADC1)); //waiting for finishing the calibration
ADC_ExternalTrigConvCmd(ADC1, ENABLE); //設置外部觸發模式使能(這個“外部“其實僅僅是相//對于ADC模塊的外部,實際上還是在STM32內部)
}
這里再注意一點上面左圖最頂上的那句話:當外部觸發信號被選為ADC規則或注入轉換時,只有它的上升沿可以啟動轉換。這跟下面的定時器2的正確配置關系很大。
void TIM2_Configuration(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_TimeBaseStructure.TIM_Period = 10000;//設置100ms一次TIM2比較的周期
TIM_TimeBaseStructure.TIM_Prescaler = 719;//系統主頻72M,這里分頻720,相當于100K的定時器2時鐘
TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, & TIM_TimeBaseStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//下面詳細說明
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//TIM_OutputState_Disable;
TIM_OCInitStructure.TIM_Pulse = 5000;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;//如果是PWM1要為Low,PWM2則為High
TIM_OC2Init(TIM2, & TIM_OCInitStructure);
TIM_Cmd(TIM2, ENABLE);
TIM_InternalClockConfig(TIM2);
TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable);
TIM_UpdateDisableConfig(TIM2, DISABLE);
}
上圖頂上是TIM2的自動重裝寄存器和計數器寄存器,下面4個Capture/compare x register是TIM2_CCRx寄存器。
要使用TIM2的CC2來觸發ADC,看懂這個圖是關鍵。
首先要明確,這個圖的紅框部分和藍框部分,是不會同時工作的,紅框是配置為輸入捕捉模式才能生效,藍框是配置為輸出比較模式才能生效,通過配置TIM2_CCMR1_CC2S來控制TIM2_CC2究竟是處于哪種模式(CC2S=0為比較輸出,》0為輸入捕捉),請注意:這里藍框的其中一個輸出是TIMx_CH2,而TIM2_CH2又是ADC規則通道的觸發源,也就是說如果要觸發ADC,則需要每次比較匹配時,在TIM2_CH2上產生一次上升沿。
那么我們首先需要操作藍框內的最左邊部分也就是OC2REF,要使比較匹配時發生一次上升沿,(以定時器向上計數為例,)就需要在TIM2_CNT《TIM2_CCR2時,通道2為低電平,TIM2_CNT》=TIM2_CCR2時,通道2為高電平。
從參考手冊定時器一章4.7節的CCMR1寄存器中的0C2M[2:0]的介紹可以看出來,只有在PWM模式才能滿足上面所說的條件,任何單純的凍結、配置OC2REF為高或者為低、強制OC2REF為高或者為低,都無法滿足要求,不少同學就是死在這個上面,以為是配置TIMING模式,實際上這樣根本無法改變OC2REF的電平,就無從觸發ADC了。
CCMR1_CCxS(x為1、2、3、4,決定是哪個通道)是選擇為捕捉輸入還是比較輸出,這里我們需要配置為輸出。 以上兩段配置程序,可以以100ms的周期驅動AD轉換一次,不再需要使用TIM和ADC中斷資源。
總結:
想要使用STM32的定時器觸發ADC,必須將定時器配置為比較輸出PWM模式,并且一定要注意TIMx_CHx輸出上升沿才出發,若是在比較匹配的瞬時產生的不是上升沿而是下降沿,那么就不一定是在比較匹配的瞬間觸發ADC了,特別是在類似于電機控制的應用中要注意這一點。
評論
查看更多