AnsweredAssumed Answered

STM32F100 dev board interrupt not working

Question asked by khan.saud on Jun 17, 2014
Latest reply on Jun 18, 2014 by khan.saud
Hi All,

I have got an issue where I cant get the interrupts to work on my STM32F100 dev board. I am trying to get an interrupt on PA0 (Falling edge) and PA1 (Rising edge). I cant seem to find where I am going wrong. Can someone please help me? I need help urgently!

/******************************************************************************
 * Author:  Saud Khan
 * Version: V2.8
 * Date:    05/06/2014
 * Brief:   Generate CAM and Crank PWM on receiving T50 request and switch off
 *          on receiving T15 request
 * Library: Standard Peripheral Library
 * Comments:
 ******************************************************************************/
//Includes
#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_conf.h"
#include "stm32f10x_tim.h"
#include "antilib_gpio.h"
#include "stm32f10x_usart.h"
 
/* Global define ------------------------------------------------------------*/
uint16_t ARR_Val_CAM = 400; //always keep it an even number
uint16_t CCR_Val_CAM = 0; // starting with 0% duty cycle.
uint16_t ARR_Val_CRANK = 400;
uint16_t CCR_Val_CRANK = 0; // starting with 0% duty cycle.
char Log[20];
/* Private function prototypes -----------------------------------------------*/
void RCC_Configuration(void);
void GPIO_Configuration(void);
void USART1_Init(void);
 
/*******************************************************************************
 * Function Name  : RCC_Configuration
 * Description    : Configures all RCC parameters for DMA, ADC, USART and PWM
 * Input          : None
 * Output         : None
 * Return         : None
 *******************************************************************************/
void RCC_Configuration(void) {
 
    /* ADC RCC Configuration --------------------------------------------------*/
#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL)
    /* ADCCLK = PCLK2/2 */
    RCC_ADCCLKConfig(RCC_PCLK2_Div2);
#else
    /* ADCCLK = PCLK2/4 */
    RCC_ADCCLKConfig(RCC_PCLK2_Div4);
#endif
 
    /* USART RCC Configuration -----------------------------------------------*/
    // clock for GPIO
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
 
    /* Enable USART clock---------------------------------------------------- */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
    /*------------------------------------------------------------------------*/
 
    /*PWM RCC Configuration --------------------------------------------------*/
    /* TIM3 clock enable */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
    /* TIM2 clock enable */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
 
    /* GPIOA, GPIOB and GPIOC clock enable */ //PORT A, B kept enabled for future programming
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB |
    RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO, ENABLE);
    /*-----------------------------------------------------------------------*/
 
    /* EXTI RCC configuration------------------------------------------------*/
    /* Enable GPIOC clock */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    /*-----------------------------------------------------------------------*/
}
 
/*******************************************************************************
 * Function Name  : GPIO_Configuration
 * Description    : GPIO configuration for ADC and PWM
 * Input          : T50 and T15 from BCM
 * Output         : CAM signal
 *******************************************************************************/
void GPIO_Configuration(void) {
    GPIO_InitTypeDef GPIO_InitStructure;
 
    /*Configuration for USART -------------------------------------------------*/
 
    /* Configure the GPIO ports( USART1 Transmit and Receive Lines) */
    /* Configure the USART1_Tx as Alternate function Push-Pull */
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
 
    /* Configure the USART1_Rx as input floating */
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    /*------------------------------------------------------------------------*/
 
    /*GPIOB Configuration: TIM3 channel 1 for PWM*/
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; //Set pin PB4
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //Set mode
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //Set frequency
    GPIO_Init(GPIOB, &GPIO_InitStructure); //initialise the port
    GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //remapped to CH1 PB4.
 
    /*GPIOB Configuration: TIM2 channel 2 for PWM*/
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; //Set pin PB3
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //Set mode
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //Set frequency
    GPIO_Init(GPIOB, &GPIO_InitStructure); //initialise the port
    GPIO_PinRemapConfig(GPIO_FullRemap_TIM2, ENABLE); //remapped to CH2 PB3.
 
    /* JTAG-DP Disabled and SW-DP Enabled */
    GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE); // Off PB3/PB4 - REQUIRED
 
    /*------------------------------------------------------------------------*/
 
    /*GPIOA Configuration: EXTI pin for T50 and T15*/
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
 
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    /*----------------------------------------------------------------------*/
 
    /*GPIOC Configuration: Output LED*/
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //Output Push Pull
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; //Set Speed
    GPIO_Init(GPIOC, &GPIO_InitStructure);
 
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //Output Push Pull
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; //Set Speed
    GPIO_Init(GPIOC, &GPIO_InitStructure);
    /*----------------------------------------------------------------------*/
}
 
/*******************************************************************************
 * Function Name  : EXTI Configuration
 * Description    : Configures all EXTI parameters for external interrupt on PA0
 *                  and PA1
 * Input          : None
 * Output         : None
 * Return         : None
 *******************************************************************************/
void EXTI_Configuration(void) {
    EXTI_InitTypeDef EXTI_InitStructure;
 
    /* Enable AFIO clock */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
    // Connect sources to EXTI Lines
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource1);
 
    // Configure T15 (IGNITION OFF) - Falling Edge
    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);
 
    // Configure T50 (CRANK) - Rising Edge
    EXTI_InitStructure.EXTI_Line = EXTI_Line1;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);
}
 
/*******************************************************************************
 * Function Name  : SerialPutChar
 * Description    : Print a character on the HyperTerminal
 * Input          : - c: The character to be printed
 * Output         : None
 * Return         : None
 *******************************************************************************/
void SerialPutChar(char c) {
    USART_SendData(USART1, c);
    while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET)
        ;
}
 
/*******************************************************************************
 * Function Name  : Serial_PutString
 * Description    : Print a string on the HyperTerminal
 * Input          : - s: The string to be printed
 * Output         : None
 * Return         : None
 *******************************************************************************/
void Serial_PutString(char *s) {
    while (*s != '\0') {
        SerialPutChar(*s); // keep calling the SerialPutChar function :P
        s++;
    }
}
 
/*******************************************************************************
 * Function Name  : USART1_Init
 * Description    : Initialize the IAP: Configure RCC, USART and GPIOs.
 * Input          : None
 * Output         : None
 * Return         : None
 * Note           : You have to run RCC_Configuration() before calling this function
 *******************************************************************************/
void USART1_Init(void) {
    USART_InitTypeDef USART_InitStructure;
 
    /* USART1 configuration ------------------------------------------------------*/
    /* USART1 configured as follow:
     - BaudRate = 9600 baud
     - Word Length = 8 Bits
     - One Stop Bit
     - No parity
     - Hardware flow control disabled (RTS and CTS signals)
     - Receive and transmit enabled
     */
    USART_InitStructure.USART_BaudRate = 115200;
    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;
 
    /* Configure the USART1 */
    USART_Init(USART1, &USART_InitStructure);
 
    /* Enable USART1 interrupt */
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
    USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
 
    /* Enable the USART1 */
    USART_Cmd(USART1, ENABLE);
}
 
/*******************************************************************************
 * Function Name  : PWM_Configuration
 * Description    : Initialise the PWM parameter
 * Input          : Frequency (Beta), Duty cycle
 * Output         : None
 * Return         : None
 * Note           : Frequency function is still beta. Set frequency manually for
 *                  now. Change the code accordingly.
 *******************************************************************************/
void CRANK_PWM_Configuration(void) {
 
    /* -----------------------------------------------------------------------
     TIM2 Configuration: generate PWM signals with 50% duty cycles:
     In this example only Channel 1 is used. The TIM3CLK frequency is set to
     SystemCoreClock (Hz). To get TIM2 counter clock at 24 MHz the Prescaler
     is computed as following:
 
     Prescaler = (TIM2CLK / TIM2 counter clock) - 1
 
     Formula used to determine the TIM2 Frequency = TIM3 counter clock/(ARR + 1)
 
     Dutycycle = CCR_Val/ARR_Val. ARR_Val is the Timer period(top value).
     ----------------------------------------------------------------------- */
 
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    TIM_OCInitTypeDef TIM_OCInitStructure;
 
    //uint16_t ARR_Val_CRANK = 400;
    //uint16_t CCR_Val_CRANK = 0; // starting with 50% duty cycle. BETA function -
    uint16_t Prescaler = 2399; // Setting prescaler as high frequency not needed
    /* Time base configuration */
    TIM_TimeBaseStructure.TIM_Period = ARR_Val_CRANK;
    TIM_TimeBaseStructure.TIM_Prescaler = Prescaler; //PrescalerValue = (uint16_t) (SystemCoreClock / 239000) - 1;
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
 
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
 
    /* PWM1 Mode configuration: PB.03 TIM2_CH2 */
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse = CCR_Val_CRANK;
 
    TIM_OC2Init(TIM2, &TIM_OCInitStructure);
    TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable);
    TIM_ARRPreloadConfig(TIM2, ENABLE);
 
    /* TIM2 enable counter */
    TIM_Cmd(TIM2, ENABLE);
}
 
/*******************************************************************************
 * Function Name  : PWM_Configuration
 * Description    : Initialise the PWM parameter
 * Input          : Frequency (Beta), Duty cycle
 * Output         : None
 * Return         : None
 * Note           : Frequency function is still beta. Set frequency manually for
 *                  now. Change the code accordingly.
 *******************************************************************************/
void CAM_PWM_Configuration(void) {
 
    /* -----------------------------------------------------------------------
     TIM3 Configuration: generate PWM signals with 50% duty cycles:
     In this example only Channel 1 is used. The TIM2CLK frequency is set to
     SystemCoreClock (Hz). To get TIM3 counter clock at 24 MHz the Prescaler
     is computed as following:
 
     Prescaler = (TIM3CLK / TIM3 counter clock) - 1
 
     Formula used to determine the TIM3 Frequency = TIM3 counter clock/(ARR + 1)
 
     Dutycycle = CCR_Val/ARR_Val. ARR_Val is the Timer period(top value).
     ----------------------------------------------------------------------- */
 
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    TIM_OCInitTypeDef TIM_OCInitStructure;
 
    //uint16_t ARR_Val_CAM = 400; //always keep it an even number
    //uint16_t CCR_Val_CAM = 0; // starting with 50% duty cycle.
    uint16_t Prescaler = 2399; // Setting prescaler as high frequency not needed
    /* Time base configuration */
    TIM_TimeBaseStructure.TIM_Period = ARR_Val_CAM;
    TIM_TimeBaseStructure.TIM_Prescaler = Prescaler; //PrescalerValue = (uint16_t) (SystemCoreClock / 239000) - 1;
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
 
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
 
    /* PWM1 Mode configuration: PB.04 TIM3_CH1 */
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse = CCR_Val_CAM;
 
    TIM_OC1Init(TIM3, &TIM_OCInitStructure);
    TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);
    TIM_ARRPreloadConfig(TIM3, ENABLE);
 
    /* TIM3 enable counter */
    TIM_Cmd(TIM3, ENABLE);
}
 
/*******************************************************************************
 * Function Name  : InitialiseTimer
 * Description    : Timer2 for 1 second interrupt. In this interrupt, data will be
 *                  logged and USART data will be transmitted.
 * Input          : None
 * Output         : None
 * Return         : None
 * Note           : None
 *******************************************************************************/
void InitialiseTimer() {
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
 
    TIM_TimeBaseInitTypeDef timerInitStructure;
    timerInitStructure.TIM_Prescaler = 23999;
    timerInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
    timerInitStructure.TIM_Period = 1000;
    timerInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    timerInitStructure.TIM_RepetitionCounter = 0;
    TIM_TimeBaseInit(TIM4, &timerInitStructure);
    TIM_Cmd(TIM4, ENABLE);
    TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);
}
 
/*******************************************************************************
 * Function Name  : EnableTimerInterrupt
 * Description    : Enableing interupt on timer2 at update
 * Input          : None
 * Output         : None
 * Return         : None
 * Note           : None
 *******************************************************************************/
void EnableTimerInterrupt() {
    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
 
    /* Enable T15 EXTI Interrupts */
    NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
 
    /* Enable T50 EXTI Interrupts */
    NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}
 
/*******************************************************************************
 * Function Name  : EXTI0_IRQHandler
 * Description    : When T15 is set low, this interrupt occurs
 * Input          : None
 * Output         : None
 * Return         : None
 * Note           : None
 *******************************************************************************/
void EXTI0_IRQHandler() {
    if (EXTI_GetITStatus(EXTI_Line0) != RESET) {
        Serial_PutString("Request Ignition Off.");
        TIM2->CCR2 = 0; //0% duty cycle = ignition off - no CAM signal
        TIM3->CCR1 = 0; //0% duty cycle = ignition off - no CAM signal
        GPIOC->ODR ^= GPIO_Pin_8; // Set pin 8 as high when in PM6
        sprintf(Log, "%s", "Labcar Status: PM6. \r\n");
    }
}
 
/*******************************************************************************
 * Function Name  : EXTI1_IRQHandler
 * Description    : When T50 goes high this interrupt occurs
 * Input          : None
 * Output         : None
 * Return         : None
 * Note           : None
 *******************************************************************************/
void EXTI1_IRQHandler() {
    if (EXTI_GetITStatus(EXTI_Line1) != RESET) {
        Serial_PutString("Crank Request Detected.");
        TIM2->CCR2 = ARR_Val_CRANK / 2; //50% duty cycle = CRANKING - valid CAM signal
        TIM3->CCR1 = ARR_Val_CAM / 2; //50% duty cycle = CRANKING - valid CAM signal
        GPIOC->ODR ^= GPIO_Pin_9; //Set pin 9 as high when in PM7
        sprintf(Log, "%s", "Labcar Status: PM7. \r\n");
    }
}
/*******************************************************************************
 * Function Name  : TIM4_IRQHandler
 * Description    : This is the timer interrupt subroutine. This is where we will
 *                  log the data and send it over USART
 * Input          : None
 * Output         : None
 * Return         : None
 * Note           : None
 *******************************************************************************/
void TIM4_IRQHandler() {
    if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET) {
        TIM_ClearITPendingBit(TIM4, TIM_IT_Update); //clear the flags
 
        //GPIOC->ODR ^= GPIO_Pin_8;
        //GPIOC->ODR ^= GPIO_Pin_9;
        Serial_PutString(Log);
    }
}
 
/*******************************************************************************
 * Function Name  : main
 * Description    : Main function where we call all functions to initialise all
 *                  parameters for RCC, GPIO, USART1, PWM, Timer2 and
 *                  interrupt.
 * Input          : None
 * Output         : None
 * Return         : None
 * Note           : None
 *******************************************************************************/
int main(void) {
 
    /* System clocks configuration ---------------------------------------------*/
    RCC_Configuration(); // Important to be kept first for setting the timers for pins
 
    /* GPIO configuration ------------------------------------------------------*/
    GPIO_Configuration(); // Important to be kept second for setting the pins
 
    /* USART Configuration -----------------------------------------------------*/
    USART1_Init(); // Now we can use USART for debugging :)
    Serial_PutString("Dynamic Labcar initialisation Started.\r\n");
 
    /* PWM Configuration -------------------------------------------------------*/
    CRANK_PWM_Configuration();
    CAM_PWM_Configuration();
 
    /*Timer2 Configuration -----------------------------------------------------*/
    InitialiseTimer(); //for interrupts and PWM
 
    Serial_PutString("Initialisation Complete.\r\n");
    sprintf(Log, "%s", "Labcar Status: PM4. \r\n");
 
    /*Timer2 Interrupt Configuration ------------------------------------------*/
    EnableTimerInterrupt();
 
    while (1) {
 
    }
}

Outcomes