2
votes

I have a problem with my STM32F103C8T6 microcontroller. I am using (as an exercise) external interrupts to toggle on/off a led, by pressing an external switch wich in turn is connected to PC13. I am using StdPeriph Library.

When the chip has programmed, nothing happens. On the contrary, when I am using the debugger (debug in Coocox), the chip is working fine. I can not figure out where is the problem.

Can you help me please? Here is my code.

#include<stm32f10x.h>
#include<stm32f10x_rcc.h>
#include<stm32f10x_gpio.h>

#include<stm32f10x_exti.h>
#include<misc.h>

typedef enum{
    on,
    off
}state;
state led=on;

int main(void){

    // enable clocks
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);

    // uncomment to disable/remap JTAG pins
    GPIO_PinRemapConfig(GPIO_Remap_SWJ_NoJTRST,ENABLE);
    GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);

    // configure PC13 as input
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_13;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_2MHz;
    GPIO_Init(GPIOC,&GPIO_InitStructure);

    // configure PB8 as led output
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_2MHz;
    GPIO_Init(GPIOB,&GPIO_InitStructure);

    // connect PC13 to EXTI controller
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource13);

    // enable and configure EXTI controller
    EXTI_InitTypeDef EXTI_InitStructure;
    EXTI_InitStructure.EXTI_Line=EXTI_Line13;
    EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling;
    EXTI_InitStructure.EXTI_LineCmd=ENABLE;
    EXTI_Init(&EXTI_InitStructure);

    // enable IRQ
    NVIC_EnableIRQ(EXTI15_10_IRQn);
    NVIC_SetPriorityGrouping(NVIC_PriorityGroup_2);

    // Configure NVIC
    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel=EXTI15_10_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority=2;
    NVIC_Init(&NVIC_InitStructure);

    // switch on led
    GPIO_WriteBit(GPIOB,GPIO_Pin_8,Bit_SET);

    while(1);

    return 0;
}

void EXTI15_10_IRQHandler(void){

    // clear pending bit
    if(EXTI_GetITStatus(EXTI_Line13)!=RESET){
        EXTI_ClearITPendingBit(EXTI_Line13);
    }

    if(led==off){
        GPIO_WriteBit(GPIOB,GPIO_Pin_8,Bit_SET);
        led=on;
    }else{
        GPIO_WriteBit(GPIOB,GPIO_Pin_8,Bit_RESET);
        led=off;
    }
}

#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t * file,uint32_t line){
    /* Infinite loop */
    while (1);
}
#endif
4
working when you debug it often means uninitialized variables.Jean-François Fabre♦
Thank you Jean-François Fabre for your answer. I think that everything is initialized.jojosthegreat
Do you reset after programming? Where is the code running? Flash or RAM? Is there a breakpoint staying somewhere?Cyril Fougeray
I haven't used Coocox, but can you make sure that your build and debug settings are not targeting different things or have different settings?Cody G
caveat: I'm not very familiar with the indicated chip family. However, I do not see where the code is enabling the peripheral clock and I do not see where the code is enabling the 'master' interrupt enable bit. The debugger will do all that, but the standalone code must do that also, so the code operates correctly when the debugger is not attached. I also do not see where the 'watchdog' is being initialized nor where the 'watchdog is being either disabled or 'kicked' on a regular basis.user3629249

4 Answers

1
votes

I had this issue as well. I'm using a STM32F030. The problem for me was not having the SYSCFG clock enabled, which is bit 0 of RCC APB2ENR register. I'm guessing this setting is enabled in debug, so that the software can debug? Otherwise the clock is disabled!

I finally found this by looking into the STM32F1 reference manual, which is slightly more comprehensive.

0
votes

It is generally a very bad idea to use external interrupts for the buttons and keys. You should use the timer interrupt instead.

You can see simple implementation of the key in the timer interrupt (click, double click, long click events supported) here : https://www.diymat.co.uk/arm-three-function-click-double-and-long-click-button-library-timer-interrupt-driven/

0
votes

I don't have knowledge about the mentioned controller, but I worked on STM32L4 series controllers. In STM32L4 push button is connected to the PC13 pin. I observed gpio debouncing when pressing the push button. In your EXTI15_10_IRQHandler() implement debouncing logic. Make sure the interrupt is reaching this function for only once per button press. May be the debugger is slowing down the processor(cpu running in lower frequency compared to free run) and you are getting the interrupts properly.

-1
votes

Do you use different build config for debug? If so, try making the led variable volatile and see if it helps. If not: add some delay loop, i.e. voliatile unsigned i; for (i=0; i < 50000u; ++i); after clearing the EXTI bit in the ISR. This is generally a bad pratcice to use blocking delays in the interrupt service (if it's ever a good practice...) but might be helpful to see if it is related to debuncing not done properly. If it helps, then debouncing the switch is the most likely problem.

EDIT: consider using bit-banding (if possible) to access the output port, then you could do sth like bind_band_led_port ^= 1;, but that's just a side note.