Lecture 8 – Simple I/O (Input and Output) Devices Contents 8.1. Interface with Light-emitting Diode (LEDs) ............................................................................................................... 2 8.2. LED Circuit of MC9S12DG256 (the Dragon12-Plus Board) ..................................................................................... 2 1. Example 8.2.1 (Example 4.12) – LEDs....................................................................................................................... 3 8.3. Interfacing with Seven-Segment Displays .................................................................................................................. 4 1. Seven-Segment Displays on MC9S12DG256 ............................................................................................................. 5 1. Example 8.3.1 – Seven-segment LEDs ....................................................................................................................... 7 8.4. Generating a Digital Waveform Using I/O Pins.......................................................................................................... 9 1. Example 8.4.1 (Example 4.16) – Generating Siren ..................................................................................................... 9 8.5. Interfacing with Dual Inline Package (DIP) Switches............................................................................................... 11 1. Example 8.5.1 – DIP Switches .................................................................................................................................. 11 Lecture 8 – Simple I/O Devices Page 1 of 11 Many embedded systems require simple input or output devices such as switches, light-emitting diode (LED), keypads, and seven-segment displays 8.1. Interface with Light-emitting Diode (LEDs) LED is often used to indicate the system operation mode such as power is turned on, the system is in normal mode. An LED can illuminate when it is forward biased and has sufficient current flowing through it (1mA ~ 10mA). The forward voltage across LED varies from 1.6V to 2.2V. There three ways to interface with LEDs: positive direct drive, inverse direct drive, and buffered drive. VCC Port pin Port pin ` VCC R1 (a) Positive direct drive R2 (b) Inverse direct drive Port pin 74HC04 (c) Buffered drive R3 Figure 1 – LED Connection Methods (a) and (b) are often used for a LED because it needs a small current (1mA ~ 2mA) to produce enough brightness. Method (c) is for LED with a high current to light up. Resistors R1, R2, and R3 are called current-limiting resistors because it they limit the maximum current following through LED. For methods (a) and (b), the current-limiting resistor should be large (between 1.5kΩ to 3kΩ). 8.2. LED Circuit of MC9S12DG256 (the Dragon12-Plus Board) The HCS12 board has 8 LEDs connected to Port B. The cathodes of LEDs are connected to PJ1 through current-limiting resistors (2.7kΩ) as below: H C S1 2 1.5 K PB7 P B6 PB5 PB4 PB3 PB 2 PB 1 PB 0 PJ1 Lecture 8 – Simple I/O Devices Page 2 of 11 1. Example 8.2.1 (Example 4.12) – LEDs Write an assembly program that turns on each LED, in turn from left to right and then from right to left with each LED lighted for about half of a second and repeat. Solution: LEDs are driven by pins PB7~PB0 once at a time by sending to Port B the values $80, $40, $20, $10, $08, $04, $02, …, and $01. ; export symbols XDEF Entry, _Startup ; export 'Entry' symbol ABSENTRY Entry ; for absolute assembly: mark this as entry point ; Include derivative-specific definitions INCLUDE 'derivative.inc' ROMStart EQU $4000 ; absolute address to place my code/constant data ;********************************************************************************** ; variables / data section ifdef _HCS12_SERIALMON ORG $3FFF - (RAMEnd - RAMStart) Else ORG RAMStart endif ;********************************************************************************** ; Variables for the program ;********************************************************************************** lpcnt DS.B 1 ;********************************************************************************** ; Code section ORG ROMStart ;********************************************************************************** ; This table contains values for LEDs ;********************************************************************************** LED_tab DC.B $80,$40,$20,$10,$08,$04,$02,$01 DC.B $01,$02,$04,$08,$10,$20,$40,$80 Entry: _Startup: ; remap the RAM & EEPROM here. See EB386.pdf ifdef _HCS12_SERIALMON ; set registers at $0000 CLR $11 ; INITRG= $0 ; set ram to end at $3FFF LDAB #$39 STAB $10 ; INITRM= $39 ; set EEPROM to end at $0FFF LDAA #$9 STAA $12 ; INITEE= $9 LDS #$3FFF+1 ; See EB386.pdf, initialize the stack pointer else LDS #RAMEnd+1 ; initialize the stack pointer endif ; Set 24MHz clock bus: PLL code for 24MHz bus speed from a 4/8/16 crystal LDX #$00 ; BCLR CLKSEL, X, mCLKSEL_PLLSEL ; clear bit 7, clock derived from oscclk BSET PLLCTL, X, mPLLCTL_PLLON ; Turn PLL on, bit 6=1 PLL on, bit 6=0 PLL off LDAA #$05 ; 5+1=6 multiplier STAA SYNR, X ; Lecture 8 – Simple I/O Devices Page 3 of 11 LDAA #$01 ; divisor=1+1=2, 8*2*6 /2 = 48MHz PLL STAA BRCLR BSET ; for 8 MHz crystal REFDV, X CRGFLG, X, mCRGFLG_LOCK, * ; Wait until bit 3 = 1 CLKSEL, X, mCLKSEL_PLLSEL ; freq, ; Configure Port for LEDs MOVB #$FF, DDRB ; configure port B for output BSET DDRJ, $02 ; configure PJ1 pin for output BCLR PTJ, $02 ; enable LEDs to light forever: MOVB #16, lpcnt ; initialize LED pattern count LDX #LED_tab ; Use X as the pointer to LED pattern table led_lp MOVB 1,X+, PORTB ; turn on one LED LDY #50 ; wait for half a second JSR Delay10ms ; " DEC lpcnt ; reach the end of the table yet? BNE led_lp BRA forever ; start from beginning ;********************************************************************************** ; The following subroutine creates a time Delay which is equal to [Y] times 10ms. ; The timer prescaler is 1:8. ;********************************************************************************** Delay10ms: PSHD ; save ACCD onto the stack BSET TIOS, mTIOS_IOS0; enable OC0 LDD TCNT Again_10ms: ADDD #30000 ; start an output compare operation STD TC0 ; with 10ms time Delay BRCLR TFLG1, mTFLG1_C0F, * LDD TC0 DBNE Y, Again_10ms ; BCLR TIOS, mTIOS_IOS0; disable OC0 PULD ; Restore the value of ACCD RTS ;********************************************************************************** ;* Interrupt Vectors * ;********************************************************************************** ORG $FFFE DC.W Entry ; Reset Vector END 8.3. Interfacing with Seven-Segment Displays Seven-segment displays are often used when the embedded system needs to display only a few digits. Seven-segment displays are mainly used to display decimal digits and a small subset of letters. Although an HCS12 has enough current to drive a seven-segment display, it is not advisable to use the HCS12 to drive the seven-segment display directly because the HCS12 may need to drive other I/O devices in its system. A buffer chip (such as 74HC244) is used to drive seven-segment display. Lecture 8 – Simple I/O Devices Page 4 of 11 470 each H CS12 a 74HC244 PB6 PB5 PB4 PB3 PB2 PB1 PB0 b f c a b g d e e c f d g com m on cathode Figure 2 – Driving a Single Seven-segment Display with Buffer Chip 74HC244 In the circuit above, Port B of the HCS12 drives a common-cathode seven-segment display through the buffer chip 74HC244. Since the output voltage of the buffer chip VOH is about 5V, 470-Ω resistors will limit the current to about 6.4 mA, which is sufficient to light an LED segment. In this circuit, the light patterns corresponding to 10 BCD digits are shown in the table below: Segment Corresponding Decimal Digit PB6 PB5 PB4 PB3 PB2 PB1 PB0 Hex Number a b c d e f g 0 1 1 1 1 1 1 0 $7E 1 0 1 1 0 0 0 0 $30 2 1 1 0 1 1 0 1 $6D 3 1 1 1 1 0 0 1 $79 4 0 1 1 0 0 1 1 $33 5 1 0 1 1 0 1 1 $5B 6 1 0 1 1 1 1 1 $5F 7 1 1 1 0 0 0 0 $70 8 1 1 1 1 1 1 1 $7F 9 1 1 1 1 0 1 1 $7B 1. Seven-Segment Displays on MC9S12DG256 The Dragon Plus board has 4 seven-segment displays. The connection is quite different from the standard connect. Each seven-segment display on the Dragon Plus board has a decimal point. The two of the digits (DSP3 and DSP4) at the right are deliberately placed upside down and the hardware connections compensate for this configuration. The reason for the upside down digits is to place two decimal pointers on the middle as a colon for a clock display. Lecture 8 – Simple I/O Devices Page 5 of 11 Figure 3 – Hardware Connection for 7-Segement LEDs display The digit 3, 2, 1, and 0 are driven by PP0, PP1, PP2 and PP3, respectively, as shown below. A zero on pin of Port P will turn on the digit display. #3 #0 800 a b . . . . . . g 800 g common cathode PB6 PB0 PB1 74HC244 HCS12 #2 #1 a b 74HC367 PP0 A0 Y0 PP1 A1 Y1 PP2 A2 Y2 PP3 A3 Y3 PP4 A4 Y4 PP5 A5 Y5 #1 #0 a. . . a b. . . b g. . . common cathode #5 a #0 #1 b . . g . g common cathode . . . common common cathode cathode . . . Figure 4 – Four Seven-segment LEDs on the Dragon Plus Board The segments A, B, C, D, E, F, G and Decimal Point are driven by PB0, PB1, PB2, PB3, PB4, PB5, PB6, and PB7. The hex value of the segment code is shown in the following tables: Table 1 – Hex Values of Digit without Decimal Point Number DP G F E D C B A Hex Value 0 0 0 1 1 1 1 1 1 $3F 1 0 0 0 0 0 1 1 0 $06 2 0 1 0 1 1 0 1 1 $5B 3 0 1 0 0 1 1 1 1 $4F 4 0 1 1 0 0 1 1 0 $66 5 0 1 1 0 1 1 0 1 $6D 6 0 1 1 1 1 1 0 0 $7C 7 0 0 0 0 0 1 1 1 $07 8 0 1 1 1 1 1 1 1 $7F 9 0 1 1 0 0 1 1 1 $67 Lecture 8 – Simple I/O Devices Page 6 of 11 Table 2 – Hex Values of Digit with Decimal Point Number DP G F E D C B A Hex Value 0 1 0 1 1 1 1 1 1 $BF 1 1 0 0 0 0 1 1 0 $86 2 1 1 0 1 1 0 1 1 $DB 3 1 1 0 0 1 1 1 1 $CF 4 1 1 1 0 0 1 1 0 $E6 5 1 1 1 0 1 1 0 1 $ED 6 1 1 1 1 1 1 0 0 $FC 7 1 0 0 0 0 1 1 1 $87 8 1 1 1 1 1 1 1 1 $FF 9 1 1 1 0 0 1 1 1 $E7 1. Example 8.3.1 – Seven-segment LEDs Write an assembly program to display “1234” on 4 digits of seven-segment LEDs. Solution: The digits 1, 2, 3, and 4 are displayed on display #3, #2, #1, and #0. The values to send to Port B and Port P to display one digit at time are in the table below. Each digit is displayed for 1ms. Port P Seven-segment Displayed Port Display BCD Digit B PP7 PP6 PP5 PP4 PP3 PP2 PP1 PP0 Hex #3 1 $06 1 1 1 1 1 1 1 0 $FE #2 2 $5B 1 1 1 1 1 1 0 1 $FD #1 3 $4F 1 1 1 1 1 0 1 1 $FB #0 4 $66 1 1 1 1 0 1 1 1 $F7 ; export symbols XDEF Entry, _Startup ; export 'Entry' symbol ABSENTRY Entry ; for absolute assembly: mark this as entry point ; Include derivative-specific definitions INCLUDE 'derivative.inc' ROMStart EQU $4000 ; absolute address to place my code/constant data ;********************************************************************************** ; variables / data section ifdef _HCS12_SERIALMON ORG $3FFF - (RAMEnd - RAMStart) Else ORG RAMStart endif ;********************************************************************************** ; Variables for the program ;********************************************************************************** lpcnt DS.B 1 ;********************************************************************************** ; Code section ORG ROMStart ;********************************************************************************** ; This table contains values for 7-segment LEDs ;********************************************************************************** DispTab DC.B $06,$FE Lecture 8 – Simple I/O Devices Page 7 of 11 DC.B DC.B DC.B $5B,$FD $4F,$FB $66,$F7 Entry: _Startup: ; remap the RAM & EEPROM here. See EB386.pdf ifdef _HCS12_SERIALMON ; set registers at $0000 CLR $11 ; INITRG= $0 ; set ram to end at $3FFF LDAB #$39 STAB $10 ; INITRM= $39 ; set EEPROM to end at $0FFF LDAA #$9 STAA $12 ; INITEE= $9 LDS #$3FFF+1 ; See EB386.pdf, initialize the stack pointer else LDS #RAMEnd+1 ; initialize the stack pointer endif ; Set 24MHz clock bus: PLL code for 24MHz bus speed from a 4/8/16 crystal LDX #$00 ; BCLR CLKSEL, X, mCLKSEL_PLLSEL ; clear bit 7, clock derived from oscclk BSET PLLCTL, X, mPLLCTL_PLLON ; Turn PLL on, bit 6=1 PLL on, bit 6=0 PLL off LDAA #$05 ; 5+1=6 multiplier STAA SYNR, X ; LDAA #$01 ; divisor=1+1=2, 8*2*6 /2 = 48MHz PLL freq, ; for 8 MHz crystal STAA REFDV, X BRCLR CRGFLG, X, mCRGFLG_LOCK, * ; Wait until bit 3 = 1 BSET CLKSEL, X, mCLKSEL_PLLSEL ; MOVB #$FF, DDRB ; configure port B for output MOVB #$0F, DDRP ; configure port P for output (PP0~PP3) forever: MOVB #4, lpcnt ; initialize LED pattern count LDX #DispTab ; Use X as the pointer to display table again: MOVB 1,X+, PORTB ; display segment pattern MOVB 1,X+, PTP ; select the digit for display LDY #1 ; wait for half a second JSR Delay1ms ; " DEC lpcnt ; reach the end of the table yet? BNE again BRA forever ; start from beginning ;********************************************************************************** ; The following function creates a time Delay which is equal to the multiple ; of 1ms. The value passed in Y specifies the number of 1 milliseconds to be ; delayed. ;********************************************************************************** Delay1ms: PSHD ; save ACCD onto the stack BSET TIOS, mTIOS_IOS0 ; enable OC0 LDD TCNT Again_1ms: ADDD #3000 ; start an output compare operation ; 1ms = 3000 * 8 / 24Mhz STD TC0 ; with 1ms time Delay BRCLR TFLG1, mTFLG1_C0F, * ; wait until C0F is set LDD TC0 ; load TC0 for the next loop DBNE Y, Again_1ms ; BCLR TIOS, mTIOS_IOS0; disable OC0 PULD ; Restore the value of ACCD RTS ;********************************************************************************** ;* Interrupt Vectors * ;********************************************************************************** Lecture 8 – Simple I/O Devices Page 8 of 11 ORG DC.W END $FFFE Entry ; Reset Vector 8.4. Generating a Digital Waveform Using I/O Pins A periodic digital waveform can be easily generated by manipulating I/O pin voltage level and inserting an appropriate delay between the two voltage levels. A 1-kHz periodic square wave can be generated from the PT5 pin (pin 5 of Port T) using the following steps: Step 1 – configure the PT5 pin for output Step 2 – Pull the PT5 pin to high Step 3 – wait for 0.5 ms (the first half of the period) Step 4 – Pull the PT5 pin to low Step 5 – wait for 0.5 ms (the second half of the period) Step 6 – Go back to Step 2. The PT5 pin, on the Dragon Plus board, is connected to a small speaker. If the frequency of the square wave is in the audible range, it can be heard. If we alter the frequency of the generated square wave from the I/O pin between two different values, a two-tone siren can be generated. The duration of the siren tone is variable. The siren would sound more urgent if the tone duration were shorter. 1. Example 8.4.1 (Example 4.16) – Generating Siren Write an assembly program that generate two-tone siren. It alternates between 250Hz and 500Hz with each siren tone lasting half of a second. Solution: 500 Hz: T = 1/500 = 2ms, half of the period = 1ms; lasting for 0.5s repeating 0.5/2ms = 250 times. 250 Hz: T = 1/250 = 4ms, half of the period = 2ms, lasting for 0.5s repeating 0.5/4ms = 125 times. ; export symbols XDEF Entry, _Startup ABSENTRY Entry point ; export 'Entry' symbol ; for absolute assembly: mark this as entry ; Include derivative-specific definitions INCLUDE 'derivative.inc' ROMStart EQU $4000 ; absolute address to place my code/constant data ;********************************************************************************** ; variables / data section ifdef _HCS12_SERIALMON ORG $3FFF - (RAMEnd - RAMStart) Else ORG RAMStart endif ;********************************************************************************** ; Code section ORG ROMStart Entry: _Startup: ; remap the RAM & EEPROM here. See EB386.pdf Lecture 8 – Simple I/O Devices Page 9 of 11 ifdef _HCS12_SERIALMON ; set registers at $0000 CLR $11 ; INITRG= $0 ; set ram to end at $3FFF LDAB #$39 STAB $10 ; INITRM= $39 ; set EEPROM to end at $0FFF LDAA #$9 STAA $12 ; INITEE= $9 LDS #$3FFF+1 ; See EB386.pdf, initialize the stack pointer else LDS #RAMEnd+1 ; initialize the stack pointer endif ; Set 24MHz clock bus: PLL code for 24MHz bus speed from a 4/8/16 crystal LDX #$00 ; BCLR CLKSEL, X, mCLKSEL_PLLSEL ; clear bit 7, clock derived from oscclk BSET PLLCTL, X, mPLLCTL_PLLON ; Turn PLL on, bit 6=1 PLL on, bit 6=0 PLL off LDAA #$05 ; 5+1=6 multiplier STAA SYNR, X ; LDAA #$01 ; divisor=1+1=2, 8*2*6 /2 = 48MHz PLL freq, ; for 8 MHz crystal STAA REFDV, X BRCLR CRGFLG, X, mCRGFLG_LOCK, * ; Wait until bit 3 = 1 BSET CLKSEL, X, mCLKSEL_PLLSEL ; BSET DDRT, mDDRT_DDRT5 ; configure PT5 pin for output Forever: LDX #250 ; repeat 500Hz waveform for 250 times Tone1: BSET PTT, mPTT_PTT5 ; pull PT5 pin high LDY #1 ; first half period of 500Hz JSR Delay1ms ; BCLR PTT, mPTT_PTT5 ; pull PT5 pin low LDY #1 ; second half period of 500Hz JSR Delay1ms ; DBNE X, Tone1 ; LDX #125 ; repeat 250Hz waveform for 125 times Tone2: BSET PTT, mPTT_PTT5 ; pull PT5 pin high LDY #2 ; first half period of 250Hz JSR Delay1ms ; BCLR PTT, mPTT_PTT5 ; pull PT5 pin low LDY #2 ; second half period of 250Hz JSR Delay1ms ; DBNE X, Tone2 ; BRA Forever ;********************************************************************************** ; The following function creates a time Delay which is equal to the multiple ; of 1ms. The value passed in Y specifies the number of milliseconds to be ; delayed. ;********************************************************************************** Delay1ms: PSHD ; save ACCD onto the stack BSET TIOS, mTIOS_IOS0 ; enable OC0 LDD TCNT Again_1ms: ADDD #3000 ; start an output compare operation ; 1ms = 3000 * 8 / 24Mhz STD TC0 ; with 1ms time Delay BRCLR TFLG1, mTFLG1_C0F, * ; wait until C0F is set LDD TC0 ; load TC0 for the next loop DBNE Y, Again_1ms ; BCLR TIOS, mTIOS_IOS0; disable OC0 PULD ; Restore the value of ACCD RTS Lecture 8 – Simple I/O Devices Page 10 of 11 ;********************************************************************************** ;* Interrupt Vectors * ;********************************************************************************** ORG $FFFE DC.W Entry ; Reset Vector END 8.5. Interfacing with Dual Inline Package (DIP) Switches A switch is the simplest input device. A set of eight switches organized as a dual inline package (DIP) is often used. In the Dragon Plus board, DIP switches are connected to Port H. Each Port H pin is pulled up to high through 51kΩ when a switch is opened. When a switch is closed, the associated Port H pin input is 0. V CC SW DIP-8 10 K 51 kΩ HCS12 PA0 PH0 PH1 PA1 PH2 PA2 PH3 PA3 PH4 PA4 PH5 PA5 PA6 PH6 PH7 PA7 In addition, there are pushbutton switches SW5, SW4, SW3, and SW2 that are also connected to PH0, PH1, PH2, and PH3 accordingly. Similar to DIP, when these pushbutton switches are opened, the Port H pins are pulled high. When a pushbutton switch is pressed, the associated Port H pin input is 0. 1. Example 8.5.1 – DIP Switches Write a sequence of assembly instructions that read the value from an eight-switch DIP that connected to Port H of MC9S12DG256. Solution: … MOVB LDAA Lecture 8 – Simple I/O Devices #$00, DDRH PTH ; configure Port H for input ; read the value of DIP switches Page 11 of 11