1
\$\begingroup\$

I am doing simple ADC test with potentiometer on STM32F103C8, it seems to work fine for 5 seconds or so, but then the whole uC just stops - even while loop stops doing what it is supposed to do(so I guess it doesn't even leave interrupt routine when it fails).
It probably has to do something with ADC initialization, but I can't see what exactly is wrong.
Below is my ADC.c with ADC initialization and my main.c(note that I outputting "1" and "2" just to monitor if it is still doing while loop stuff - and it doesn't, everything freezes)
If it is not initialization, then maybe it is hardware problem, but with such circuit I can't think of anything that can go wrong, board has capacitor for ADC and I even tried to put another one between signal and ground, nothing...

UPD
OK, Now I look like a total idiot... It turned out that it was not microcontroller that got stuck, but the LCD. I tried to change it to different LCD (it was 4x20, changed to 2x16) and it not halting now. I noticed that it is if I would fiddle the wires a little bit it would halt with bigger probability, so probably if the connection is not solid 100% of time LCD encounters some kind of internal error and got stuck, it does not happen with other LCD for some reason. Apparently vibration from me touching breadboard did something to connection and LCD freaked out. So whoever encounters same problem - try using different LCD, check the wiring(try to fiddle it to see if it affects anything), check if driver code is good, etc.

ADC.c


void ADC_init(void)
{
    GPIO_InitTypeDef adcpin; 
    ADC_InitTypeDef MyADCinit;

    ///
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

    adcpin.GPIO_Pin = GPIO_Pin_0;
    adcpin.GPIO_Mode = GPIO_Mode_AIN;

    GPIO_Init(GPIOB, &adcpin);
    ////

    ////
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); // Turn on ADC clock
    ////




  /* Initialization of ADC */
  MyADCinit.ADC_Mode = ADC_Mode_Independent;
  MyADCinit.ADC_ScanConvMode = DISABLE;
  MyADCinit.ADC_ContinuousConvMode = DISABLE;
  MyADCinit.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
  MyADCinit.ADC_DataAlign = ADC_DataAlign_Right;
  MyADCinit.ADC_NbrOfChannel = 1;

    ADC_Init(ADC1, &MyADCinit);


    // specify channel we want to use
    ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 1, ADC_SampleTime_55Cycles5); // Rank - the order number by which scanning is done

    // enable interrupts on ADC
    NVIC_EnableIRQ(ADC1_2_IRQn);

    // enable interrupts on the end of conversion
    ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE);

    // Turn on ADC
    ADC_Cmd(ADC1, ENABLE);

}

main.c


#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#include "HD44780.h"
#include "ADC.h"
#include 

uint16_t data_adc;
char adcResult[4];


void ADC1_2_IRQHandler(void)
{
    if (ADC_GetITStatus(ADC1, ADC_IT_EOC) == SET)
    {
        ADC_ClearITPendingBit(ADC1, ADC_IT_EOC);
        data_adc = ADC_GetConversionValue(ADC1);

        LCD_GoTo(0,0);
        sprintf(adcResult, "ADC = %d", data_adc);
        LCD_SendText(adcResult);
        LCD_SendText("   ");
    }
}

int main (void)
{
    RCC_Configuration(); // Configure the system clocks.
    LCD_Init();          // Initialize the LCD.
    LCD_Clear();         //Clear the LCD.
    delay_ms(1000);
    ADC_init();

    while(1)
    {
        delay_ms(10);
        ADC_SoftwareStartConvCmd(ADC1, ENABLE); // check functional state... wtf is that
        LCD_GoTo(0,0);
        LCD_SendText ("1");
        delay_ms(100);
        LCD_GoTo(0,0);
        LCD_SendText ("2");
        delay_ms(50);
    }

}

\$\endgroup\$
20
  • \$\begingroup\$ You will need to restart the ADC to start again a conversion.You are doing this by disable and enable the ADC. \$\endgroup\$ Commented Oct 11, 2015 at 3:30
  • \$\begingroup\$ Sprintf inside an ISR ain't advisable. Your stack could overflow triggering a hard fault. Put a breakpoint in your hardfault handler and see if the control is transferred to your hardfault handler. I am guessing your hard fault handler has an infinite loop running causing the controller to halt \$\endgroup\$
    – Adithya
    Commented Oct 11, 2015 at 10:06
  • \$\begingroup\$ @Adithya, I tried outputting without using sprintf - same stuff, it freezes. And even if sprintf was the problem - it is not usual, sure it is not optimal output method, but it is used in countless examples and it does not causes the entire uC to halt for everyone who tries it. \$\endgroup\$ Commented Oct 11, 2015 at 11:55
  • \$\begingroup\$ Your string "ADC = %d" will always be greater than 4 characters won't it? Try increasing the size of your ADC array? I am not sure if sprintf truncates the extra characters or tries to store it in addresses that aren't a part of your array. \$\endgroup\$
    – Adithya
    Commented Oct 11, 2015 at 12:01
  • \$\begingroup\$ @Adithya, even if I completely delete sprintf line and just output some random commands(directly sending them to lcd without any sprintf conversion) it halts, sprintf is not the stuff to look at here since even if it does not exist in code uC freezes. And yes, char array is smaller than sprintf conversion, thanks, haven't noticed... but that's beside the point \$\endgroup\$ Commented Oct 11, 2015 at 12:08

1 Answer 1

1
\$\begingroup\$

Try only getting the ADC value in the IRQ handler and letting the main loop do the LCD processing which may be triggering an interrupt that is preempted by the ADC interrupt you are already in, causing a lock.

Maybe make sure your ADC clock is correctly configured.

Maybe try without the interrupt:

    ADC_SoftwareStartConvCmd(ADC1, ENABLE);
    while(ADC_GetSoftwareStartConvStatus(ADC1));
    while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));
    data_adc = ADC_GetConversionValue(ADC1);
    ADC_ClearFlag(ADC1, ADC_FLAG_EOC);
\$\endgroup\$
1
  • \$\begingroup\$ Hey, thanks for your answer, it turned out to be completely different problem(read edit to original post). Thanks for your time anyway. :) \$\endgroup\$ Commented Oct 11, 2015 at 13:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.