2025-04-07 1:13 AM - last edited on 2025-04-07 3:19 AM by Andrew Neil
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…
Solved! Go to Solution.
2025-04-07 3:16 AM - edited 2025-04-07 3:17 AM
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.
2025-04-07 3:16 AM - edited 2025-04-07 3:17 AM
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.
2025-04-07 8:10 PM
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()?
2025-04-08 1:55 AM
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.
2025-04-08 2:19 AM
Appreciate your advices. I'll give it a try.
2025-04-08 3:00 AM
Also, I should mention, since I cannot see your hardware design, have oyu thought about what happens if you press two keys at the same time? Is there any possibility that a user could connect the "high" of one column to the "low" of another, that would not be a good situation!
2025-04-08 3:56 AM
It's 4x4 keypad. I coded with the assumption that there would be no pressing keys at the 'exact' same time. There must be, i think, the first one and the last one even if they seem to be simultaneous to human perspective. I'm using the first one as a real input while ignoring the last one. and... since It's just 4x4 keypad, i guess there's no possibility what you concern about.
2025-04-08 9:38 AM