Shawn wrote:
Hello all...
I'm new to the world of C programming, and am working with an
embedded microcontroller as a hobby. I have a reasonably simple
program running now, but I'm having trouble figuring out how to test
for a specific bit when an interrupt is triggered.
Basically when the interrupt is set, the program reads a register to
determine what caused the interrupt. It could be one or both of 2
values - bit 2 and/or biit 4. Depending on which or both it is, I
want to do different things.
If the hex result of the interrupt register is 0x08, bit 4 is set -
OK, likewise 0x02 would mean bit 2 - again, no problem. 0x10 would
mean both were set.
My question is more of style, and more complicated situations - is
the best way to handle this just with IF statements and test for the
3 different conditions? Likewise, if I want to use some of the other
interrupt conditions, how would I handle circumstances with 5 or 6
different interrupts, and a ton of different possibilities?
Thanks up front for any help from an old guy that is trying to catch
up!
It completely depends on what you want to do. It's not a C-specific
problem, strictly speaking, just a question of design.
If bit 2 and 4 are set, do you want to perform the actions associated
with bit 2, then those with bit 4, or do you want to do something
completely different altogether? Do you want the option of altering the
actions at runtime for every possible combination of bits? Are the
actions drawn from a small pool of predefined possibilities?
Here's one basic approach, assuming that the conditions are independent
and you do not need runtime flexibility.
#define FOO 0x02
#define BAR 0x08
extern volatile unsigned char global_register;
void handle_interrupt(void) {
if (global_register & FOO) {
/* Actions associated with FOO condition */
}
if (global_register & BAR) {
/* Actions associated with BAR condition */
}
}
If the conditions are interdependent, you could do:
#define FOOBAR (FOO | BAR)
void handle_interrupt(void) {
switch (global_register) {
case FOO: {
/* Actions associated with FOO-only condition, */
}; break;
case BAR: {
/* Actions associated with BAR-only condition */
}; break;
case FOOBAR: {
/* Actions associated with FOO and BAR-condition */
}; break;
default: {
/* Default actions if no predefined condition combinations apply */
}
}
You can even mix these. Here's assuming that FOO and BAR are dependent,
but some BAZ has two independent FOO and BAR conditions:
#define BAZ 0x..
void handle_interrupt(void) {
switch (global_register) {
case FOO: {
/* Actions associated with FOO-only condition */
}; break;
case BAR: {
/* Actions associated with BAR-only condition */
}; break;
case FOOBAR: {
/* Actions associated with FOO and BAR-condition */
}; break;
default: {
if (global_register & BAZ) {
if (global_register & FOO) {
/* Actions associated with BAZ and FOO condition */
}
if (global_register & BAR) {
/* Actions associated with BAZ and BAR condition */
}
} else {
/* Default actions */
}
}
This rapidly gets hard to read, however; I recommend turning the various
branches in functions.
If you want the option of associating handlers for each condition or
combination of condition at runtime, things change yet again, and you'll
want a (possibly dynamic) table of bitmasks. I'll defer this.
Basically, you can get as simple or complicated as you like, depending
on your needs.
S.