当我在 STM32 上激活 ADC 中断时,程序停止工作

Posted

技术标签:

【中文标题】当我在 STM32 上激活 ADC 中断时,程序停止工作【英文标题】:Program stop working as I activated ADC interrupt on STM32 【发布时间】:2022-01-03 22:15:23 【问题描述】:

我编写了生成方脉冲的代码。一切正常,直到我通过 NVIC 命令激活 ADC 中断。 ADC IRQ Handler 是否正确编写?(我对 Handler 似是而非)。 ADC 设置为仅使用一个通道的连续模式。 End_of_Conversion 和 End_of_Sequence 中断标志​​已设置。

#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】:

您的程序进入ADC1_IRQHandler 并永远停留在那里,因为处理程序是空的。

如果你启用了一个中断,你必须处理它——至少清除中断源。不要看SysTick_Handler,它是自动重置的特例。对于其他中断,必须重置相应的状态位,或执行特殊的操作序列。详细信息通常在状态寄存器的描述中找到,在您的情况下是ADC_ISR

启用 End_Of_Conversion 和 End_Of_Sequence 后,可以通过 EOC 和 EOSEQ 状态位触发中断。两者都可以通过向其写入 1 来清除。处理程序应如下所示:

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;
    

处理程序的名称取决于使用的启动,它必须与启动文件的中断向量表中的占位符名称匹配。在 Cube 生成的项目中,这是 Startup 文件夹中的一个汇编文件 (.s)(例如 /Core/Startup/startup_stm32f407zgtx.s)

【讨论】:

它可以工作,但必须编辑处理函数:ADC1_IRQHandler 到 ADC_IRQHandler 你说得对,我已经添加了有关处理程序名称的注释。 如果你使用调试器,你应该已经注意到了。在第三个千年中必须使用调试器(如果可能):D。如果这不可能,请在涉及中断时仔细检查向量表中的处理程序名称(在您的情况下,您可能可以在名为 startup_stm32f0*.S 的文件中找到它,* 是通配符或仅搜索部分名称在链接描述文件中定义)

以上是关于当我在 STM32 上激活 ADC 中断时,程序停止工作的主要内容,如果未能解决你的问题,请参考以下文章

STM32:模拟看门狗只触发一次中断HAL_ADC_LevelOutOfWindowCallback

STM32定时器触发ADC怎么配置

STM32 中定时器中断回调函数中加入adc采样轮换查询后,中断函数不执行?请问怎么解决?

重学STM32---ADC

STM32L1xx——ADC(中断/DMA)样例代码

STM32 ADC的规则通道和注入通道的区别