2020-09-09 09:22 AM
This has me scratching my head - my program runs fine UNLESS the interrupt occurs, after which it gets stuck in a for loop near the start of the program. I can't see any way these two things are connected with each other - there dont share variables. The main loop is as follows
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_ADC1_Init();
MX_SPI1_Init();
MX_TIM1_Init();
MX_TIM2_Init();
MX_TIM16_Init();
ADC12_COMMON ->CCR |= 1<<19 | 1 <<17; // set ADC clock options
ADC1->CR |= 1>>0; // enable ADC
ADC1->CR |= ADC_CR_ADSTART; // start conversion
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2);
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_3);
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_2);
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_4);
HAL_TIM_PWM_Start(&htim16, TIM_CHANNEL_1);
while (1)
{
while(((ADC1->ISR) & 0b00000100)==0)
{
}
for(j=0;j<10;j++)
{
ADC_result_pre[i][j] = ADC1->DR; //fetch adc data
}
VCA_raw[i]= (ADC_result_pre[i][0]+ADC_result_pre[i][1]+ADC_result_pre[i][2]+ADC_result_pre[i][3]+ADC_result_pre[i][4]+ADC_result_pre[i][5]+ADC_result_pre[i][6]+ADC_result_pre[i][7]);
ADC_result[i] = VCA_raw[i] / 8;
switch(ADC1->SQR1) //switch dac channel to the next
{
case 0b101000000:
ADC1 ->SQR1 = 0b110000000;
i=1;
break;
case 0b110000000:
ADC1 ->SQR1 = 0b101000000;
i=0;
break;
}
ADC1->CR |= ADC_CR_ADSTART;
//======================================================================
LED1_prep = ADC_result[0]>>4;
RED1 = 255 - LED1_prep;
BLUE1 = LED1_prep;
if(RED1 <= 127)
{
GREEN1 = RED1*2;
}
else
GREEN1 = BLUE1*2;
set_rgb1(RED1,BLUE1,GREEN1); //second spot is actually blue // third is green
LED2_prep = ADC_result[1]>>4;
RED2 = 255 - LED2_prep;
BLUE2 = LED2_prep;
if(RED2 <= 127)
{
GREEN2 = RED2*2;
}
else
GREEN2 = BLUE2*2;
set_rgb2(RED2,BLUE2,GREEN2); //1st green, 2nd red, third blue
//========================================================================
Prepare_States(ADC_result[0],0); //get the mode info for the first channel
prep_values(0);
// dac_channel = 1;
Prepare_States(ADC_result[1],1); //and for the second
// prep_values(1);
}
}
It gets stuck on the for loop on line 32. I can see j incrementing up to 9, then it gets reset and stays in the loop. The interrupt is as follows
void EXTI15_10_IRQHandler(void)
{
uint32_t mask = 0;
uint32_t Chuff = ChangeFlag;
if (Chuff & 1<<2)
mask = (1<<4);
else
mask = (1<<20);
if (Chuff & 1<<3)
mask |= (1<<12);
else
mask |= (1<<28);
GPIOA->BSRR = mask;
Chuff |= 1<<0;
ChangeFlag |= Chuff;
EXTI->PR1 |= 1<<11; //turn off interrupt request
}
I can't see any way these things are related. Any help much appreciated!
2020-09-09 02:37 PM
Next time, include your chip number.
There's nothing on line 32 for it to get stuck on.
It's possible an interrupt is being called continuously which prevents the processor from doing anything in the main loop. It's not clear if you're enabling interrupts with ADC or not. It doesn't look like you clear the ISR flags anywhere.
for(j=0;j<10;j++)
{
ADC_result_pre[i][j] = ADC1->DR; //fetch adc data
}
This isn't going to work as intended. The DR register is not a FIFO, it only holds the last conversion. Maybe I'm missing the logic here.
2020-09-10 03:48 AM
Thanks for the comment. Im using an STM32L412. I didn't want to use the HAL to clear the interrupt request so Im using
EXTI->PR1 |= 1<<11;
is this OK? it seems to work fine and in any case, using the HAL
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_11);
doesn't solve the problem.
The problem seems to be with the variable 'changeflag'. I want this to be accessible within my main program, so I've declared it as
extern volatile uint8_t ChangeFlag;
in both the program and the interrupt file. Is this the correct way to declare it?
2020-09-10 05:28 AM
> EXTI->PR1 |= 1<<11;
> is this OK?
Yes, I missed that.
> The problem seems to be with the variable 'changeflag'
I don't understand. You're saying ChangeFlag is causing the program to be stuck in a for loop? How did you reach that conclusion? You're not even using ChangeFlag in the main loop anywhere.
The variable should be declared/defined normally in one source file and the declared as "extern" in the others, or in an included header.
2020-09-10 05:41 AM
It sounds like you understand exactly what im saying
When i run in debug mode, I run the program and it runs fine. As soon as I connect the external trigger to the circuit it enters the interrupt, then when it exits it stays in that for loop on line 32 forever - im using the step into command to see each line of execute. i see the variable j increment up to 9, reset and count up again without ever leaving the for loop.
I deleted everything from the interrupt apart from a slightly modified command
ChangeFlag |= 1<<0;
it still happens. If i delete that and leave the interrupt blank, it stops happening.
it seems weird to me too
2020-09-10 07:12 AM
so if i have
uint32_t ChangeFlag;
in main.c and
extern uint32_t ChangeFlag;
in stm32l4xx_it.c - this is correct?