1. STM32F103 ADC
本例使用STM32F103芯片的PA1引腳測試模擬輸入的電壓值。
查看文檔《STM32F103X.pdf》第31頁,引腳定義圖:
得知PA1使用ADC1的通道1。
查看文檔《STM32F103X.pdf》第13頁,時鍾樹圖:
得知ADC1可2,4,6,8分頻,又ADC輸入時鍾不得超過14MHZ(參見STM32參考手冊RM0008第11章ADC)。
//初始化ADC //這里我們僅以規則通道為例 //我們默認將開啟通道0~3 void Adc_Init(void) { ADC_InitTypeDef ADC_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1, ENABLE ); //使能ADC1通道時鍾 RCC_ADCCLKConfig(RCC_PCLK2_Div6); //設置ADC分頻因子6 72M/6=12,ADC最大時間不能超過14M //PA1 作為模擬通道輸入引腳 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模擬輸入引腳 GPIO_Init(GPIOA, &GPIO_InitStructure); ADC_DeInit(ADC1); //復位ADC1,將外設 ADC1 的全部寄存器重設為缺省值 ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC工作模式:ADC1和ADC2工作在獨立模式 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數據右對齊 ADC_InitStructure.ADC_NbrOfChannel = 1; //順序進行規則轉換的ADC通道的數目 ADC_Init(ADC1, &ADC_InitStructure); //根據ADC_InitStruct中指定的參數初始化外設ADCx的寄存器 ADC_Cmd(ADC1, ENABLE); //使能指定的ADC1 ADC_ResetCalibration(ADC1); //使能復位校准 while(ADC_GetResetCalibrationStatus(ADC1)); //等待復位校准結束 ADC_StartCalibration(ADC1); //開啟AD校准 while(ADC_GetCalibrationStatus(ADC1)); //等待校准結束 ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的軟件轉換啟動功能 }
//獲得ADC值 //ch:通道值 0~3 u16 Get_Adc(u8 ch) { //設置指定ADC的規則組通道,一個序列,采樣時間 ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 ); //ADC1,ADC通道,采樣時間為239.5周期 ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的軟件轉換啟動功能 while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待轉換結束 return ADC_GetConversionValue(ADC1); //返回最近一次ADC1規則組的轉換結果 } 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; } void ADCTask(void) { float vol, adcx; while(1) { adcx=Get_Adc_Average(ADC_Channel_1,10); //ADC的值 vol=(float)adcx*(3300/4096); //電壓值(mv) delay_ms(200); } }
2、 STM32F407 ADC
本例使用STM32F407芯片的PF9引腳測試模擬輸入的電壓值。
查看文檔《STM32F4x7-Datasheet.pdf》第43頁,引腳定義圖:
查看文檔《STM32F4x7-Reference manual.pdf》第51頁,內存映射:
點擊鏈接查看ADC寄存器映射:
又查看數據寄存器偏移量:
得知數據寄存器地址:#define ADC3_DR_ADDRESS ((uint32_t)0x4001224C)
查看《STM32F4x7-Reference manual.pdf》第165頁DMA2 request mapping:
得知使用DMA2 Stream0 通道2映射ADC3。
#define ADC3_DR_ADDRESS ((uint32_t)0x4001224C) __IO uint16_t ADC3ConvertedValue = 0; __IO uint32_t ADC3ConvertedVoltage = 0; //ADC3 channel07 with DMA configuration void ADC3_CH7_DMA_Config(void) { ADC_InitTypeDef ADC_InitStructure; ADC_CommonInitTypeDef ADC_CommonInitStructure; DMA_InitTypeDef DMA_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; /* Enable ADC3, DMA2 and GPIO clocks ****************************************/ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2 | RCC_AHB1Periph_GPIOF, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE); /* DMA2 Stream0 channel2 configuration **************************************/ DMA_InitStructure.DMA_Channel = DMA_Channel_2; DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC3_DR_ADDRESS; DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADC3ConvertedValue; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; DMA_InitStructure.DMA_BufferSize = 1; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_Init(DMA2_Stream0, &DMA_InitStructure); DMA_Cmd(DMA2_Stream0, ENABLE); /* Configure ADC3 Channel7 pin as analog input ******************************/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; GPIO_Init(GPIOF, &GPIO_InitStructure); /* ADC Common Init **********************************************************/ ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent; ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2; ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; ADC_CommonInit(&ADC_CommonInitStructure); /* ADC3 Init ****************************************************************/ ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; ADC_InitStructure.ADC_ScanConvMode = DISABLE; ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfConversion = 1; ADC_Init(ADC3, &ADC_InitStructure); /* ADC3 regular channel7 configuration *************************************/ ADC_RegularChannelConfig(ADC3, ADC_Channel_7, 1, ADC_SampleTime_3Cycles); /* Enable DMA request after last transfer (Single-ADC mode) */ ADC_DMARequestAfterLastTransferCmd(ADC3, ENABLE); /* Enable ADC3 DMA */ ADC_DMACmd(ADC3, ENABLE); /* Enable ADC3 */ ADC_Cmd(ADC3, ENABLE); } int main(void) { /* ADC3 configuration *******************************************************/ /* - Enable peripheral clocks */ /* - DMA2_Stream0 channel2 configuration */ /* - Configure ADC Channel7 pin as analog input */ /* - Configure ADC3 Channel7 */ ADC3_CH7_DMA_Config(); /* Start ADC3 Software Conversion */ ADC_SoftwareStartConv(ADC3); while (1) { ADC3ConvertedVoltage = ADC3ConvertedValue *3300/0xFFF;
delay_ms(200); } }