0

I wrote code for generation square pulse. Everything works fine till I activate ADC Interrupt by NVIC commands. Is ADC IRQ Handler wrote correctly?(I am specious on Handler). ADC Sets on continuous mode by only one channel is using. End_of_Conversion and End_of_Sequence Interrupt flag have been set.

#include <stdint.h>
#include "stm32f0xx.h"

//static __IO uint32_t RPM;
//uint32_t RPM=1000;
#define DUTY_CYCLE 0.1

void SysTick_Handler(void);
void ADC1_IRQHandler(void);

void Delay_10us(__IO uint32_t nTime);
static __IO uint32_t TimingDelay;
static __IO uint32_t adcValue;
//int calibration_factor;
uint32_t rpm;
int global_counter=0;

int main(void)
{
    //  Set SysTick for create 10 microsecond delay
    if(SysTick_Config(80))
    {
        while(1);
    }
    //CLOCK
    RCC->CR|=RCC_CR_HSEON;
    while(!(RCC->CR&RCC_CR_HSERDY));
    RCC->CR|=RCC_CR2_HSI14ON;
    while(!(RCC->CR2|=RCC_CR2_HSI14RDY));
    RCC->CFGR|=RCC_CFGR_SW_HSE;
    while(!(RCC->CFGR&=RCC_CFGR_SWS_HSE));
    RCC->APB2ENR|=RCC_APB2ENR_ADCEN;
    //  ADC1->CFGR2|=ADC_CFGR2_CKMODE_1;
    RCC->AHBENR|=RCC_AHBENR_GPIOAEN;
    //GPIO
    GPIOA->MODER|=GPIO_MODER_MODER4_0;
    GPIOA->PUPDR|=GPIO_PUPDR_PUPDR4_0;
    GPIOA->ODR|=GPIO_ODR_4;
    GPIOA->MODER|=GPIO_MODER_MODER5;
    //NVIC
    NVIC_EnableIRQ(ADC1_COMP_IRQn);/*if I comment this two lines everything works*/
    NVIC_SetPriority(ADC1_COMP_IRQn,0);/*if I comment this two lines everything works*/
    //ADC
    ADC1->CR&=~ADC_CR_ADEN;
    ADC1->SMPR|=ADC_SMPR1_SMPR;
    ADC1->CFGR1|=ADC_CFGR1_CONT;
    ADC1->IER|=ADC_IER_EOSIE|ADC_IER_EOCIE;
    ADC1->CHSELR|=ADC_CHSELR_CHSEL5;
    //  for(int i=0;i<10;i++);
    //  ADC1->CR|=ADC_CR_ADCAL;
    //  while(ADC1->CR&ADC_CR_ADCAL);
    //  calibration_factor=ADC1->DR;
    for(int i=0;i<10;i++);
    ADC1->ISR|=ADC_ISR_ADRDY;
    ADC1->CR|=ADC_CR_ADEN;
    while(!(ADC1->ISR&=ADC_ISR_ADRDY));
    ADC1->CR|=ADC_CR_ADSTART;
    /* Loop forever */
    int counter=0;
    while(1){
        if(rpm<250){rpm=250;}
        int T=10000/rpm;
        int OnDelay=T*DUTY_CYCLE;
        int OffDelay=T*(1-DUTY_CYCLE);
        GPIOA->ODR &=~GPIO_ODR_4;
        Delay_10us(OffDelay);
        GPIOA->ODR|=GPIO_ODR_4;
        Delay_10us(OnDelay);
        counter++;
        if(counter==59)
        {
            GPIOA->ODR &=~GPIO_ODR_4;
            Delay_10us(2*T);
            counter=0;
            continue;
        }
    }
}
void Delay_10us(__IO uint32_t nTime)
{
    TimingDelay = nTime;

    while(TimingDelay != 0);
}

void SysTick_Handler(void){
    if (TimingDelay != 0x00)
    {
        TimingDelay--;
    }
}
void ADC1_IRQHandler()
{
//  
}

1 Answer 1

1

Your program enters ADC1_IRQHandler and stays there forever, since the handler is empty.

If you've enabled an interrupt, you must handle it - at least clear the interrupt source. And don't look at the SysTick_Handler it is a special case with autoreset. For other interrupts the corresponding status bit must be reset, or a special sequence of operations performed. Details are usually found in the description of a status register, in your case it is ADC_ISR.

With End_Of_Conversion and End_Of_Sequence enabled, the interrupt could be triggered by the EOC and EOSEQ status bits. Both could be cleared by writing 1 to it. The handler should look something like this:

void ADC1_IRQHandler()
{
    if(ADC1->ISR & ADC_ISR_EOC)
    {
        //Handle end of conversion
        ADC1->ISR = ADC_ISR_EOC;
    }
    if(ADC1->ISR & ADC_ISR_EOSEQ)
    {
        //Handle end of sequence
        ADC1->ISR = ADC_ISR_EOSEQ;
    }
}

The name of a handler depends on the startup used, it must match name of a placeholder in the interrupt vector table of the startup file. In Cube-generated projects this is an assembler file (.s) in Startup folder (eg. /Core/Startup/startup_stm32f407zgtx.s)

Sign up to request clarification or add additional context in comments.

3 Comments

It works but must edit handler function: ADC1_IRQHandler to ADC_IRQHandler
You're right, I've added note regarding handler names.
You should have noticed it if you use a debugger. Using an debugger (if possible) is mandatory in the third millenium :D. In case that is not possible, double check you handler names in the vector table when interrupt are involved (in your case you can probably find it in a file called startup_stm32f0*.S, the * is a wildcard or just search for the section name defined in your linker script)

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.