STM32F0的多路ADC 无DMA
Posted Montauk
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了STM32F0的多路ADC 无DMA相关的知识,希望对你有一定的参考价值。
前段时间几乎用了一下午的时间, 就为了调F0的两路ADC, 一开始想的办法是将采样的连续模式(ADC_ContinuousConvMode)使能, 然后连续拿两个值, 拿完分别返回.
坏处不用说, 看着就傻, 就算你只需要一个ADC通道的值, 也要拿足N个, 比如你一共要拿5个ADC引脚的电压, 那就要全拿, 然后取其中第若干个, 如果你要拿8个做平均, 就要把时间再乘8, 看着就蠢.
但是反复调试发现如果不连续采样, 第一次ok, 但是后面每次就只采后一个通道了, 很奇怪, 结果发现原来是居然没有一个方法去reset一个记录通道的寄存器, 看完规格书只能手动重置了.
ADC初始化:
void ADC1_DMA_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_Init(GPIOA, &GPIO_InitStructure);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 , ENABLE);
ADC_DeInit(ADC1);
ADC_StructInit(&ADC_InitStructure);
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_ScanDirection = ADC_ScanDirection_Upward;
ADC_Init(ADC1, &ADC_InitStructure);
ADC_ChannelConfig(ADC1, ADC_Channel_7 , ADC_SampleTime_239_5Cycles); /* Convert the ADC1 Channel 1 with 239.5 Cycles as sampling time */
ADC_ChannelConfig(ADC1, ADC_Channel_0 , ADC_SampleTime_239_5Cycles); /* Convert the ADC1 Channel 1 with 239.5 Cycles as sampling time */
ADC_GetCalibrationFactor(ADC1);
ADC_Cmd(ADC1, ENABLE);
}
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
关掉连续模式.
接着是重点:
uint32_t getBatteryVol(void){
__IO uint32_t i;
__IO uint32_t result;
__IO uint16_t tempADCResult=0,tempADCResultRef=0, tempADCBetween=0;
__IO uint32_t average=0;
ADC1->CHSELR = 0;
ADC_ChannelConfig(ADC1, ADC_Channel_0 , ADC_SampleTime_239_5Cycles); /* Convert the ADC1 Channel 1 with 239.5 Cycles as sampling time */
ADC_ClearFlag(ADC1, ADC_FLAG_EOC);
ADC_StartOfConversion(ADC1);
while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);
tempADCResultRef = ADC_GetConversionValue(ADC1);
average = tempADCResultRef;
for(i=1; i<8; i++){
ADC_StartOfConversion(ADC1);
while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET){}
tempADCResult = ADC_GetConversionValue(ADC1);
if( tempADCResult >= tempADCResultRef){
tempADCBetween= tempADCResult - tempADCResultRef;
}else{
tempADCBetween = tempADCResultRef - tempADCResult;
}
if(tempADCBetween <= ADC_Smoth){
average += tempADCResult;
tempADCResultRef = tempADCResult;
}else{
average += tempADCResultRef;
}
}
result = ((average >> 3 )* 2500 >> 12) * 2;
return result;
}
ADC1->CHSELR = 0;
先把这个记录通道的寄存器(ADC1->CHSELR)reset掉, 然后制定再指定通道, 然后取8次相加再除8, 还做了一个平滑处理, 其实没必要.最后按照2.5伏参考电压再结合50%的分压返回一个实际的mv为单位的值.
然后另一个取ADC的函数跟这个完全一样, 除了一行:
ADC_ChannelConfig(ADC1, ADC_Channel_0 , ADC_SampleTime_239_5Cycles); /* Convert the ADC1 Channel 1 with 239.5 Cycles as sampling time */
换成:
ADC_ChannelConfig(ADC1, ADC_Channel_7 , ADC_SampleTime_239_5Cycles); /* Convert the ADC1 Channel 7 with 239.5 Cycles as sampling time */
其他一毛一样, 就能取A7引脚, ADC1_7通道的值了, 最后分压啥的,就不多说了.
以上是关于STM32F0的多路ADC 无DMA的主要内容,如果未能解决你的问题,请参考以下文章