单片机
返回首页

关于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);

}

进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

精选电路图
  • 光控音效发生器电路

  • 如何利用ESP8266制作一个简单的四轴飞行器

  • 离子检测器电路分析

  • 如何使用LED驱动器LM3915制作振动计

  • 电谐波图形均衡器示意图

  • 一种构建12V和230V双直流电源的简单方法

    相关电子头条文章