Implementing a State Machine

IAR Application Note #8611-003 IAR Application Note #6811-003 Implementing a State Machine by Stefan Nyman [mailto:[email protected]] SUMMAR...
6 downloads 1 Views 86KB Size
IAR Application Note #8611-003

IAR Application Note #6811-003

Implementing a State Machine by Stefan Nyman [mailto:[email protected]]

SUMMARY

By describing a problem in terms of states, tests and tasks you can easily solve it in a straightforward switch statement.

KEYWORDS

State machine, switch

State Machine for Keyboard Scanning This example shows how to use a state machine in the program. In most programs, important parts can be regarded as state machines. As an illustration, a 2-key rollover keyboard scanner is implemented. The benefit of using a state machine is that the behavior of the program can easily be described in a graph. The graph is then implemented in a table.

No Yes

State 0 AnyKey?

No

ScanKey

State 1 SameKey? Yes FindKey

ClearKey No

No

State 3

SameKey?

State 2

Yes

SameKey?

Yes

The graph above shows one way to accomplish a very secure detection of keys on a cheap keyboard matrix - or anything that needs filtering. By describing the filtering in the state graph, we can create a good method of reading the keys. The machine starts in State 0. 1

IAR Application Note #8611-003

State 0: When a key is detected, the corresponding code (read from a port) is remembered, and the machine switches to state 1. State 1: If the same code is detected, it is approved, a flag is set and the key value is passed to other programs (via a mailbox). State 2: As long as the same code is detected, nothing is done. If the code changes, the state shifts to see if the change is occasional. State 3: If the change was occasional, the machine returns to state 2; otherwise it restarts to look for another keycode. The graph can easily be converted to a switch statement: void Scan_Keyboard(void) { switch (KeyState) { case 0: { if (AnyKey()) { ScanKey(); KeyState = 1; } } case 1: { if (SameKey()) { FindKey(); KeyState = 2; } else KeyState = 0; } case 2: { if (SameKey()) { } else KeyState = 3; } case 3: { if (SameKey()) { KeyState = 2; } else { ClearKey(); KeyState = 0; } } } }

The keyboard is connected as shown below. By setting one bit to 1 in PORTB, you can detect the key pressed.

2

IAR Application Note #8611-003

PORTA 2

PORTB 1

0

6

5

4

3

10 kΩ 10 kΩ 10 kΩ

With this state machine and the task routines, we are going to build a versatile program component which will behave like a 74HC922. Variables: // State: char KeyState; // Bit pattern after each scan: char KeyCode; // Output value from the virtual 74HC922: char KeyValue; // KeyDown is set if key is down: char KeyDown; // KeyNew is set every time a new key is down: char KeyNew;

Test Functions: // AnyKey is true if any key is down char AnyKey(void) { PORTB |= 0x78; return (PORTA & 0x07); } // SameKey is true if same key is still down char SameKey(void) { PORTB = ((PORTB & 0x87) | ( KeyCode & 0x78)); return ((KeyCode & PORTA) & 0x07); }

3

IAR Application Note #8611-003

Tasks: // ScanKey generates a bit pattern in KeyCode void ScanKey(void) { PORTB = (PORTB & 0x87) | 0x08; while (PORTB & 0X78) { if (PORTA & 0x07) { KeyCode = ((PORTA & 0x07) | (PORTB & 0x78)); } PORTB = (PORTB & 0x87) | (((PORTB & 0x78)