typedef struct
{
uint32_t ADC_Mode;//多重ADC模式选择
uint32_t ADC_Prescaler; //ADC预分频
uint32_t ADC_DMAAccessMode; //DMA访问模式
uint32_t ADC_TwoSamplingDelay; //2个采样阶段之间的延迟
}ADC_CommonInitTypeDef;
ADC_CommonInitTypeDef ADC_CommonInitStructure;
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;//独立模式
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;//两个采样阶段之间的延迟5个时钟
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;//DMA失能
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;
ADC_CommonInit(&ADC_CommonInitStructure);
void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct);
typedef struct
{
uint32_t ADC_Resolution;//ADC分辨率
FunctionalState ADC_ScanConvMode; //是否使用扫描模式。ADC_CR1位8:SCAN位
FunctionalState ADC_ContinuousConvMode; //单次转换OR连续转换:ADC_CR2的位1:CONT
uint32_t ADC_ExternalTrigConvEdge; //外部触发使能方式:ADC_CR2的位29:28,EXTEN
uint32_t ADC_ExternalTrigConv; //触发方式:ADC_CR2的位[19:17] :EXTSEL[2:0]
uint32_t ADC_DataAlign; //对齐方式:左对齐还是右对齐:ADC_CR2的位11:ALIGN
uint8_t ADC_NbrOfChannel;//规则通道序列长度:ADC_SQR1的位[23:20]: L[3:0]
}ADC_InitTypeDef;
第一个参数ADC_Resolution用来设置ADC转换分辨率。取值范围为:ADC_Resolution_6b, ADC_Resolution_8b,ADC_Resolution_10b 和 ADC_Resolution_12b。
第二个参数 ADC_ScanConvMode 用来设置是否打开扫描模式。这里我们设置单次转换所以不打开扫描模式,值为 DISABLE。
第三个参数 ADC_ContinuousConvMode 用来设置是单次转换模式还是连续转换模式,这里我们是单次,所以关闭连续转换模式,值为 DISABLE。
第四个参数 ADC_ExternalTrigConvEdge 用来设置外部通道的触发使能和检测方式。这里我 们直接禁止触发检测,使用软件触发。还可以设置为上升沿触发检测,下降沿触发检测以及上升沿和下降沿都触发检测。
第五个参数 ADC_DataAlign 用来设置数据对齐方式 。取值范围为右对齐 ADC_DataAlign_Right 和左对齐 ADC_DataAlign_Left。
第五个参数 ADC_NbrOfConversion 用来设置规则序列的长度,这里我们是单次转换,所以值为 1 即可。
实际上还有个参数 ADC_ExternalTrigConv 是用来为规则组选择外部事件。因为我们前面配 置的是软件触发,所以这里我们可以不用配置。如果选择其他触发方式方式,这里需要配置。
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;//12位模式
ADC_InitStructure.ADC_ScanConvMode = DISABLE;//非扫描模式
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//关闭连续转换
ADC_InitStructure.ADC_ExternalTrigConvEdge
= ADC_ExternalTrigConvEdge_None;//禁止触发检测,使用软件触发
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//右对齐
ADC_InitStructure.ADC_NbrOfConversion = 1;//1个转换在规则序列中
ADC_Init(ADC1, &ADC_InitStructure);//ADC初始化
void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState);
ADC_Cmd(ADC1, ENABLE); //使能指定的ADC1
void ADC_SoftwareStartConvCmd(ADC_TypeDef* ADCx,FunctionalState NewState)
ADC_SoftwareStartConvCmd(ADC1, ENABLE);//使能ADC1的软件转换启动
void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);
ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 1,ADC_SampleTime_480Cycles);
uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx);
ADC_GetConversionValue(ADC1);//获取ADC1转换结果
①开启PA口时钟和ADC1时钟,设置PA1为模拟输入。RCC_AHB1PeriphClockCmd (RCC_AHB1Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
GPIO_Init();
② 复位ADC1,同时设置ADC1分频因子。
ADC_DeInit();
③ 初始化ADC_CCR寄存器。
ADC_CommonInit();
④初始化ADC1参数,设置ADC1的工作模式以及规则序列的相关信息。
void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct);
⑤ 使能ADC。
ADC_Cmd(ADC1, ENABLE);
⑥配置规则通道参数:
ADC_RegularChannelConfig();
⑦开启软件转换:ADC_SoftwareStartConvCmd(ADC1);
⑧ 等待转换完成,读取ADC值。
ADC_GetConversionValue(ADC1);
void Adc_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
ADC_CommonInitTypeDef ADC_CommonInitStructure;
ADC_InitTypeDef ADC_InitStructure;
RCC_AHB1PeriphClockCmd (RCC_AHB1Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;//模拟输入
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化
ADC_DeInit();
ADC_CommonInitStructure.ADC_DMAAccessMode=ADC_DMAAccessMode_Disabled;
ADC_CommonInitStructure.ADC_Mode=ADC_Mode_Independent;
ADC_CommonInitStructure.ADC_Prescaler=ADC_Prescaler_Div4;
ADC_CommonInitStructure.ADC_TwoSamplingDelay=ADC_TwoSamplingDelay_5Cycles;
ADC_CommonInit(&ADC_CommonInitStructure);
ADC_InitStructure.ADC_ContinuousConvMode=DISABLE;
ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;
ADC_InitStructure.ADC_ExternalTrigConvEdge=ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_NbrOfConversion=1;
ADC_InitStructure.ADC_Resolution=ADC_Resolution_12b;
ADC_InitStructure.ADC_ScanConvMode=DISABLE;
ADC_Init(ADC1,&ADC_InitStructure);
ADC_Cmd(ADC1, ENABLE);
}
u16 Get_Adc(u8 ch)
{
ADC_RegularChannelConfig(ADC1,ch,1,ADC_SampleTime_480Cycles);
ADC_SoftwareStartConv(ADC1);
while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));
return ADC_GetConversionValue(ADC1);
}
u16 Get_Adc_Average(u8 ch,u8 times)
{
u32 aver=0;
u8 t=0;
for(;t<times;t++)
{
aver+=Get_Adc(ch);
delay_ms(5);
}
return aver/times;
}
main函数
int main(void)
{
u16 adcx;
float temp;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
delay_init(168); //延时初始化
uart_init(115200); //串口初始化波特率为115200
Adc_Init();
LED_Init(); //初始化与LED连接的硬件接口
LED1=0;
while(1)
{
adcx=Get_Adc_Average(ADC_Channel_5,20);//获取通道5的转换值,20次取平均
printf("ADC_Channel_5_VAL:%d\t\t",adcx); //显示ADCC采样后的原始值
temp=(float)adcx*(3.3/4096); //获取计算后的带小数的实际电压值,比如3.1111
printf("ADC_Channel_5_VOL:%.4fV\r",temp);
LED0=!LED0;
delay_ms(250);
}
}
运行结果
ADC模数转换实验