Hello I want to interface a keypad in stm32 l053r8 with timer interrupt. I have a SysTick_Handler function which I am handling there the switch debouncing of push buttons and every time the push button counter gets equal to 10 I am using a flag in order to check when the button is pressed. So now I have all the rows of the keypad as input and all the collumns of the keypad as output. My idea is 1) every timer int, it activates a new column and reads the 4 row inputs. 2) check if a button flag is "1" and send the appropriate message to the screen. I have an implementation but it is not working.For example in main function I have a condition that checks if the key1(expect 1 as output in screen) is pressed but it dont do anything. Any advice would be great.
void TIM2_IRQHandler(void){
if (TIM2->SR & TIM_SR_UIF ){
//Clear Timer 2 Flag
CLEAR_BIT(TIM2->SR, TIM_SR_UIF);
if (column_counter==4)
column_counter=0;
column_counter ;
keypad_scanning(column_counter); // activate col=1 or 2 or 3 depends on counter.
}
}
void keypad_scanning(uint8_t column_pos){
switch (column_pos){
case 1:
SET_BIT(GPIOC->ODR,GPIO_ODR_OD15); // C1 HIGH
CLEAR_BIT(GPIOA->ODR,GPIO_ODR_OD1); // C2 LOW
CLEAR_BIT(GPIOA->ODR,GPIO_ODR_OD4); // C3 LOW
if (flag0.fl.f5 && !(flag0.fl.f6) && !(flag0.fl.f7)){
key0.fl.f1 = 1; // key 1 is pressed.
}
if (!(flag0.fl.f5) && flag0.fl.f6 && !(flag0.fl.f7)){
key0.fl.f4 = 1; // key 4 is pressed.
}
if (!(flag0.fl.f5) && !(flag0.fl.f6) && flag0.fl.f7){
key0.fl.f7 = 1; // key 7 is pressed.
}
break;
case 2:
CLEAR_BIT(GPIOC->ODR,GPIO_ODR_OD15); // C1 LOW
SET_BIT(GPIOA->ODR,GPIO_ODR_OD1); // C2 HIGH
CLEAR_BIT(GPIOA->ODR,GPIO_ODR_OD4); // C3 LOW
if (flag0.fl.f5 && !(flag0.fl.f6) && !(flag0.fl.f7)){
key0.fl.f2 = 1; // key 2 is pressed.
}
if (!(flag0.fl.f5) && flag0.fl.f6 && !(flag0.fl.f7)){
key0.fl.f5 = 1; // key 5 is pressed.
}
if (!(flag0.fl.f5) && !(flag0.fl.f6) && flag0.fl.f7){
key0.fl.f8 = 1; // key 8 is pressed.
}
break;
case 3:
CLEAR_BIT(GPIOC->ODR,GPIO_ODR_OD15); // C1 LOW
CLEAR_BIT(GPIOA->ODR,GPIO_ODR_OD1); // C2 LOW
SET_BIT(GPIOA->ODR,GPIO_ODR_OD4); // C3 HIGH
if (flag0.fl.f5 && !(flag0.fl.f6) && !(flag0.fl.f7)){
key0.fl.f3 = 1; // key 3 is pressed.
}
if (!(flag0.fl.f5) && flag0.fl.f6 && !(flag0.fl.f7)){
key0.fl.f6 = 1; // key 6 is pressed.
}
if (!(flag0.fl.f5) && !(flag0.fl.f6) && flag0.fl.f7){
key0.fl.f9 = 1; // key 9 is pressed.
}
break;
}
}
void SysTick_Handler(void){
//------------------------------
//key 1 sampling ( ROW 1 FLAG)
if(!flag0.fl.f5){
if(!KEY1_READ()){
if(key1_counter == 10)
flag0.fl.f5 = 1; // R1 is HIGH
key1_counter = 0;
}else{
if(key1_counter < 10) //10 ms sampling
key1_counter ;
}
}
//------------------------------
//------------------------------
//key 2 sampling (ROW 2 FLAG)
if(!flag0.fl.f6){
if(!KEY2_READ()){
if(key2_counter == 10)
flag0.fl.f6 = 1; // R2 is HIGH
key2_counter = 0;
}else{
if(key2_counter < 10) //10 ms sampling
key2_counter ;
}
}
//------------------------------
//------------------------------
//key 3 sampling (ROW 3 FLAG)
if(!flag0.fl.f7){
if(!KEY3_READ()){
if(key3_counter == 10)
flag0.fl.f7 = 1; // R3 is HIGH
key3_counter = 0;
}else{
if(key3_counter < 10) //10 ms sampling
key3_counter ;
}
}
//------------------------------
}
CodePudding user response:
First, your title says 4x4 but the code appears to be for 3x3.
Next, an electrical signal can propagate through a key matrix almost instantaneously. You should do do every column one straight after the other, you don't need a timer to do that. Just do: column high, read row, column low, next column high, etc.
After that, you only read the state of the key if it is not already pressed. You try to debounce the rising edge, but once the key is pressed it seems to stay pressed for ever, you never look for the falling edge when the key is released. Falling edges can bounce too, so you need to have a count there too.
Also, you are checking for the state where only one row is active with if(x && !y && !z)
. What if the user presses more than one button at a time? For each flag you only need to check for one input.
These points won't fix everything, but hopefully will get you further along the way!
CodePudding user response:
I suspect the following code to cause you some problems.
if(!KEY1_READ()){
if(key1_counter == 10)
What are the chances that you will release the button when counter is exactly 10?
You seem to want an on-release event, so I would write the scanning code like so:
if (KEY1_READ()) {
key1_counter ;
} else {
if (key1_counter > 10) {
flag0.fl.f5 = 1;
}
key1_counter = 0;
}
Don't forget to reset the flag after you're done processing it.