Author Topic: Enabling TIM6 ISR makes ADC1 not working - STM32F303  (Read 736 times)

0 Members and 1 Guest are viewing this topic.

Offline ppTRNTopic starter

  • Regular Contributor
  • *
  • Posts: 169
  • Country: it
Enabling TIM6 ISR makes ADC1 not working - STM32F303
« on: March 26, 2025, 06:37:17 pm »
Hi all,
as my journey in peripherals programming continues, i am facing a whole new problem. I want to generate a square wave which period depends on some data read by the ADC. First I tested the ADC acquisition and works perfectly. I sample two channels in single conversion mode, where each conversion is triggered by a function called by the Systick. The ADC resouls are retrived from its ISR. Again, it works just fine.

On the same code we have also TIM15, TIM16 and TIM17 that does other jobs.

Now, when I enable the interrupts of TIM6, the ADC stops working. I tought it was about interrupt priorities, but it appears to be complitely unlinked. I also tought that it was due to my messing with the TIM6 ARR "on the fly", but it was not.

Would you please help me?

As always I thank you for the time you spent for me until now.

ADC CODE:

Code: [Select]
extern int Q, I;

void ADC1_Init(void) {
    // Enable clock for GPIOA and ADC1
    RCC->AHBENR |= RCC_AHBENR_GPIOAEN;
    RCC->AHBENR |= RCC_AHBENR_ADC12EN;

    // Configure GPIOA pins 0 (PA0) and 1 (PA1) as analog mode
    GPIOA->MODER |= (3U << (0 * 2)) | (3U << (1 * 2));

    // Set ADC1 clock prescaler and clock source
    RCC->CFGR2 |= RCC_CFGR2_ADCPRE12_DIV4; // Set ADC clock prescaler
    ADC12_COMMON->CCR &= ~ADC12_CCR_CKMODE; // Select synchronous clock mode (HCLK/1)

    // Enable ADC1 voltage regulator
    ADC1->CR &= ~ADC_CR_ADVREGEN;
    ADC1->CR |= ADC_CR_ADVREGEN_0;

    // Configure ADC resolution and alignment
    ADC1->CFGR &= ~ADC_CFGR_RES; // 12-bit resolution
    ADC1->CFGR &= ~ADC_CFGR_ALIGN; // Right alignment
    ADC1->CFGR &= ~ADC_CFGR_CONT;  // Ensure single conversion mode

    // Enable ADC1
    ADC1->ISR |= ADC_ISR_ADRDY;
    ADC1->CR |= ADC_CR_ADEN;
    while (!(ADC1->ISR & ADC_ISR_ADRDY)); // Wait for ADC to be ready

ADC1->IER |= 1<<2; // Interrupt enable on EOC
NVIC_SetPriority(ADC1_2_IRQn, 2);
NVIC_EnableIRQ(ADC1_2_IRQn);
}

void ADC1_Read(uint8_t channel) {
  ADC1->SQR1 = 0; // Clear previous selection 

if (channel == 1) ADC1->SQR1 |= 1<<6; // Select channel 1 (PA0)
   
if (channel == 2) ADC1->SQR1 |= 1<<7; // Select channel 2 (PA1)

ADC1->CR |= ADC_CR_ADSTART; // Start conversion
}

void ADC1_2_IRQHandler(){
ADC1->ISR = 1<<2; // Clear EOC interrupt flag
if(ADC1->SQR1 & 1<<6) Q = ADC1->DR;
if(ADC1->SQR1 & 1<<7) I = ADC1->DR;
}


TIM6 CODE:

Code: [Select]
/*
This function uses TIM6 in order to generate the low frequency tone.
The tone is linked to the Q signal sampled by the ADC and it rises in
frequency if the Q signal LOWERS while it lowers in frequency otherwise.
The signal is outputed on pin PA5 and its generation is gated by
the reach of a predetermined threshold, in order to avoid a noisy search.

FREQUENCY DYNAMIC: 330Hz to 630Hz (means toggle at 660Hz and 1260Hz)

We can set the PSC in order to generate exactly 330Hz and then move the ARR
in order to decrease the frequency.

If we choose a PSC = 10 we get a Ftick of 6.4MHz -> Ttick = 156.25ns
This means that we can place our ARR at 9696 for a 660Hz toggle.
  We can change the tone going up by simply adding the difference
  of the ADC reading from its steady value (2048) multiplied by
four in order to increase sensitivity.

ARR = ARRbase + (Q - 2048)*4;


*/

#include "stm32f303x8.h"


extern int Q, Qthreshold, ARRbaseLow;

void QtoneInit(){

RCC->APB1ENR |= RCC_APB1ENR_TIM6EN;

RCC->AHBENR |= RCC_AHBENR_GPIOAEN; // GPIOA clock enable

GPIOA->MODER &= ~(1<<11); // GPIOA5 in output mode
GPIOA->MODER |= 1<<10;

GPIOA->PUPDR |= 1<<11; // GPIOA5 internal pulldown enable

TIM6->DIER |= 1<<0; // Interrupt on update event
TIM6->SR |= 0; // Interrupt flags registers
TIM6->ARR = ARRbaseLow;
TIM6->PSC = 9696;
TIM6->CR1 |= 1; // TIM6 enabled

NVIC_SetPriority(TIM6_DAC1_IRQn, 5);
NVIC_EnableIRQ(TIM6_DAC1_IRQn);
}

void TIM6_IRQHandler(){
TIM6->SR = 1<<0; // Clear pending interrupt flag

if(Q <= 2048-Qthreshold || Q >= 2048+Qthreshold){ // If we are above threshold
GPIOA->ODR ^= 1<<5; // We toggle the tone pin
}
else GPIOA->ODR &= ~(1<<5); // If not we turn it off
}

A PIECE OF MAIN:

Code: [Select]
/* ********** INVERTING CHARGE PUMP SIGNAL GENERATION ********* */
timer16Init();
/* ********** QUADRATURE AND PHASE SIGNAL GENERATION ********** */
timer15Init();
/* ************* FREQUENCY MEASURE INITIALIZATION ************* */
  timer17Init();
EXTI0Config();
/* ************* ROTARY ENCODER INITIALIZATION ************* */
EXTI1Config();
EXTI2Config();
/* ******************* 10ms SysTick CONFIGURATION ****************** */
SysTick->CTRL |= 1<<1 | 1<<0;
SysTick->LOAD = 640000;  
/* ************* ANALOG TO DIGITAL CONVERSION ************ */
ADC1_Init();
/* ************* TONE GENERATION INITIALIZATION ************* */
//QtoneInit();
//ItoneInit();
/* ************************************************************ */

  while (1){
if(conversion == 0 && conversionFlag == 0){ // Q channel conversion
ADC1_Read(1); // Q channel acquisition
TIM6->ARR = ARRbaseLow + (Q - 2048)*4; // Value to generate the low frequency tone
conversionFlag = 1;
}
if(conversion == 1 && conversionFlag == 1){ // I channel conversion
ADC1_Read(2); // I channel acquisition
//TIM7->ARR = ARRbaseHigh + (I - 2048)*24; // Value to generate the high frequency tone
conversionFlag = 0;
}
  }
 

Online ajb

  • Super Contributor
  • ***
  • Posts: 2830
  • Country: us
Re: Enabling TIM6 ISR makes ADC1 not working - STM32F303
« Reply #1 on: March 26, 2025, 07:15:17 pm »
Can you be a little more specific with "when I enable the interrupts of TIM6, the ADC stops working"? 

What happens exactly when the ADC "stops working" -- do you get incorrect results, does the ISR not run, or something else?

If you comment/uncomment just the NVIC_EnableIRQ call for the timer, does that toggle the ADC failure? 
 

Offline ppTRNTopic starter

  • Regular Contributor
  • *
  • Posts: 169
  • Country: it
Re: Enabling TIM6 ISR makes ADC1 not working - STM32F303
« Reply #2 on: March 26, 2025, 07:38:01 pm »
Hi,

the fault disappears when i comment one of the following:
Code: [Select]
TIM6->DIER |= 1<<0; // Interrupt on update event
or
NVIC_EnableIRQ(TIM6_DAC1_IRQn);

Both clearely in charge of enabling the interrupt.

When I say that the ADC stops working I mean that it no longer performs conversions because the lines of code inside the while(1) are never executed.
Those lines performs alternatively the conversion of CH1 and CH2, and they are triggered bu the Systick
Code: [Select]
void SysTick_Handler(void)
{
conversion = 1-conversion;
  HAL_IncTick();
}
The systick ISR is reached every time, so it always updates the variable "conversion". But it is like the only thing alive in the system. The code inside the while(1) is never executed.

I am noticing one more thing tho. After executing the systick ISR the code jumps to a
Code: [Select]
B      .
instruction on the startup .s file. That's why it gets stuck. But why? This instruction is at the end of the ISR names exports.
It is like it never returns form the  ISR maybe? But again, why do it only when the TIM6 interrutps are enabled?

 I hope I answared clearely, thank you
 

Offline ppTRNTopic starter

  • Regular Contributor
  • *
  • Posts: 169
  • Country: it
Re: Enabling TIM6 ISR makes ADC1 not working - STM32F303
« Reply #3 on: March 26, 2025, 07:39:58 pm »
Oh my... I think I called the ISR TIM6_IRQHandler while its name is supposed to be TIM6_DAC1_IRQHandler.... Let me try it
 

Offline Dan N

  • Contributor
  • Posts: 25
  • Country: us
Re: Enabling TIM6 ISR makes ADC1 not working - STM32F303
« Reply #4 on: March 26, 2025, 08:09:29 pm »
Code: [Select]
TIM6->SR = 1<<0; // Clear pending interrupt flag

You have to carefully read the reference manual for these flags.  This one is cleared by writing a 0 (writing 1 has no effect):

Code: [Select]
TIM6->SR = ~(1<<0); // Clear pending interrupt flag

more readable if you use the defines in the cmsis headers:
        TIM6->SR = ~TIM_SR_UIF
 
The following users thanked this post: voltsandjolts

Offline ppTRNTopic starter

  • Regular Contributor
  • *
  • Posts: 169
  • Country: it
Re: Enabling TIM6 ISR makes ADC1 not working - STM32F303
« Reply #5 on: March 26, 2025, 09:31:16 pm »
Damn, here's another mistake.  :palm: Why do they do this? Why in the same chip there are peripherals whose interrupt flag is cleared by writing a 1 and others in which it is the opposite?

Thanks tho, I sometimes feel like this errors are really stupid, I guess I need to put more attention in what I do, and I do not want to abuse of your help and patience. Tomorrow I will fix it and see if it works.

Thanks a lot for your help
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf