cancel
Showing results for 
Search instead for 
Did you mean: 

EXTI Interrupts with STM32VLDISCOVERY

aa_talaat
Associate II
Posted on January 04, 2014 at 13:40

Hello,

I am using STM32VLDISCOVERY and connected 4 tiny push buttons to Pins PB12, PB13, PB14 and PB I am using external pull-up resistors of 100K each (I guess 10K would be much better). Using the following code, I found out that pressing one button generates interrupt on the corresponding pin as well as others (I put multiple breakpoints in the interrupt handle and watched the behaviour using the debugger). I suspected something wrong with my buttons circuitry. So, I disconnected my external board that holds the buttons and pull-up resistors, and changed the code to use the internal pull-up resistors in the STM Just touching the PINs with my finger generates interrupts on these PINs. If the interrupt triggering is that sensitive to the 50Hz induced by touching the pin then how should I handle the circuitry around my buttons to ensure a stable operation. Thank you.

#include ''stm32f10x.h''
void GPIO_In_Floating(void);
void Buttons_Config(void);
/**
**===========================================================================
**
** Abstract: main program
**
**===========================================================================
*/
int main(void)
{
/* Configure system clock to HSI @ 8MHz in the system_stm32f10x.c */
/* change all IOs into Analog INP to save power */
GPIO_In_Floating();
/* Configure EXTI on User push button */
Buttons_Config();
/* Infinite loop */
while (1)
{
PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
}
}
void GPIO_In_Floating(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
/* Configure all GPIO as analog to reduce current consumption on non used IOs */
/* Enable GPIOs clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC, ENABLE);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_All;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_Init(GPIOC, &GPIO_InitStruct);
// Keep the STLink Pins alive.
GPIO_InitStruct.GPIO_Pin = ~(GPIO_Pin_13 | GPIO_Pin_14);
GPIO_Init(GPIOA, &GPIO_InitStruct);
/* Disable GPIOs clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC, DISABLE);
}
void Buttons_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
/* Enable GPIOB clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
/* Configure PB0-PB3 pin as input floating */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // external pull-up 100K resistor
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* Enable AFIO clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
/* Connect EXTI12-15 Line to PB.12-15 pin */
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource12);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource13);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource15);
/* Configure EXTI12-15 line initially for active low push button detection */
EXTI_InitStructure.EXTI_Line = EXTI_Line12 | EXTI_Line13 | EXTI_Line14 | EXTI_Line15;
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 to the lowest priority */
NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}

void EXTI15_10_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line12) != RESET)
{
/* Clear the EXTI line 12 pending bit */
EXTI_ClearITPendingBit(EXTI_Line12);
}
if(EXTI_GetITStatus(EXTI_Line13) != RESET)
{
/* Clear the EXTI line 13 pending bit */
EXTI_ClearITPendingBit(EXTI_Line13);
}
if(EXTI_GetITStatus(EXTI_Line14) != RESET)
{
/* Clear the EXTI line 14 pending bit */
EXTI_ClearITPendingBit(EXTI_Line14);
}
if(EXTI_GetITStatus(EXTI_Line15) != RESET)
{
/* Clear the EXTI line 15 pending bit */
EXTI_ClearITPendingBit(EXTI_Line15);
}
}

7 REPLIES 7
chen
Associate II
Posted on January 06, 2014 at 12:00

Hi

''I am using STM32VLDISCOVERY and connected 4 tiny push buttons''

''I suspected something wrong with my buttons circuitry. So, I disconnected my external board that holds the buttons and pull-up resistors, and changed the code to use the internal pull-up resistors in the STM32.

Just touching the PINs with my finger generates interrupts on these PINs''

What happens when you ground yourself and touch the pins?

Could it be that the buttons are so small that you are touching the pins of the buttons?

'' I am using external pull-up resistors of 100K each (I guess 10K would be much better).''

Yes, 100K is probably too large (Makes it subseptiable to noise as you have found) - 5K or even 2K will work as well.

DO not forget you must debounce the push buttons!

aa_talaat
Associate II
Posted on January 12, 2014 at 17:27

Hi,

Problem solved. I reduced the value of the pull-up resistor to 3.3K and de-bounced each of the buttons using an RC combination of 33kOhm and 100nf.

No more unexpected triggering of interrupts.

aa_talaat
Associate II
Posted on October 28, 2014 at 20:06

Hi,

This time, I changed to a 4x4 membrane keypad with 8 pin connector. 4 pins are connected to each row and the other 4 pins are connected to each column.

I configured the STM32 to use PB12-15 as exti and connected to the 4 pins of the keypad columns. The PB12-15 are configured as well as input with internal pullup.

Once again, pressing one key on the keypad, generates interrupt on all other 4 pins starting with the pin that I really pressed. It is kind of random. So, for example pressing a key that generates an interrupt on Pin 2 will sometime generate interrupts pending as well on pin 1 and 4 and sometimes pin 3 and 4 and so on.

I was using msp430 before with buttons directly, and was not facing such issue. Can't I operate the keypad without hardware debouncing. That is really strange.

I think the below post is describing something very similar but he did not get any answer.

https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=https%3a//my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Problem%20with%20multiple%20EXTI%20on%20the%20same%20Port&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD0650...

chen
Associate II
Posted on October 29, 2014 at 10:48

Hi

It is best to start a new thread for this but we will carry on with this existing thread.

''The PB12-15 are configured as well as input with internal pullup.''

''Can't I operate the keypad without hardware debouncing.''

I do not believe the STM32 series has 'hardware debounce'

''Once again, pressing one key on the keypad, generates interrupt on all other 4 pins starting with the pin that I really pressed.''

Does the code just hold PB12-15 high?

If all are high then it is likely that more than 1 IP will cause an EXTI irq.

This is a matrix which will require matrix scanning.

ie each of the row/column must be pull high one at a time, if a key is pressed then only the currently selected row and column will generate the EXTI irq.

aa_talaat
Associate II
Posted on October 29, 2014 at 12:29

Hi,

Yes, what I do is the following:

  • Configure PB12-15 as input pull-up with interrupt on rising/falling, and PB8-PB11 as output low.
  • PB12-15 are connected to the 4 columns of the keypad, and PB8-11 are connected to the 4 rows of the keypad.
  • When the user presses one of the 16 keys on the keypad, an interrupt is generated on one of the PB12-15 indicating which column was impacted by this action.
  • Later one, I do a scanning on the rows to find out exactly which key was pressed.
My issue is that when a keypad button is pressed, I get interrupt flag set on more than one of the PB12-15 pins. So, for example if the user presses ''1'', I am supposed to receive interrupt only on PB12. However, what happens is that I get this interrupt and process it, and then the ISR gets called again and this time indicating that PB13 was pressed. This should not happen.

There is some kind of mysterious coupling between these pins that I fail to understand. I faced similar issue using the same set of PB12-15 with individual small push buttons, and this strange interference only disappeared when I provided HW debounce around these keys using capacitors and resistors.

My understanding is that HW debounce can be by passed using SW techniques which I am using already in my code but it is very strange that I get wrong indications from the STM32 about interrupts on pins which are not supposed to be causing these interrupts.

chen
Associate II
Posted on October 29, 2014 at 13:28

''

  • When the user presses one of the 16 keys on the keypad, an interrupt is generated on one of the PB12-15 indicating which column was impacted by this action.
  • Later one, I do a scanning on the rows to find out exactly which key was pressed.
''

No, keeping all the rows at 1 would cause more than 1 column to trigger.

You MUST do the scanning as part of the key press detect.

You must do key debounce as well.

aa_talaat
Associate II
Posted on October 30, 2014 at 11:38

Hi,

I found a work around by masking the EXTI interrupt when first EXTI interrupt is received for the correct user action and activating it back once the SW debouncing is completed within the Timer service routine.

/*
* Enable the specific interrupt number
*/
void EnableButton_IRQ(void){
// Clear the EXTI line 12 pending bit
EXTI_ClearITPendingBit(EXTI_Line12 | EXTI_Line13 | EXTI_Line14 | EXTI_Line15);
EXTI->IMR = EXTI_IMR_MR12 | EXTI_IMR_MR13 | EXTI_IMR_MR14 | EXTI_IMR_MR15;
}
/*
* Disable the specific interrupt number
*/
void DisableButton_IRQ(void){
// Mask interrupt
EXTI->IMR &= ~(EXTI_IMR_MR12 | EXTI_IMR_MR13 | EXTI_IMR_MR14 | EXTI_IMR_MR15);
// Clear the EXTI line 12 pending bit
EXTI_ClearITPendingBit(EXTI_Line12 | EXTI_Line13 | EXTI_Line14 | EXTI_Line15);
}