Example: Button Interrupt with Dynamic Callbacks
#include <stdio.h>
#include <stdint.h>
// Define a callback type
typedef void (*ButtonCallback)(void);
// Global variables
volatile uint8_t button_pressed_flag = 0;
ButtonCallback button_callback = NULL;
// ISR: fast, only sets flag
void BUTTON_IRQHandler(void) {
button_pressed_flag = 1;
}
// Register a callback dynamically
void register_button_callback(ButtonCallback cb) {
button_callback = cb;
}
// Two possible actions
void turn_on_led(void) {
printf("LED turned ON!\n");
}
void send_message(void) {
printf("Message sent!\n");
}
int main() {
// At runtime, we can decide which action to use
int user_choice;
while (1) {
printf("Choose action: 1=LED, 2=Message: ");
scanf("%d", &user_choice);
if (user_choice == 1)
register_button_callback(turn_on_led); // set LED action
else
register_button_callback(send_message); // set message action
// Simulate button press
BUTTON_IRQHandler();
// Handle button press safely outside ISR
if (button_pressed_flag) {
button_pressed_flag = 0;
// Here is the **callback in action**
if (button_callback != NULL) {
button_callback(); // Calls the function dynamically
}
}
}
return 0;
}
Key Points Highlighting the Advantage of Callbacks
| Aspect | Without Callback | With Callback |
|---|---|---|
| ISR behavior | Hardcoded to one action | ISR stays fast; action is dynamic |
| Changing behavior | Must edit ISR code | Change button_callback at runtime |
| Flexibility | Low — each ISR tied to one function | High — ISR works for any registered function |
| Heavy processing | Can block ISR if inside | Run safely outside ISR via callback |
✅ Why we use callback here:
-
We can change the button behavior at runtime without touching the interrupt code.
-
The ISR stays short and safe, even if the actions are complex.
-
The system becomes modular and reusable: the same button can do different things in different program contexts.
Comments
Post a Comment