2016-12-16 1:07 AM
Hello Everyone.
I would like to infrom you that I am trying to measure battery voltage which is connected to ADC12_IN4 pin of stm32f103c8t6 microcontroller with ADC.
I wrote proper code for configurations and reading battery voltage.But Unfortunately it only shows ''0'' as battery voltage in integer.I obtain this data and analyze using web server, in this case I am able to see what is the value of battery voltage.
My question is; Is there anything wrong in my code?
I would like to show you my circuit design,datasheet and part of code for clear understanding
Datasheet, pin connection
Part of my circuit design with microcontroller
My codes for ADC configurations
&sharpinclude ''ADCTIMER.h''
&sharpinclude ''stdio.h''&sharpinclude ''string.h''&sharpinclude ''stm32f10x.h''&sharpinclude ''stm32f10x_flash.h''&sharpinclude ''stm32f10x_gpio.h''&sharpinclude ''stm32f10x_adc.h''&sharpinclude ''stm32f10x_rcc.h''//ADC GPIO CONFIGURATIONS
void ADC::ADC_GPIO_INIT(void){GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin= GPIO_Pin_4; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; GPIO_Init(GPIOA,&GPIO_InitStructure); }//ADC CONFIGURATIONSvoid ADC::ADC_Battery_Voltage (void) {ADC_InitTypeDef ADC_InitStructure;
//PCLK2 is the APB2 clock //ADCCLK = PCLK26 = 726 = 12MHz RCC_ADCCLKConfig(RCC_PCLK2_Div6);RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
//Put everything back to power-on defaults ADC_DeInit(ADC1); ADC_InitStructure.ADC_Mode=ADC_Mode_Independent; ADC_InitStructure.ADC_ScanConvMode=DISABLE; ADC_InitStructure.ADC_ContinuousConvMode=ENABLE; ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfChannel = 1 ; ADC_Init(ADC1,&ADC_InitStructure);ADC_Cmd(ADC1,ENABLE);
ADC_ResetCalibration(ADC1); while(ADC_GetResetCalibrationStatus(ADC1)); ADC_StartCalibration(ADC1); while(ADC_GetCalibrationStatus(ADC1)); }//NVIC INTERRUPT METHODE FOR ADCvoid ADC::NVIC_Interrupt_ADC(){ NVIC_InitTypeDef NVIC_InitStructure; ADC_RegularChannelConfig(ADC1,ADC_Channel_4,1,ADC_SampleTime_13Cycles5); NVIC_InitStructure.NVIC_IRQChannel=ADC1_2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0; NVIC_InitStructure.NVIC_IRQChannelSubPriority=0; NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE; NVIC_Init(&NVIC_InitStructure);}
//Read adc value methode
int ADC::ADC1_Read_Value(){int ADC_value; ADC_RegularChannelConfig(ADC1,ADC_Channel_4,1,ADC_SampleTime_1Cycles5); ADC_SoftwareStartConvCmd(ADC1,ENABLE); while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET); ADC_value = ADC_GetConversionValue(ADC1); ADC_ClearFlag(ADC1, ADC_FLAG_EOC); check_adc_value = activate; return ADC_value;}
My main NVIC Interrupt handler code
////----------------------------------------ADC APPLICATION NVIC INTERRUPT CONTROLLER--------------------------------int ADC_Value_battery;
extern ''C''{void ADC1_2_IRQHandler(void){if(ADC_GetITStatus(ADC1,ADC_IT_EOC != RESET)){ if(adc.check_adc_value){ADC_Value_battery = adc.ADC1_Read_Value(); }ADC_ClearITPendingBit(ADC1,ADC_IT_EOC);}}}My main code(for example, shortened)
int main(void){
adc.ADC_GPIO_INIT();
adc.ADC_Battery_Voltage(); adc.NVIC_Interrupt_ADC();while(1)
{gsm.sendGPSData(gpsData,trailer,ADC_Value_battery);
}
}
Here what I see in my server (ALL ZERO ''0'')
Any help highly apreciated.
#interrupt #nvic #c++ #stm32-adc #interrupt-handler2016-12-16 9:37 AM
Your code doesn't have any sensible flow or logic to it. You don't enable the interrupt on the ADC, nor do you create the conditions for the EOC interrupt to occur.
I'm assuming here the IRQ handler never gets called, something you could perhaps confirm with some debugging. Consequently the variable never changes from zero.
When you get an EOC interrupt the data is already available, you read it and start the *next* conversion. More sensibly you use a TIM to pace the conversions are some reasonable frequency, a value you write at 1Hz doesn't need to sample thousands of times per second.
Move all the initialization stuff into one spot, put the channel selection and start conversion stuff .
2016-12-16 11:01 AM
A less muddled approach using your code as a basis
#include 'ADCTIMER.h'
#include 'stdio.h'
#include 'string.h'
#include 'stm32f10x.h'
#include 'stm32f10x_flash.h'
#include 'stm32f10x_gpio.h'
#include 'stm32f10x_adc.h'
#include 'stm32f10x_rcc.h'
//ADC GPIO CONFIGURATIONS
void ADC::ADC_GPIO_INIT(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin= GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOA,&GPIO_InitStructure);
}
//ADC CONFIGURATIONS
void ADC::ADC_Battery_Voltage (void)
{
ADC_InitTypeDef ADC_InitStructure;
//PCLK2 is the APB2 clock
//ADCCLK = PCLK26 = 726 = 12MHz
RCC_ADCCLKConfig(RCC_PCLK2_Div6);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
//Put everything back to power-on defaults
ADC_DeInit(ADC1);
ADC_InitStructure.ADC_Mode=ADC_Mode_Independent;
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_InitStructure.ADC_NbrOfChannel = 1;
ADC_Init(ADC1,&ADC_InitStructure);
/* Configure the channel(s) */
ADC_RegularChannelConfig(ADC1,ADC_Channel_4,1,ADC_SampleTime_13Cycles5);
ADC_Cmd(ADC1,ENABLE);
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));
}
//NVIC INTERRUPT METHODE FOR ADC
void ADC::NVIC_Interrupt_ADC()
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel=ADC1_2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* Enable EOC interrupt */
ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE);
/* Start first conversion */
ADC_SoftwareStartConvCmd(ADC1,ENABLE);
}
////----------------------------------------ADC APPLICATION NVIC INTERRUPT CONTROLLER--------------------------------int ADC_Value_battery;
extern 'C' void ADC1_2_IRQHandler(void)
{
if (ADC_GetITStatus(ADC1, ADC_IT_EOC != RESET))
{
ADC_Value_battery = ADC_GetConversionValue(ADC1);
ADC_SoftwareStartConvCmd(ADC1,ENABLE); // Start Next
// Reading ADC Should clear this
// ADC_ClearITPendingBit(ADC1,ADC_IT_EOC);
}
}
int main(void)
{
adc.ADC_GPIO_INIT();
adc.ADC_Battery_Voltage();
adc.NVIC_Interrupt_ADC();
while(1)
{
gsm.sendGPSData(gpsData,trailer, ADC_Value_battery); // make sure variable is volatile
// Consider starting next conversion here
}
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?
2016-12-18 11:16 PM
Thank you Clive,
I will try to configure as you mentioned above.This is first time I tried ADC pins for arm and I am still learning new things on it.