关于STM32F0系列多路ADC单独采样数据相同问题的处理
2021-09-26 来源:eefocus
先看一下,大家认为“正确”的代码
void MYADC_init(void) {
//时钟使能
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
//GPIO配置
GPIO_InitTypeDef PORT_ADC;
PORT_ADC.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
PORT_ADC.GPIO_Mode = GPIO_Mode_AN;
PORT_ADC.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &PORT_ADC);
//ADC配置
ADC_InitTypeDef ADC_InitStuctrue;
ADC_InitStuctrue.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStuctrue.ADC_ContinuousConvMode = DISABLE;
ADC_InitStuctrue.ADC_ExternalTrigConv= ADC_ExternalTrigConvEdge_None;
ADC_InitStuctrue.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStuctrue.ADC_ScanDirection = ADC_ScanDirection_Backward;
ADC_Init(ADC1, &ADC_InitStuctrue);
//ADC使能
ADC_Cmd(ADC1, ENABLE);
}
unsigned short MYADC_getValue(unsigned char arg0) {
if(arg0==1){
ADC_ChannelConfig(ADC1, ADC_Channel_1, ADC_SampleTime_239_5Cycles);
}else if(arg0==2){
ADC_ChannelConfig(ADC1, ADC_Channel_2, ADC_SampleTime_239_5Cycles);
}else if(arg0==3){
ADC_ChannelConfig(ADC1, ADC_Channel_3, ADC_SampleTime_239_5Cycles);
}
while (ADC_GetFlagStatus(ADC1, ADC_FLAG_ADRDY) == RESET);
ADC_StartOfConversion(ADC1);
while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);
return ADC_GetConversionValue(ADC1);
}
int main(void){
//此处完成你的各种初始化
MYADC_init();
unsigned short adcValue1;
unsigned short adcValue2;
unsigned short adcValue3;
while(1){
adcValue1=MYADC_getValue(1);
//此处加入程序,如将adcValue打印发送出来
adcValue2=MYADC_getValue(2);
//此处加入程序,如将adcValue打印发送出来
adcValue3=MYADC_getValue(3);
//此处加入程序,如将adcValue打印发送出来
}
}
以上代码,是我之前认为“正确”的代码,但是当执行while时,一开始打印出来的3个值adcValue1,adcValue2和adcValue3都是正确的,但是后面继续打印的数据都是同adcValue3。
那是什么原因造成的吗?
原来,问题出在ADC_ChannelConfig()函数。
大家可以在STM32库源文件中找到如下图所示代码。
问题在于,库函数中对ADC通道选择寄存器的赋值用的是或“|”,当while(1)第一次执行该函数时,ADC_Channel=0x00000001,CHSELR=0x00000001,ADC转换数据对应第一通道,第二次执行该函数的时候,ADC_Channel=0x00000010,CHSELR=0x00000011,因为是独立采样模式,系统对高位有效通道进行采样,对应结果为第2通道的值。第三次执行该函数时,ADC_Channel=0x0000100,CHSELR=0x00000111,同样,因为是独立采样模式,对应结果为第3通道的值。在while再次循环时,我们预期结果希望是第一通道,但是实际上此时的CHSELR值已经是0x00000111了,在和0x00000001相或,值还是0x00000111,所以实际结果是最高位,即第3通道的值。
针对多通道单独采样模式,个人建议直接对CHSELR寄存器进行赋值,使用方法如下:
unsigned short MYADC_getValue(unsigned char arg0) {
if(arg0==1){
ADC_ChannelConfig(ADC1, ADC_Channel_1, ADC_SampleTime_239_5Cycles);
ADC1->CHSELR =ADC_Channel_1;
}else if(arg0==2){
ADC_ChannelConfig(ADC1, ADC_Channel_2, ADC_SampleTime_239_5Cycles);
ADC1->CHSELR =ADC_Channel_2;
}else if(arg0==3){
ADC_ChannelConfig(ADC1, ADC_Channel_3, ADC_SampleTime_239_5Cycles);
ADC1->CHSELR =ADC_Channel_3;
}
while (ADC_GetFlagStatus(ADC1, ADC_FLAG_ADRDY) == RESET);
ADC_StartOfConversion(ADC1);
while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);
return ADC_GetConversionValue(ADC1);
}