1. 程式人生 > >STM32_庫函式學習筆記_ADC_01

STM32_庫函式學習筆記_ADC_01

STM32庫函式ADC學習筆記

(學習材料為正點原子ALIENTEK TM32F1精英版光碟內容)

常用ADC庫函式

1、ADC初始化函式

包含兩個引數:ADCx、ADC_InitStruct

void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct)

ADCx 為目標ADC控制器編號:

#define IS_ADC_ALL_PERIPH(PERIPH) (((PERIPH) == ADC1) || \
                                   ((PERIPH) == ADC2) || \
                                   ((PERIPH) == ADC3))

ADC_InitStruct 為初始化結構體:

typedef struct
{
  uint32_t ADC_Mode;
  FunctionalState ADC_ScanConvMode;
  FunctionalState ADC_ContinuousConvMode;
  uint32_t ADC_ExternalTrigConv;
  uint32_t ADC_DataAlign;
  uint8_t ADC_NbrOfChannel;
}ADC_InitTypeDef;

ADC_Mode:ADC模式:配置ADC_CR1暫存器的位[19:16]:DUALMODE[3:0]位。

DUALMOD[3:0]:雙模式選擇 (Dual mode selection)
軟體使用這些位選擇操作模式。
0000:獨立模式(常用)
0001:混合的同步規則+注入同步模式
0010:混合的同步規則+交替觸發模式
0011:混合同步注入+快速交叉模式
0100:混合同步注入+慢速交叉模式
0101:注入同步模式
0110:規則同步模式
0111:快速交叉模式
1000:慢速交叉模式
1001:交替觸發模式
注: 在ADC2和ADC3中這些位為保留位
在雙模式中,改變通道的配置會產生一個重新開始的條件,這將導致同步丟失。建議在進行任
何配置改變前關閉雙模式。

ADC_ScanConvMode:是否使用掃描模式。ADC_CR1位8:SCAN位。

SCAN:掃描模式 (Scan mode)
該位由軟體設定和清除,用於開啟或關閉掃描模式。在掃描模式中,轉換由ADC_SQRx或
ADC_JSQRx暫存器選中的通道。
0:關閉掃描模式;
1:使用掃描模式。
注:如果分別設定了EOCIE或JEOCIE位,只在最後一個通道轉換完畢後才會產生EOC或
JEOC中斷。

ADC_ContinuousConvMode:單次轉換OR連續轉換:ADC_CR2的位1:CONT位。

CONT:連續轉換 (Continuous conversion)
該位由軟體設定和清除。如果設定了此位,則轉換將連續進行直到該位被清除。
0:單次轉換模式;
1:連續轉換模式。

ADC_ExternalTrigConv:觸發方式:ADC_CR2的位[19:17] :EXTSEL[2:0]位。

EXTSEL[2:0]:選擇啟動規則通道組轉換的外部事件 (External event select for regular group)
這些位選擇用於啟動規則通道組轉換的外部事件
ADC1和ADC2的觸發配置如下
000:定時器1的CC1事件
100:定時器3的TRGO事件
001:定時器1的CC2事件
101:定時器4的CC4事件
110:EXTI線11/ TIM8_TRGO事件,僅大容量產
品具有TIM8_TRGO功能
010:定時器1的CC3事件
011:定時器2的CC2事件
111: SWSTART(軟體觸發)
ADC3的觸發配置如下
000:定時器3的CC1事件
100:定時器8的TRGO事件
001:定時器2的CC3事件
101:定時器5的CC1事件
010:定時器1的CC3事件
110:定時器5的CC3事件
011:定時器8的CC1事件
111:SWSTART(軟體觸發)

ADC_DataAlign:對齊方式:左對齊還是右對齊:ADC_CR2的位11:ALIGN位。

ALIGN:資料對齊 (Data alignment)
該位由軟體設定和清除。
0:右對齊;
1:左對齊。

ADC_NbrOfChannel:規則通道序列長度:ADC_SQR1的位[23:20]: L[3:0]。

L[3:0]:規則通道序列長度 (Regular channel sequence length)
這些位由軟體定義在規則通道轉換序列中的通道數目。
0000: 1個轉換
0001: 2個轉換
……
1111: 16個轉換

2、ADC使能函式

void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState)  

NewState取值:

#define IS_FUNCTIONAL_STATE(STATE) (((STATE) == DISABLE) || ((STATE) == ENABLE))

3、ADC使能軟體轉換函式

void ADC_SoftwareStartConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState)

4、ADC規則通道配置函式,包含三個引數:ADCx、ADC_Channel、Rank、ADC_SampleTime

void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime)

ADC_Channel為目標ADC通道編號:

#define IS_ADC_CHANNEL(CHANNEL) (((CHANNEL) == ADC_Channel_0) || ((CHANNEL) == ADC_Channel_1) || \
                                 ((CHANNEL) == ADC_Channel_2) || ((CHANNEL) == ADC_Channel_3) || \
                                 ((CHANNEL) == ADC_Channel_4) || ((CHANNEL) == ADC_Channel_5) || \
                                 ((CHANNEL) == ADC_Channel_6) || ((CHANNEL) == ADC_Channel_7) || \
                                 ((CHANNEL) == ADC_Channel_8) || ((CHANNEL) == ADC_Channel_9) || \
                                 ((CHANNEL) == ADC_Channel_10) || ((CHANNEL) == ADC_Channel_11) || \
                                 ((CHANNEL) == ADC_Channel_12) || ((CHANNEL) == ADC_Channel_13) || \
                                 ((CHANNEL) == ADC_Channel_14) || ((CHANNEL) == ADC_Channel_15) || \
                                 ((CHANNEL) == ADC_Channel_16) || ((CHANNEL) == ADC_Channel_17))

STM32F10x 最多支援18個ADC通道(外部16個+內部2個)。其中144角的晶片因為帶PF腳,所以支援21個外部通道。
ADC通道和引腳對應關係如圖:
ADC通道和引腳對應關係

Rank 為該通道在順序規則轉換的隊伍中的序號,最多16位:

#define IS_ADC_REGULAR_RANK(RANK) (((RANK) >= 0x1) && ((RANK) <= 0x10))

ADC_SampleTime 為可程式設計通道取樣時間

#define IS_ADC_SAMPLE_TIME(TIME) (((TIME) == ADC_SampleTime_1Cycles5) || \
                                  ((TIME) == ADC_SampleTime_7Cycles5) || \
                                  ((TIME) == ADC_SampleTime_13Cycles5) || \
                                  ((TIME) == ADC_SampleTime_28Cycles5) || \
                                  ((TIME) == ADC_SampleTime_41Cycles5) || \
                                  ((TIME) == ADC_SampleTime_55Cycles5) || \
                                  ((TIME) == ADC_SampleTime_71Cycles5) || \
                                  ((TIME) == ADC_SampleTime_239Cycles5))

ADC使用若干個ADC_CLK週期對輸入電壓取樣,取樣週期數目可以通過ADC取樣時間暫存器ADC_SMPR1和ADC_SMPR2中的SMPx[2:0]位更改。

SMPx[2:0]:選擇通道x的取樣時間 (Channel x Sample time selection)
這些位用於獨立地選擇每個通道的取樣時間。在取樣週期中通道選擇位必須保持不變。
000: 1.5週期
100: 41.5週期
001: 7.5週期
101: 55.5週期
010: 13.5週期
110: 71.5週期
011: 28.5週期
111: 239.5週期
注: ADC1的模擬輸入通道16和通道17在晶片內部分別連到了溫度感測器和VREFINT。
ADC2的模擬輸入通道16和通道17在晶片內部連到了Vss。
ADC3模擬輸入通道14、 15、 16、 17與Vss相連,ADC3模擬輸入通道9與Vss相連。

總轉換時間T_CONV = 取樣時間 + 12.5個週期
例如:
當ADC_CLK=14MHz,取樣時間為1.5週期
T_CONV = 1.5 + 12.5 = 14週期 = 1μs

5、ADC獲取轉換結果函式

uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx)

實驗:ADC1的通道1(PA1)進行單次轉化

1、開啟PA口時鐘和ADC1時鐘,設定PA1為模擬輸入

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1,ENABLE);    //使能時鐘  

GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;       //設定模擬輸入
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);

2、復位ADC1,同時設定ADC1分頻因子

ADC_DeInit(ADC1);                   //復位
RCC_ADCCLKConfig(RCC_PCLK2_Div6);   //72M/6=12M,ADC最大采樣頻率不超過14M

3、初始化ADC1引數,設定ADC1的工作模式以及規則序列的相關資訊

ADC_InitTypeDef ADC_InitStructure; 
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;                  //獨立模式
ADC_InitStructure.ADC_ScanConvMode = DISABLE;                       //單通道模式
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;                 //單次轉換模式
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //軟體觸發(非外部觸發)
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;              //資料右對齊
ADC_InitStructure.ADC_NbrOfChannel = 1;                             //順序進行規則轉換通道數為1
ADC_Init(ADC1, &ADC_InitStructure);                                 //初始化

4、使能ADC並校準

ADC_Cmd(ADC1, ENABLE);                           //使能
ADC_ResetCalibration(ADC1);                      //使能復位校準
while(ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);                      //開啟AD校準
while(ADC_GetCalibrationStatus(ADC1));

原子編寫ADC初始化函式void Adc_Init(void)完成步驟1-4。

5、配置規則通道引數

ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 );    //ADC1,通道數ch,序列1,取樣週期239.5週期

6、開啟軟體轉換,等待轉換完成

ADC_SoftwareStartConvCmd(ADC1, ENABLE); 
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));

7、讀取ADC值

return ADC_GetConversionValue(ADC1);    //返回ADC結果

原子編寫函式u16 Get_Adc(u8 ch)完成步驟5-7。
同時函式u16 Get_Adc_Average(u8 ch,u8 times)可以取樣times次,取平均值。

u16 Get_Adc_Average(u8 ch,u8 times)
{
    u32 temp_val=0;
    u8 t;
    for(t=0;t<times;t++)
    {
        temp_val+=Get_Adc(ch);
        delay_ms(5);
    }
    return temp_val/times;
}

8、換算電壓值

u16 adcx;
adcx=Get_Adc_Average(ADC_Channel_1,10);
temp=(float)adcx*(3.3/4096);    //12位ADC,參考電壓3.3V
adcx=temp;                      //整數部分
temp-=adcx;
temp*=1000;                     //小數部分,用於LCD數顯