AnsweredAssumed Answered

STM32F0: Multiple interrupts and TIM2 Clock

Question asked by jooya.ali on Jun 4, 2014
Latest reply on Mar 11, 2016 by Clive One
Hello,
I am working on a frequency monitor code. It uses TIM2 to measures the frequency and period of an external signal (PA0). I don't want to use capture mode for this. 
The code works but the reported frequency and period are not correct. I don't know If I have messed up with multiple interrupt sources (IRQ and TIM2) or I am using the wrong frequency for TIM2 input clock.

When I enter an ISR, I first disable all interrupts (is it necessary?) and at the end of ISR I re-enable them.
I have set the priority of both interrupts to 0. And I am using "Clock_PCK" as the clock frequency of TIM2. 

Any help is appreciated.

Here is my code:

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32f0xx.h"
#include "stm32f0_discovery.h"
#include <stdio.h>


__IO uint32_t CNT_Value; // timer counter value
__IO uint32_t Frequency = 0;
__IO uint32_t SPeriod = 0;
__IO uint32_t Timmer_Events=0; // number of timer overflows between two rising edges of the external signal
__IO uint32_t SysClk=0;
__IO uint32_t Clock_HCK=0;
__IO uint32_t Clock_SCK=0;
__IO uint32_t Clock_PCK=0;

int timer_disabled=1;
uint16_t Period;
uint32_t Prescalar;


int main(void)
{
     int Prescalar, Period;  // TIM2 prescalar and period




     EXTI_InitTypeDef   EXTI_InitStructure;
     GPIO_InitTypeDef   GPIO_InitStructure;
     NVIC_InitTypeDef   NVIC_InitStructure;
     USART_InitTypeDef USART_InitStructure;
     TIM_TimeBaseInitTypeDef timerInitStructure;
     NVIC_InitTypeDef nvicStructure;
     RCC_ClocksTypeDef RCC_Clocks;




     //Frequency and Period for TIM2!
     Prescalar=0;
     Period=10000;

     /* Enable SYSCFG clock */
     RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);


     RCC_SYSCLKConfig(RCC_SYSCLKSource_HSI); //HSI used as system clock
     SysClk=RCC_GetSYSCLKSource(); //AHB clock = SYSCLK
     RCC_HCLKConfig(RCC_SYSCLK_Div1); //APB clock = SYSCLK
     RCC_PCLKConfig(RCC_HCLK_Div1); //APB clock = HCLK (AHB clock)


     RCC_GetClocksFreq(&RCC_Clocks);
     Clock_HCK = RCC_Clocks.SYSCLK_Frequency;
     Clock_SCK = RCC_Clocks.HCLK_Frequency;
     Clock_PCK = RCC_Clocks.PCLK_Frequency;


     // USART configuration
     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);

     RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);

     GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1);
     GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1);

     /* Configure USART1 pins:  Rx and Tx ----------------------------*/
     GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_9 | GPIO_Pin_10;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
     GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
     GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
     GPIO_Init(GPIOA, &GPIO_InitStructure);


     USART_InitStructure.USART_BaudRate = 9600;
     USART_InitStructure.USART_WordLength = USART_WordLength_8b;
     USART_InitStructure.USART_StopBits = USART_StopBits_1;
     USART_InitStructure.USART_Parity = USART_Parity_No;
     USART_InitStructure.USART_HardwareFlowControl =          USART_HardwareFlowControl_None;
     USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
     USART_Init(USART1, &USART_InitStructure);


     USART_Cmd(USART1,ENABLE);




     /* Enable GPIOA clock */
     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
     /* ADC1 and TIM1 Periph clock enable */
     RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);


     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
     GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
     GPIO_Init(GPIOA, &GPIO_InitStructure);

     /* Connect EXTI0 Line to PA0 pin */
     SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);


     /* Configure EXTI0 line */
     EXTI_InitStructure.EXTI_Line = EXTI_Line0;
     EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
     EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
     EXTI_InitStructure.EXTI_LineCmd = ENABLE;
     EXTI_Init(&EXTI_InitStructure);

     /* Enable and set EXTI0 Interrupt */
     NVIC_InitStructure.NVIC_IRQChannel = EXTI0_1_IRQn;
     NVIC_InitStructure.NVIC_IRQChannelPriority = 0x00;
     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
     NVIC_Init(&NVIC_InitStructure);
     /* Generate software interrupt: simulate a edge applied on EXTI0 line */
     EXTI_GenerateSWInterrupt(EXTI_Line0);

     timerInitStructure.TIM_Prescaler = Prescalar;
     timerInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
     timerInitStructure.TIM_Period = Period;
     timerInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
     TIM_TimeBaseInit(TIM2, &timerInitStructure);

     // To be able to reset timer counter value at each rising edge of the input signal
     //     TIM_UpdateRequestConfig(TIM2,TIM_UpdateSource_Regular);
     //     TIM_UpdateDisableConfig(TIM2,ENABLE);

     nvicStructure.NVIC_IRQChannel = TIM2_IRQn;
     nvicStructure.NVIC_IRQChannelPriority = 0x00;
     nvicStructure.NVIC_IRQChannelCmd = ENABLE;
     NVIC_Init(&nvicStructure);


     TIM_Cmd(TIM2, ENABLE);
     TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);


     while(1)
     {}
}





void EXTI0_1_IRQHandler(void)
{
     __disable_irq(); // disable all intrrupts
     if(EXTI_GetITStatus(EXTI_Line0) != RESET)
     {
          if (timer_disabled)
          {
               TIM_Cmd(TIM2, ENABLE);
               timer_disabled=0;
          }
          else
          {
               TIM_Cmd(TIM2, DISABLE);
               CNT_Value=TIM_GetCounter(TIM2);
               TIM_SetCounter(TIM2,((uint32_t)0x0000));
               uint32_t TICKS=(CNT_Value+(Timmer_Events*Period));
               Frequency=Clock_PCK/TICKS;
               if (Frequency)
               {
                    SPeriod=1000000/Frequency;
               }
               printf("F=%d, SP=%d, TE=%d, CNT=%d,TIK=%d\r\n",Frequency,SPeriod,Timmer_Events,CNT_Value,TICKS);
               Timmer_Events=0;
               timer_disabled=1;
          }


          EXTI_ClearITPendingBit(EXTI_Line0);
          __enable_irq();
     }
}


void TIM2_IRQHandler(void)
{
     __disable_irq();
     if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
     {
          Timmer_Events=Timmer_Events+1;
          //          printf("T\r\n");
          //          TIM2->SR = (uint16_t)~TIM_IT_Update;
          TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
     }
     __enable_irq();
}


int __io_putchar(int ch)
{
     /* Place your implementation of fputc here */
     /* e.g. write a character to the USART */


     /* Loop until the transmission buffer is empty */
     while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);


     USART_SendData(USART1, (uint8_t) ch);


     return(ch);
}




/**
 * @brief  Retargets the C library scanf function to the USART (GNU)
 * @param  None
 * @retval None
 */
int __io_getchar(void)
{
     /* Place your implementation of fgetc here */
     /* e.g. read a character from the USART */


     /* Loop until the reception buffer is not empty */
     while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);


     return((int)USART_ReceiveData(USART1));
}




#ifdef  USE_FULL_ASSERT


/**
 * @brief  Reports the name of the source file and the source line number
 *   where the assert_param error has occurred.
 * @param  file: pointer to the source file name
 * @param  line: assert_param error line source number
 * @retval None
 */
void assert_failed(uint8_t* file, uint32_t line)
{
     /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */


     /* Infinite loop */
     while (1)
     {}
}
#endif

Outcomes