Common alarm-control panels contain several input devices and require user displays. The usual components for these systems include:
- A device to accept input from the user: a 4 x 4 switch keypad.
- A device to display output to the user: an LCD display.
- An input device: a magnetic reed switch.
- An output device: a piezoelectric horn.
These several components can be managed and controlled by a simple application and the powerful, flexible MAXQ2000 microcontroller. This application, available for download
, was written in MAXQ assembly language using the MAX-IDE development environment. The code was targeted for the MAXQ2000 evaluation kit board, using the following additional hardware:
- Keypad: Grayhill 16-button (4 rows by 4 columns) keypad 96BB2-006-F
- Piezoelectric horn: CEP-1172
- Magnetic reed switch: standard single-loop type
Our example application performs the following tasks:
Figure 1. The alarm control application operates in four main states: CLOSED, OPEN, SET, AND ALERT.
- Monitors the magnetic reed switch to determine if a door/window is open or closed.
- Allows the user to arm or disarm the system by entering a PIN on the keypad.
- Displays status information to the user on the LCD.
- Provides audio indications of keypresses and sensor open/close events by sounding the piezoelectric horn.
- Sounds the horn continuously if the sensor is opened while the system is armed.
The behavior of the alarm control application consists of four discrete states: CLOSED, OPEN, SET, and ALERT (Figure 1).
Interfacing to the Magnetic Reed Switch
In an alarm system, magnetic reed switches are installed in two parts: a magnet and the actual reed switch. The magnet portion is placed on the moving section of a door or window, while the switch portion is placed on the frame. When the door or window is closed, the magnet closes the reed switch, indicating a nonalarming condition. If the system is armed and the window or door is opened, the reed switch changes state, allowing the MAXQ2000 to sound an intrusion alert.
The reed switch is interfaced to the MAXQ2000 simply by connecting it between port pins P5.2 and P5.3. With P5.2 set to an active-low pulldown (PD = 1, PO = 0) and P5.3 set to a weak pullup input (PD = 0, PO = 1), P5.3 will read zero when the reed switch is closed and one when the reed switch is open.
move PD5.2, #1 ; Drive one side of reed switch LOW
move PO5.2, #0
move PD5.3, #0 ; Set weak pullup high on other side
move PO5.3, #1
move C, PI5.3
jump NC, ML_Closed_L ; Switch is closed, continue in this state
jump ML_Open ; Switch is open, transition to OPEN state
Interfacing to the 4 x 4 Keypad
Keypads are used in alarm control systems for secure PIN entry, to arm/disarm the system, and to change configurations. The keypad used in this example application consists of 16 switches, organized in a 4 x 4 grid. The switches are tied together in a row and column matrix (Figure 2
) so that depressing a keypad switch connects one row line to one column line. For example, depressing the "3" key connects row 1 and column 3 together.
Figure 2. The keypad switches form a grid of four rows and four columns.
The keypad provides eight interface pins, one pin for each row and column of the keypad matrix. The keypad and the MAXQ2000 EV kit are connected as shown.
For this application, the EV kit board should be configured as follows.
- DIP switches.
- The following switches must be OFF: All SW1 switches, SW3.1, SW3.7, SW3.8, SW6.1, SW6.4, SW6.5, SW6.6, SW6.7, and SW6.8.
- All other DIP switches can be in any state.
- The following jumpers must be OPEN: JU5, JU6, JU8, and JU9.
- The following jumpers must be CLOSED: JU1, JU2, JU3 and JU11.
- All other jumpers can be in any state.
Scanning by Columns
The row and column arrangement of the keypad makes it easy to read the state of four switches at any one time, on either a row or column basis. To read four switches in one column, first the line for that column must be pulled low, and all other columns tri-stated (Figure 3
). Next, a weak pullup must be set on each row line. Finally, the four row lines are connected to port pin inputs. The input from a row will be low when the switch on that row is depressed, and high otherwise.
Similarly, the state of four switches in a row can be read by pulling that row line low and setting inputs and weak pullups on all four columns. The rows and columns are interchangeable.
In our setup, the four row lines (keypad pins 1 through 4) are all connected to the same input port (P6[3:0]), which makes it easier to read them simultaneously. For this reason, the example application scans one column of switches at a time. There are four setup states for the eight port-pin lines connected to the keypad, each of which allows four of the switches to be read. All input lines read low when the switch being read is closed, and high when the switch is open.
Figure 3. The MAXQ2000 pulls column 1 low to read the state of the first four keypad switches.
||Input - 1
||Input - 4
||Input - 7
||Input - *
||Input - 2
||Input - 5
||Input - 8
||Input - 0
||Input - 3
||Input - 6
||Input - 9
||Input - #
||Input - A
||Input - B
||Input - C
||Input - D
An Interrupt-Driven State Machine
The four columns must be strobed quickly so that any keypress has time to be read before it is released. Additionally, to prevent a switch's bouncing contacts from registering multiple presses, a key must be held down for a certain amount of time before it registers. Both of these factors can be done at once by making a timer-driven interrupt routine the heart of the application. This allows the application to scan through each one of the four columns in a periodic manner and to count the length of time a key has been depressed.
RELOAD equ 0FF00h
move IIR.3, #1 ; Enable interrupts for module 3
move IMR.3, #1
move T2V0, #RELOAD
move T2R0, #0h
move T2C0, #0h
move Acc, T2CFG0 ; Set timer 0 to run from HFClk/128
move T2CFG0, Acc
move T2CNA0.3, #1 ; Start timer 0
move T2CNA0.7, #1 ; Enable timer 0 interrupts
The reload value for the timer controls how often the interrupt will fire. This value must be short enough so that all keypresses are recognized. Additionally, to ensure that key response is not sluggish, the reload value must also be long enough so that it does not occupy an excessive amount of processing time. The value 0FF00h shown above (once about every 2.4ms) was reached through experimentation.
Once the column line for a group of four switches is driven low, some time may be required for the connection operating through a depressed switch to pull its input line low. This time is affected by the switch's on-resistance and by how many column switches are depressed at once. To avoid having to delay the interrupt service routine between pulling the column line low and reading the four switches, the column line for a given state is driven low in the previous state (Figure 4
Figure 4. In each of the four key-scanning states, the application reads the status of four switches and prepares to read the next four.
Because the interrupt vector (IV) for the MAXQ2000 can be set on-the-fly, the application holds the next-state value in the interrupt vector register. Whenever the timer interrupt fires, the handler routine for the current key-scanning state sets the interrupt vector address to the next state's handler routine.
move PD6, #010h ; For state 1
move PO6, #00Fh ; For all states
move PD7, #000h ; For state 1
move PO7, #000h ; For all states
move IV, #State1
move IC, #1 ; Enable global interrupts
move Acc, PI6
and #000Fh ; Grab lowest four bits only
move A, Acc
move PD6, #020h ; For state 2
move PD7, #000h
move T2V0, #RELOAD ; Set reload value
move T2CNB0.1, #0 ; Clear interrupt flags
move T2CNB0.3, #0
move IV, #State2
The handler routines for the other four states are similar, with a slight adjustment to OR in the previously collected switch bits in the A holding register. There are three working accumulators used by the state routines.
A holds the bit array of all the switch states read on the current pass through the keypad. After the State 4 read completes, this register contains the following bits, where a one bit represents an open (released) key switch and a zero bit represents a closed (depressed) key switch.
After State 4 is reached and all keys are scanned, a decision must be made whether to accept any keys that are pressed. A simple way to handle debouncing is to maintain a counter value for each of the 16 switches. Every time State 4 is reached and the key is pressed, the counter is incremented. If the key is not pressed, the counter is decremented. When the counter reaches a certain value, the keypress is registered. To prevent a held-down key from repeating (which typically is allowed on computer keyboards, but not on keypads), the counter must be allowed to decrement back to zero (by releasing the key) before that key may be registered again.
As we have the state of all 16 keys in a single register, there is a simpler, less memory-intensive solution for debouncing. The application maintains a single counter value that is incremented each time the bit pattern matches the pattern read on the previous pass.
move Acc, PI6
and #000Fh ; Grab low four bits only
jump E, State4_End ; Ignore the last debounced pattern
jump E, State4_Match
move LC, #DEBOUNCE
move A, Acc ; Reset current bit array
To prevent keys from repeating, once a bit pattern has been static long enough to be accepted, a different bit pattern (which includes the idle state where no keys are depressed) must be accepted before the first bit pattern can be accepted again.
Handling Simultaneous Keypresses
Simultaneous keypresses are possible when using a keypad input device. The debouncing code ensures that if a second key is pressed right after the first, the debounce interval will start over, but be short enough in practice so that this is not an issue.
Once a bit pattern has been accepted, the action for each depressed-key bit can be taken by rotating all 16 bits into the carry bit individually using the accumulator and checking each in turn. The following code responds only to the first depressed key, but this could be easily changed.
djnz LC, State4_End
move A, Acc ; Reset last debounced pattern
jump NC, State4_KeyA
jump NC, State4_KeyB
jump NC, State4_KeyC
jump NC, State4_KeyD
jump NC, State4_Key3
jump NC, State4_Key6
jump NC, State4_Key9
jump NC, State4_KeyPound
jump NC, State4_Key2
jump NC, State4_Key5
jump NC, State4_Key8
jump NC, State4_Key0
jump NC, State4_Key1
jump NC, State4_Key4
jump NC, State4_Key7
jump NC, State4_KeyStar
Interfacing to the LCD Display
The LCD display included with the MAXQ2000 EV kit has segments defined as shown (Figure 5
Figure 5. The LCD display contains four-and-a-half 7-segment characters.
First, the LCD display must be initialized to static drive mode and enabled. Once this has been done, characters can be written to the display by setting segments appropriately.
move LCRA, #03E0h ; xxx0001111100000
; 00 - DUTY : Static
; 0111 - FRM : Frame freq
; 1 - LCCS : HFClk / 128
; 1 - LRIG : Ground VADJ
; 00000 - LRA : RADJ = max
move LCFG, #0F3h ; 1111xx11
; 1111 - PCF : All segments enabled
; 1 - OPM : Normal operation
; 1 - DPE : Display enabled
move LCD0, #00h ; Clear all segments
move LCD1, #00h
move LCD2, #00h
move LCD3, #00h
move LCD4, #00h
Entering the PIN
In the CLOSED, SET, and ALERT states, a PIN can be entered to change the alarm controller to another state. As each character is entered, the working value held in A is shifted left and ORed with the new character, and the decimal point on the LCD display moves left to indicate the number of characters entered. For security reasons, the PIN being entered is not shown on the display.
move Acc, #0000h
move Acc, #0001h
move Acc, #0002h
move A, Acc
move Acc, A
cmp #0FFFFh ; flag indicating no PIN entry allowed
; in current state
jump E, State4_NoKey
move Acc, A ; key count
cmp #04 ; if already at 4 (should have been cleared)
jump E, State4_NoKey
move A, Acc
move Acc, A
move A, Acc
Once all four characters are entered, the PIN is checked against a hard-coded value. If the entered value matches the PIN, the appropriate state transition occurs.
PIN_VALUE equ 03870h ; Just a random number
;; "Closed" state code
move A, #00000h ; Reset PIN value
move A, #0 ; Reset number of PIN chars entered
move LCD3, #LCD_CHAR_C
move LCD2, #LCD_CHAR_L
move LCD1, #LCD_CHAR_5
move LCD0, #LCD_CHAR_D
move Acc, A
cmp #4 ; 4 characters entered?
jump NE, ML_Closed_Check
move Acc, A
cmp #PIN_VALUE ; PIN matches?
jump E, ML_Set
call LongBeep ; Beep on incorrect PIN and reset
move A, #0000h
move A, #0
move LCD3.7, #0
move C, PI5.3 ; Check reed switch
jump NC, ML_Closed_L ; Closed, stay in current state
call ShortBeep ; 4 short beeps signal transition
jump ML_Open ; Switch opened, go to OPEN state
Using the Piezoelectric Horn
In our application, a small piezoelectric horn is used to perform two functions: (1) provide audio feedback when keys are pressed or when an incorrect PIN is entered, and (2) sound an alarm when the reed switch opens while the system is armed.
For demonstration purposes, a small piezoelectric horn can be interfaced with the MAXQ2000 by connecting it between two port pins. The port pins are driven differentially to increase the current drive to the piezoelectric horn, and the loop counts used in the driver code determine the frequency of the tone emitted.
move LC, #100 ; Number of cycles
move PO5.6, #0
move PO5.7, #1
move Acc, #2000 ; Count for forward polarity period
jump NZ, SB_L2
move PO5.6, #1
move PO5.7, #0
move Acc, #2000 ; Count for reverse polarity period
jump NZ, SB_L3
djnz LC, SB_L1
In an actual alarm system, stronger drive circuitry would be used to run the piezoelectric horn, and the horn would be driven at its resonant frequency to increase the volume.
The MAXQ2000 interfaces easily and directly to LCD displays by means of its dedicated LCD controller peripheral. Multiplexed keypads can be read in a straightforward manner using the flexible port-pin configuration provided by the MAXQ2000. A timer-interrupt-driven state machine allows all keys in the matrix to be scanned and debounced with minimal effect on processor overhead. Finally, a piezoelectric horn and magnetic reed switch can be controlled easily as well, using the general-purpose port pins available on the MAXQ2000.
This article appears in the MER Vol 5.