Skip to main content
Associate
April 7, 2025
Solved

Receive keypad input using the timer interrupt of the STM32.

  • April 7, 2025
  • 1 reply
  • 1511 views

and main.c code is as follows.

After debugging, I confirmed through the live expression window that current_index changes periodically due to the timer interrupt.
I wrote code that processes the keyPressed value based on row input only when a specific current_index (i.e., a specific column is HIGH), using statements like if (current_index == 0); for each value from 0 to 3.

However, in the live expression window, I observed that keyPressed keeps changing sequentially from '1' to 'D' at every timer cycle, even without pressing any key. Eventually, the message “failed to evaluate expression” appeared, and I couldn’t monitor the value anymore.

Question 1. Is the above code appropriate for the keypad behavior I want (i.e., when I press '1', '1' is stored in keyPressed, and when I press '*', '*' is stored)?

Question 2. How can I solve the “failed to evaluate expression” issue?
I’ve already tried “freshen all files,” rebuild, and adjusting the debug level, but nothing worked.

I’d really appreciate your help…

 

Best answer by KMill

In the main.c code you attached, there is nothing calling ScanKeypad() so the compiler has optimised away all of it's resources, hence why you get "failed to evaluate expression..."

 

Also, the current method you are using has a massive race-condition. (Assuming you call ScanKeypad in a loop somewhere)

The timer could fire at any time, including while the proecessor is executing ScanKeypad...

It could fire (and change which pin is HIGH) in between any statement anywhere.

So you need to either stop the timer before each scan or move the code to scan the keyboard into the Timer routine.

1 reply

KMill
KMillBest answer
Senior
April 7, 2025

In the main.c code you attached, there is nothing calling ScanKeypad() so the compiler has optimised away all of it's resources, hence why you get "failed to evaluate expression..."

 

Also, the current method you are using has a massive race-condition. (Assuming you call ScanKeypad in a loop somewhere)

The timer could fire at any time, including while the proecessor is executing ScanKeypad...

It could fire (and change which pin is HIGH) in between any statement anywhere.

So you need to either stop the timer before each scan or move the code to scan the keyboard into the Timer routine.

Associate
April 8, 2025

Thx. I made main() call ScanKeypad() in while(1) and finally managed to make it.

is it better way to move ScanKeypad() into timer callback function than just to leave it in main()?

KMill
Senior
April 8, 2025

This is a really good project to learn a bit about MCUs and programming them. Especially becuae you are using timers, interrupts and loops. You have a good chance to learn optimisation and how interrupts can give unexpected results! (The timer callback is fired from an interrupt).

Since I assume the hardware cannot be changed, it's also a good chance to analyse a problem and work on a solution. 

If it were me, I would not separate the changing of the selected column, from the scanning of the rows. 
I'd use the timer to do both, increment the column index, and scan the row at the same time. This results in scanning the keyboard at a fixed frequency, rather than in a tight loop in main().

 

In the ISR this is what I would do (in pseudo code, so you can work on the implementation ;) )

1. ASSERT the column bit for a single column,

2. SCAN the row for pressed keys, and update a global volatile variable with the result.

3. Compare the result to the last time through the loop and set a flag (keyPressAvailable or similar) if it has changed.

4. DEASSERT the column bit.

5. Increment the column index, and wrap round if needed.

 

In main you can examine the flag, and if it's set take some action and reset the flag.

 

Then when you have that working, you could try adding some more logic (again in the timer callback) for:

1. De-bounce the keypresses (ie does it stay pressed for more than some fixed time) (HINT: don't do a loop inside the timer for this)

2. Implement key-repeat when the key is held down more than some amount of time.

 

It's good to know that a timer interrupt will not interrupt itself, but may be interrupted by some other interrupt with a higher priority.