当我在 STM32 上激活 ADC 中断时程序停止工作
Program stop working as I activated ADC interrupt on STM32
我写了生成方波的代码。一切正常,直到我通过 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()
{
//
}
您的程序进入 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;
}
}
处理程序的名称取决于所使用的启动,它必须与启动文件的中断向量 table 中占位符的名称相匹配。在多维数据集生成的项目中,这是启动文件夹中的一个汇编文件 (.s)(例如 /Core/Startup/startup_stm32f407zgtx.s)
我写了生成方波的代码。一切正常,直到我通过 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()
{
//
}
您的程序进入 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;
}
}
处理程序的名称取决于所使用的启动,它必须与启动文件的中断向量 table 中占位符的名称相匹配。在多维数据集生成的项目中,这是启动文件夹中的一个汇编文件 (.s)(例如 /Core/Startup/startup_stm32f407zgtx.s)