Download presentation
Presentation is loading. Please wait.
Published byAlexia Walsh Modified over 6 years ago
1
The 68HC11 Microcontroller Minnesota State University, Mankato
Chapter 1: Introduction to 68HC11 The 68HC11 Microcontroller Han-Way Huang Minnesota State University, Mankato
2
Computer Hardware Organization
What is a computer? Software Hardware Computer Hardware Organization Control unit common bus Arithmetic logic unit memory output input Registers program data unit unit storage storage Figure 1.1 Computer hardware organization
3
The processor The microprocessor The Microcontroller
Registers -- storage locations in the processor Arithmetic logic unit Control unit program counter keeps track of the address of the next instruction to be executed status register flags the instruction execution result The microprocessor A processor implemented on a very large scale integration (VLSI) chip Peripheral chips are needed to construct a product The Microcontroller The processor and peripheral functions implemented on one VLSI chip
4
Features of the 68HC11A8 microcontroller
- 8-bit CPU - 256 bytes SRAM - 512 bytes EEPROM - 8 KB ROM - 3 input capture channels - 5 output compare functions - one 8-bit pulse accumulator - one serial communication interface (SCI) - one serial peripheral interface (SPI) - real-time interrupt (RTI) circuit - 8-channel 8-bit A/D converter - computer operate properly (COP) watchdog system
6
Examples of microcontroller applications
- Displays - Printers - Keyboards - Modems - Charge card phones - Refrigerators - Washing machines - Microwave ovens - Automobile engine fuel injection - Fax machines - Motor speed control - etc.
7
Random-access memory (RAM): same amount of time
Semiconductor memory - Random-access memory (RAM): same amount of time is required to access any location on the same chip Read-only memory (ROM): can only be read but not written by the processor Random-access memory - Dynamic random-access memory (DRAM): periodic refresh is required to maintain the contents of a DRAM chip - Static random-access memory (SRAM): no periodic refresh is required Read-only memory - Mask-programmed read-only memory (MROM): programmed when being manufactured - Programmable read-only memory (PROM): the memory chip can be programmed by the end user
8
- Erasable programmable ROM (EPROM)
1. electrically programmable many times 2. erased by ultraviolet light (through a window) 3. erasable in bulk (whole chip in one erasure operation) - Electrically erasable programmable ROM (EEPROM) 1. electrically programmable many times 2. electrically erasable many times 3. can be erased one location, one row, or whole chip in one operation - Flash memory 3. can only be erased in bulk
9
Computer software - Computer programs are known as software - A program is a sequence of instructions Machine instruction - A sequence of binary digits which can be executed by the processor - Hard to understand for human being Assembly language - Defined by assembly instructions - An assembly instruction is a mnemonic representation of a machine instruction - Assembly programs must be translated before it can be executed -- translated by an assembler
10
High-level language - Syntax of a high-level language is similar to English - A translator is required to translate the program written in a high-level language -- done by a compiler Source code - A program written in assembly or high-level language Object code - The output of an assembler or compiler
12
Memory Addressing Memory consists of addressable locations
A memory location has 2 components: address and contents address contents Data transfer between CPU and memory involves address bus and data bus address bus lines CPU memory data bus lines Figure 1.5 Data transfer between CPU and memory
13
68HC11 addressing modes Table 1.1 Prefix for number representation Base Prefix binary octal decimal hexadecimal % @ nothing* $ *Note: Some assemblers use & Operands needed in an instruction are specified by one of the 6 addressing modes Immediate mode The actual operand is contained in the byte or bytes immediately following the instruction opcode LDAA #22 ADDA LDD #1000
14
Direct mode ADDA $10 SUBA $20 LDD $30 Extended mode LDAA $1000
A one-byte value is used as the address of a memory operand (located in on-chip SRAM) ADDA $10 SUBA $20 LDD $30 Extended mode A two-byte value is used as the address of a memory operand LDAA $1000 LDX $1000 ADDD $1030 Indexed mode The sum of one of the index registers and an 8-bit value is used as the address of a memory operand ADDA 10,X LDAA 3,Y
15
Inherent mode ABA INCB INX Relative mode ... BEQ there ADDA #10
- Operands are implied by the instruction - No address information is needed ABA INCB INX Relative mode - Used in branch instructions to specify the branch target - Specified using either a 16-bit value or a label (preferred) ... BEQ there ADDA #10 there DECB
16
A Sample of 68HC11 Instructions
The LOAD instructions A group of instructions that place a value or copy the contents of a memory location (or locations) into a register LDAA <opr> LDAB <opr> LDD <opr> LDX <opr> LDY <opr> LDS <opr> <opr> can be immediate, direct, extended, or index mode Examples LDAA $10 LDX #$1000
17
The ADD instruction ABA ABX ABY ADDA <opr> ADDB <opr>
A group of instructions perform addition operation ABA ABX ABY ADDA <opr> ADDB <opr> ADDD <opr> ADCA <opr> ADCB <opr> <opr> is specified using immediate, direct, extended, or index mode Examples. ADDA #10 ADDA $20 ADDD $30
18
SBCA <opr> ; A [A] - <opr> - C flag
The SUB instruction A group of instructions that perform the subtract operation SBA SUBA <opr> SUBB <opr> SUBD <opr> SBCA <opr> ; A [A] - <opr> - C flag SBCB <opr> ; A [B] - <opr> - C flag <opr> can be immediate, direct, extended, or index mode Examples SUBA #10 SUBA $10 SUBA 0,X SUBD 10,X
19
<addr> can be direct, extended, or index mode Examples: STAA $20
The STORE instruction A group of instructions that store the contents of a register into a memory location or memory locations STAA <addr> STAB <addr> STD <addr> STX <addr> STY <addr> STS <addr> <addr> can be direct, extended, or index mode Examples: STAA $20 STAA 10,X STD $10 STD $1000 STD 0,X
20
The 68HC11 Machine Code A 68HC11 instruction consists of 1 to 2 bytes of opcode and 0 to 3 bytes of operand information Examples Machine instructions Assembly instruction (in hex format) LDAA # D STAA $ ADDA $ B 02 STAA $ INY
21
Decoding machine language instructions
Procedure Step 1 Compare the first one or two bytes with the opcode table to identify the corresponding assembly mnemonic and format. Step 2 Identify the operand bytes after the opcode field. Step 3 Write down the corresponding assembly instruction. Step 4 Repeat step 1 to 3 until the machine code file is exhausted. A sample of machine codes and assembly instruction format machine code assembly instruction format 01 NOP 86 LDAA IMM 96 LDAA DIR C6 LDAB IMM D6 LDAB DIR CC LDD IMM DC LDD DIR 8B ADDA IMM 9B ADDA DIR CB ADDB IMM
22
machine code assembly instruction format
DB ADDB DIR C3 ADDD IMM D3 ADDD DIR 97 STAA DIR D7 STAB DIR DD STD DIR Example. Disassemble the following machine code to its corresponding assembly instructions. B Solution: The disassembly process starts from the leftmost byte. We next look up the machine code table to see which instruction it corresponds to. Instruction 1. Step 1. The first byte 96 corresponds to the instruction LDAA DIR. Step 2. The second byte, 30, is the direct address. Step 3. Therefore, the first instruction is LDAA $30.
23
Instruction 2. Step 1. The third byte (8B) corresponds to the instruction ADDA IMM. Step 2. The immediate value is 07. Step 3. Therefore, the second instruction is ADDA $07. Instruction 3. Step 1. The fifth byte (97) corresponds to the instruction STAA DIR. Step 2. The DIR address is the next byte 30. Step 3. Therefore, the third instruction is STAA $30. Instruction 4. Step 1. The seventh byte (96) corresponds to the instruction LDAA DIR. Step 2. The DIR value is the next byte 31. Step 3. Therefore, the four instruction is LDAA $31.
24
machine code assembly instruction format
01 NOP 86 LDAA IMM 96 LDAA DIR C6 LDAB IMM D6 LDAB DIR CC LDD IMM DC LDD DIR 8B ADDA IMM 9B ADDA DIR CB ADDB IMM DB ADDB DIR C3 ADDD IMM D3 ADDD DIR 97 STAA DIR D7 STAB DIR DD STD DIR
25
The 68HC11 Instruction Execution Cycle
- Perform a sequence of read cycles to fetch instruction opcode byte and address information. - Optionally perform read cycle(s) required to fetch the memory operand. - Perform the operation specified by the opcode. - Optionally write back the result to a register or a memory location. - Consider the following 3 instructions Assembly instruction Memory location Opcode LDAA $2000 $C000 B ADAA $3000 $C003 BB 30 00 STAA $2000 $C006 B
26
Instruction LDAA $2000 Step 1. Place the value in PC on the address bus with a request to read the contents of that location. Step 2. The opcode byte $B6 at $C000 is returned to the CPU and PC is incremented by 1.
27
Step 3. CPU performs two read cycles to obtain the extended address $2000 from locations
$C001 and $C002. At the end the value of PC is incremented to $C003
28
Step 4. The CPU performs another read to get the contents of the memory location at
$2000, which is $19. The value $19 will be loaded into accumulator A.
29
Chapter 2: 68HC11 Assembly Programming
The 68HC11 Microcontroller Han-Way Huang Minnesota State University, Mankato
30
Assembly Program Structure
C program main () { int i, j, k; ; i, j, k are integer variables i = 75; ; assign 75 to i j = 10; ; assign 10 to j k = i + j - 6; }
31
Assembly Program (1) * Data storage declaration section (2) ORG $00 (3) i RMB 1 ; variable i (4) j RMB 1 ; variable j (5) k RMB 1 ; variable k (6) * program instruction section (7) start ORG $C000 ; starting address of program (8) LDAA #75 (9) STAA i ; initialize i to 75 (10) LDAA #10 (11) STAA j ; initialize j to 10 (12) ADDA i ; compute i + j (13) SUBA #6 ; compute i + j -6 (14) STAA k ; store i + j - 6 to k (15) END
32
Global View of a 68HC11 Assembly Program
1. Assembler Directives - define data and symbol - reserve and initialize memory locations - set assembler and linking condition - specify output format - etc. 2. Assembly Language Instructions 3. END directive - last statement of a program - any statement after END will be ignored 4. Comments - explain the function of a single or a group of instructions
33
Fields of a 68HC11 Instruction
1. Label field - is optional - starts with a letter and followed by letters, digits, or special symbols (_ or .) - can start from any column if ended with “:” (not true for Motorola freeware as11) - must start from column 1 if not ended with “:” 2. Operation field - contains the mnemonic of a machine instruction or a directive - is separated from the label by at least one space 3. Operand field - follows the operation field and is separated from the operation field by at least one space - contains operands for instructions or arguments for assembler directives 4. Comment field - a whole line comment starts with a * - is separated from the operand and operation field for at least one space
34
Identify the Four Fields of an Instruction
Example 2.3 loop ADDA #$40 ; add 40 to accumulator A (1) “loop” is a label (2) “ADDA” is an instruction mnemonic (3) “#$40” is the operand (4) “add #$40 to accumulator A” is a comment
35
Assembler Directives -- a sample
1. END - ends a program to be processed by an assembler - any statement following the END directive is ignored - not supported by the Motorola freeware as11 2. ORG - sets a new value for the location counter of the assembler - tells the assembler where to put the next byte it generates after the ORG directive The sequence ORG $C000 LDAB #$FF will put the opcode byte for the instruction LDAB #$FF at location $C000. 3. RMB -- reserve memory bytes - reserve memory bytes without initialization - syntax is [<label>] RMB <expression> [<comment>] The statement buffer RMB 100 allocates 100 bytes for data and can be referred to by the label “buffer”.
36
BSZ -- block storage of zeros
- causes the assembler to allocate a block of bytes that are initialized to zeros - syntax is [<label>] BSZ <expression> [<comment>] The statement buffer BSZ 80 reserves a block of 80 bytes and their value are initialized to 0. FCB -- form constant byte - reserves as many bytes as the number of arguments in the directive - each argument specifies the initial value of the corresponding byte [<label>] FCB [<expression>][,<expression>,...,<expression>][<comment>] ABC FCB $11,$22,$33 reserves three consecutive memory bytes and initializes their values to $11, $22, and $33.
37
FDB -- form double byte - reserves 2 bytes for each argument of the directive - each argument specifies the initial value of the corresponding double bytes - syntax is [<label>] FDB [<expression>][,<expression>,...,<expression>] [comment>] The directive ABC FDB $11,$22,$33 will initialize 6 consecutive bytes in memory to $00 $11 $00 $22 $00 $33 FCC -- form constant character - generates ASCII code bytes for the letters in the arguments [label] FCC “<string>“ [<comment>] ALPHA FCC “DEF” will generate the values $44 $45 $46 in memory
38
DCB -- define constant block
- reserve an area of memory and initialize each byte to the same constant value - syntax is [label] DCB <length>,<value> - not supported by the Motorola freeware as11 The directive space DCB 80,$20 will generate a line of 80 space characters. FILL -- fill a block of constant values - serve as the same purpose as does the DCB directive - syntax [<label>] FILL <value>,<length> ones FILL 1,40 will force the freeware assembler to fill each of the 40 memory locations with a 1.
39
EQU -- equate - allows the user to use a symbolic name in place of a number - syntax is <label> EQU <expression> [<comment>] The directive ROM EQU $E000 tells the assembler that wherever ROM appears in the program, the value $E000 is to be substituted.
40
Flowchart Symbols of Flowchart - is a form of program documentation
- is a tool for developing program logic flow Symbols of Flowchart Terminal A Process Subroutine Input or output B yes Off-page connector Decision A On-page connector no
41
Procedure of Using Computer in Solving the Problem
start analyze the problem Express the solution to the problem using flowchart or other method Convert the flowchart into source code Compile or assemble to generate machine code Place the executable code in the computer Refine the solution Run the program and evaluate the result No Is the result satisfactory? Yes Stop
42
Programs to do simple arithmetic
Example 2.4 Write a program to add the values of memory locations at $00, $01, and $02, and save the result at $03. LDAA $00 ; load the contents of memory location at $00 into A ADDA $01 ; add the contents of memory location at $01 to A ADDA $02 ; add the contents of memory location at $02 to A STAA $03 ; save the result at memory location at $03 Example 2.5 Write a program to subtract 6 from three 8-bit numbers stored at $00, $01, and $02 respectively. LDAA $00 ; load the first number into A SUBA #06 ; subtract 6 from the first number STAA $00 ; store the decremented value back to $00 LDAA $01 ; load the second number into A SUBA #06 ; subtract 6 from the second number STAA $01 ; store the decremented value back to $01 LDAA $02 ; load the third number into A SUBA #06 ; subtract 6 from the third number STAA $02 ; store the decremented value back to $02
43
The Carry Flag - bit 0 of the CCR register
- set to 1 when the addition operation produces a carry 1 - set to 1 when the subtraction operation produces a borrow 1 - enables the user to implement multi-precision arithmetic Example 2.6 Write a program to add the 3-byte numbers stored at $00-$02 and $03-$05 and save the result at $06-$08. Solution: The addition starts from the least significant byte. LDAA $02 ; add the LSBs ADDA $05 ; “ STAA $08 ; “ LDAA $01 ; add the middle bytes ADCA $04 ; “ STAA $07 ; “ LDAA $00 ; add the MSBs ADCA $03 ; “ STAA $06 ; “
44
Example 2.7 Write a program to subtract the 3-byte number stored at $03-$05
from the 3-byte number stored at $00-$02 and save the result at $10-$12. Solution: The subtraction starts from the LSBs. LDAA $02 ; subtract the LSBs SUBA $05 ; “ STAA $12 ; “ LDAA $01 ; subtract the middle bytes SUBA $04 ; “ STAA $11 ; “ LDAA $00 ; subtract the MSBs SUBA $03 ; “ STAA $10 ; “
45
BCD numbers and addition
- each digit is encoded by 4 bits - two digits are packed into one byte - the addition of two BCD numbers is performed by binary addition and an adjust operation using the DAA instruction - the instruction DAA can be applied after the instructions ADDA, ADCA, and ABA - simplifies I/O conversion For example, the instruction sequence LDAA $00 ADDA $01 DAA STAA $02 adds the BCD numbers stored at $00 and $01 and saves the sum at $02.
46
Multiplication - MUL computes the product of A and B and leaves the result in D - multi-byte multiplication can be performed by using a method similar to the pen-and-pencil method (partial products are generated and added together) Example Multiply the two 16-bit numbers stored at M and N and save the product at location P. Solution: Rewrite M and N as MHML and NHNL where MH and NH are upper 8 bits of M and N respectively ML and NL are lower 8 bits of M and N respectively MH and ML are stored at M and M+1 respectively NH and NL are stored at N and N+1 respectively
47
Illustration of 16-bit by 16-bit Multiplication
8-bit bit bit bit upper byte lower byte MLNL upper byte lower byte MHNL MLNH MHNH M × N upper byte lower byte upper byte lower byte address P P P P+3 MSB LSB
48
Example 2.10 Program for multiplying two 16-bit numbers
ldaa M+1 ; place ML in A ldab N+1 ; place NL in B mul ; compute ML × NL std P+2 ; save ML × NL to memory locations P+2 and P+3 ldaa M ; place MH in A ldab N ; place NH in B mul ; compute MH × NH std P ; save MH × NH to memory locations P and P+1 ldab N+1 ; place NL in B mul ; compute MH × NL addd P+1 ; add MH × NL to memory locations P+1 and P+2 std P+1 ; “ ldaa P ; add the C flag to memory location P adca #0 ; “ staa P ; “ ldaa M+1 ; place ML in A mul ; compute ML × NH addd P+1 ; add ML × NH to memory locations P+1 and P+2 adca ; “
49
Divide Instructions 1. IDIV: integer division
- D is the dividend and X is the divisor - Quotient is left in X and remainder is left in D - The quotient is set to $FFFF in the case of divide by 0 2. FDIV: fractional division - D is the dividend, X is the divisor - The radix point is assumed to be in the same place for both the dividend and divisor - The radix is to the left of bit 15 - The dividend must be smaller than the divisor - The quotient is set to $FFFF in the case of divide by 0 or overflow 3. Example 2.12 Divide the fractional number $.2222 by $.4444 LDD #$2222 ; divide $ by $0.4444 LDX #$4444 ; “ FIDV ; “
50
The 68HC11 provides swap instructions so that further division to the quotient
can be performed. - XGDX: swap the contents of D and X - XGDY: swap the contents of D and Y Example Write a program to convert the 16-bit number stored at $00-$01 to BCD format and store the result at $02-$06. Each BCD digit is stored in one byte. Solution: - A binary number can be converted to BCD format by using repeated division by 10. - The largest 16-bit binary number is which has five decimal digits. - The first division by 10 obtains the least significant digit, the second division by 10 obtains the second least significant digit, and so on.
51
LDD $00 ; place the 16-bit number in D
LDX #10 IDIV ; compute the least significant digit STAB $06 ; save the least significant BCD digit XGDX ; place the quotient in D IDIV ; compute the second least significant BCD digit STAB $05 ; save the second least significant BCD digit IDIV ; compute the middle BCD digit STAB $04 ; save the middle BCD digit XGDX IDIV ; compute the second most significant digit STAB $03 ; the second most significant BCD digit STAB $02 ; save the most significant BCD digit END
52
Program Loops Types of program loops: finite and infinite loops Looping mechanisms: 1. DO statement S forever 2. FOR i = n1 to n2 DO statement S or FOR i = n2 downto n1 DO statement S 3. WHILE C DO statement S 4. REPEAT statement S until C Program loops are implemented by using the conditional branch instructions and the execution of these instructions depends on the contents of the CCR register.
53
Condition Code Register
X H I N Z V C - C: carry flag - V: overflow flag - Z: zero flag - N: negative flag - H: half carry flag Conditional Branch Instruction [<label>] Bcc rel [<comment>] where cc is a condition code listed in Table 2.1. Unconditional Branch Instruction [<label>] BRA rel [<comment>]
54
Table 2.1 Branch Condition Codes
Condition code Meaning CC carry clear CS carry set EQ equal to 0 GE greater than or equal to 0 (signed comparison) GT greater than 0 (signed comparison) HI higher (unsigned comparison) HS higher or same (unsigned comparison) LE less than or equal to 0 LO lower (unsigned comparison) LS lower or same (unsigned comparison) LT less than 0 (signed comparison) MI minus (signed comparison) NE not equal to 0 PL plus (signed comparison) VC overflow bit clear VS overflow bit set
55
Conditional Branch Instructions that check only one condition flag
- C flag: BCC branch if C flag is 0 BCS branch if C flag is 1 BLO branch if C flag is 1 BHS branch if C flag is 0 - Z flag BEQ branch if Z flag is 1 BNE branch if Z flag is 0 - N flag BPL branch if N flag is 0 BMI branch if N flag is 1 - V flag BVS branch if V flag is 1 BVC branch if V flag is 0 Conditional Branch Instructions that check more than one condition flag - BGE branch if (N Å V) = 0 - BGT branch if (Z + (N Å V)) = 0 - BHI branch if (C + Z) = 0 - BLE branch if (Z + (N Å V)) = 1 - BLS branch if (C + Z) = 1 - BLT branch if (N Å V) = 1
56
Decrementing and Incrementing Instructions
- DECA: A ¬ [A] - 1 - DECB: B ¬ [B] - 1 - DEC opr: mem[opr] ¬ [mem[opr]] - 1 - DES: SP ¬ [SP] - 1 - DEX: X ¬ [X] - 1 - DEY: Y ¬ [Y] - 1 - INCA: A ¬ [A] + 1 - INCB: B ¬ [B] + 1 - INC opr: mem[opr] ¬ [mem[opr]] + 1 - INS: SP ¬ [SP] + 1 - INX: X ¬ [X] + 1 - INY: Y ¬ [Y] + 1 Note 1. Incrementing and decrementing instructions can be used to update the loop indices. Note 2. The memory operand opr is specified in either extended or index addressing mode.
57
Example 2. 15 Write a program to compute 1 + 2 +
Example Write a program to compute and save the sum at $00. Solution: Start * The following program use accumulator B as the loop index * i and A as the sum. N equ 20 ldab #0 ; initialize loop index i to 0 ldaa #0 ; initialize sum to 0 again incb ; increment i aba ; add i to sum cmpb #20 ; compare i with the upper limit bne again ; continue if i is less than 20 staa $00 ; save the sum end i = 0 sum = 0 i = i + 1 sum = sum + i no i = 20 ? yes Stop
58
Example 2.16 Write a program to find the largest number from an array of 20
8-bit numbers. The array is stored at $00-$13. Save the result at $20. Solution: Start array max ¬ array [0] i ¬ 1 yes array max < array [i] ? array max ¬ array [i] i ¬ i + 1 no no i = array count - 1? yes Stop
59
* The following program uses A to hold the temporary array max and uses B
* as the loop index. N equ ; array count org $00 array fcb ; array ldaa array ; set array[0] as the temporary array max ldab #1 ; initialize loop index to 1 loop ldx #array ; point X to array[0] abx ; compute the address of array[i] cmpa 0,X ; compare temp. array max to the next element bhs chkend ; do we need to update the temporary array max? ldaa 0,X ; update the temporary array max chkend cmpb #N-1 ; compare loop index with loop limit beq exit ; is the whole array checked yet? incb ; increment loop index bra loop exit staa $20 ; save the array max end
60
Compare Instructions - are executed to set the condition flags of the CCR register - are often used to implement the program loop Table HC11 Compare Instructions Instruction format [<label>] CBA [<comment>] compare A to B [<label>] CMPA opr [<comment>] compare A to a memory location or value [<label>] CMPB opr [<comment>] compare B to a memory location or value [<label>] CPD opr [<comment>] compare D to a memory location or value [<label>] CPX opr [<comment>] compare X to a memory location or value [<label>] CPY opr [<comment>] compare Y to a memory location or value [<label>] TST opr [<comment>] test a memory location for negative or zero [<label>] TSTA [<comment>] test A for negative or zero [<label>] TSTB [<comment>] test B for negative or zero opr is specified in one of the following addressing modes: - EXT - INDX - INDY - IMM (not applicable to “TST opr”) - DIR (not applicable to “TST opr”)
61
Special Conditional Branch Instructions
[<label>] BRCLR (opr) (msk) (rel) [<comment>] [<label>] BRSET (opr) (msk) (rel) [<comment>] where opr specifies the memory location to be checked and must be specified using either the direct or index addressing mode. msk is an 8-bit mask that specifies the bits of the memory location to be checked. The bits of the memory byte to be checked correspond to those bit positions that are 1s in the mask. rel is the branch offset and is specified in the relative mode. For example, the sequence ldx #$1000 here brclr $30,X % here ldaa $31,X will force the 68HC11 continue to execute the second instruction until the bit 7 is set to 1.
62
Example 2.17 Write a program to compute the sum of the odd numbers in an array
with 20 8-bit elements. The array is stored at $00-$13. Save the sum at $20-$21. Solution: Start sum ¬ 0 ptr ¬ 0 bit 0 of mem[ptr] = 0? no sum ¬ sum + [mem[ptr]] no ptr ¬ ptr + 1 ptr = $13? yes Stop
63
* The index register X is used as the pointer to the array element.
N equ $13 org $20 sum rmb 2 org $C000 ldaa #$00 staa sum ; initialize sum to 0 staa sum+1 ; “ ldx #$00 ; point X to array[0] loop brclr 0,X $01 chkend ; is it an odd number? ldd sum ; add the odd number to the sum addb 0,X ; “ adca #0 ; “ std sum ; “ chkend cpx #N ; compare the pointer to the address of the last element bhs exit ; is this the end? inx bra loop ; not yet done, continue exit end
64
Instructions for Variable Initialization
1. [<label>] CLR opr [<comment>] where opr is specified using the extended or index addressing mode. The specified memory location is cleared. 2. [<label>] CLRA [<comment>] Accumulator A is cleared to 0 3. [<label>] CLRB [<comment>] Accumulator B is cleared to 0
65
Shift and Rotate Instructions
The 68HC11 has shift and rotate instructions that apply to a memory location, accumulators A, B and D. A memory operand must be specified using the extended or index addressing mode. There are three 8-bit arithmetic shift left instructions: [<label>] ASL opr [<comment>] -- memory location opr is shifted left one place [<label>] ASLA [<comment>] -- accumulator A is shifted left one place [<label>] ASLB [<comment>] -- accumulator B is shifted left one place The operation is C b b0
66
The 68HC11 has one 16-bit arithmetic shift left instruction:
[<label>] ASLD [<comment>] The operation is C b b0 b b0 accumulator A accumulator B The 68HC11 has arithmetic shift right instructions that apply to a memory location and accumulators A and B. [<label>] ASR opr [<comment>] -- memory location opr is shifted right one place [<label>] ASRA [<comment>] -- accumulator A is shifted right one place [<label>] ASRB [<comment>] -- accumulator B is shifted right one place The operation is b b0 C
67
The 68HC11 has logical shift left instructions that apply to a memory location and
accumulators A and B. [<label>] LSL opr [<comment>] -- memory location opr is shifted left one place [<label>] LSLA [<comment>] -- accumulator A is shifted left one place [<label>] LSLB [<comment>] -- accumulator B is shifted left one place The operation is C b b0 The 68HC11 has one 16-bit logical shift left instruction: [<label>] LSLD [<comment>] The operation is C b b0 b b0 accumulator A accumulator B
68
The 68HC11 has three logical shift right instructions that apply to 8-bit operands.
[<label>] LSR opr [<comment>] -- memory location opr is shifted right one place [<label>] LSRA [<comment>] -- accumulator A is shifted right one place [<label>] LSRB [<comment>] -- accumulator B is shifted right one place The operation is b b0 C The 68HC11 has one 16-bit logical shift right instruction: [<label>] LSRD [<comment>] The operation is b b0 b b0 C accumulator A accumulator B
69
The 68HC11 has three rotate left instructions that operate on 9-bit operands.
[<label>] ROL opr [<comment>] -- memory location opr is rotated left one place [<label>] ROLA [<comment>] -- accumulator A is rotated left one place [<label>] ROLB [<comment>] -- accumulator B is rotated left one place The operation is b b0 C The 68HC11 has three rotate right instructions that operate on 9-bit operands. [<label>] ROR opr [<comment>] -- memory location opr is rotated right one place [<label>] RORA [<comment>] -- accumulator A is rotated right one place [<label>] RORB [<comment>] -- accumulator B is rotated right one place The operation is C b b0
70
Example 2. 18 Suppose that [A] = $74 and C = 1
Example Suppose that [A] = $74 and C = 1. Compute the new values of A and C after the execution of the instruction ASLA. Solution: The operation is C A Result: [A] = % C = 0 Example Suppose that [mem[$00]] = $F6 and C = 1. Compute the new values of mem[$00] and the C flag after the execution of the instruction ASR $00. Solution: The operation is mem[$00] C Result: [mem[$00]] = % C = 0
71
Example 2. 20 Suppose that [mem[$00]] = $F6 and C = 1
Example Suppose that [mem[$00]] = $F6 and C = 1. Compute the new contents of mem[$00] and the C flag after the execution of the instruction LSR $00. Solution: The operation is mem[$00] C Result: [mem[$00]] = % C = 0 Example Suppose that [B] = $BE and C = 1. Compute the new values of B after the execution of the instruction ROLB. Solution: The operation is 1 1 B C Result: [B] = % C = 1
72
Example 2. 22 Suppose that [B] = $BE and C = 1
Example Suppose that [B] = $BE and C = 1. Compute the new values of mem[$00] after the execution of the instruction RORB. Solution: The operation is 1 C B Result: [B] = % C = 0
73
Example 2.23 Write a program to count the number of 1s in the 16-bit number stored
at $00-$01 and save the result in $02. Solution: * The 16-bit number is shifted to the right up to 16 time or until the shifted value becomes 0. * If the bit shifted out is a 1 then increment the 1s count by 1. org $C000 ldaa #$00 ; initialize the 1s count to 0 staa $02 ; “ ldd $00 ; place the number in D loop lsrd ; shift the lsb of D to the C flag bcc testzero ; is the C flag a 0? inc $02 ; increment 1s count if the lsb is a 1 testzero cpd #0 ; check to see if D is already 0 bne loop end
74
Shift a multi-byte number
For shifting right 1. The bit 7 of each byte will receive the bit 0 of its immediate left byte with the exception of the most significant byte which will receive a 0. 2. Each byte will be shifted to the right by 1 bit. The bit 0 of the least significant byte will be lost. Suppose there is a k-byte number that is stored at loc to loc+k-1. method for shifting right Step 1: Shift the byte at loc to the right one place. Step 2: Rotate the byte at loc+1 to the right one place. Step 3: Repeat Step 2 for the remaining bytes.
75
For shifting left 1. The bit 0 of each byte will receive the bit 7 of its immediate right byte with the exception of the least significant byte which will receive a 0. 2. Each byte will be shifted to the left by 1 bit. The bit 7 of the most significant byte will be lost. Suppose there is a k-byte number that is stored at loc to loc+k-1. method for shifting left Step 1: Shift the byte at loc+k-1 to the leftt one place. Step 2: Rotate the byte at loc+K-2 to the left one place. Step 3: Repeat Step 2 for the remaining bytes.
76
Example 2.24 Write a program to shift the 32-bit number stored at $20-$23 to the
right four places. Solution: ldab #4 ; set up the loop count ldx #$20 ; use X as the pointer to the left most byte again lsr 0,X ror 1,X ror 2,X ror 3,X decb bne again end
77
Program Execution Time
An easy way to create a delay is to use program loops. Use the instructions in Table 2.3 as an example. Table 2.3 Execution times of a sample of instructions Instruction Execution time (E clock cycles) BNE <rel> DECB DEX LDAB <imme> 2 LDX <imme> 3 NOP 2 The following instruction sequence takes 5 ms to execute for 2 MHz E clock signal. again nop ; 2 E cycles nop ; 2 E cycles dex ; 3 E cycles bne again ; 3 E cycles
78
Example 2.25 Write a program loop to create a delay of 100 ms.
Solution: A delay of 100 ms can be created by repeating the previous loop times. The following instruction sequence creates a delay of 100 ms. ldx #20000 again nop nop dex bne again Longer delays can be created by using nested program loops. Example Write a program to create a 10-second delay. Solution: A 10-second delay can be created by repeating the loop in example times. ldab #100 outer ldx #20000 inner nop bne inner decb bne outer
79
Chapter 2: 68HC11 Assembly Programming
The 68HC11 Microcontroller Han-Way Huang Minnesota State University, Mankato
80
Assembly Program Structure
C program main () { int i, j, k; ; i, j, k are integer variables i = 75; ; assign 75 to i j = 10; ; assign 10 to j k = i + j - 6; }
81
Assembly Program (1) * Data storage declaration section (2) ORG $00 (3) i RMB 1 ; variable i (4) j RMB 1 ; variable j (5) k RMB 1 ; variable k (6) * program instruction section (7) start ORG $C000 ; starting address of program (8) LDAA #75 (9) STAA i ; initialize i to 75 (10) LDAA #10 (11) STAA j ; initialize j to 10 (12) ADDA i ; compute i + j (13) SUBA #6 ; compute i + j -6 (14) STAA k ; store i + j - 6 to k (15) END
82
Global View of a 68HC11 Assembly Program
1. Assembler Directives - define data and symbol - reserve and initialize memory locations - set assembler and linking condition - specify output format - etc. 2. Assembly Language Instructions 3. END directive - last statement of a program - any statement after END will be ignored 4. Comments - explain the function of a single or a group of instructions
83
Fields of a 68HC11 Instruction
1. Label field - is optional - starts with a letter and followed by letters, digits, or special symbols (_ or .) - can start from any column if ended with “:” (not true for Motorola freeware as11) - must start from column 1 if not ended with “:” 2. Operation field - contains the mnemonic of a machine instruction or a directive - is separated from the label by at least one space 3. Operand field - follows the operation field and is separated from the operation field by at least one space - contains operands for instructions or arguments for assembler directives 4. Comment field - a whole line comment starts with a * - is separated from the operand and operation field for at least one space
84
Identify the Four Fields of an Instruction
Example 2.3 loop ADDA #$40 ; add 40 to accumulator A (1) “loop” is a label (2) “ADDA” is an instruction mnemonic (3) “#$40” is the operand (4) “add #$40 to accumulator A” is a comment
85
Assembler Directives -- a sample
1. END - ends a program to be processed by an assembler - any statement following the END directive is ignored - not supported by the Motorola freeware as11 2. ORG - sets a new value for the location counter of the assembler - tells the assembler where to put the next byte it generates after the ORG directive The sequence ORG $C000 LDAB #$FF will put the opcode byte for the instruction LDAB #$FF at location $C000. 3. RMB -- reserve memory bytes - reserve memory bytes without initialization - syntax is [<label>] RMB <expression> [<comment>] The statement buffer RMB 100 allocates 100 bytes for data and can be referred to by the label “buffer”.
86
BSZ -- block storage of zeros
- causes the assembler to allocate a block of bytes that are initialized to zeros - syntax is [<label>] BSZ <expression> [<comment>] The statement buffer BSZ 80 reserves a block of 80 bytes and their value are initialized to 0. FCB -- form constant byte - reserves as many bytes as the number of arguments in the directive - each argument specifies the initial value of the corresponding byte [<label>] FCB [<expression>][,<expression>,...,<expression>][<comment>] ABC FCB $11,$22,$33 reserves three consecutive memory bytes and initializes their values to $11, $22, and $33.
87
FDB -- form double byte - reserves 2 bytes for each argument of the directive - each argument specifies the initial value of the corresponding double bytes - syntax is [<label>] FDB [<expression>][,<expression>,...,<expression>] [comment>] The directive ABC FDB $11,$22,$33 will initialize 6 consecutive bytes in memory to $00 $11 $00 $22 $00 $33 FCC -- form constant character - generates ASCII code bytes for the letters in the arguments [label] FCC “<string>“ [<comment>] ALPHA FCC “DEF” will generate the values $44 $45 $46 in memory
88
DCB -- define constant block
- reserve an area of memory and initialize each byte to the same constant value - syntax is [label] DCB <length>,<value> - not supported by the Motorola freeware as11 The directive space DCB 80,$20 will generate a line of 80 space characters. FILL -- fill a block of constant values - serve as the same purpose as does the DCB directive - syntax [<label>] FILL <value>,<length> ones FILL 1,40 will force the freeware assembler to fill each of the 40 memory locations with a 1.
89
EQU -- equate - allows the user to use a symbolic name in place of a number - syntax is <label> EQU <expression> [<comment>] The directive ROM EQU $E000 tells the assembler that wherever ROM appears in the program, the value $E000 is to be substituted.
90
Flowchart Symbols of Flowchart - is a form of program documentation
- is a tool for developing program logic flow Symbols of Flowchart Terminal A Process Subroutine Input or output B yes Off-page connector Decision A On-page connector no
91
Procedure of Using Computer in Solving the Problem
start analyze the problem Express the solution to the problem using flowchart or other method Convert the flowchart into source code Compile or assemble to generate machine code Place the executable code in the computer Refine the solution Run the program and evaluate the result No Is the result satisfactory? Yes Stop
92
Programs to do simple arithmetic
Example 2.4 Write a program to add the values of memory locations at $00, $01, and $02, and save the result at $03. LDAA $00 ; load the contents of memory location at $00 into A ADDA $01 ; add the contents of memory location at $01 to A ADDA $02 ; add the contents of memory location at $02 to A STAA $03 ; save the result at memory location at $03 Example 2.5 Write a program to subtract 6 from three 8-bit numbers stored at $00, $01, and $02 respectively. LDAA $00 ; load the first number into A SUBA #06 ; subtract 6 from the first number STAA $00 ; store the decremented value back to $00 LDAA $01 ; load the second number into A SUBA #06 ; subtract 6 from the second number STAA $01 ; store the decremented value back to $01 LDAA $02 ; load the third number into A SUBA #06 ; subtract 6 from the third number STAA $02 ; store the decremented value back to $02
93
The Carry Flag - bit 0 of the CCR register
- set to 1 when the addition operation produces a carry 1 - set to 1 when the subtraction operation produces a borrow 1 - enables the user to implement multi-precision arithmetic Example 2.6 Write a program to add the 3-byte numbers stored at $00-$02 and $03-$05 and save the result at $06-$08. Solution: The addition starts from the least significant byte. LDAA $02 ; add the LSBs ADDA $05 ; “ STAA $08 ; “ LDAA $01 ; add the middle bytes ADCA $04 ; “ STAA $07 ; “ LDAA $00 ; add the MSBs ADCA $03 ; “ STAA $06 ; “
94
Example 2.7 Write a program to subtract the 3-byte number stored at $03-$05
from the 3-byte number stored at $00-$02 and save the result at $10-$12. Solution: The subtraction starts from the LSBs. LDAA $02 ; subtract the LSBs SUBA $05 ; “ STAA $12 ; “ LDAA $01 ; subtract the middle bytes SUBA $04 ; “ STAA $11 ; “ LDAA $00 ; subtract the MSBs SUBA $03 ; “ STAA $10 ; “
95
BCD numbers and addition
- each digit is encoded by 4 bits - two digits are packed into one byte - the addition of two BCD numbers is performed by binary addition and an adjust operation using the DAA instruction - the instruction DAA can be applied after the instructions ADDA, ADCA, and ABA - simplifies I/O conversion For example, the instruction sequence LDAA $00 ADDA $01 DAA STAA $02 adds the BCD numbers stored at $00 and $01 and saves the sum at $02.
96
Multiplication - MUL computes the product of A and B and leaves the result in D - multi-byte multiplication can be performed by using a method similar to the pen-and-pencil method (partial products are generated and added together) Example Multiply the two 16-bit numbers stored at M and N and save the product at location P. Solution: Rewrite M and N as MHML and NHNL where MH and NH are upper 8 bits of M and N respectively ML and NL are lower 8 bits of M and N respectively MH and ML are stored at M and M+1 respectively NH and NL are stored at N and N+1 respectively
97
Illustration of 16-bit by 16-bit Multiplication
8-bit bit bit bit upper byte lower byte MLNL upper byte lower byte MHNL MLNH MHNH M × N upper byte lower byte upper byte lower byte address P P P P+3 MSB LSB
98
Example 2.10 Program for multiplying two 16-bit numbers
ldaa M+1 ; place ML in A ldab N+1 ; place NL in B mul ; compute ML × NL std P+2 ; save ML × NL to memory locations P+2 and P+3 ldaa M ; place MH in A ldab N ; place NH in B mul ; compute MH × NH std P ; save MH × NH to memory locations P and P+1 ldab N+1 ; place NL in B mul ; compute MH × NL addd P+1 ; add MH × NL to memory locations P+1 and P+2 std P+1 ; “ ldaa P ; add the C flag to memory location P adca #0 ; “ staa P ; “ ldaa M+1 ; place ML in A mul ; compute ML × NH addd P+1 ; add ML × NH to memory locations P+1 and P+2 adca ; “
99
Divide Instructions 1. IDIV: integer division
- D is the dividend and X is the divisor - Quotient is left in X and remainder is left in D - The quotient is set to $FFFF in the case of divide by 0 2. FDIV: fractional division - D is the dividend, X is the divisor - The radix point is assumed to be in the same place for both the dividend and divisor - The radix is to the left of bit 15 - The dividend must be smaller than the divisor - The quotient is set to $FFFF in the case of divide by 0 or overflow 3. Example 2.12 Divide the fractional number $.2222 by $.4444 LDD #$2222 ; divide $ by $0.4444 LDX #$4444 ; “ FIDV ; “
100
The 68HC11 provides swap instructions so that further division to the quotient
can be performed. - XGDX: swap the contents of D and X - XGDY: swap the contents of D and Y Example Write a program to convert the 16-bit number stored at $00-$01 to BCD format and store the result at $02-$06. Each BCD digit is stored in one byte. Solution: - A binary number can be converted to BCD format by using repeated division by 10. - The largest 16-bit binary number is which has five decimal digits. - The first division by 10 obtains the least significant digit, the second division by 10 obtains the second least significant digit, and so on.
101
LDD $00 ; place the 16-bit number in D
LDX #10 IDIV ; compute the least significant digit STAB $06 ; save the least significant BCD digit XGDX ; place the quotient in D IDIV ; compute the second least significant BCD digit STAB $05 ; save the second least significant BCD digit IDIV ; compute the middle BCD digit STAB $04 ; save the middle BCD digit XGDX IDIV ; compute the second most significant digit STAB $03 ; the second most significant BCD digit STAB $02 ; save the most significant BCD digit END
102
Program Loops Types of program loops: finite and infinite loops Looping mechanisms: 1. DO statement S forever 2. FOR i = n1 to n2 DO statement S or FOR i = n2 downto n1 DO statement S 3. WHILE C DO statement S 4. REPEAT statement S until C Program loops are implemented by using the conditional branch instructions and the execution of these instructions depends on the contents of the CCR register.
103
Condition Code Register
X H I N Z V C - C: carry flag - V: overflow flag - Z: zero flag - N: negative flag - H: half carry flag Conditional Branch Instruction [<label>] Bcc rel [<comment>] where cc is a condition code listed in Table 2.1. Unconditional Branch Instruction [<label>] BRA rel [<comment>]
104
Table 2.1 Branch Condition Codes
Condition code Meaning CC carry clear CS carry set EQ equal to 0 GE greater than or equal to 0 (signed comparison) GT greater than 0 (signed comparison) HI higher (unsigned comparison) HS higher or same (unsigned comparison) LE less than or equal to 0 LO lower (unsigned comparison) LS lower or same (unsigned comparison) LT less than 0 (signed comparison) MI minus (signed comparison) NE not equal to 0 PL plus (signed comparison) VC overflow bit clear VS overflow bit set
105
Conditional Branch Instructions that check only one condition flag
- C flag: BCC branch if C flag is 0 BCS branch if C flag is 1 BLO branch if C flag is 1 BHS branch if C flag is 0 - Z flag BEQ branch if Z flag is 1 BNE branch if Z flag is 0 - N flag BPL branch if N flag is 0 BMI branch if N flag is 1 - V flag BVS branch if V flag is 1 BVC branch if V flag is 0 Conditional Branch Instructions that check more than one condition flag - BGE branch if (N Å V) = 0 - BGT branch if (Z + (N Å V)) = 0 - BHI branch if (C + Z) = 0 - BLE branch if (Z + (N Å V)) = 1 - BLS branch if (C + Z) = 1 - BLT branch if (N Å V) = 1
106
Decrementing and Incrementing Instructions
- DECA: A ¬ [A] - 1 - DECB: B ¬ [B] - 1 - DEC opr: mem[opr] ¬ [mem[opr]] - 1 - DES: SP ¬ [SP] - 1 - DEX: X ¬ [X] - 1 - DEY: Y ¬ [Y] - 1 - INCA: A ¬ [A] + 1 - INCB: B ¬ [B] + 1 - INC opr: mem[opr] ¬ [mem[opr]] + 1 - INS: SP ¬ [SP] + 1 - INX: X ¬ [X] + 1 - INY: Y ¬ [Y] + 1 Note 1. Incrementing and decrementing instructions can be used to update the loop indices. Note 2. The memory operand opr is specified in either extended or index addressing mode.
107
Example 2. 15 Write a program to compute 1 + 2 +
Example Write a program to compute and save the sum at $00. Solution: Start * The following program use accumulator B as the loop index * i and A as the sum. N equ 20 ldab #0 ; initialize loop index i to 0 ldaa #0 ; initialize sum to 0 again incb ; increment i aba ; add i to sum cmpb #20 ; compare i with the upper limit bne again ; continue if i is less than 20 staa $00 ; save the sum end i = 0 sum = 0 i = i + 1 sum = sum + i no i = 20 ? yes Stop
108
Example 2.16 Write a program to find the largest number from an array of 20
8-bit numbers. The array is stored at $00-$13. Save the result at $20. Solution: Start array max ¬ array [0] i ¬ 1 yes array max < array [i] ? array max ¬ array [i] i ¬ i + 1 no no i = array count - 1? yes Stop
109
* The following program uses A to hold the temporary array max and uses B
* as the loop index. N equ ; array count org $00 array fcb ; array ldaa array ; set array[0] as the temporary array max ldab #1 ; initialize loop index to 1 loop ldx #array ; point X to array[0] abx ; compute the address of array[i] cmpa 0,X ; compare temp. array max to the next element bhs chkend ; do we need to update the temporary array max? ldaa 0,X ; update the temporary array max chkend cmpb #N-1 ; compare loop index with loop limit beq exit ; is the whole array checked yet? incb ; increment loop index bra loop exit staa $20 ; save the array max end
110
Compare Instructions - are executed to set the condition flags of the CCR register - are often used to implement the program loop Table HC11 Compare Instructions Instruction format [<label>] CBA [<comment>] compare A to B [<label>] CMPA opr [<comment>] compare A to a memory location or value [<label>] CMPB opr [<comment>] compare B to a memory location or value [<label>] CPD opr [<comment>] compare D to a memory location or value [<label>] CPX opr [<comment>] compare X to a memory location or value [<label>] CPY opr [<comment>] compare Y to a memory location or value [<label>] TST opr [<comment>] test a memory location for negative or zero [<label>] TSTA [<comment>] test A for negative or zero [<label>] TSTB [<comment>] test B for negative or zero opr is specified in one of the following addressing modes: - EXT - INDX - INDY - IMM (not applicable to “TST opr”) - DIR (not applicable to “TST opr”)
111
Special Conditional Branch Instructions
[<label>] BRCLR (opr) (msk) (rel) [<comment>] [<label>] BRSET (opr) (msk) (rel) [<comment>] where opr specifies the memory location to be checked and must be specified using either the direct or index addressing mode. msk is an 8-bit mask that specifies the bits of the memory location to be checked. The bits of the memory byte to be checked correspond to those bit positions that are 1s in the mask. rel is the branch offset and is specified in the relative mode. For example, the sequence ldx #$1000 here brclr $30,X % here ldaa $31,X will force the 68HC11 continue to execute the second instruction until the bit 7 is set to 1.
112
Example 2.17 Write a program to compute the sum of the odd numbers in an array
with 20 8-bit elements. The array is stored at $00-$13. Save the sum at $20-$21. Solution: Start sum ¬ 0 ptr ¬ 0 bit 0 of mem[ptr] = 0? no sum ¬ sum + [mem[ptr]] no ptr ¬ ptr + 1 ptr = $13? yes Stop
113
* The index register X is used as the pointer to the array element.
N equ $13 org $20 sum rmb 2 org $C000 ldaa #$00 staa sum ; initialize sum to 0 staa sum+1 ; “ ldx #$00 ; point X to array[0] loop brclr 0,X $01 chkend ; is it an odd number? ldd sum ; add the odd number to the sum addb 0,X ; “ adca #0 ; “ std sum ; “ chkend cpx #N ; compare the pointer to the address of the last element bhs exit ; is this the end? inx bra loop ; not yet done, continue exit end
114
Instructions for Variable Initialization
1. [<label>] CLR opr [<comment>] where opr is specified using the extended or index addressing mode. The specified memory location is cleared. 2. [<label>] CLRA [<comment>] Accumulator A is cleared to 0 3. [<label>] CLRB [<comment>] Accumulator B is cleared to 0
115
Shift and Rotate Instructions
The 68HC11 has shift and rotate instructions that apply to a memory location, accumulators A, B and D. A memory operand must be specified using the extended or index addressing mode. There are three 8-bit arithmetic shift left instructions: [<label>] ASL opr [<comment>] -- memory location opr is shifted left one place [<label>] ASLA [<comment>] -- accumulator A is shifted left one place [<label>] ASLB [<comment>] -- accumulator B is shifted left one place The operation is C b b0
116
The 68HC11 has one 16-bit arithmetic shift left instruction:
[<label>] ASLD [<comment>] The operation is C b b0 b b0 accumulator A accumulator B The 68HC11 has arithmetic shift right instructions that apply to a memory location and accumulators A and B. [<label>] ASR opr [<comment>] -- memory location opr is shifted right one place [<label>] ASRA [<comment>] -- accumulator A is shifted right one place [<label>] ASRB [<comment>] -- accumulator B is shifted right one place The operation is b b0 C
117
The 68HC11 has logical shift left instructions that apply to a memory location and
accumulators A and B. [<label>] LSL opr [<comment>] -- memory location opr is shifted left one place [<label>] LSLA [<comment>] -- accumulator A is shifted left one place [<label>] LSLB [<comment>] -- accumulator B is shifted left one place The operation is C b b0 The 68HC11 has one 16-bit logical shift left instruction: [<label>] LSLD [<comment>] The operation is C b b0 b b0 accumulator A accumulator B
118
The 68HC11 has three logical shift right instructions that apply to 8-bit operands.
[<label>] LSR opr [<comment>] -- memory location opr is shifted right one place [<label>] LSRA [<comment>] -- accumulator A is shifted right one place [<label>] LSRB [<comment>] -- accumulator B is shifted right one place The operation is b b0 C The 68HC11 has one 16-bit logical shift right instruction: [<label>] LSRD [<comment>] The operation is b b0 b b0 C accumulator A accumulator B
119
The 68HC11 has three rotate left instructions that operate on 9-bit operands.
[<label>] ROL opr [<comment>] -- memory location opr is rotated left one place [<label>] ROLA [<comment>] -- accumulator A is rotated left one place [<label>] ROLB [<comment>] -- accumulator B is rotated left one place The operation is b b0 C The 68HC11 has three rotate right instructions that operate on 9-bit operands. [<label>] ROR opr [<comment>] -- memory location opr is rotated right one place [<label>] RORA [<comment>] -- accumulator A is rotated right one place [<label>] RORB [<comment>] -- accumulator B is rotated right one place The operation is C b b0
120
Example 2. 18 Suppose that [A] = $74 and C = 1
Example Suppose that [A] = $74 and C = 1. Compute the new values of A and C after the execution of the instruction ASLA. Solution: The operation is C A Result: [A] = % C = 0 Example Suppose that [mem[$00]] = $F6 and C = 1. Compute the new values of mem[$00] and the C flag after the execution of the instruction ASR $00. Solution: The operation is mem[$00] C Result: [mem[$00]] = % C = 0
121
Example 2. 20 Suppose that [mem[$00]] = $F6 and C = 1
Example Suppose that [mem[$00]] = $F6 and C = 1. Compute the new contents of mem[$00] and the C flag after the execution of the instruction LSR $00. Solution: The operation is mem[$00] C Result: [mem[$00]] = % C = 0 Example Suppose that [B] = $BE and C = 1. Compute the new values of B after the execution of the instruction ROLB. Solution: The operation is 1 1 B C Result: [B] = % C = 1
122
Example 2. 22 Suppose that [B] = $BE and C = 1
Example Suppose that [B] = $BE and C = 1. Compute the new values of mem[$00] after the execution of the instruction RORB. Solution: The operation is 1 C B Result: [B] = % C = 0
123
Example 2.23 Write a program to count the number of 1s in the 16-bit number stored
at $00-$01 and save the result in $02. Solution: * The 16-bit number is shifted to the right up to 16 time or until the shifted value becomes 0. * If the bit shifted out is a 1 then increment the 1s count by 1. org $C000 ldaa #$00 ; initialize the 1s count to 0 staa $02 ; “ ldd $00 ; place the number in D loop lsrd ; shift the lsb of D to the C flag bcc testzero ; is the C flag a 0? inc $02 ; increment 1s count if the lsb is a 1 testzero cpd #0 ; check to see if D is already 0 bne loop end
124
Shift a multi-byte number
For shifting right 1. The bit 7 of each byte will receive the bit 0 of its immediate left byte with the exception of the most significant byte which will receive a 0. 2. Each byte will be shifted to the right by 1 bit. The bit 0 of the least significant byte will be lost. Suppose there is a k-byte number that is stored at loc to loc+k-1. method for shifting right Step 1: Shift the byte at loc to the right one place. Step 2: Rotate the byte at loc+1 to the right one place. Step 3: Repeat Step 2 for the remaining bytes.
125
For shifting left 1. The bit 0 of each byte will receive the bit 7 of its immediate right byte with the exception of the least significant byte which will receive a 0. 2. Each byte will be shifted to the left by 1 bit. The bit 7 of the most significant byte will be lost. Suppose there is a k-byte number that is stored at loc to loc+k-1. method for shifting left Step 1: Shift the byte at loc+k-1 to the leftt one place. Step 2: Rotate the byte at loc+K-2 to the left one place. Step 3: Repeat Step 2 for the remaining bytes.
126
Example 2.24 Write a program to shift the 32-bit number stored at $20-$23 to the
right four places. Solution: ldab #4 ; set up the loop count ldx #$20 ; use X as the pointer to the left most byte again lsr 0,X ror 1,X ror 2,X ror 3,X decb bne again end
127
Program Execution Time
An easy way to create a delay is to use program loops. Use the instructions in Table 2.3 as an example. Table 2.3 Execution times of a sample of instructions Instruction Execution time (E clock cycles) BNE <rel> DECB DEX LDAB <imme> 2 LDX <imme> 3 NOP 2 The following instruction sequence takes 5 ms to execute for 2 MHz E clock signal. again nop ; 2 E cycles nop ; 2 E cycles dex ; 3 E cycles bne again ; 3 E cycles
128
Example 2.25 Write a program loop to create a delay of 100 ms.
Solution: A delay of 100 ms can be created by repeating the previous loop times. The following instruction sequence creates a delay of 100 ms. ldx #20000 again nop nop dex bne again Longer delays can be created by using nested program loops. Example Write a program to create a 10-second delay. Solution: A 10-second delay can be created by repeating the loop in example times. ldab #100 outer ldx #20000 inner nop bne inner decb bne outer
129
Chapter 3: Data Structures and Subroutine Calls
The 68HC11 Microcontroller Han-Way Huang Minnesota State University, Mankato
130
Examples of Data Structures
1. Strings. A sequence of characters. 2. Arrays. An ordered set of elements of the same type. 3. Stacks. A data structure with a top and bottom. Elements can be added or removed only at the top of the stack. 4. Queues. A data structure to which elements can be added at only one end (called head) and removed only from the other end (called tail). 5. Dequeues. A data structure in which elements can be added and removed at both ends. 6. Trees. A data structure in which one element is called the root and the remaining elements are partitioned into m disjoint subtrees, each of which is itself a tree. 7. Graphs. A data structure that consists of a set of nodes and a set of arcs (or edges). Each arc in a graph is specified by a pair of nodes. 8. Linked lists. A data structure that consists of linked nodes. Each node consists of two fields, an information field and a next address field. The information field holds the actual element on the list, and the next address field contains the address of the next node in the list. Operations performed on data structures - adding and deleting elements - traversing and searching a data structure - etc.
131
- The 68HC11 CPU registers can be pushed into the stack.
The 68HC11 Stack low address SP top element . high address bottom - A 16-bit stack pointer (SP) points to the location above the top byte of the stack. - The 68HC11 CPU registers can be pushed into the stack. - The top element (s) of the stack can be pulled into a CPU register. - The stack grows from high addresses toward lower addresses. Push and Pull Instructions - PSHA: Push A onto the stack - PSHB: Push B onto the stack - PSHX: Push X onto the stack (low order byte is pushed first) - PSHY: Push Y onto the stack (low order byte is pushed first) - PULA: Pull A from the stack - PULB: Pull B from the stack - PULX: Pull X from the stack (high order byte is pulled first) - PULY: Pull Y from the stack (high order byte is pulled first)
132
Example 3. 1 Suppose that [A] = $33, [B] = $20, [SP] = $00FF
Example 3.1 Suppose that [A] = $33, [B] = $20, [SP] = $00FF. What will be the contents of the top byte of the stack before and after the execution of PSHA? What will be the contents of the top two bytes of the stack if PSHB is executed? Solution: The contents of the stack before and after the execution of PSHA and PSHB are: XX [SP] = $00FD [SP] = $00FE XX $20 XX [SP] = $00FF $33 $33 original stack after PSHA after PSHB
133
Instructions Related to the Stack Pointer (SP)
[<label>] DES [<comment>] decrements the contents of the stack pointer by 1 [<label>] INS [<comment>] increments the contents of the stack pointer by 1 [<label>] LDS <opr> [<comment>] loads the contents of a memory location or an immediate value into SP [<label>] STS <opr> [<comment>] stores the contents of the stack pointer in a memory location [<label>] TSX [<comment>] places the contents of SP plus one into X [<label>] TSY [<comment>] places the contents of SP plus one into Y [<label>] TXS [<comment>] places the contents of X minus one into SP [<label>] TYS [<comment>] places the contents of Y minus one into SP Example 3.2 Write down an instruction sequence to load the top element of the stack into A and the 9th element from the top of the stack into B. Solution: TSX ; points the index register X to the top element of the stack LDAA 0,X ; places the top element of the stack in A LDAB 9,X ; places the 9th element from the top of the stack in B
134
Indexable Data Structures
- Vectors and matrices are indexable data structures - A vector is one dimensional and a matrix is two dimensional - The first element of a vector is associated with index 0 - Vectors and matrices can be defined by one or multiple FCB or FDB directives Example 3.3 Write a program to search an array with N 16-bit elements that are stored starting at $10 using the key stored at $00-$01 and save the address of the first matched element at $02-$03. Save the value $FFFF (-1) if no element matches the key. Solution: start i ¬ 0 result ¬ $FFFF array[i] = key? yes result ¬ address of array[i] i ¬ i + 1 no i = N - 1? yes Stop
135
N equ 10 ; array count notfound equ -1 org $00 key FDB xxxx ; the key to be used for searching result RMB 2 ; memory locations to store the address org $D000 array FDB $20,$40,$202,$1,$200,$10,$22,$21,$300,$101 org $C000 ldd #notfound ; store a -1 to result and result+1 std result ; “ ldd key ; get the key ldx #array ; get the starting address of the array ldy #0 ; initialize the loop count loop cpd 0,X ; compare with the key beq found ; found it? inx ; increment the pointer by 2 inx ; “ iny ; increment the loop count cpy #N-1 ; check the loop count bne loop jmp stop found stx result ; stop the search stop end
136
- can be stored in row major order or column major order
Matrices - can be stored in row major order or column major order - a matrix element can be accessed by specifying its row and column numbers The following matrix mat = can be stored in row major order mat1 FCB 01, 02, 03, 04, 05 FCB 06, 07, 08, 09, 10 FCB 11, 12, 13, 14, 15 or FCB 16, 17, 18, 19, 20 FCB 21, 22, 23, 24, 25 in column major order mat2 FCB 01, 06, 11, 16, 21 FCB 02, 07, 12, 17, 22 FCB 03, 08, 13, 18, 23 FCB 04, 09, 14, 19, 24 FCB 05, 10, 15, 20, 25
137
Address Calculation for a N × M Matrix Elements
- row major order address of mat1(i, j) = (i × M) + j + address of mat1(0,0) * Suppose memory locations i and j hold the row and column indices * The following instruction sequence computes the address of mat1(i, j) ldaa i ; place row index in A ldab #M ; place matrix dimension M in B mul ; compute i × M addb j ; compute i × M + j adca #0 ; “ addd #mat1 ; compute i × M+ j + mat1(0,0) xgdx ; place the address in X
138
- column major order address of mat2(i, j) = (j × N) + i + address of mat2(0, 0) * Suppose memory locations i and j hold the row and column indices * The following instruction sequence computes the address of mat2(i, j) ldaa j ; place row index in A ldab #N ; place matrix dimension N in B mul ; compute j × N addb i ; compute j × N + i adca #0 ; “ addd #mat2 ; compute j × N + i + mat2(0,0) xgdx ; place the address in X
139
Example 3. 4 Write a program to compute the sum of two 8 × 8 matrices
Example 3.4 Write a program to compute the sum of two 8 × 8 matrices. The starting addresses of these two matrices are MA and MB and that the result matrix is MC. These matrices are stored in memory in row major order. Each element is one byte. Solution: N equ $8 ; dimension of the matrix org $00 MA fcb .... ; matrix MA is here .... MB fcb .... ; matrix MB is here MC rmb 64 ; matrix MC is here i rmb 1 ; row index j rmb 1 ; column index buf rmb 1 ; buffer to hold element disp rmb 2 ; memory to hold the value of i × N + j org $C000 ldaa #N ; start from the last row staa i ; initialize the index i out_lp dec i ldab #N ; start from the last column toward the 0th column stab j
140
* The following 10 instructions fetch MA(i, j) and place it at buf
in_lp dec j ldaa i ; place row index in A ldab #N ; place N in B mul ; compute N × i addb j ; compute N × i + j adca #0 ; “ std disp ; save the value of N × i + j addd #MA ; compute MA(0,0) + N × i + j xgdx ldaa 0,X staa buf * The following 4 instructions fetch MB(i, j) into A ldd disp addd #MB adda buf ; compute MA(i, j) + MB(i, j) staa buf ; save the sum in buf
141
* The following 3 instructions compute the address of MC(i, j) and leave it in X
ldd disp addd #MC xgdx ldaa buf ; get the sum staa 0,X ; save the sum in MC(i,j) dec j ; decrement the column number beq in_lp ; not reach the end of a column yet? dec i ; decrement the row number beq out_lp ; is this the end of all computation end Matrix Transpose The transpose MT of a matrix M is defined as a matrix obtained by writing the rows of M as the columns of MT. MT can be obtained by swapping the (i, j)th element with the (j, i)th element for each i and j from 0 to N-1. Example 3.4 Write a program to transpose an N × N matrix.
142
- swap each element in the upper right
A breakdown of matrix a0,0 a0, a0,n-1 a1,0 a1,1 upper right lower left an-2,n-1 an-1,0 an-1,n-2 an-1,n-1 - swap each element in the upper right with an element in the lower left - row index i runs from 0 to n-2 for the upper right elements - for row i column index j runs from i+1 to n-1 - diagonal elements need not be swapped
144
N equ 8 ; matrix dimension ilimit equ N-2 ; upper limit of index i
Matrix Transpose Program N equ 8 ; matrix dimension ilimit equ N-2 ; upper limit of index i jlimit equ N-1 ; upper limit of index j org $00 i rmb 1 ; row index j rmb 1 ; column index ORG $D000 ; starting address of the matrix mat FCB ; matrix to be transposed FCB ; “ . ; “ ORG $C000 clr i ; initialize i to 0 row_loop ldaa i inca staa j ; initialize j to i + 1 * The following 7 instructions compute the address of mat(i,j) col_loop ldaa i ldab #N mul addb j adca #0
145
addd #mat xgdx * The following 7 instructions compute the address of mat(j,i) and leave address in Y ldaa j ldab #N mul addb i adca #0 xgdy * The following 4 instructions swap mat(i,j) with mat(j,i) ldaa 0,X ldab 0,Y staa 0,Y stab 0,X ldab j inc j ; update index j cmpb #jlimit ; j = N - 1? bne col_loop ldaa i inc i ; update index i cmpa #ilimit ; i = N - 2? bne row_loop END
146
Strings Example 3.6 Write a program to append a string to the end of another string. Solution: There are two steps in this program: Step 1 Find the end of the first string. Step 2 Copy string 1. ORG $C000 LDX #string2 again LDAA 0,X BEQ copy INX BRA again copy LDY #string1 copy_loop LDAA 0,Y STAA 0,X BEQ done INY BRA copy_loop done NOP SWI
147
… ORG $D000 string1 FCC “….” FCB 0 string2 FCC “….” END Example 3.7 Write a program to count the number of characters and words contained in a string. Solution: The first non-white-space character to the right of one or more spaces is the beginning of a new word. Parameters used in the program: - char_cnt: character count - wd_cnt: word count - str_ptr: string pointer - curr_char: current character
148
character and word count program
Figure 3.7 Flowchart for character and word count program
149
tab equ $09 ; ASCII code for horizontal tab character
sp equ $20 ; ASCII code for SPACE CR equ $0D ; ASCII code for carriage return LF equ $0A ; ASCII code for line feed org $00 char_cnt rmb 1 wd_cnt rmb 1 ORG $D000 string_X fcc “xxxxxxxxxxxxxxxx” ; the string to be processed fcb 0 ; the NULL character to terminate the previous string org $C000 ldx #string_X clr char_cnt ; initialize the character count to 0 clr wd_cnt ; initialize the word count to 0 string_lp ldab 0,X ; fetch the current character beq exit ; is this a NULL character? inx ; move to the next character inc char_cnt * The following 8 instructions skip the spaces between words cmpb #sp beq string_lp ; skip the space character cmpb #tab beq string_lp ; skip the tab character
150
cmpb #CR beq string_lp ; skip the carriage return character cmpb #LF beq string_lp ; skip the line feed character * A non-space character is the beginning of a new word inc wd_cnt wd_loop ldab 0,X beq exit ; null character is not included in character count inc char_cnt inx ; move the character pointer * The following 8 instructions check the end of a word cmpb #sp beq string_lp cmpb #tab * A non-space character is part of a word bra wd_loop exit swi end
151
Example 3.8 Write a program to search a certain word from a given string.
Solution: The flowchart of the word search program is in Figure 3.8.
152
tab equ $09 ; ASCII code for horizontal tab
sp equ $20 ; ASCII code for SPACE CR equ $0D ; ASCII code for carriage return LF equ $0A ; ASCII code for line feed NULL equ $00 ; ASCII code for NULL org $00 search rmb 1 ; flag to indicate if the given word is in the string string_X fcc “xxxxxxxxxxxxxxxx” ; a string terminated by NULL fcb 0 word_X fcc “yyyyyyy” ; a word terminated by NULL org $C000 clr search ; initialize the search flag to 0 ldx #string_X ; place the string address in X loop ldab 0,X inx * The following 10 instructions skip the white spaces to search for the next word * in the string tstb beq done ; is this the end of the string? cmpb #sp ; is the current character a space? beq loop ; skip the space cmpb #tab ; is the current character a tab?
153
beq loop ; skip the tab character
cmpb #CR ; is this a carriage return? beq loop ; skip it cmpb #LF ; is this a line feed? * The occurrence of the first non-white character indicates the beginning of a word, * and the comparison should be started ldy #word_X ; place the word address in Y ldaa 0,Y ; place the current character of word_X in A iny ; move the word pointer next_ch cba ; compare the character in A and B bne end_of_wd ; check the next word cmpa #NULL ; is this the end of a word? beq matched ; if yes, the word is found in the string ldaa 0,Y ; get the next character in word_X ldab 0,X ; get the next character in string_X inx iny bra next_ch ; check the next pair of characters * The following 10 instructions check to see if the end of the given word is reached end_of_wd cmpa #NULL bne next_wd ; if the not the end of the given word, then not matched cmpb #CR
154
beq matched cmpb #LF cmpb #tab cmpb #sp * The following twelve instructions skip the unmatched word in the string next_wd ldab 0,X ; get the next character in the string beq done ; stop if this is the end of the string inx cmpb #CR beq jmp_loop ; the label loop is too far away to use a conditional branch beq jmp_loop bra next_wd jmp_loop jmp loop matched ldab #1 ; set the search flag to 1 stab search ; “ done swi ; return to monitor (buffalo)
155
Subroutines - A sequence of instructions that can be called from various places in the program - Allows the same operation to be performed with different parameters - Simplifies the design of a complex program by using the divide-and-conquer approach Instructions related subroutine calls [<label>] BSR <rel> [<comment>] ; branch to subroutine [<label>] JSR <opr> [<comment>] ; jump to subroutine [<label>] RTS [<comment>] ; return from subroutine where <rel> is the offset to the subroutine <opr> is the address of the subroutine and is specified in the DIR, EXT, or INDexed addressing mode.
156
Program Structure Subroutine Processing
157
Issues in Subroutine Calls
1. Parameter passing - use registers - use the stack - use global memory 2. Returning results - use the stack (caller created a hole in which the result will be placed) 3. Local variables allocation - allocated by the callee - use as many DES instructions when no more than 5 bytes are needed - use the following instruction sequence to allocate more than 5 bytes. TSX XGDX SUBD #N ; allocate N bytes TXS ; move the stack pointer up by N bytes
158
Issues in Subroutine Calls (continued)
4. Local variables deallocation - use as many INS instructions as needed when no more than 5 bytes are to be deallocated - use the following instruction sequence when more than 5 bytes are deallocated TSX XGDX ADDD #N ; deallocate N bytes TXS ; move down the stack pointer by N bytes Stack Frame The region in the stack that holds incoming parameters, the subroutine return address, local variables, and saved registers is referred to as stack frame.
160
instruction of the subroutine subx is executed.
Example 3.9 Draw the stack frame for the following program segment when the 9th instruction of the subroutine subx is executed. ldaa #N psha ldx #mat pshx bsr subx ... Subx: (1) pshb (2) psha (3) pshx (4) pshy (5) tsx (6) xgdx (7) subd #6 (8) xgdx (9) txs Solution:
161
Using Registers to Pass Parameters
Example 3.10 Write a subroutine to compute the average of an array with N 8-bit elements and an instruction sequence to call the subroutine. The array starts at ARRAY. Use registers to pass parameters and return the average in B. Solution: The instruction sequence to call this subroutine is: LDX #ARRAY LDAA #N BSR average .... The subroutine saves array count A in the stack and also push a 0 into the stack so that 0 and N can be loaded into X when computing the average.
163
* The following subroutine computes the average of an array and returns it in B
average psha ; save the array count clra psha ; clear the top byte of the stack to 0 tsy ; Y points to the top byte of the stack ldab 1,Y ; place the array count in B cmpb #1 ; check the array count blo exit ; is the array empty? bhi do ; does the array have more than one element? ldab 0,X ; get the single element and return bra exit ; “ do xgdy ; place N in Y and use Y as the loop count clra ; use D as the sum and initialize it to 0 clrb ; “ again addb 0,X ; add an element to the sum adca #0 ; add the carry to the upper 8 bits inx ; move the array pointer dey ; decrement the loop bne again ; is the end of the loop? tsy ; point Y to the top of the stack ldx 0,Y ; place N in X
164
idiv ; compute the average of the array
xgdx ; exchange X and D so that D contains the quotient * ; in which A contains 0 and B contains the quotient exit pula ; restore registers pula ; “ rts
165
Using the Stack to Pass Parameters
Example Write a subroutine to find the largest element of an array and an instruction sequence to call this subroutine. The following parameters are passed to this subroutine in the stack: - array: the starting address of the given array - arcnt: the array count - amax: address of the memory location to hold the maximum element of the array Solution: The instruction sequence that calls this subroutine is: ldx #array pshx ldaa #arcnt psha ldx #armax bsr max ; call the subroutine tsx ; clean up the stack ldab #5 ; “ abx ; “ txs ; “
168
array equ 11 ; array base address offset from the top of the stack
arcnt equ 10 ; array count offset from the top of the stack armax equ 8 ; array max address offset from the top of the stack max pshx ; save al registers pshy ; “ pshb ; “ psha ; “ tsy ; point Y to the top of the stack ldx array,Y ; load the base address into X ldab arcnt,Y ; load the array count into B ldaa 0,X ; assign the first element as the temporary array max cmpb #1 ; check array count blo exit ; return if the array is empty bhi start ; look for the array max if the array count is larger than 1 bra done ; the array has only one element start inx ; set X to point to the second element of the array decb ; loop limit is arcnt - 1 again cmpa 0,X ; compare the next element with the array max bge noswap ; should array max be updated? ldaa 0,X ; update the array max noswap inx ; move to the next element
169
decb ; decrement the loop count
bne again ; is it done? done ldx armax,Y ; get the address for the array max staa 0,X ; save the array max exit pula ; restore registers pulb ; “ puly ; “ pulx ; “ rts
170
Example 3.12 Write a program to compute the greatest common divisor (gcd) of
two 16-bit integers. The caller pushes these two integers onto the stack and this subroutine returns the gcd in double accumulator D. Solution: Let these two integers be n1 and n2. Assume n1 n2. If not, swap them. Algorithm: Step 1 If n1 > n2 then swap n1 and n2. Step 2 i = 2, gcd = 1. Step 3 If (n1 = 1) or (n2 = 1) return. Step 4 If both n1 and n2 can be divided by i then gcd i. Step 5 If i = n1 then stop. Otherwise, i i + 1. Go to step 4.
171
Stack frame of gcd subroutine
Instruction sequence to call find_gcd … LDX <operand n1> PSHX LDX <operand n2> JSR find_gcd INS
172
n1_dis EQU 8 ; offset of n1 from the top of the stack
gcd_dis EQU 0 ; offset of gcd from the top of the stack i_dis EQU 2 ; offset of i from the top of the stack Find_gcd PSHY TSY DES LDX #1 STX gcd_dis,Y LDD n2_dis,Y ; if n2 = 1 then gcd = 1 CPD #1 ; “ BEQ done ; “ LDD n1_dis,Y ; if n1 = 1 then gcd = 1 CPD n2_dis,Y BLS start ; if n1 is smaller then start to compute gcd LDX n2_dis,Y ; n1 is larger than n2, so swap them
173
done INS INS RTS STD n2_dis,Y STX n1_dis,Y
start LDX #2 ; initialize i to 2 STX i_dis,Y ; “ again LDD n1_dis,Y IDIV CPD #0 ; can i divide n1? BNE next_i ; “ LDD n2_dis,Y LDX i_dis,Y ; can i divide n2? IDIV ; “ CPD #0 ; “ BNE next_i LDD i_dis,Y ; use current i as STD gcd_dis,Y ; the temporary gcd next_i LDX i_dis,Y ; have we done with CPX n1_dis,Y ; all the test yet? BEQ done INX STX i_dis,Y JMP again done INS INS RTS
174
Example 3.13 Write a subroutine that can divide a 32-bit number into another 32-bit number.
Solution: Use repeated subtraction method to implement the division. Assume we have the hardware shown in Figure 3.0.
175
Algorithm of Division Using Repeated Subtraction
Step 1 Shift the register pair (R, Q) one bit to the left. Step 2 Subtract register P from register R, put the result back to R if the difference is nonnegative. Step 3 If the result in step 2 is negative, set the least significant bit of Q to 0. Otherwise, set it to 1. Step 4 Repeat Step 1 to 4 for 31 times. The caller allocates 8 bytes in the stack to hold the remainder and quotient. Both the dividend and the divisor are pushed into the stack. The subroutine allocates 13 bytes for local variables. The calling instruction sequence is TSX XGDX SUBD #8 TXS LDX divsor ; push divisor PSHX ; “ LDX didend ; push dividend JSR div32
176
buf EQU 0 ; space used as a buffer
R EQU 5 ; offset of register R from the top of the stack Q EQU 9 ; offset of register Q from the top of the stack divisor EQU 21 ; offset of divisor from the top of the stack dividend EQU 25 ; offset of dividend from the top of the stack i EQU 4 ; offset of variable i from the top of the stack local EQU 13 ; number of bytes of local variables div32 PSHA PSHB PSHX PSHY TSX ; allocate local variables XGDX ; “ SUBD #local ; “ XGDX ; “ TXS ; “ TSY ; Y points the top byte of the stack LDD #0 ; initialize R to 0 STD R,Y ; “ STD R+2,Y ; “ LDD dividend,Y ; transfer dividend to Q STD Q,Y ; “ LDD dividend+2,Y ; “
177
Stack frame for the div32 subroutine
178
STD Q+2,Y ; transfer dividend to Q
LDAA #32 ; initialize loop count to 32 STAA i,Y ; “ loop LSL Q+3,Y ; shift register pair (R, Q) to the left one place ROL Q+2,Y ; “ ROL Q+1,Y ; “ ROL Q,Y ; “ ROL R+3,Y ; “ ROL R+2,Y ; “ ROL R+1,Y ; “ ROL R,Y ; “ LDD R+2,Y ; subtract the divisor P from R SUBD divisor+2,Y ; “ STD buf+2,Y ; “ LDAA R+1,Y ; “ SBCA divisor+1,Y ; “ STAA buf+1,Y ; “ LDAA R,Y ; “ SBCA divisor,Y ; “ BCS smaller ; is [R] – divisor < 0? STAA R,Y ; store the difference back to R when the difference is positive LDD buf+2,Y ; “ STD R+2,Y ; “
179
LDAA buf+1,Y STAA R+1,Y LDAA Q+3,Y ORAA #01 ; set the lsb of Q to 1 STAA Q+3,Y ; “ BRA looptest smaller LDAA Q+3,Y ; set the lsb of Q to 0 ANDA #$FE ; “ looptest DEC i,Y BNE loop LDD R,Y ; return the remainder in the hole in the stack STD rem,Y ; “ LDD R+2,Y ; “ STD rem+2,Y ; “ LDD Q,Y ; return the quotient in the hole in the stack STD quo,Y ; “ LDD Q+2,Y ; “ STD quo+2,Y ; “ TSX XGDX ADDD #local ; deallocate local variables
180
XGDX TXS PULY PULX PULB PULA RTS
181
Example 3.14 Write a subroutine to sort an array of 8-bit numbers using the bubble sort
method, and also write an instruction sequence to call the subroutine. The starting address of the array and is arr_base, and the array count is N. Use the stack to pass parameters to this routine. Solution: Up to N – 1 (labeled as 0th to (N – 2)th) iterations of comparisons and swaps are performed: 1. N - i – 1 comparisons are performed in iteration i. 2. Set an in-order flag to 1 at the beginning of each iteration. 3. Start from array element with index 0 to index N – i –2, compare each element with its adjacent element and swap them if they are not in the right order (ascending or descending). 4. Clear the in-order flag whenever a swap is made. 5. Check the in-order flag at the end of each iteration. If the flag is 1, then stop. Otherwise, continue. Four local variables are used: 1. iteration: keeps track of the numbers of rounds remained to be performed 2. inner: keeps track of the number of comparisons remained to be performed in a round 3. in_order: indicates if the given array is already in sorted order 4. buf: buffer for swapping elements
183
arr EQU 13 ; offset of array base from the top of the stack
arcnt EQU 12 ; offset of array count from the top of the stack buf EQU 3 ; offset of buf from the top of the stack in_order EQU 2 inner EQU 1 iteration EQU 0 true EQU 1 false EQU 0 bubble PSHB PSHA PSHY PSHX DES ; allocate space for local variables DES ; “ TSY ; set Y to point to the top byte of the stack LDAA arcnt,Y DECA ; compute the number of iterations that need to be performed STAA iteration,Y ; “
184
ploop LDAA #true ; set in-order flag to true
STAA in_order,Y ; “ LDX arr,Y ; place the array base address in X LDAA iteration,Y STAA inner,Y ; initialize inner loop count cloop LDAA 0,X ; get one element CMPA 1,X ; compare it with the next element BLE looptest * the following 5 instructions swap the two adjacent elements STAA buf,Y LDAA 1,X STAA 0,X LDAA buf,Y STAA 1,X LDAA #false ; reset the in_order flag looptest INX ; move the array pointer DEC inner,Y BNE cloop TST in_order,Y BNE done DEC iteration,Y BNE ploop
185
* the following four instructions deallocate space allocated to local variables
done INS INS PULX PULY PULA PULB RTS
186
Buffalo Input and Output Routines
- The Buffalo monitor in EVB and CMD11A8 provides a set of I/O routines. - These I/O routines are located in the Buffalo ROM. - A jump table is implemented so that the user program can call these routines by jumping to the desired entry. Buffalo I/O Routines UPCASE converts the character in accumulator A to uppercase WCHK tests the character in A and returns with Z bit set if character is white space (space, comma, tab) DECHK tests the character in A and return with Z bit set if character is delimiter (carriage return or whitespace) INIT initializes I/O device INPUT reads I/O device OUTPUT writes I/O device OUTLHLF converts left nibble of A to ASCII and outputs to terminal port OUTRHLF converts right nibble of A to ASCII and outputs to terminal port OUTA outputs the ASCII character in A OUT1BYT converts the binary byte at the address in index register X to two ASCII characters and outputs them; returns address in index register X pointing to next byte
187
OUT1BSP converts the binary byte at the address in index register X to two ASCII
characters and outputs them followed by a space; returns address in index register X pointing to next byte OUT2BSP converts two consecutive bytes starting at address in index register X to four ASCII characters and outputs the characters followed by a space; returns address in index register X pointing to next byte OUTCRLF outputs ASCII carriage return followed by a line feed OUTSTRG outputs a string of ASCII bytes pointed to by the address in index register X until character is an end-of-transmission ($04) OUTSTRG0 same as OUTSTRG, except that leading carriage returns and line feeds are skipped INCHAR inputs ASCII character to A and echoes back; this routine loops until character is actually received
188
Table 3.4 The EVB/EVBU I/O routine jump table
Address Instruction $FFA0 JMP UPCASE $FFA3 JMP WCHEK $FFA6 JMP DCHEK $FFA9 JMP INIT $FFAC JMP INPUT $FFAF JMP OUTPUT $FFB2 JMP OUTLHLF $FFB5 JMP OUTRHLF $FFB8 JMP OUTA $FFBB JMP OUT1BYT $FFBE JMP OUT1BSP $FFC1 JMP OUT2BSP $FFC4 JMP OUTCRLF $FFC7 JMP OUTSTRG $FFCA JMP OUTSTRG0 $FFCD JMP INCHAR
189
Calling the EVB I/O Routines
Execute a JSR instruction to call an EVB I/O routine: To output the character in accumulator A JSR $FFB8 To output a string pointed by index register X JSR $FFC7 A better approach is to use assembler directives to make the I/O routine call more readable: outa equ $FFB8 outstrg equ $FFC7 JSR outa . JSR outstrg
190
Example 3.16 Write a subroutine to input a string from the keyboard and save the string in
a buffer pointed by X. The input string is terminated by the carriage-return character. Solution: getchar EQU $FFCD ; use mnemonic to represent hex address CR EQU $0D EOT EQU $04 get_string JSR getchar CMPA #CR BEQ done STAA 0,X INX BRA get_string done LDAA #EOT RTS
191
Chapter 4: C Language Programming
The 68HC11 Microcontroller Han-Way Huang Minnesota State University, Mankato
192
Introduction to C - C has gradually replaced assembly language in many embedded applications. A summary of C language constructs that will be used in 68HC11 programming. Books on C language 1. Kernighan & Ritchie, “The C Programming Language”, Prentice Hall, 1988. 2. Deitel & Deitel, “C: How to Program”, Prentice Hall, 1998. 3. Kelly & Pohl, “A Book on C: Programming in C”, Addison-Wesley, 1998. A C program consists of functions and variables. A function contains statements that specify the operations to be performed. Types of statements: 1. Declaration 2. Assignment 3. Function call 4. Control 5. Null A variable stores a value to be used during the computation. The main () function is required in every C program.
193
A C Program Example #include <stdio.h> causes the file stdio.h to be included /* this is where program execution begins */ a comment main () program execution begins { marks the start of the program int a, b, c; declares three integer variables a, b, and c a = 3; assigns 3 to variable a b = 5; assigns 5 to variable b c = a + b; assigns the sum of a and b to variable c printf (“ a + b = %d\n”, c); prints the string a + b = followed by value of c return 0; returns 0 to the caller of main( ) } ends the main( ) function Types, Operators, and Expressions - variables must be declared before they can be used. - A variable declaration must include the name and type of the variable and may optionally provide its initial value.
194
- The name of a variable consists of letters and digits.
- The underscore character “_” can be used to improve readability of long variables. Data Types - C has four basic data types: char, int, float, and double. - A variable of type char can hold a single byte of data. - A variable of type int is an integer that is the natural size for a particular machine. - The type float refers to a 32-bit single-precision floating-point number. - The type double refers to a 64-bit double-precision floating-point number. - Qualifiers short and long can be applied to integers. For ImageCraft C compiler, short is 16 bits and long is 32 bits. - Qualifiers signed and unsigned may be applied to data types char and integer. Declarations - A declaration specifies a type, and contains a list of one or more variables of that type.
195
Examples of declarations
int i, j, k; char cx, cy; int m = 0; char echo = ‘y’; /* the ASCII code of letter y is assigned to variable echo. Constants - There are four kinds of constants: integers, characters, floating-point numbers, and strings. - A character constant is written as one character within single quotes, such as ‘x’. A character constant is represented by the ASCII code of the character. - A string constant is a sequence of zero or more characters surrounded by double quotes, as “68HC11 is made by Motorola” or “”, which represented an empty string. Each individual character in the string is represented by its ASCII code. - An integer constant like 1234 is an int. A long constant is written with a terminal l or L, as in L.
196
-. A number in C can be specified in different bases
- A number in C can be specified in different bases. The method to specify the base of a number is to add a prefix to the number: Arithmetic Operators + add and unary plus - subtract and unary minus * multiply / divide -- truncate quotient to integer when both operands are integers. % modulus (or remainder) -- cannot be applied to float or double ++ increment (by 1) -- decrement (by 1)
197
Bitwise Operators - C provides six operators for bit manipulations; they may only be applied to integral operands. & AND | OR ^ XOR ~ NOT >> right shift << left shift - & is often used to clear one or more bits of an integral variable to 0. PORTD = PORTD & 0xBD /* clears bit 6 and bit 1 of PORTD to 0 */ /* PORTD is of type char */ - | is often used to set one or more bits to 1. PORTB = PORTB | 0x40; /* sets bit 6 to 1 (PORTB is of type char) */ - ^ can be used to toggle a bit. abc = abc ^ 0xF0; /* toggles upper four bits (abc is of type char) */
198
- >> can be used to shift the involved operand to the right for the specified number
of places. xyz = xyz >> 3; -- shift right 3 places - << can be used to shift the involved operand to the left for the specified number xyz = xyz << 4; -- shift left 4 places - The assignment operator = is often combined with the operator. For example, PORTD &= 0xBD; PORTB |= 0x40; xyz >>= 3; xyz <<= 4;
199
Relational and Logical Operators
- Relational operators are used in expressions to compare the values of two operands. - The value of the expression is 1 when the result of comparison is true. Otherwise, the value of the expression is 0. - Relational and logical operators: == equal to != not equal to > greater than >= greater than or equal to < less than <= less than or equal to && and || or ! not (one’s complement)
200
Examples of Relational and Logical Operators:
if (!(ADCTL & 0x80) statement1; /* if bit 7 is 0, then execute statement1 */ if (i < 10 && i > 0) statement2; /* if 0 < i < 10 then execute statement2 */ if (a1 == a2) statement3; /* if a1 = a2 then execute statement3 */ Control Flow - The control-flow statements specify the order in which computations are performed. - Semicolon is a statement terminator. - Braces { and } are used to group declarations and statements together into a compound statement, or block.
201
If-Else Statement if (expression) statement1 else -- The else part is optional. statement2 Example, if (a != 0) r = b; else r = c; A more concise way for this statement is r = (a != 0)? b : c;
202
Multiway Conditional Statement
if (expression1) statement1 else if (expression2) statement2 else if (expression3) statement3 … else statementn Example, if (abc > 0) return 5; else if (abc = 0) return 0; else return -5;
203
Switch Statement Example
switch (expression) { switch (i) { case const_expr1; case 1: printf(“#”); statement1; break; break; case 2: printf(“##”); case const_expr2; break; statement2; case 3: printf(“###”); break; break; … case 4: printf(“####”); default: break; statementn; case 5: printf(“#####”); } break; }
204
For-Loop Statement for (expr1; expr2; expr3) statement; where, expr1 and expr2 are assignments or function calls and expr3 is a relational expression. Example sum = 0; for (i = 1; i < 10; i++) sum += i * i; for (i = 1; i < 20; i++) if (i % 2) printf(“%d “, i);
205
While Statement while (expression) statement Example int_cnt = 5; while (int_cnt); /* do nothing while the variable int_cnt 0 */ Do-While Statement Example do int digit = 9; statement do while (expression); printf(“%d “, digit--); while (digit >= 1);
206
Input and Output Examples
- Not part of the C language itself. - Four I/O functions will be discussed. 1. int getchar ( ). char xch; -- returns a character when called xch = getchar (); 2. int putchar (int). putchar(‘a’); -- outputs a character on a standard output device 3. int puts (const char *s). puts (“Welcome to USA! \n”); -- outputs the string pointed by s on a standard output device 4. int printf (formatting string, arg1, arg2, …). -- converts, formats, and prints its arguments on the standard output device.
207
Formatting String for Printf
- The arguments of printf can be written as constants, single variable or array names, or more complex expressions. - The formatting string is composed of individual groups of characters, with one character group associated with each output data item. - The character group starts with %. - The simplest form of a character group consists of the percent sign followed by a conversion character indicating the type of the corresponding data item. - Multiple character groups can be contiguous, or they can be separated by other characters, including whitespace characters. These “other characters” are simply sent to the output device for display. - Examples printf (“this is a challenging course ! \n”); printf(%d %d %d”, x1, x2, x3); /* outputs x1, x2, and x3 using minimal number of digits with one space separating each value */ printf(“Today’s temperature is %4.1d\n”, temp);
208
Rules for Conversion String
- Between the % and the conversion character there may be, in order: 1. A minus sign, -- specify left adjustment. 2. A number that specifies the minimum field width. 3. A period that separates the field width from precision. 4. A number, the precision, that specifies the maximum number of characters to be printed from a string, or the number of digits after the decimal point, or the minimum of digits for an integer. 5. An h if the integer is to be printed as a short, or l (letter ell) if as a long.
209
Functions and Program Structure
- Every C program consists of one or more functions. - Definition of a function cannot be embedded within another function. - A function will process information passed to it from the calling portion of the program, and return a single value. - Syntax of a function definition: return_type function_name (declarations of arguments) { declarations and statements } Example char lower2upper (char cx) if cx > ‘a’ && cx <= ‘z’) return (cx - (‘a’ - ‘A’)); else return cx;
210
Example 4.1 Write a function to test if an integer is a prime number.
Solution: A number is a prime if it is indivisible by any integer between 2 and half of itself. /* this function returns a 1 if a is prime. Otherwise, it returns a 0. */ char test_prime (int a) { int i; if (a == 1) return 0; for (i = 2; i < a/2; i++) if ((a % i) == 0) return 0; return 1; } - A function must be defined before it can be called. - Function prototype declaration allows us to call a function before it is defined. - Syntax of a function prototype declaration: return_type function_name (declarations of arguments);
211
Example 4.2 Write a program to find out the number of prime numbers between
100 and 1000. Solution: #include <stdio.h> char test_prime (int a); /* prototype declaration for the function test_prime */ main ( ) { int i, prime_count = 0; for (i = 100; i <= 1000; i++) { if (test_prime(i)) prime_count ++; } printf(“\n The total prime numbers between 100 and 1000 is %d\n”, prime_count); char test_prime (int a) int i; if (a == 1) return 0; for (i = 2; i < a/2; i++) if ((a % i) == 0) return 0; return 1;
212
Pointers and Addresses
- A pointer is a variable that holds the address of a variable. - Pointers provide a way to return multiple data items from a function via function arguments. - Pointers also permit references to other functions to be specified as arguments to a given function. - Syntax for pointer declaration: type_name *pointer_name; Examples int *ax; char *cp; - Use the dereferencing operator * to access the value pointed by a pointer. int a, *b; … a = *b; /* assigns the value pointed by b to a */
213
- Use the unary operator & to assign the address of a variable to a pointer. For example,
int x, y; int *ip; ip = &x; y = *ip; /* y gets the value of x */
214
Example 4.3 Write a bubble sort function to sort an array of integers.
Solution: void swap (int *, int *); /* function prototype declaration */ void bubble (int a[], int n) /* n is the array count */ { int i, j; for (i = 0; i < n - 1; i++) for (j = n - 1; j > i; j--) if (a[j - 1] > a[j]) swap (&a[j - 1], & a[j]); } void swap(int *px, int *py) int temp; temp = *px; *px = *py; *py = temp;
215
Arrays - An array consists of a sequence of data items that have common characteristics. - Each array is referred to by specifying the array name followed by one or more subscripts, with each subscript enclosed in brackets. Each subscript is a nonnegative integer. - The number of subscripts determines the dimensionality of the array. For example, x[i] is an element of an one-dimensional array y[i][j] refers to an element of a two-dimensional array - Syntax for one-dimensional array declaration: data-type array_name [expression]; - Syntax for two-dimensional array declaration: data-type array_name [expr1] [expr2];
216
Pointers and Arrays - Any operations that can be achieved by array subscripting can also be done with pointers. - The pointer version will in general be faster but, somewhat harder to understand. - For example, int ax[20]; /* array of 20 integers */ int *ip; /* ip is an integer pointer */ ip = &ax[0] /* ip contains the address of ax[0] */ x = *ip; /* copy the contents of ax[0] into x. - If ip points to ax[0], then ip + 1 points to ax[1], and ip + i points to ax[i], etc.
217
Passing Arrays to a Function
- An array name can be used as an argument to a function. - To pass an array to a function, the array name must appear by itself, without brackets or subscripts, as an actual argument within the function call. - When declaring a one-dimensional array as a formal argument, the array name is written with a pair of empty square brackets. - When declaring a two-dimensional array as a formal argument, the array name is written with two pairs of empty square brackets. - Example, int average (int n, int arr[ ]); main ( ) { int n, avg; int arr[50]; … avg = average (n, arr); /* function call with array name as an argument */ } int average (int k, int brr [ ]) /* function definition */
218
External Variables - A variable declared inside a function is called an internal variable. - A variable defined outside of a function is called a external variable. - An external variable is available to many functions. - External variables provide an alternative to function arguments and return values for communicating data between functions. - Any function may access an external variable by referring to it by name if the the name has been declared somewhere. Scope Rules - The functions and external variables that make up a C program can be compiled separately. - The source text of the program may be kept in several files. - The scope of a name is the part of the program within which the name can be used. - For a variable declared at the beginning of a function, the scope is the function in which the name is declared. - Local (internal) variables of the same name in different functions are unrelated. - The scope of an external variable or a function lasts from the point at which it is declared to the end of the file being compiled.
219
In the following program segment
In the following program segment The use of external variables are illustrated in the following 2-file C program … in file 1 void f1 (…) extern int xy; { extern long arr [ ]; … main ( ) } { … int a, b, c; } void f2(…) void foo (int abc) { … } { long soo (void) { … } } in file 2 int xy; Variables a, b, and c are accessible to long arr [100]; function f2 but not f1.
220
Using the ImageCraft C Compiler
- An Integrated Development Software (IDS) may consist of a text editor, a compiler, a linker, a librarian, an assembler, a simulator, and debugger, etc. - An IDS uses project as the unit to control the software development. - A user creates C functions in one or multiple files using the editor provided by the integrated software. - The compiler is then invoked to compile each individual file. In most cases, you will need to eliminate syntax errors in this step. - Create a new project and add the files just created into this project. - Build the project. The IDS will combine all object modules into one executable module and may translate it into appropriate format suitable for downloading into a demo board for execution. - Download the module into a demo board for execution. - In the following, we will use a project that consists of a single file to illustrate the process of using the ImageCraft C compiler for program development:
221
Step 1. Invoke the ICC11 by clicking the icon of ICC1 program
Step 1. Invoke the ICC11 by clicking the icon of ICC1 program. A window appears as follows:
222
Step 2. Click the file menu and select new to create a new file for entering a new program.
The screen look like this:
223
Step 3. Type in the new program and save it in an appropriate directory. An example is shown
in Figure 4.3.
224
Step 4. Create a new project by clicking the project menu and select new. The screen is shown
in Figure 4.4. After selecting new, the screen changes to Figure 4.5. After this, we need to enter the project name and the result is shown in Figure 4.6.
227
Step 5. Add the program to the newly created project
Step 5. Add the program to the newly created project. Press the Add button on Figure 4.6. A list of files will be displayed and you can select those files that you want to include in this project. Click on the file add.c and the result is shown in Figure 4.7.
228
Step 6. Setting appropriate options for the compiler, editor, and terminal program. The options
available can be seen by pressing the Options menu shown in Figure 4.8.
229
Step 7. Set compiler preprocessor options
Step 7. Set compiler preprocessor options. There are three sets of options that need to be set in the compiler: preprocessor, compiler, and linker. Select Compiler in Figure 4.8 and then click on Preprocessor and the screen shown in Figure 4.9a will be brought up. Enter the appropriate include path. Do not click on OK.
230
Step 8. Set compiler options. Click on the item compiler
Step 8. Set compiler options. Click on the item compiler. The default options shown in Figure 4.9b are OK.
231
Step 9. Set linker options. Click the Linker button on Figure 4
Step 9. Set linker options. Click the Linker button on Figure 4.9a to bring up the linker option screen. The appropriate option values for EVB demo board are shown in Figure 4.9c. The appropriate option values for CMD11A8 are shown in Figure 4.9d.
233
Step 10. Set terminal options
Step 10. Set terminal options. Go back to Option menu and select Terminal. This will bring up the terminal option screen as shown in Figure The com port can be com1 or com2. Baud rate should be set to 9600 for both EVB and CMD11A8. Flow control should be set to none. Font also need to set properly. A popular font is Courier or Courier New (shown in Figure 4.11). Click on OK and the screen will change back to Figure 4.8.
235
Step 10. Build the project. Click the Build button and ICC11 will start to process your file.
The Build button will be dimmed before it is done. When it is done, the Build button will change back to bold. Minimize both the project and source code windows and maximize the status window and the result is shown in Figure 4.12.
236
Step 11. Download the program onto the demo board for execution
Step 11. Download the program onto the demo board for execution. Click the Target menu and select Terminal and this will bring up the terminal window as shown in Figure Type load t followed by the enter key, and click on the Browse button. This would bring up a popup window (shown in Figure 4.14) for you to select a file to download. Select add.s19 and click OK button. Click the ASCII Download button to start downloading. The downloading process looks like that in Figure A successful download should look like Figure 4.16.
237
Select a File to Download
238
Download Process
239
A Successful Download
240
Step 12. Program Execution and Debugging
Step 12. Program Execution and Debugging. ICC11 terminal program allows you to use all the Buffalo commands to debug the program when using an EVB and CMD11A8 demo board. Type G 2000 to run this program on the CMD11A8 demo board and the result would look like Figure (Type G C000 on the EVB board).
241
Chapter 5: Operation Modes and Memory Expansion
The 68HC11 Microcontroller Han-Way Huang Minnesota State University, Mankato
242
The 68HC11 Operation Modes - Single chip mode: a mode in which the 68HC11 functions without external address and data buses. The 68HC11 has 5 I/O ports (A, B, C, D, and E) to use in this mode. - Expanded mode: a mode in which the 68HC11 has the capability to access a 64KB address space. In this mode, port B is used as the upper address signals (A15-A8) and port C is used as time-multiplexed address/data bus (A7/D7-A0/D0). Only three I/O ports are available for direct use. - Special test mode: mainly used by Motorola in fabrication testing. - Special Bootstrap mode: a mode in which a bootstrap ROM is enabled. The bootstrap ROM contains a loader program that will be executed after the RESET signal is going high and this program will load in a 256-byte program from the SCI subsystem to the on-chip SRAM and then transfer the CPU control to that loaded program. Establishment of the operation mode On the rising edge of the RESET, the voltage levels on pins MODA and MODB are latched into the HPRIO register, which determines the operation mode of the 68HC11.
243
Memory Technologies and Terminology
1. Nonvolatile and volatile memories: differentiated by whether a memory component will lose its contents when the power is removed. 2. ROMs and RAMs: differentiated by whether a a memory component can be read/write from/into for roughly the same amount of time. 3. Dynamic and Static RAMs: differentiated by whether a RAM requires periodic refresh operation in order to maintain its stored information. 4. Memory capacity: the total number of bits that a memory chip contains. 5. Memory organization: describes the number of bits that can be accessed from a memory chip in one operation. The organization is specified as m n, where m is the total number of locations and n is the number of bits in each location.
244
Example 5.1 Using the following memory chips, how many SRAM chips will be
needed to build a 512KB, 16-bit memory system for a 16-bit microprocessor? a. 256K × 1 SRAM b. 256K × 4 SRAM c. 256K × 8 SRAM d. 64K × 8 SRAM Solution: a. Sixteen SRAM chips with × 1 organization are needed to construct a 16-bit memory system K × 1 chips are required to build a 512KB 16-bit memory system. b. Four SRAM chips with × 4 organization are needed to construct a 16-bit memory system. Four 256K × 4 SRAM chips are needed to construct a 512 KB 16-bit memory system. c. Two SRAM chips with × 8 organization are needed to construct a 16-bit memory system. Two 256K × 8 SRAM chips are needed to construct a 512 KB 16-bit d. Two SRAM chips with × 8 organization are needed to construct a 16-bit memory system. Eight 64K × 8 SRAM chips are needed to construct a 512 KB 16-bit
245
Reposition 68HC11 on-chip SRAM and I/O registers
- The upper four bits of the INIT register reposition the on-chip SRAM to the beginning of any 4KB page - The lower four bits of the INIT register reposition the I/O registers to the beginning of any 4KB page. - The repositioning of SRAM and I/O registers can only be done within 64 E clock cycles after reset. Example 5.2 Reposition the 68HC11 on-chip SRAM to $2000-$20FF and remap I/O registers to $3000-$303F. Solution: Set the upper four bits and lower four bits of the INIT register to $2 and $3, respectively. SRAM equ $20 ; value to remap SRAM to $2000-$20FF IOREG equ $03 ; value to remap I/O registers to $3000-$303F remap equ SRAM+IOREG INIT equ $1030 ldab #remap staa INIT …
246
External Memory Expansion Issues
address space assignment address decoding timing consideration Address space assignment - only unallocated memory space should be assigned to external memory components - memory space is often allocated in the unit of 2n KB (n is an integer) for 8-bit microcontrollers - address decoder can be simplified if memory space is divided into blocks of the same size. Allocated space for the 68HC11A8 $0000-$00FF: SRAM $1000-$103F: I/O registers $B600-B7FF: EEPROM $E000-$FFFF: ROM
247
Example 5.3 Assign the 68HC11 memory space using a block size of 4KB.
Solution: The 64KB memory space can be divided into 16 4KB blocks.
248
Address decoding methods
Example 5.4 Assign the 68HC11 memory space using a block size of 8KB. Solution: The 64 KB space can be divided into eight 8KB blocks. Block number Address range 1 2 3 4 5 6 7 $0000-$1FFF $2000-$3FFF $4000-$5FFF $6000-$7FFF $8000-$9FFF $A000-$BFFF $C000-$DFFF $E000-$FFFF Address decoding methods - partial-decoding: each addressable location responds to more than one address on the system bus - full-decoding: each addressable location responds only to one specific address
249
TTL Decoder Chips : a 3-to-8 decoder : dual 2-to-4 decoder
250
Example 5.5 Use a full decoding scheme to design an address decoder for a computer
that has the following address space assignments: SRAM1: $2000-$3FFF ROM1: $4000-$5FFF E2PROM: $6000-$7FFF SRAM2: $A000-$BFFF ROM2: $C000-$DFFF Solution: Each memory component is 8KB. A 3-to-8 decoder 74LS138 can be used as the address decoder. The highest 3 address bits will be used as the address inputs to the decoder. The highest three address bits for each component are: SRAM1: 001 ROM1: 010 E2PROM: 011 SRAM2: 101 ROM2: 110 The decoder circuit is:
251
Example 5.6 Design an address decoder for a 68HC11-based product that has 2KB of
external E2PROM and 2KB of external SRAM using partial decoding method. Solution: - Use the dual 2-to-4 decoder as the address decoder. - Divide the 64KB address space of the 68HC11 into four 16 KB blocks. - Use the two highest address signals A15A14 as the address inputs to the decoder. - Assign the address space $4000-$7FFF to E2PROM. - Assign the address space $8000-$BFFF to SRAM.
252
Example 5.7 Make space assignment for an 8-bit microcontroller-based system
with 2 external 8KB SRAM chips, 2 8KB EPROM chips, 1 8KB flash memory chip, and 8 I/O devices. After making space assignment, design a decoder for it. Solution: Use a two-level space assignment and two to perform addressing decoding. The level one and level two space assignments are:
253
The decoding circuitry is as follows:
254
Conventions of Timing Diagrams
- Ideal signals have 0 rise and fall times - A real signal has nonzero rise and fall times
255
- Normal signal representation
- Unknown signals (when they are changing) representation
256
Floating signal representation
- A floating signal is represented by a level half way between logic high and low.
257
Signal causal relationships
258
The 68HC11 Bus Cycle Timing Diagrams
- A 68HC11 external bus cycle can only be performed in expanded mode and controlled by the E clock signal. - All read and write bus cycles take one E clock cycles to complete. - All timing parameters use 20% and 70% of the power supply voltage as reference points. (Motorola is using this convention) - Most timing parameters are measured relative to the rising and falling edges of the E clock signal. - The phrase before the rising edge of the E clock uses the time when the magnitude of the E clock signal is 0.2VDD as a reference point. - The phrase after the rising edge of the E clock uses the time when the magnitude of the E clock signal is 0.7VDD as a reference point. - The phrase before the falling edge of the E clock uses the time when the magnitude of - The phrase after the falling edge of the E clock uses the time when the magnitude of
259
MC68HC11 Read Bus Cycle Timing Diagram
260
For the 2 MHz E clock signal and the 68HC11 read bus cycle timing diagram
- PWEL is the E clock low pulse width (227 ns) - PWEH is the E clock high pulse width (222 ns) - A15-A8 and R/W signals are valid tAV (94ns) before the rising edge of E clock - A15-A8 and R/W signal remain valid for tAH (30 ns) after the falling edge of E clock - A7-A0 and D7-D0 are multiplexed on the same PC7-PC0 pins - PC7-PC0 are used as A7-A0 when E clock is low - PC7-PC0 are used as D7-D0 when E clock is high - A7-A0 are valid tAVM (86 ns) before the rising edge of E clock - Read data must be valid for tDSR (30 ns) before the falling edge of E clock so that 68HC11 can read it correctly - Read data must remain valid for tDHR (0-83ns) after the falling edge of E clock so - The falling edge of the AS signal is often used by the address latch to latch A7-A0 and A7-A0 remain valid for tAHL (26 ns) after AS falls - Multiplexed address delay is tMAD (83 ns) after the falling edge of E clock.
261
68HC11 Write Bus Cycle Timing Diagram
262
For the 2 MHz E clock and the 68HC11 Write bus cycle timing diagram, most
signals are identical to those in read bus cycle timing diagram except - the 68HC11 drives the data bus when E clock is high - the 68HC11 drives D7-D0 tDDW (128 ns) after the rising edge of the E clock until tDHW (33 ns) after the falling edge of the E clock
263
Adding an 8KB SRAM HM6264A to the 68HC11
- The HM6264A has 13 address pins to address each of the 8192 locations on the chip. - The HM6264A uses × 8 organization. - There are two chip enable signals: one (CS1) is active low, the other (CS2) is active high. - The active low signals WE and OE control the data in and out from the chip.
264
The HM6264A Read Cycle Timing Diagrams
There are four access times: 1. Address access time (tAA) 2. CS1 access time (tCO1) 3. CS2 access time (tCO2) 4. OE access time (tOE)
265
HM6264A Write Cycle Timing diagram
- Write data must be valid for tDW before WE goes high and remain valid for at least tDH after WE goes high - the pulse width of WE must be at least tWP
266
Interfacing the HM6264A-12 with the 2 MHz 68HC11
- Address space assigned to the HM6264A-12 is $4000-$5FFF - The 74F138, having a propagation delay of 8 ns, is used as the address decoder - The 74F373, having a propagation delay of 11.5 ns, is used as the low address latch - The WE signal is generated by NANDing the E clock and the inverting copy of R/W. - The NAND gate has a propagation delay of 15 ns. - The inverter that is used to invert the R/W signal has a propagation delay of 15 ns - The circuit connection is in Figure 5.17 of the next slide
268
Read Access Timing Analysis
- Timing verification is illustrated using an overlapped 68HC11 and HM6264A timing diagram in Figure 5.18. - The time when the data outputs from the HM6264A become valid is determined by the last asserted input signal -- CS1 in this example - A15-A8 are valid 94 ns before E rises - A7-A0 are latched into the 74F373 at 41.5 ns before the rising edge of E clock The lower address signals A7-A0 are latched by the AS signal The AS signal falls to 0.7 VDD at 53 ns before the rising edge of E clock The 74F373 has a propagation of 11.5 ns A7-A0 is valid at 41.5 ns ( ) before E rises - WE is high for a read cycle - E3 is the last asserted input signal for 74F138 and hence dictates the output valid time - O2 is asserted 8 ns after the rising edge of E clock - Data output from the HM6264A is valid 128 ns after the rising edge of the E clock or 94 ns ( ) before the rising edge of the E clock -- this satisfies the 68HC11 read data setup time (30 ns)
270
- The data hold time is the smaller one (8ns - 43ns) of the following two values:
1. The output hold time from address change (tOH = 10 ns). Address inputs become invalid 33 ns after the E clock falls. Therefore, it holds up to 43 ns after E falls. 2. Chip selection CS1 to output in high impedance time tHZ1: ns. - The data hold time requirement (0 to 83 ns) is violated. However, the data is held valid by the capacitance of the printed circuit board until other component drives the multiplexed address/data bus -- the earliest time is 138 ns after the falling edge of the E clock (or 53 ns before the rising edge of the next E clock cycle). - Both the read data setup and hold times are satisfied for the 68HC11. - The analysis about the PCB capacitance holds data valid follows:
271
Analysis on the duration of the data holding time by PCB capacitance
- Each data pin (D7-D0) and the PCB ground plane form a capacitor - After memory chip stops driving data pins, the charge across the capacitor leaks away via 1. input leakage current into the 68HC11 data pin (on the order of 10 mA) 2. input leakage current into the memory chip (on the order of 2 mA) 3. other leakage paths on the printed circuit board - Let DV = voltage change required for a data bus signal to change from 1 to 0 and is 2.5V for a 5V power supply Dt = the time that it takes the voltage across the capacitor to drop by DV I = total leakage current C = the capacitance on the PCB. C is 20 pF/ft for a typical PCB Assume the data bus signal path is 1 foot long Then Dt = CDV ÷ I = 20 pF × 2.5 V ÷ 12 mA = 4 ms Even if the leakage current is ten times larger, the PCB capacitance can still hold the data for up to 400 ns.
272
timing diagram in Figure 5.19.
Write Bus Cycle Timing Analysis - Timing verification is illustrated using an overlapped 68HC11 and HM6264A timing diagram in Figure 5.19. - The following timing parameters must be satisfied: 1. write cycle time (120 ns min.) 2. write pulse width (70 ns min.) 3. address setup time (0 ns min.) 4. address valid to end of write (85 ns min.) 5. data valid to end of write (50 ns min.) 6. data hold time (0 ns min.) 7. write recovery time (0 ns min.)
274
Calculation of Write Cycle Time
Write cycle time is the period during which the address inputs to the HM6264A are valid and is equal to the sum of the following parameters: - Address inputs (A12-A0) to the HM6264A valid time before the rising edge of the E clock (A7-A0 become valid later than A12-A8). - E clock rise time (20 ns at 2 MHz) - Pulse width when the E clock is high - E clock fall time - Address inputs hold time after the E clock falls (33 ns). (A12-A8 become invalid earlier than A7-A0). tWC = 41.5 ns + tr + PWEH + tf + tAH = ns (120 ns min. required)
275
Calculation of Write Pulse Width (WE)
Since the WE signal is the NAND function of the R/W and E clock, the width is equal to the high pulse width of the E clock and is equal to 222 ns (70 ns is required).
276
Calculation of Address Setup Time
The address setup time is measured from the moment that all address inputs are valid until the write enable signal goes low. A12-A8 become valid 94 ns before the rising edge of E clock and A7-A0 become valid 41.5 ns before the rising edge of the E clock. The WE signal becomes valid 15 ns after the rising edge of the E clock due to the propagation delay of the NAND gate. The address setup time is calculated as follows: tAS = 41.5 ns + tr + 15 ns = 76.5 ns The calculated value satisfies the requirement (0 ns min.).
277
Time from Address Valid till the End of Write
This parameter is measured from the moment when all address inputs are valid until the write enable signal becomes invalid. This parameter is the sum of the following terms: 1. the lead time from address signals become valid to the rising edge of the E clock (41.5 ns) 2. the E clock rise time (20 ns) 3. the E clock high pulse width (222 ns) 4. the E clock fall time (20 ns) 5. the propagation delay of the NAND gate (15 ns) tAW = 41.5 ns + 20 ns ns + 20 ns + 15 ns = ns (85 ns min. required)
278
Calculation of Write Data Setup Times
The write data setup time (tDW) is measured from the moment that the 68HC11 drives the data on the data bus until the WE signal goes high (50 ns min. required). tDW = PWEH - t DDW + delay of the NAND gate = 222 ns ns + 15 ns = 109 ns 222 ns E tDDW D7-D0 15 ns WE write data setup time
279
Write Data Hold Time (tDH)Calculation
- tDH is measured from the moment when WE becomes invalid until D7-D0 become invalid. tDH = tDHW - NAND delay = 33 ns - 15 ns = 18 ns (> 0 ns) E 15 ns WE tDH tDHW = 33 ns D7-D0
280
Calculation of Write Recovery Time
Write recovery time (tWR) is measured from the moment that the earliest chip select signal (CS1 in this example) becomes invalid until the moment that the address signals are invalid. The calculation of tWR is illustrated in Figure 5.23. All timing parameters have been verified to satisfy the requirements.
281
Chapter 6: Interrupts and Resets
The 68HC11 Microcontroller Han-Way Huang Minnesota State University, Mankato
282
Basics of Interrupts What is an interrupt? A special event that requires the CPU to stop normal program execution and perform some service related to the event. Examples of interrupts include I/O completion, timer time-out, illegal opcodes, arithmetic overflow, divide-by-0, etc. Functions of Interrupts - Coordinating I/O activities and preventing CPU from being tied up - Providing a graceful way to exit from errors - Reminding the CPU to perform routine tasks Interrupt Maskability - Interrupts that can be ignored by the CPU are called maskable interrupts. A maskable interrupt must be enabled before it can interrupt the CPU. An interrupt is enabled by setting an enable flag. - Interrupts that can’t be ignored by the CPU are called nonmaskable interrupts.
283
Interrupt priority The order in which the CPU will service interrupts when all of them occur at the same time. Interrupt Service The CPU provides service to an interrupt by executing a program called the interrupt service routine. A complete interrupt service cycle includes 1. Saving the program counter value in the stack 2. Saving the CPU status (including the CPU status register and some other registers) in the stack 3. Identifying the cause of interrupt 4. Resolving the starting address of the corresponding interrupt service routine 5. Executing the interrupt service routine 6. Restoring the CPU status and the program counter from the stack 7. Restarting the interrupted program
284
Interrupt Vector Starting address of the interrupt service routine Interrupt Vector Table A table where all interrupt vectors are stored. Methods of Determining Interrupt Vectors 1. Predefined locations (8051 approach) 2. Fetching the vector from a predefined memory location (68HC11) 3. Executing an interrupt acknowledge cycle to fetch a vector number in order to locate the interrupt vector (68000 and x86 families) Steps of Interrupt Programming Step 1. Initializing the interrupt vector table Step 2. Writing the interrupt service routine Step 3. Enabling the interrupt
285
The Overhead of Interrupts
Saving and restoring of CPU status and other registers. (68HC11 needs to save all CPU registers)
286
Resets - The initial values of some CPU registers, flip-flops, and the control registers in I/O interface chips must be established in order for the computer to function properly. - The reset mechanism establishes these initial conditions for the computer system. - There are at least two types of resets: power-on reset and manual reset. - The power-on reset establishes the initial values of registers and I/O control registers. - The manual reset without power-down allows the computer to get out of most error conditions if hardware doesn’t fail. - A reset is nonmaskable.
287
68HC11 Interrupts The 68HC11 supports 16 hardware interrupts and two software interrupts. Hardware interrupts include: SCI serial system SPI serial transfer Pulse accumulator input edge Pulse accumulator overflow Timer overflow Timer output compare 5 Timer output compare 4 Timer output compare 3 Timer output compare 2 Timer output compare 1 Timer input capture 3 Timer input capture 2 Timer input capture 1 Real time interrupt IRQ pin XIRQ pin Software interrupts: SWI instruction and illegal opcode. Both are nonmaskable.
288
The 68HC11 Interrupt-Handling Procedure
- Saving the CPU registers in the stack - Fetching the interrupt vector from a predefined memory location for the pending interrupt. - Resuming program execution from the fetched interrupt vector. The 68HC11 Interrupt Stacking Order
289
68HC11 Interrupt Vector Address and Priority
290
Example 6.1 The 68HC11 is executing the TAP instruction of the following program when
the IRQ interrupt occurs. List the stack contents immediately before the interrupt service routine is entered. Solution: 1. After line 1: [B] = $20 2. After line 2: [SP] = $FF 3. After line 3: [X] = $1000 4. After line 4: [A] = 0 5. After line 5: [Y] = $100 6. After line 6: [CCR] = $00 The Stack contents are shown in Figure 6.4 in next page.
292
Priority Structure of the 68HC11 Maskable Interrupts
- The priority of each 68HC11 interrupt source is fixed. - The user can promote one of the maskable interrupts to the highest priority among those maskable interrupts by programming the HPRIO register. - The selection of highest priority interrupt is shown in Table 6.2.
294
IRQ interrupt - can be masked by the I bit of the CCR register - is level-sensitive by default (asserted low) - IRQ interrupt can be configured to be falling edge-sensitive by setting the IRQE bit (bit 5) of the OPTION register to 1 within the first 64 E clock cycles after reset. - IRQ interrupt vector is shared by the IRQ pin interrupt and the I/O handshake subsystem XIRQ interrupt - can be masked by the X bit of the CCR register - the X bit can only be cleared during the first 64 E clock cycles after reset and cannot be cleared and reset after that - when an XIRQ interrupt occurs, all registers are saved in the stack and the X bit in the CCR register is set to 1 (not by the user program) to prevent further XIRQ interrupts. - XIRQ interrupt is often used to detect emergent situation because of its high priority. Illegal Opcode Trap - some of the opcode byte (s) combinations are not defined and hence are illegal instructions - can’t be masked
295
The Software Interrupt Instruction (SWI)
- CPU registers are saved in the stack like any other maskable instruction - cannot be masked by the I and X bits in the CCR register - often used to implement the breakpoint Low-Power Modes - A microcontroller is mainly used as the controller of an embedded product. - An embedded product is often powered by batteries. - A good microcontroller should consume as little power as possible. - The power consumption can’t be avoided during normal operation. - The power consumption of a microcontroller-based product should be reduced to minimal when the CPU is not performing useful works. - The 68HC11 provides two low-power modes: WAIT and STOP modes. The WAIT instruction - The 68HC11 is placed in a low power mode while keeping the oscillator running. - Upon the execution of this instruction, all CPU registers are saved in the stack. - The wait state can be exited only through an unmasked interrupt or reset. - This instruction can be used when the CPU has nothing to do but wait for the arrival of an interrupt.
296
The STOP instruction - When the S bit in the CCR register is 0, the STOP instruction places the CPU in the lowest power mode. - All clocks including the internal oscillator are stopped, causing all internal processing to be stopped. - Exit from the STOP mode can be accomplished by RESET, an XIRQ interrupt, or an unmasked IRQ interrupt. - When the XIRQ interrupt is used and the X bit in the CCR register is 1, then no XIRQ service routine is executed. The CPU continue to execute the instruction following the STOP instruction. Otherwise, the XIRQ service routine will be executed.
297
The 68HC11 Resets Four possible sources of resets: RESET pin, power-on reset, computer operating properly, and clock monitor failure. RESET pin Reset - This pin must be driven low for 8 E clock cycles in order to be detected. - This pin should be kept low when VDD is below its minimum operating level so that the contents of the EEPROM won’t be corrupted. - A low-voltage inhibit circuit that holds reset pin low whenever VDD is below its minimum operating level is required to protect against EEPROM corruption.
298
The Power-On Reset - The power-on reset occurs when a positive transition is detected on VDD. - The power-on circuitry provides a 4064-cycle time delay from the time of the first oscillator operation. - This reset should not be used to detect drops in power supply. The CPU after reset - After reset, the CPU fetches the reset vector from locations $FFFE and $FFFF ( $BFFE and $BFFF in the special test or bootstrap mode) during the first three cycles and begins instruction execution. - The stack pointer and other CPU registers are indeterminate after reset. - The X and I bits of the CCR register are set to mask any interrupt requests. - The S bit of the CCR register is set to 1 to disable the STOP mode. - All I/O control registers are initialized by reset.
299
Establishing the Mode of Operation
- The voltage levels on MODA and MODB pins are latched on the rising edge of the RESET signal to determine the mode of operation. - The upper four bits of the HPRIO register are also set by these mode select signals.
300
The Computer Operating Properly (COP) Watchdog Timer Reset
- The COP watchdog timer system is intended to detect software processing errors. - The COP circuit will not reset the CPU as long as the application software reset the COP timer before it times out. - If the COP timer times out, it is an indication that the application software is no longer being executed in the intended sequence and thus a system reset is initiated. - The COP system is enabled by clearing the NOCOP bit in the CONFIG register and is disabled by setting the same bit. After the change of the NOCOP bit, the CPU must be reset before the new status becomes effective. - The software COP reset is a two-step sequence. The first step is to write a $55 to the COPRST register and then write a $AA into the same register.
301
- The default COP time-out interval is 215 E cycles.
- The COP time out interval is programmable by setting the CR1 and CR0 bits of the OPTION register. - CR1 and CR0 together select a divide factor for E/215.
302
Clock Monitor Reset - The clock monitor circuit is based on an internal RC time delay. - If no clock (E clock) edges are detected within this RC time delay, the clock monitor can optionally generate a system reset (by asserting the RESET pin). - The clock monitor function is enabled/disabled by the CME bit (bit 3) of the OPTION register. - The RC time-out may vary from lot to lot and from part to part due to the IC fabrication process variation. - An E clock frequency lower than 10 KHz will be definitely detected as a clock monitor error and an E clock frequency higher than 200 KHz will not be detected as a clock monitor error. - The clock monitor is often used as a backup for the COP watchdog system because the COP system requires a clock signal to operate. - The second application of the clock monitor is to protect against unintentional execution of the STOP instruction.
303
Writing the Interrupt Service Routine
- In assembly language xxx_ISR … … RTI - In C language #pragma interrupt_handler xxx_ISR void xxx_ISR ( ) { } The statement “#pragma …” tells the C compiler to generate RTI instead of RTS as the last instruction of the function.
304
Set Up Interrupt Vector Table
- Use assembler directives to set up interrupt vector table - For example, the vector entry for IRQ interrupt can be set up as follows (in assembly language): ORG $FFF2 FDB IRQ_ISR where IRQ_ISR is the label of the first instruction in the service routine. In C language, #pragma abs_address:0xfff2 void (*interrupt_vectors [ ]) (void) = { IRQ_ISR } #pragma end_abs_address
305
- The complete interrupt vector table in C language is as follows :
#pragma abs_address:0xffd6 void (*interrupt_vectors [ ] (void) = { SCI_ISR, /* SCI interrupt service routine */ SPI_ISR, /* SPI */ PAI_ISR, /* PAI */ PAOV_ISR, /* PAOV */ TOF_ISR, /* TOF */ TOC5_ISR, /* TOC5 */ TOC4_ISR, /* TOC4 */ TOC3_ISR, /* TOC3 */ TOC2_ISR, /* TOC2 */ TOC1_ISR, /* TOC1 */ TIC3_ISR, /* TIC3 */ TIC2_ISR, /* TIC2 */ TIC1_ISR, /* TIC1 */ RTI_ISR, /* RTI */ IRQ_ISR, /* IRQ */ XIRQ_ISR, /* XIRQ */ SWI_ISR, /* SWI */ ILLOP_ISR, /* ILLOP */ COP_ISR, /* COP */ CLM_ISR, /* clock monitor */ _start /* reset */ }
306
The EVB & EVBU Interrupt Vector Jump Table
- The design of EVB and EVBU precludes the user program to write into interrupt vector table because the memory space for the interrupt table is in ROM. - The EVB and EVBU reserve 60 bytes ($00C4-$00FF) of the on-chip SRAM as an interrupt vector jump table. - Each entry of the vector jump table consists of three bytes. The first byte should be set to the opcode ($7E) of the JMP instruction, and the second and third bytes should be set to the starting address of the corresponding service routine. - Each entry (two bytes) of the default vector table of the 68HC11 should contain the address of the first byte of the corresponding entry in the interrupt vector jump table. - To set up interrupt vector jump table (use IRQ as an example) In assembly language, In C language, ORG $00EE void IRQ_ISR ( ); JMP IRQ_HND main ( ) { … *(unsigned char *)0xee = 0x7E; *(void (**)())0xef = IRQ_ISR; }
307
Interrupt Vector Jump Table for Demo Boards that Use Buffalo Monitor
308
Enable Interrupts - Clear the I bit of the CCR register will enable interrupt globally. - Most maskable interrupts have an enable bit that must be set to enable the individual interrupt in addition to setting the I bit. - For example, to enable the OC1 interrupt, we need to use the following statements: In assembly, In C language TMSK1 EQU $22 Use in-line assembly code asm (“cli”); or LDX #$1000 macro INTR_ON ( ); to enable interrupt BSET TMSK1,X $80 globally. CLI Use the statement TMSK1 |= 0x80 to enable OC1 interrupt locally.
309
Example 6. 2 Write a main program and an interrupt service routine
Example 6.2 Write a main program and an interrupt service routine. The main program will initialize a variable count to 5, enable the IRQ interrupt, and stay in a loop to check the value of count. When the value of count is 0, the program jump to the BUFFALO monitor. The IRQ pin is connected to some circuit that will generate an interrupt from time to time. Solution: * set up the interrupt vector jump table entry ORG $00EE JMP IRQ_ISR * the main program is in the following ORG $00 count rmb 1 ORG $C000 SEI ; disable all maskable interrupts LDS #$DFFF ; set up stack pointer for EVB LDAA #5 ; initialize the variable count to 100 STAA count ; “ CLI ; enable interrupt to the 68HC11 loop LDAA count BNE loop SWI ; jump to BUFFALO monitor IRQ_ISR DEC count RTI END
310
Example 6.3 Write a C program for the problem in Example 6.2.
Solution: #include <hc11.h> int count; main ( ) { count = 5; *(unsigned char *)0xee = 0x7E; *(void (**)())oxef = IRQ_ISR; INTR_ON ( ): while (count); INTR_OFF ( ); asm (“swi”); } #pragma interrupt_handler IRQ_ISR ( ) void IRQ_ISR ( ) count -= 1;
311
Chapter 7: Parallel I/O Ports
The 68HC11 Microcontroller Han-Way Huang Minnesota State University, Mankato
312
Basic I/O Concepts Peripheral devices Pieces of equipment that exchange data with a computer. Examples include switches, light-emitting diodes, cathode-ray tube screens, printers, modems, keyboards, and disk drives. Interface (peripheral) chip - A chip whose function is to synchronize data transfer between the CPU and I/O devices. - An interface may consist of control registers, status registers, data direction latches, and control circuitry. - An interface chip has pins that are connected to the CPU and I/O port pins that are connected to the I/O devices. - Each interface chip has a chip enable signal input or inputs, when asserted, allow the interface chip to react to the data transfer request. - Data transfer between an I/O device and the CPU can be proceeded bit-by-bit or in multiple bits.
314
I/O Schemes 1. Isolated I/O scheme - The microprocessor has dedicated instructions for I/O operations - The microprocessor has a separate address space for I/O devices 2. Memory-mapped I/O scheme - The microprocessor uses the same instruction set for I/O operations - The I/O devices and memory components are resident in the same memory space
315
I/O Transfer Synchronization
The role of an interface chip 1. Synchronizing data transfer between CPU and interface chip. 2. Synchronizing data transfer between interface chip and I/O device.
316
Synchronizing the Microprocessor and the Interface Chip
The polling method 1. for input -- the microprocessor checks a status bit of the interface chip to find out if the interface chip has received new data from the input device. 2. for output -- the microprocessor checks a status bit of the interface chip to find out if it can send new data to the interface chip. The interrupt-driven method 1. for input -- the interface chip interrupts the microprocessor whenever it has received new data from the input device. 2. for output -- the interface chip interrupts the microprocessor whenever it can accept new data from the microprocessor.
317
Synchronizing the Interface Chip and the I/O Devices
Brute-force method -- useful when the data timing is unimportant 1. for input -- nothing special is done. The microprocessor reads the interface chip and the interface chip returns the voltage levels on the input port pins to the microprocessor. 2. for output -- nothing special is done. The interface chip places the data that it received from the microprocessor directly on the output port pins. The strobe method -- a strobe signal is used to indicate that data are stable on I/O port pins 1. for input -- the interface chip latches the data into its data register using the strobe signal. 2. for output -- the interface chip places the data on port pins that it received from the microprocessor and asserts the strobe signal. The output device latches the data using the strobe signal. The handshake method -- used when timing is crucial - two handshake signals are used to synchronize the data transfer. One signal, call it H1, is asserted by the interface chip. The other signal, call it H2, is asserted by the I/O device. - two handshake modes are available -- pulse mode and interlocked mode.
318
Input Handshake Protocol
Step 1. The interface chip asserts (or pulses) H1 to indicate its intention to input data. Step 2. The input device puts data on the data port pins and also asserts (or pulses) the handshake signal H2. Step 3. The interface chip latches the data and de-asserts H1. After some delay, the input device also de-asserts H2.
319
Output Handshake Protocol
Step 1. The interface chip places data on the port pins and asserts (or pulses) H1 to indicate that it has valid data to be output. Step 2. The output device latches the data and asserts (or pulses) H2 to acknowledge the receipt of data. Step 3. The interface chip de-asserts H1 following the assertion of H2. The output device then de-asserts H2.
320
68HC11 Parallel I/O Overview
- The 68HC11A8 has 40 I/O pins that are arranged in five I/O ports. - All I/O pins serve multiple functions. - Ports A, B, and E with the exception of port A pin 7 are fixed-direction inputs or outputs. - Ports C and D are bi-directional I/O pins under the control of their associated data direction registers. - Port C, port B, the STRA pin, and the STRB pin are used for strobed and handshake parallel I/O, as well as for general-purpose I/O. Port Registers - To input, the 68HC11 reads from the port data register - To output, the 68HC11 writes into the port data register - All except port C have one data register: PORTA (at $1000) PORTB (at $1004) PORTC (at $1003) PORTCL (at $1005) PORTD (at $1008) PORTE (at $100A)
321
Fixed Direction I/O (ports A, B, and E)
To input from an input port, execute a load instruction with the port data register as the source operand. For example, the following instruction sequence reads a byte from port E: REGBAS equ $1000 ; I/O register block base address PORTE equ $0A ; offset of port E data register from REGBAS ldx #REGBAS ldaa PORTE,X To output a byte to an output port, write to the port data register directly. For example, the following instruction sequence outputs the value #$38 to port B: PORTB equ $04 ; offset of port B data register from REGBAS ldaa #$38 staa PORTB,X
322
Bi-directional I/O (Ports C and D)
- Each pin of ports C and D has an associated bit in a specific data register and another in a data direction register. - The primary direction of a pin is set by its associated bit in the data direction register. - When an output pin is read, the value at the input to the pin driver is returned. - The data direction registers are cleared by reset to configure all bi-directional I/O pins for input. - Before performing I/O operation to these two ports, the software should set up the data direction registers of these two ports.
323
Example 7.1 Write an instruction sequence to output the value $CD to port D.
Solution: REGBAS equ $1000 PORTD equ $08 DDRD equ $09 ldx #REGBAS ldaa #$3F ; set up the directions of port D pins staa DDRD,X ; “ ldaa #$CD ; output $CD to port D staa PORTD,X ; “ In C language, DDRD = 0x3F; /* configure port D for output */ PORTD = 0xCD; /* output data to port D */
324
Parallel I/O Control Register (PIOC)
- All strobed mode I/O and handshake I/O are controlled by this register
325
Strobe Input Port C - Strobe mode I/O is selected when the bit 4 of the PIOC register is set to 0 and port C becomes a strobe input port. - The bit 1 of the PIOC register selects the active edge of the STRA pin. - The active edge of the STRA signal latches the values of the port C pins into the PORTCL register. - Reading the PORTC register returns the current values on the port C pins. - Reading the PORTCL register returns the contents of the latched PORTCL. - When enabled, the active edge of the STRA signal will generate an interrupt to the 68HC11.
326
Strobed Output Port B The strobe signal STRB is pulsed for two E clock cycles each time there is a write to port B.
327
Port C Input Handshake Protocol
- STRA is a latch command asserted by an input device (active edge is rising in the figure). - STRB is a ready output driven by the 68HC11 (active high in the figure). - When ready for accepting new data, the 68HC11 asserts (or pulses) STRB pin. - The input device places data on input port pins and asserts the STRA signal. The active edge of STRA latches data into the PORTCL register, sets the STAF flag in PIOC register and de-asserts the STRB signal. The de-assertion of STRB inhibits external device from strobing new data into port C. - Not until the 68HC11 reads PORTCL, new data cannot be applied on port C pins.
328
Port C Output Handshake Protocol
- STRA is an acknowledge input (driven by the external device) - STRB is a ready output (driven by the 68HC11) - In this figure, the active edge of STRA is rising and the active level of STRB is high. - The 68HC11 writes data into PORTCL and then asserts STRB to indicates there are valid data on port C pins - The external device then asserts STRA to acknowledge the receipt of data which will then cause STRB to be de-asserted and the STAF flag to be set. - After the de-assertion of STRB, STRA is also de-asserted.
329
Simple Input Devices: switches, analog-to-digital converter, keyboards, etc.
Example 6.2 Connect an 8-DIP switch to port E of the 68HC11 and read a byte from it. Solution: REGBAS equ $1000 PORTE equ $0A LDX #REGBAS LDAA PORTE,X . In C #include <stdio.h> main () { char xx; … xx = PORTE; }
330
Interfacing Parallel Ports to the Keyboard
- A keyboard is arranged as an array of switches, which can be mechanical, membrane, capacitive, or Hall-effect in construction. - In mechanical switches, two metal contacts are brought together to complete a circuit. - Mechanical switches have a problem called contact bounce. A series of pulses are generated because the switch contacts do not come to rest immediately. - The response time of the switch is several orders of magnitude slower than that of a computer. - A debouncing process is needed to solve the contact bounce problem. Keyboard input procedure Step 1. Keyboard scanning to find out which key has been pressed. Step 2. Key debouncing to make sure a key was pressed. Step 3. Table lookup to find the ASCII code of the key that has been pressed.
331
Keyboard Scanning Techniques
- A keyboard with more than a few keys is often arranged as a matrix of switches that uses two decoding and selecting devices to determine which key was pressed. An example of 64-key keyboard is shown in Figure 7.13. - The MC14051 is an analog multiplexor and is used to select the row. - The 74LS138 selects the column. - PC5-PC3 select the row and PC2-PC0 select the column to be scanned. - X7-X0 are pulled up to 5 V by the pull-up resistors. - The decoder 74LS138 outputs are asserted low. - A pressed key will send a low to the X output to the port C pin 7 and hence can be detected.
332
Keyboard Scanning Algorithm
The basic algorithm is shown in Figure 7.14. Since we use port C pin 0 to 2 to select the column and pin 3 to 5 to select the row, we can use the INC PORTC,X instruction to move to the next key. This is done in the program on next page.
333
The program to scan the keyboard in Figure 7.13
Pins PC7 should be configured for input while PC5-PC0 should be configured for output. REGBAS equ $1000 ; base address of I/O register block DDRC equ $07 ; offset of port C data direction register from REGBAS KEYBD equ $03 ; port C is used as keyboard ldaa #$3F ; set up port C pin directions staa DDRC,X ; “ resetc clr KEYBD,X ; start from row 0 and column 0 scan brclr KEYBD,X $80 debnce ; detect a pressed key brset KEYBD,X $3F resetc ; need to reset the row and column count inc KEYBD,X ; check the next row or column bra scan end
334
Keyboard Debouncing The signal output from the key switch falls and rises a few times within a period of 5 ms as the contact bounces. A human being cannot press and release a key in less than 20 ms, a debouncer will recognize that the switch is closed/open after the voltage is low/high for 10 ms. - Both hardware and software debouncing techniques are available. Hardware debouncing techniques 1. Set-reset flip-flops 2. Non-inverting CMOS gates with high-input impedance 3. Integrating debouncers
335
Software Debouncing Techniques
The easiest software debouncing technique is the wait-and-see technique. After detecting a key switch has been pressed, this technique simply wait for 10 ms and recheck the same key. REGBAS equ $1000 ; base address of the I/O register block KEYBD equ $03 ; offset of PORTC from REGBAS TEN_MS equ 2000 ; loop count for creating 10 ms delay debnce ldy #REGBAS ldx #TEN_MS wait10ms nop ; wait for 10 ms nop ; “ dex ; “ bne wait10ms ; “ ldaa KEYBD,X ; recheck the pressed key bmi scan ; rescan the keyboard if the key is not pressed jmp getcode ; the key switch is indeed pressed end
336
ASCII Code Table Lookup
After the key has been debounced, the keyboard should look up the ASCII table and send the corresponding ASCII code to the CPU. keytab FCC “ ” FCC ... . FCC … getcode LDX #REGBAS LDAB KEYBD,X CLRA ANDB #$3f ; compute the address of the ASCII code of the pressed ADDD #keytab ; key and leave it in X XGDX ; “ LDAA 0,X ; get the ASCII code END
337
Example 7. 3 Write a C routine to read a character from the keyboard
Example 7.3 Write a C routine to read a character from the keyboard. This routine will perform keyboard scanning, debouncing, and ASCII code lookup and return the ASCII code to the caller. Solution: char get_ascii (); void delay10ms (); char tab[64] = {….}; /* ASCII code table */ char read_kb () { char scanned, pressed; scanned = 0; PORTC = 0; while (1) { while (!scanned) { if (PORTC & 0X80) {/* If key is not pressed */ if ((PORTC & 0x3F) == 0x3F) /* read row 7 and column 7 */ PORTC = 0x00; /* reset to row 0 column 0 */ else PORTC ++; /* scan the next key */ }
338
else scanned = 1; /* detect a pressed key */ } delay10ms (); /* wait for 10 ms to recheck the same key */ if (!(PORTC &0x80)) return (get_ascii ()); /* the key is really pressed */ else { scanned = 0; /* the following subroutine use OC2 function to create a 10 ms delay */ void delay10ms () { TFLG1 = 0x40; /* clear OC2F */ TOC2 = TCNT ; /* start an OC2 operation to create 10 ms delay */ while (!(TFLG1 & 0x40)); /* wait until 10 ms is over */ char get_ascii () char i; i = PORTC & 0x3F; /* obtain the row and column number for table lookup */ return tab[i];
339
Interfacing 68HC11 with a Keypad
- People are using 12- to 24-key keypad for many applications. - An example of 16-key membrane keypad is shown in Figure The row selection is shown in Table 7.4.
340
Example 7.4 Write a C program to read a character from the keypad shown in Figure 7.16.
This program will perform keypad scanning, debouncing, and ASCII code lookup. Solution: void wait_10ms ( ); char get_key ( ) { DDRC = 0xF0; /* configure PC7-PC4 for output and PC3-PC0 for input */ while (1){ PORTC = 0xE0; /* prepare to scan the row controlled by PC4 */ if (!(PORTC & 0x01)) { wait_10ms ( ): if (!(PORTC & 0x01)) return 0x30; /* return ASCII code of 0 */ } if (!(PORTC & 0X02)) { if (!(PORTC & 0x02)) return 0x31; /* return ASCII code of 1 */
341
return 0x32; /* return ASCII code of 2 */ } if (!(PORTC & 0X08)) {
wait_10ms ( ): if (!(PORTC & 0x04)) return 0x32; /* return ASCII code of 2 */ } if (!(PORTC & 0X08)) { if (!(PORTC & 0x08)) return 0x33; /* return ASCII code of 3 */ PORTC = 0xD0; /* set PC5 to low to scan second row */ if (!(PORTC & 0X01)) { if (!(PORTC & 0x01)) return 0x34; /* return ASCII code of 4 */ if (!(PORTC & 0X02)) { if (!(PORTC & 0x02)) return 0x35; /* return ASCII code of 5 */
342
return 0x36; /* return ASCII code of 6 */ } if (!(PORTC & 0X08)) {
wait_10ms ( ): if (!(PORTC & 0x04)) return 0x36; /* return ASCII code of 6 */ } if (!(PORTC & 0X08)) { if (!(PORTC & 0x08)) return 0x37; /* return ASCII code of 7 */ PORTC = 0xB0; /* set PC6 to low to scan the third row */ if (!(PORTC & 0X01)) { if (!(PORTC & 0x01)) return 0x38; /* return ASCII code of 8 */ if (!(PORTC & 0X02)) { if (!(PORTC & 0x02)) return 0x39; /* return ASCII code of 8 */
343
if (!(PORTC & 0X04)) { wait_10ms ( ): if (!(PORTC & 0x04)) return 0x41; /* return ASCII code of A */ } if (!(PORTC & 0X08)) { if (!(PORTC & 0x08)) return 0x42; /* return ASCII code of B */ PORTC = 0x70; /* set PC7 to low to scan the fourth row */ if (!(PORTC & 0X01)) { if (!(PORTC & 0x01)) return 0x43; /* return ASCII code of C */ if (!(PORTC & 0X02)) { if (!(PORTC & 0x02)) return 0x44; /* return ASCII code of D */
344
if (!(PORTC & 0X04)) { wait_10ms ( ): if (!(PORTC & 0x04)) return 0x45; /* return ASCII code of E */ } if (!(PORTC & 0X08)) { if (!(PORTC & 0x08)) return 0x46; /* return ASCII code of F */
345
Simple Output Devices A Single Light-Emitting Diode (LED)
- An LED will illuminate when it is forward biased and has enough current flowing through it. - The current required to light an LED brightly ranges from a few mA to more than ten mA. - The voltage drop across a forward-biased LED ranges from 1.7V to more than 2 V. - The voltage drop across the LED with 10 mA current flowing through it is assumed to be 1.7V in this chapter. - In Figure 7.17, the 74HC04 has an high output 4.9V and a low output 0.1V. A high applied to the input of 74HC04 will light the LED. - The 68HC11 does not have the current capability to drive the LED. A chip like the 74HC04 is needed to provide the required current capability.
346
Example 7.5 Use the 68HC11 port B pins PB3, PB2, PB1, and PB0 to drive blue, green, red,
and yellow LEDs. Light the blue LED for 2 s, then the green LED for 4 s, then the red LED for 8 s, and finally the yellow LED for 16 seconds. Repeat this operation forever. Solution: The circuit is shown in Figure 7.18. - To light the blue LED, output $08 to port B. - To light the green LED, output $04 to port B. - To light the red LED, output $02 to port B. - To light the yellow LED, output $01 to port B. - The required time can be created by repeating the following delay loop for 20, 40, 80, and 160 times: ldx #20000 tenth_s nop nop dex bne tenth_s
347
regbas equ $1000 portb equ $04 org $00 lt_tab fcb 20,$08,40,$04,80,$02,160,$01 org $C000 loop ldy #lt_tab next ldab 0,Y ; get the repetition count ldaa 1,Y ; get the light pattern iny ldx #regbas staa portb,X pt_lp ldx #20000 tenth_s nop nop dex bne tenth_s decb bne pt_lp cpy #lt_tab+8 ; reach the table end? bne next bra loop end The Program:
348
The Seven-Segment Display
- A seven-segment display consists of seven LED segments (a, b, c, d, e, f, and g). - A seven-segment display can be found in common-cathode or common-anode type.
349
Driving the seven-segment displays with the 68HC11 parallel ports
- A segment requires 10 mA to be lighted brightly. - A buffer chip like 74ALS244 can be used to boost the 68HC11’s current capability. - The 74ALS244 has a 3V output when it is high and a 0.2V output when it is low. - For the circuit shown in Figure 7.20, a segment will have a current of 13 mA when it is lighted. - To display a BCD digit, an appropriate value must be written to the port register. The value is listed in Table 7.6. - When multiple digits are to be displayed, the multiplexing technique is often used to reduce the number of port pins required.
350
Using Multiplexing Method to Display Multiple BCD Digits
- The 2N2222 can sink mA of current and can handle the maximum current (91 mA) flowing into the collector from the common cathode. - To light seven-segment display #5, send out the segment pattern to port B and output the value $20 to port D. - To light display #4, send out the segment pattern to port B and output the value $10 to port D. - etc.
351
How the Multiplexing Method Works
- To light the display #5,…,#0, the corresponding value to be written into port D are $20, $10, $08, $04, $02, and $01 respectively. For example, the following instruction sequence will display the digit 6 on the display #3: REGBAS equ $1000 ; base address of I/O register block PORTB equ $04 ; offset of PORTB from REGBAS PORTD equ $08 ; offset of PORTD from REGBAS DDRD equ $09 ; offset of DDRD from REGBAS six equ $7D ; segment pattern of 6 third equ $08 ; value to allow display #3 to light output equ $3F org $C000 ldx #REGBAS ldaa #output ; configure port D for output staa ddrd,X ; “ ldaa #six ; send the segment pattern of 6 to port B staa PORTB,X ; “ ldaa #third ; select display #3 to be lighted staa PORTD,X ; “ end
352
In C language, DDRD = 0x3F; PORTB = 0x5F; PORTD = 0x08; Principle of Multiplexing multiple displays: Persistence of vision. As long as one and only one display is lighted and then turned off for a short period of time within one second all digits will appear to be lighted simultaneously.
353
Example 7.6 Display 123456 on the six seven-segment displays shown in Figure 7.21.
Solution: The first step is to build a table of segment patterns (to port B) and display selection values (to port D). This Table can be set up by the following assembler directives: org $00 display FCB $06,$20 FCB $5B,$10 FCB $4F,$08 FCB $66,$04 FCB $6D,$02 FCB $7D,$01
354
Algorithm for Displaying Multiple Digits Using Time Multiplexing Technique
355
regbas equ $1000 PORTB equ $04 PORTD equ $08 DDRD equ $09 output equ $3F org $00 display fcb $06,$20 fcb $5B,$10 fcb $4F,$08 fcb $66,$04 fcb $6D,$02 fcb $7D,$01 org $C000 ldx #regbas ldaa #output staa ddrd,X forever ldy #display next ldaa 0,Y staa PORTB,X ldaa 1,Y staa PORTD,X iny ldx #200 ; loop to delay for 1 ms again nop ; “ nop ; “ dex ; “ bne again ; “ cpy #display+12 ; end of table? beq forever bra next ; light the next display end
356
C language version #include <hc11.h> char display [6][2] = {{0x30, 0x20}, {0x6D, 0x10}, {0x79, 0x08}, {0x33, 0x04}, {0x5B, 0x02}, {0x5F, 0x01}}; void delay_1ms ( ); main ( ) { int i; while (1) { for (i = 0; i < 6; i++) { PORTB = display[i][0]; PORTD = display[i][1]; delay_1ms ( ); } void delay_1ms ( ) TFLG1 = 0x40; /* clear OC2F flag */ TOC2 = TCNT ; while (!(TFLG1 & 0x40));
357
Liquid Crystal Displays (LCD)
- An LCD must be activated in order to be lighted. - The LCD type of display that is most common today allows light to pass through it when it is activated. - The LCD displays are organized as segments for displaying digits or characters. - Activation of a segment requires a low-frequency bipolar excitation voltage of Hz. - When a voltage is placed across the segment, an electric field is set up which aligns the crystals in the liquid. This alignment allows the light to pass through. - A segment which is not aligned will reflect the light. - The LCD has very high contrast and can be seen extremely well in very bright light. - The main problem of LCD is that it requires light source in dim or dark area because it produces no light of its own.
358
Optrex DMC LCD Kit - 4 20 LCD kit that uses Hitachi HD44780 as its display controller. - Can be used with all demo boards manufactured by Axiom Manufacturing. - DB7-DB0 are used to exchange data with the microcontroller. - E pin is the enable signal to the LCD. - RS selects the signal to be accessed. - In CMD-11A8, the address $B5F0 is assigned to the control register and the address $B5F1 is assigned to data register.
359
The Setup of the DMC-20434 LCD kit
- All LCD kits need to be set up before they can be used. - To set up the LCD kit, we need to write appropriate commands into the command register. - Commands for the LCD kit are listed in table 7.8.
360
Program to initialize the DMC-20434 LCD kit
lcd_cmd EQU $B5F0 lcd_init PSHX LDX #lcd_cmd BRSET 0,X $80 * LDAA #$3C STAA 0,X ; set 4 20 display BRSET 0,X $80 * ; wait until LCD is ready LDAA #$01 STAA 0,X ; clear display and move cursor to home LDAA #$0F STAA 0,X ; turn on display LDAA #$06 STAA 0,X ; set cursor increment, shift off LDAA #$14 STAA 0,X ; set cursor shift right
361
LDAA #$02 STAA 0,X BRSET 0,X $80 * PULX RTS In C language, we need to add the following two lines to the hc11.h file in the ImageCraft C compiler so that we can use LCD_CMD and LCD_DAT to access the registers of the LCD kit: #define LCD_CMD *(unsigned char volatile *)(0xB5F0) #define LCD_DAT *(unsigned char volatile *)(0xB5F1)
362
The C language version of the LCD kit initialization function:
void lcd_init ( ) { while (LCD_CMD & 0x80); /* wait while LCD is busy */ LCD_CMD = 0x3C; /* set 4 20 display */ while (LCD_CMD & 0x80); LCD_CMD = 0x01; /* clear display and set cursor to home */ LCD_CMD = 0x0F; /* display cursor, and cursor blink on */ LCD_CMD = 0x06; /* set cursor increment, shift off */ LCD_CMD = 0x14; /* set cursor shift right */ LCD_CMD = 0x02; /* move cursor to home */ }
363
Output Data on the DMC-20434 LCD Kit
- The DMC does not display alphanumeric data in sequential order due to its internal line wrapping. - Without line adjustment, the LCD kit will display the first 20 characters in the first line, the second 20 characters in the third line, the third 20 characters in the second line, and the fourth 20 characters in the fourth line. - The following subroutine outputs one character to the LCD kit and performs line adjustment: LCD_CMD EQU $B5F0 ; LCD command register address LCD_DAT EQU $B5F1 ; LCD data register address lcdputch2lcd STAA LCD_DAT ; output 1 character to the LCD kit lcdlp LDAA LCD_CMD ; read next character position BMI lcdlp ; test if busy and wait if true CMPA #$13 ; test for line 1 wrap BEQ lcd1 ; if match, correct line wrap CMPA #$53 ; test for line 2 wrap BEQ lcd2 ; if match, correct line wrap CMPA #$27 ; test for line 3 wrap BEQ lcd3 ; if match , correct line wrap RTS
364
* correct line 1 wrap from line 3 to line 2
lcd1 LDAA #$40 ; load line 2 start position ORAA #$80 ; set command bit STAA LCD_CMD ; write to display RTS * correct line 2 wrap from line 4 to line 3 lcd2 LDAA #$14 ; load line 3 start position * correct line 3 wrap from line 2 to line 4 lcd3 LDAA #$54 ; load line 4 start position * this is the program to output a string pointed by Y and terminated by a NULL character putstr2lcd LDAA 0,Y BEQ done JSR putch2lcd INY BRA putstr2lcd done RTS
365
C Language Version of LCD Output Functions
void putch2lcd (char ch) { LCD_DAT = ch; while (LCD_CMD & 0x80); if (LCD_CMD == 0x13) { LCD_CMD = 0x40 || 0x80; /* correct line 1 wrap from line 3 to line 2 */ } if (LCD_CMD == 0x53) { /* correct line 2 wrap from line 4 to line 3 */ LCD_CMD = 0x14 || 0x80; if (LCD_CMD == 0x27) { /* correct line 3 wrap from line 2 to line 4 */ LCD_CMD = 0x54 || 0x80;
366
void putstr2lcd (char *ptr)
{ while (*ptr) { putch2lcd (*ptr); ptr++; }
367
Digital to Analog Converter
- D/A conversion is required when a digital code must be converted to an analog signal. - A general D/A converter consists of a network of precision resistors, input switches, and level shifters that activate the switches that convert a digital code to an analog voltage or current. - D/A converters have a fixed or variable reference voltage , which can be generated either internally or externally. - The reference voltage determines the switching threshold of the precision switches that form the impedance network that controls the value of the output signal. - Fixed reference D/A converts have current or voltage output values that are proportionally to the digital input. - Multiplying D/A converters produce an output signal that is proportional to the product of a varying reference level and a digital code.
368
Interfacing to the D/A Converter Using the 68HC11 Output Ports
- The AD557 is an 8-bit D/A converter that produces an output voltage proportional to the digital input code. - The AD557 can operate with a +5V supply. - Output range is 0V to +2.55V when operated as shown in Figure 6.23. - Vout = (decimal equivalent of input code) × 0.01 V
369
AD557 Input latch operation
- Data input can be latched or transparent without being latched. - The CS and CE signals together control the latching of input data. The AD557 can be used to generate analog waveforms as illustrated in the next example. It takes 1 ms to complete the conversion of one sample.
370
Example 7.8 Use the 68HC11 port B and an AD557 to generate a sawtooth waveform.
Solution: The circuit connection is shown in Figure 7.28. The program is in the following: regbas equ $1000 PORTB equ $04 org $C000 ldx #regbas clr PORTB,X again inc PORTB,X bra again end In C language, #include <hc11.h> main ( ) { PORTB = 0; while (1) { POTB ++; }
371
Example 7. 9 Using the circuit in Figure 7
Example 7.9 Using the circuit in Figure 7.28 to generate the waveform shown in Figure 7.29. Solution: REGBAS EQU $1000 PORTB EQU $04 ORG $C000 LDY #REGBAS start CLR PORTB,Y ; output 0V JSR delay_1ms ; wait for 1 ms LDAA #100 ; output 1 V JSR delay_1ms LDAA #200 ; output 2 V BRA start delay_1ms LDX #200 again NOP NOP DEX BNE again RTS
372
The C Program to Generate the waveform shown in Figure 7.29.
#include <hc11.h> void delay_1ms ( ); main ( ) { while (1) { PORTB = 0; /* output 0 V */ delay_1ms ( ); /* wait for 1 ms */ PORTB = 100; /* output 1 V */ delay_1ms ( ); PORTB = 200; /* output 2 V */ } return 0; void delay_1ms ( ) TFLG1 = 0x40; /* clear OC2F flag */ TOC2 = TCNT ; /* start an OC2 operation with 1 ms delay */ While (!(TFLG1 & 0x40)); /* wait for 1 ms */
373
Centronics Printer Interface
Signals: D7-D1: data pins. BUSY: printer busy signal (output from printer) PE: printer error (asserted high). SLCT: printer on-line (output from printer) DATA STROBE: An input to the printer. Data is latched into the printer by this signal. ACKNLG: Printer acknowledges the receipt of data using this signal. Centronics printer timing requirements
374
Interface a Centronics printer to the 68HC11 port C
Configure port C as follows: 1. Set port C for output, i.e., write the value $FF into DDRC. 2. Program PIOC to set the following parameters: pulse mode handshake output no STRA interrupt falling edge of STRA as the active edge STRB is active low normal port C pins Write the value $1C into PIOC. The timing requirements are satisfied : Data setup time is period of E ÷ 2 - tPWD + tDEB = 325 ns > 50 ns (required) Data hold time (with respect to DATA STROBE) is at least 2 E clock cycles (= 1 ms at 2 MHz). This is greater than the 100 ns requirement.
375
For the following subroutines, use these constant declarations:
regbas equ $ ; base address of I/O register block DDRC equ $07 ; offset of DDRC from regbas PIOC equ $02 ; offset of PIOC from regbas PORTCL equ $05 ; offset of PORTCL from regbas PORTE equ $0A ; offset of PORTE from regbas output equ $FF ; value to set port C as an output port Write a routine to initialize the Centronics printer in Figure 7.32. prt_init psha pshx ldx #regbas brset PORTE,X $40 * ; don’t go if printer error brclr PORTE,X $80 * ; don’t go if printer not on-line ldaa #output ; configure port C for output staa DDRC,X ; “ ldaa #$1C ; initialize PIOC staa PIOC,X ; “ pulx pula rts
376
Write subroutines to print a character and a string using polling method
The subroutine prt_char outputs the character in A. prt_char BRCLR PIOC,X $80 * ; wait until the STAF bit is set to 1 STAA PORTCL,X ; print the character in A RTS The subroutine prt_str outputs the string pointed to by index register Y. The index register X contains the base address of the I/O register block. The string is terminated by a NULL character. prt_str PSHA next LDAA 0,Y ; get the next character BEQ quit ; is this the end of the string? JSR prt_char ; print the current character INY ; move the string pointer BRA next quit PULA
377
Write subroutines to print a character and a string using interrupt-driven method
prt_str1: enable the interrupt and then wait for the printer interrupt until the whole string is printed. prt_char1: print the character in A and also move the string pointer Y. Set up the interrupt vector table: ORG $FFF2 FDB prt_char1 prt_str1 BSET PIOC,X $40 ; enable STRA interrupt CLI ; “ again LDAA 0,Y ; wait for printer interrupt BNE again ; is this end of the string BCLR PIOC,X $40 ; disable STRA interrupt SEI ; disable all interrupt RTS prt_char1 STAA PORTCL,X ; print the character INY ; move the string pointer TSX STY 5,X ; also update the saved version of Y RTI
378
C Language Version of the Printer Routines
void prt_init ( ) { while ((PORTE & 0x40) || (!(PORTE & 0x80))); DDRC = 0xFF; PIOC = 0x1C; } /* polling method version */ void prt_char (char ch) while (!(PIOC & 0x80))); PORTCL = ch; void prt_str (char *ptr) while(*ptr) { prt_char (*ptr); ptr++;
379
Interrupt-Driven Method Printer Routines
- The subroutine prti_str enable printer interrupt and then stay in a wait loop to wait for printer interrupt. - The printer interrupt service routine (prti_char) outputs the character pointed by Y. - The base address of I/O register block is passed in X. - Interrupt vector table entry for STRA interrupt must be set up properly. prti_str BSET PIOC,X $40 ; enable STRA interrupt CLI again LDAA 0,Y ; wait for interrupt BNE again ; reach the end of the string? BCLR PIOC,X $40 ; disable STRA interrupt SEI RTS prti_char STAA PORTCL,X INY TSX STY 5,X ; update the Y value in the stack RTI
380
C Language Version of the Interrupt-Driven Printer Functions
- The pointer to the string to be output is defined as a global variable char *ptr; void prti_str ( ) { PIOC |= 0x40; /* enable STRA interrupt */ INTR_ON ( ); while (*ptr); /* wait for interrupt */ PIOC &= 0xBF; /* disable STRA interrupt */ INTR_OFF ( ); } /* STRA interrupt service routine */ #pragma interrupt_handler prti_char ( ) void prti_char () PORTCL = *ptr++;
381
The i8255 Programmable Peripheral Interface (PPI)
- In expanded mode, both port B and port C are not available for I/O functions. - A possible solution to this problem is to add an parallel interface chip such as i8255 to the 68HC11. - The Intel i8255 has three 8-bit ports: port A, B, and C. - Signals A1-A0 select the registers within the PPI as follows:
382
Operation of the i8255 - When the msb is 1, the control register defines the operation mode. Otherwise it sets or clears a selected bit. - i8255 has three modes: mode 0, mode 1, and mode 2.
383
Mode 0 (basic input and output)
- There are two 8-bit ports and two 4-bit ports. - Any port can be input or output. - Outputs are latched. - Inputs are not latched. - 16 different input/output configurations are possible in this mode. - No handshake is required. - Data are simply written into or read from a specified port.
384
Mode 1 (Strobed Input/Output)
- Port A and B use the lines of port C to generate or accept “handshake” signals required in this mode. - Port A, B, and C are divided into two groups. Each group consists of one 8-bit port and one 4-bit control/data port. The 8-bit data port can be input or output. The 4-bit port is used for control and status of the 8-bit data port. - Port C pin functions are shown in Table 7.10
385
Mode 1 Input Timing - When the input buffer is not full, the input device places data on input port pins and pulses the STB signal. - The falling edge of STB latches data into the input port data register and sets the input buffer full flip-flop. - The PPI asserts the interrupt request signal INTR and the CPU reads the data in the interrupt service routine. After the data is read, the input buffer full flag is cleared.
386
Mode 1 Output Timing - When the output buffer is not full and the CPU is interrupted, the CPU writes data to the i8255. For a delay of tWB after the rising edge of the WR signal, data appears on i8255 port pins. - The OBF signal is asserted by the write operation. The falling edge of the OBF latches data into the output device and the output device asserts the ACK signal to acknowledge the receipt of data.
387
Mode 2 (Strobed bi-directional bus I/O)
- This mode provides a means for communication with peripheral device or structure on a single 8-bit bus for both transmitting and receiving data. - Only port A is used. Port A becomes an 8-bit bi-directional bus port whereas 5 bits (PC3-PC7) of port C are used as control port. - Functions of port C pins are shown in Table 7.11.
388
Mode 2 Signal Transactions
389
Mode 2 Data Output Polling approach - The software tests the OBF signal to determine whether the output buffer is empty. If it is, the data is written out. - The external circuitry also monitors OBF signal to decide if the microprocessor has sent new data to the i8255. As soon as OBF is detected to be low, the output device sends back the ACK signal to remove data from the output buffer. - The low level of the ACK signal causes the OBF signal to go high and enables the three- state output buffer so that data can be read. Interrupt-driven approach - The software first enables the i8255 interrupt. When the output buffer is empty, it generates an interrupt to the CPU. The CPU outputs a byte to the i8255 in the interrupt service routine. - The byte written to the i8255 causes the OBF signal to go low, which informs the output device to latch data. - The output device asserts the ACK signal to acknowledge the receipt of data, which causes the OBF signal to become inactive.
390
Mode 2 Data Input Polling approach - The software tests the IBF signal to determine if data have been strobed into the buffer. - If IBF is low, the input device places data on port A pins and asserts the STB signal to strobe data into the input buffer. After this, the IBF signal goes high. - When the user program detects that the IBF signal is high, it reads the data from the input buffer. The IBF signal goes low after the data is read. Interrupt-driven approach - The software first enables the i8255 to interrupt the CPU. - When the IBF is low, the input device places data on the port pins and asserts the STB signal to strobe data into the input buffer. - After data are strobed into the input buffer, the IBF signal is asserted and an interrupt is generated. - The CPU reads the data from the input buffer when executing the interrupt service routine. - Reading data brings the IBF signal to low, which further causes the STB signal to go high.
391
The i8255 on the CMD-11A8 Demo board
- Four bytes are assigned to the i8255 on the CMD-11A8 demo board: 1. $B5F4: port A register 2. $B5F5: port B register 3. $B5F6: port C register 4. $B5F7: control register Example 7.12 Configure the i8255 on the CMD-11A8 to operate in mode 0: Port A for input Port B for output Upper port C for input Lower port C for output Solution: Bit 7: set to 1 to choose mode select LDX $B5F4 Bit 6 & 5: set to 0 to configure port A to mode 0 LDAA #$98 Bit 4: set to 1 to configure port A for input STAA 3,X Bit 3: set to 1 to configure upper port C for input Bit 2: set to 0 to configure port B to mode 0 Bit 1: set to 0 to configure port B for output Bit 0: set to 0 to configure lower port C for output
392
Example 7.14 Use the auxiliary port of the CMD-11A8 demo board to drive 4 seven-segment
displays. Use port A of the i8255 to drive the segment pattern and use the upper four bits of port B of the i8255 to drive the display select signals. Write a program to display 1999. Solution: - The circuit is shown in Figure7.39. - Configure i8255 to mode 0. - Configure port A and B for output. - Write the value $80 into the register.
393
PPI_BAS EQU $B5F4 ; i8255 port A data register address
INIT_VAL EQU $80 ; value to initialize i8255 PA EQU 0 ; offset of port A from PPI_BAS PB EQU 1 ; offset of port B from PPI_BAS ORG $2000 LDAA #INIT_VAL forever LDY #distab next LDX #PPI_BAS LDAA 0,Y STAA PA,X ; send out the digit pattern LDAB 1,Y STAA PB,X ; send out the select value INY LDX #200 ; 1 ms delay again NOP ; “ NOP ; “ DEX ; “ BNE again ; “ CPY #distab+8 BEQ forever BRA next
394
distab FCB $30,$08 FCB $7B,$04 FCB $7B,$02 FCB $7B,$01 In C language, we need to add the following statements to the hc11.h file so that we can use labels to reference i8255 registers: #define PPI_PA *(unsigned char volatile *)(0xB5F4) #define PPI_PB *(unsigned char volatile *)(0xB5F5) #define PPI_PC *(unsigned char volatile *)(0xB5F6) #define PPI_CMD *(unsigned char volatile *)(0xB5F7)
395
#include <hc11.h> char distab [4][2] = {{0x30, 0x08}, {0x7B, 0x04}, {ox7B, 0x02}, {0x7B, 0x01}}; void wait_1ms ( ); main ( ) { PPI_CMD = 0x80; /* initialize the i8255 control register */ while (1) { for (i = 0; i < 4; i++) { PPI_PA = distab[i][0]; /* output segment pattern */ PPI_PB = distab[i][1]; /* send out digit select */ wait_1ms ( ); } return 0; /* create 1 ms delay */ void wait_1ms ( ) TFLG1 = 0x40; /* clear OC2F flag */ TOC2 = TCNT ; while (!(TFLG1 & 0x40));
396
The 68HC24 Port Replacement Unit
- In the early years of the 68HC11, the amount of on-chip EPROM or EEPROM that can be implemented onto the microcontroller chip is very limited. - The software of the target embedded product was to be placed in the on-chip ROM. - During the product development stage, software need to be modified many times. The expanded mode must be chosen and external EPROM must be used so that software can be modified and tested. - Ports B and C, which were needed in the final product, were lost in the expanded mode during the product development phase. - The port replacement unit 68HC24 was designed to regain ports B and C so that the products can be evaluated and tested. - After the design had been tested and evaluated to be satisfactory, the software in the external EPROM could be moved into the internal ROM without modification as long as the external EPROM and internal ROM occupied the same memory space. - The signals and an example of the 68HC24 application is shown in Figure 7.38.
397
Figure 7.38 Circuit connecting the 68HC11 and the 68HC24
VDD 68HC11 68HC24 IRQ IRQ AS AS PB0-PB7 PC0-PC7 AD0-AD7 STRA PB3 CS STRB PB4-PB7 A12-A15 PC0-PC7 E E R/W R/W RESET RESET from reset circuit Figure 7.38 Circuit connecting the 68HC11 and the 68HC24
398
Chapter 8: 68HC11 Timer Functions
The 68HC11 Microcontroller Han-Way Huang Minnesota State University, Mankato
399
Applications that Requires a Dedicated Timer System
- time delay creation and measurement - period measurement - event counting - time-of-day tracking - periodic interrupt generation to remind the processor to perform routine tasks - waveform generation - etc. A Summary of the 68HC11 Timer Functions 1. Main timer 16-bit non-stop timer read-only after reset 2. Input capture function three channels -- 1 to 3 each channel has a 16-bit latch, edge-detection logic, flag bit, and interrupt logic will load the current main timer value into the input capture register when the selected signal edge is detected can be used to measure the signal frequency, period, and pulse width and as time reference
400
3. Output compare functions
A (E) series members have five (four/five) channels (OC1…OC5) each channel has a 16-bit comparator, 16-bit register, action pin, interrupt request circuit, forced-compare function continuously compare the value of the 16-bit compare register with that of the main timer and may optionally trigger an action on a pin, generate an interrupt is often used to create a time delay and generate a waveform 4. Real-time interrupt generates periodic interrupts when enabled interrupt period is programmable 5. Computer operating properly (COP) discussed in Chapter 6 6. Pulse accumulator has an 8-bit counter has two operation modes can be used to measure events, frequency, or the duration of a pulse width
401
The Free-Running Main Timer (TCNT)
- The main timer is cleared to 0 on reset and is read-only except in test mode. - The timer counter register is meant to be read by a 16-bit read instruction such as LDD or LDX. - The block diagram is shown in Figure 8.1.
402
Registers related to Main Timer
Timer counter: TCNT Timer flag register 2: TFLG2 Timer mask register 2: TMSK2 Those bits related to main timer operation in TFLG2 and TMSK2 are in boldface. Timer counter is meant to be read using a double-byte read instruction such as LDD or LDX. If the user accesses TCNT with two 8-bit reads, the result might not be correct, because the lower byte of TCNT would be incremented when the upper byte is accessed.
403
The prescale factor for the main timer is selected by bits 1 and 0 of the timer mask register 2
as shown in Table 8.1. Example 7.1 What values will be in A and B after execution of the following three instructions if TCNT contains $5EFE when the upper byte is accessed ? Assume the bits PR1 and PR0 of TMSK2 are 00. regbas equ $1000 TCNTH equ $0E TCNTL equ $0F ldx #regbas ldaa TCNTH,X ; read the upper byte of TCNT ldaa TCNTL,X ; read the lower byte of TCNT
404
Solution: - The main timer prescale factor is 1 and hence the E clock is the clock input to TCNT. - The instruction LDAA TCNTH,X loads the upper byte (value is $5E) of TCNT into A. - The instruction LDAB TCNTL,L takes 4 E clock cycles to execute. Therefore, TCNT will have been incremented by 4 to $5F02. The accumulator B will receive the value $02. This is not what we expect. If the instruction LDD TCNT,X is executed, then A and B will contain $5E and $FE respectively.
405
Input Capture Functions
- Physical time is often represented by the contents of the main timer. - The occurrence of an event is represented by a signal edge (rising or falling edge). - The time when an event occurs can be recorded by latching the count of the main timer when a signal arrives. - The 68HC11 has three input capture channels (IC1, IC2, & IC3) to implement this operation. - Each input capture channel has a 16-bit input capture register, a flag, edge-detection logic, and interrupt request circuit.
406
- The edge to be captured is selected by programming the register TCTL2.
For example, the following instruction sequence captures the rising edge of the signal applied at PA0 (IC3): regbas equ $1000 TCTL2 equ $ ; offset of TCTL2 from regbas ldx #regbas bclr TCTL2,X % ; clear bit 1 to 0 bset TCTL2,X % ; set bit 0 to 1
407
Registers related to input capture
1. timer mask register 1 (TMSK1): OC1I OC2I OC3I OC4I OC5I IC1I IC2I IC3I - the lowest three bits (bits 2 to 0) of this register enable/disable the interrupt from the proper input capture channel - the upper five bits (bits 7 to 3) of this register enable/disable the interrupt from the corresponding output compare channels 2. timer flag register 1 (TFLG1): - the lowest three bits (bits 2 to 0) of this register are input capture flags - the arrival of a signal edge will set one of the input capture flags - the upper five bits (bits 7 to 3) of this register are output compare flags
408
How to clear a timer flag bit?
write a 1 to the flag bit to be cleared Method 1. use the BCLR instruction with a 0 at the bit position (s) corresponding to the flag (s) to be cleared. For example, BCLR TFLG1,X $FE will clear the IC3F flag. (Assume the index register contains $1000 and TFLG1 = $23) Method 2. load an accumulator with a mask that has a 1 (or 1s) in the bit (s) corresponding to the flag (s) to be cleared; then write this value to TFLG1 or TFLG2. For example, LDAA #$01 STAA TFLG1,X will clear the IC3F flag.
409
Applications of Input Capture function
- Event arrival time recording - Period measurement: the input capture function captures the main timer values corresponding to two consecutive rising or falling edges - Pulse width measurement: capture the rising and falling edges
410
- Interrupt generation: three input capture functions can be used as three edge-sensitive
interrupt sources. - Event counting: by counting the number of signal edges arrived during a period - Time reference: often used in combination with an output compare function
411
Duty Cycle Measurement
Phase Difference Measurement
412
Example 8.3 Use the input capture channel IC1 to measure the period of an unknown
signal. The period is known to be shorter than 32 ms. Write a program to set up IC1 to measure its period. Solution: two versions are available. The polling method is shown in Figure 8.15.
413
Assembly Program for Period Measurement (Polling Method)
REGBAS EQU $1000 TLFG1 EQU $23 TIC1 EQU $10 TCTL2 EQU $21 IC1rise EQU $10 ORG $00 edge1 RMB 2 period RMB 2 ORG $C000 LDX #REGBAS BCLR TFLG1,X $FB ; clear IC1F flag LDAA #IC1rise STAA TCTL2,X ; capture rising edge BRCLR TFLG1,X $04 * ; wait for the first rising edge LDD TIC1,X STD edge1 ; save the first edge BRCLR TFLG1,X $04 * ; wait for the second edge SUBD edge1 STD period ; save the period END
414
C Program for Period Measurement (Polling method)
#include <hc11.h> #include <stdio.h> main ( ) { unsigned int edge1, period; TFLG1 = 0x04; /* clear IC1F flag TCTL2 = 0x10; /* configure to capture rising edge */ while (!(TFLG1 & 0x04)); /* wait for the arrival of the first rising edge */ edge1 = TIC1; /* save the arrival time of the first rising edge */ TFLG1 = 0x04; while (!(TFLG1 & 0x04)); /* wait for the arrival of the second rising edge */ period = TIC1 – edge1; printf(“\n The period of the signal is %d E clock cycles. \n”, period); return 0; }
415
Interrupt-driven Method for Period Measurement
416
REGBAS EQU $1000 ; base address of the I/O register block
TFLG1 EQU $23 ; offset of TFLG1 from regbas TMSK1 EQU $22 ; offset of TMSK1 from regbas TIC1 EQU $10 ; offset of TIC1 from regbas TCTL2 EQU $21 ; offset of TCTL2 from regbas IC1rise EQU $10 ; value to select the rising edge of IC1 to capture IC1I EQU $04 ; mask to select the IC1 bit in TMSK1 IC1FM EQU $FB ; mask to clear IC1F using the BCLR instruction ORG $0000 edge_cnt RMB 1 ; edge count edge1 RMB 2 ; captured first edge period RMB 2 ; period in number of E clock cycles ORG $E8 ; IC1 interrupt jump table entry on the EVB JMP IC1_ISR ; “ ORG $C000 ; starting address of the main program LDS #$DFFF ; set up stack pointer LDX #REGBAS LDAA #IC1rise ; select to capture the rising edge of IC1 STAA TCTL2,X ; “ BCLR TFLG1,X IC1FM ; clear the IC1F flag LDAA #2
417
STAA edge_cnt ; initialize edge count to 2
BSET TMSK1,X IC1I ; enable IC1 interrupt CLI ; enable interrupt to the 68HC11 wait TST edge_cnt ; edge_cnt = 0? BNE wait LDD TIC1,X ; get the second edge time SUBD edge1 ; take the difference of edge 1 and 2 STD period ; save the period . # IC1 interrupt service routine in the following IC1_ISR LDX #regbas BCLR TFLG1,X IC1FM ; clear the IC1F flag DEC edge_cnt BEQ skip ; is this the second edge? LDD TIC1,X ; save the first edge time in memory STD edge1 ; “ skip RTI END
418
C Language Program for Period Measurement (Interrupt-Driven Method)
#include <hc11.h> #include <stdio.h> int edge_cnt unsigned int edge1, period; void IC1_ISR ( ); main ( ) { *(unsigned char *)0xe8 = 0x7E; /* $7E is the opcode of JMP */ *(void (**)())0xe9 = ICI_ISR; /* set up pseudo vector entry of IC1 */ TFLG1 = 0x04; /* clear IC1F flag edge_cnt = 2; TCTL2 = 0x10; /* prepare to capture the rising edge */ TMSK1 |= 0x04; /* enable IC1 interrupt locally */ INTR_ON ( ); /* enable interrupt globally */ while (edge_cnt); period = TIC1 – edge1; printf(“\n The period is %d E clock cycles. \n”, period); return 0; }
419
#pragma interrupt_handler IC1_ISR ( )
void IC1_ISR ( ) { TFLG1 = 0x04; /* clear IC1F flag */ if (edge_cnt == 2) edge1 = TIC1; /* save the first edge */ -- edge_cnt; }
420
Example 8.4 Write a subroutine to measure the pulse width of an unknown signal connected
to the IC1 pin. Return the pulse width in D. The main timer prescale factor is 1. The pulse width of the unknown signal is known to be shorter than ms. Solution: - capture the rising edge on the IC1 pin - capture the falling edge on the IC1 pin - take the difference of two captured values regbas EQU $1000 ; base address of the I/O register block TFLG1 EQU $23 ; offset of TFLG1 from regbas TIC1 EQU $10 ; offset of TIC1 from regbas TCTL2 EQU $21 ; offset of TCTL2 from regbas IC1rise EQU $10 ; value to select the rising edge of IC1 IC1fall EQU $20 ; value to select the falling edge of IC1 IC1F EQU $04 ; a mask to select the IC1F flag temp EQU $00 ; offset of temp from the top of the stack pul_width PSHX PSHY DES ; allocate two bytes for local variable temp DES TSY LDX #regbas
421
LDAA #IC1rise ; configure TCTL2 to capture the rising edge of IC1
STAA TCTL2,X ; “ LDAA #IC1F ; clear IC1F flag STAA TFLG1,X ; “ rise BRCLR TFLG1,X IC1F rise ; wait for the arrival of the rising edge LDD TIC1,X ; save the first edge STD temp,Y ; “ LDAA #IC1fall ; configure to capture the falling edge of IC1 STAA TCTL2,X ; “ fall BRCLR TFLG1,X IC1F fall ; wait for the arrival of the falling edge LDD TIC1,X ; get the captured time of the second edge SUBD temp,Y INS PULY PULX RTS
422
Measuring the period or pulse width of a slow signal (longer than 32
Measuring the period or pulse width of a slow signal (longer than ms) We need to keep track of the number of times that main timer overflows. Let ovcnt = main timer overflow count diff = difference of two edges edge1 = the captured time of the first edge edge2 = the captured time of the second edge Case 1: edge2 ³ edge1 period (or pulse width) = ovcnt × diff Case 2: edge2 < edge1 period (or pulse width) = (ovcnt - 1) × diff The main timer overflows at least once in this case.
423
Example 8.5 Write a program to measure the period of an unknown signal, which may be
longer than 216 E cycles using the IC1 input capture channel. Solution: The logic flow of the program is shown in Figure 8.17.
425
regbas EQU $1000 ; base address of I/O register block
TFLG1 EQU $23 ; offset of TFLG1 from regbas TIC1 EQU $10 ; offset of TIC1 from regbas TCTL2 EQU $21 ; offset of TCTL2 from regbas TMSK1 EQU $22 ; offset of TMSK1 from regbas TMSK2 EQU $24 ; offset of TMSK2 from regbas IC1rise EQU $10 ; value to select the rising edge of IC1 ORG $0000 edge1 RMB 2 ; captured time of the first edge ov_cnt RMB 2 ; main timer overflow count period RMB 2 ; period of the unknown signal ORG $00D0 ; setup timer overflow interrupt vector jump table entry JMP tov_ISR ; on EVB ORG $C000 LDS #$DFFF ; set up stack pointer SEI ; disable all maskable interrupts to the 68HC11 CLR ov_cnt ; initialize overflow count to 0 CLR ov_cnt+1 ; “ LDX #regbas
426
LDAA #IC1rise ; select to capture the rising edge
STAA TCTL2,X ; “ BCLR TFLG1,X $FB ; clear IC1F flag BCLR TMSK1,X $FF ; disable all input capture and output compare interrupts BRCLR TFLG1,X $FB * ; wait for the arrival of the first edge BCLR TFLG2,X $7F ; clear TOF flag BSET TMSK2,X $80 ; enable timer overflow interrupt CLI ; enable interrupt to the 68HC11 LDD TIC1,X ; save the captured time of the first edge STD edge1 ; “ BCLR TFLG1,X $FB ; clear IC1F flag BRCLR TFLG1,X $04 * ; wait for the arrival of the second edge LDD TIC1,X ; compute the difference of edge2 and SUBD edge1 ; edge1
427
STD period ; “ BCC next ; is second edge smaller? LDD ov_cnt ; decrement overflow count if second edge is smaller SUBD #1 ; “ STD ov_cnt ; “ next … tov_ISR LDX #regbas BCLR TFLG2,X $7F ; clear TOF flag LDD ov_cnt ; increment timer overflow count ADDD #1 ; “ RTI END
428
C Program for Measuring the Period of a Slow Signal
#include <hc11.h> #include <stdio.h> unsigned edge1, overflow; unsigned long period; void TOV_ISR ( ); main ( ) { *(unsigned char *)0xd0 = 0x7E; *(void(**) ( ))0xd1 = TOV_ISR; /* set up TOV pseudo vector entry */ INTR_OFF ( ); overflow = 0; TFLG1 = 0xFF; /* clear all output-compare and input-capture flags */ TFLG2 = 0x80; /* clear TOF flag */ TCTL2 = 0x10; /* configure to capture IC1’s rising edge */ TMSK1 = 0x00; /* disable all input capture and output compare interrupts */ while (!(TFLG1 & 0x04)); /* wait for the arrival of first rising edge on IC1 */ TFLG1 = 0x04; edge1 = TIC1; /* save the first rising edge */
429
TMSK2 = 0x80; /* enable timer overflow interrupt */
INTR_ON ( ); /* “ */ while (!(TFLG1 & 0x04)); /* wait for the second rising edge */ if (TIC1 < edge1) /* if the second edge is smaller, then overflow --; /* decrement the overflow count */ period = overflow * 65536; /* combine the result */ period +=TIC1 - edge1; /* “ */ printf(“\n The period is %d E clock cycles. \n”, period); return 0; } #pragma interrupt_handler TOC_ISR ( ) void TOV_ISR ( ) { TFLG2 = 0x80; /* clear TOF flag */ overflow ++;
430
Output Compare Functions
- five output compare channels: OC1-OC5 - port A pins PA7-PA3 are associated with output compare channels OC1-OC5 respectively - Each output compare channel consists of 1. a 16-bit comparator 2. a 16-bit compare register (TOCx, x = 1,…,5) 3. an output action pin 4. an interrupt request circuit 5. a forced-compare function (FOCx, x = 1,…,5) 6. control logic
431
- To use an output compare function,
1. make a copy of the main timer 2. add to this copy a value equal to the desired delay 3. store the sum onto an output-compare register - The actions that can be activated on an output compare pin include 1. pull up to high 2. pull down to low 3. toggle The action is determined by the timer control register 1 (TCTL1):
432
Example 8.6 Generate a 1KHz digital waveform with 40% duty cycle from output compare
pin OC2. Use the polling method to check the success of the compare operation. The frequency of the E clock is 2 MHz and the prescale factor to the main timer is 1. Solution: A 1KHz digital with 40% duty cycle has 400 ms high and 600 ms low in one period. The flowchart to generate this waveform is shown in Figure 8.20.
433
regbas equ $1000 ; base address of I/O register block
PORTA equ $00 ; offset of PORTA from regbas TOC2 equ $18 ; offset of TOC2 from regbas TCNT equ $0E ; offset of TCNT from regbas TFLG1 equ $23 ; offset of TFLG1 from regbas toggle equ $40 ; value to select the toggle action lotime equ ; value to set low time to 600 ms hitime equ ; value to set high time to 400 ms org $C000 ldx #regbas bset PORTA,X $40 ; set OC2 pint to high bclr TFLG1,X $BF ; clear OC2F flag ldaa #toggle ; select output compare action to be staa TCTL1,X ; toggle ldd TCNT,X ; start an OC2 operation which toggles the OC2 pin addd #hitime ; with a delay of 800 E clock cycles std TOC2,X ; “ high brclr TFLG1,X $40 high ; wait until OC2F is set to 1 bclr TFLG1,X $BF ; clear OC2F flag ldd TOC2,X ; start another OC2 operation which toggles the OC2 pin addd #lotime ; with a delay of 1200 E cycles
434
low brclr TFLG1,X $40 low ; wait until OC2F is set to 1
bclr TFLG1,X $BF ; clear OC2F flag ldd TOC2,X ; start another OC2 operation which toggles the OC2 pin addd #hitime ; with a delay of 800 E cycles std TOC2,X ; “ bra high end
435
In C language, #include <hc11.h> main ( ) { PORTA |= 0x40; /* set OC2 pint to high */ TCTL1 = 0x40; /* select toggle as the OC2 pin action */ TOC2 = TCNT + 800; /* start an OC2 operation with 800 E cycles as the delay */ TFLG1 = 0x40; /* clear OC2F flag */ while (1) { while (!(TFLG1 & 0x40)); /* wait for 400 ms */ TFLG1 = 0x40; TOC2 += 1200; /* start next OC2 operation with 1200 E cycles as delay */ while (!(TFLG1 & 0x40)); /* wait for 600 ms */ TOC2 += 800; } return 0;
436
Example 8.7 Write a function to generate one second delay using the OC2 function.
The E clock is 2 MHz and the prescale factor to the main timer is 1. Solution: A one-second delay can be created by performing 40 OC2 output compare operations. Each OC2 compare operation creates 25 ms delay. A memory location is allocated to keep track of the number of OC2 operations that have been performed.
437
regbas EQU $1000 ; base address of I/O register block
TOC2 EQU $18 ; offset of TOC2 from regbas TCNT EQU $0E ; offset of TCNT from regbas TFLG1 EQU $23 ; offset of TFLG1 from regbas dly25ms EQU ; the number of E cycles to generate 25 ms delay onesec EQU 40 ; number of OC2 operations to be performed oc2_cnt EQU 0 ; offset of oc2_cnt from the top of the stack delay_1s PSHX PSHY DES TSY LDX #regbas BCLR TFLG1,X $BF ; clear OC2F flag LDAA #40 STAA oc2_cnt,Y ; initialize oc2_cnt LDD TCNT,X wait ADDD #dly25ms STD TOC2,X ; start an OC2 operation with 25 ms delay BRCLR TFLG1,X $40 * ; wait until OC2F flag is set BCLR TFLG1,X $BF ; clear OC2F flag DEC oc2_cnt,Y
438
BEQ exit LDD TOC2,X BRA wait exit INS PULY PULX RTS C function to generate one second delay, void delay_1s ( ) { unsigned char oc2_cnt; oc2_cnt = 100; /* prepare to perform 100 OC2 operation */ TFLG1 = 0x40; /* clear OC2F flag */ TOC2 = TCNT ; /* start an OC2 operation with E cycles as the delay */ while (oc2_cnt) { while(!(TFLG1 & 0x40)); /* wait for 10 ms */ TFLG1 = 0x40; -- oc2_cnt; TOC2 += 20000; /* start the next OC2 operation */ }
439
Example 8.8 Suppose an alarm device is already connected properly and the subroutine to
turn on the alarm is also available. Write a program to implement the alarm timer--it should call the given alarm subroutine when the alarm time is reached. Solution: - Use OC2 to create the delay. - Perform OC2 operations with a delay of 20 ms - Perform 3000 such operations to create a delay of 1 minute. - Check the alarm time every second. - Call the alarm routine if the alarm time is reached. - Enable OC2 interrupt
440
regbas equ $1000 TOC2 equ $18 TCNT equ $0E TFLG1 equ $23 TMSK1 equ $22 dly20ms equ ; number of E cycles equivalent to 20 ms delay one_min equ ; number of OC2 operations to be created to * ; generate 1 minute delay org $0000 hours rmb 1 minutes rmb 1 ticks rmb 2 alarm rmb 2 routine fdb start_alarm ; starting address of the alarm routine org $00DC ; interrupt jump table entry for OC2 on EVB jmp oc2_ISR org $C000 lds #$DFFF ; set up stack pointer sei ; disable interrupt before setup is done ldd #one_min ; initialize the OC2 count to generate std ticks ; one minute delay
441
ldx #regbas bclr TFLG1,X $BF ; clear OC2F flag bset TMSK1,X $04 ; enable OC2 interrupt ldd TCNT,X ; start an OC2 operation with addd #dly20ms ; 20 ms delay std TOC2,X ; “ cli ; enable interrupt to the 68HC11 forever bra forever ; loop forever to wait for interrupt oc2_ISR ldx #regbas bclr TFLG1,X $BF ; clear OC2 flag ldd TOC2,X ; start the next OC2 operation with addd #dly20ms ; 20 ms delay ldy ticks ; decrement the minute count dey ; “ sty ticks ; “ bne case2 ; is one minute expired? ldd #one_min ; reinitialize the one-minute counter std ticks ; “ ldd hours ; load the hours and minutes
442
INCB CMPB #60 ; is it time to increment the hour? BNE case1 ; no need to update hour digits yet CLRB ; reset minutes to 0 INCA ; increment the hour CMPA #24 ; it is time to reset hours to 0? BNE case1 ; no need to reset hour yet CLRA ; reset hours to 00 case1 STD hours ; save the current time in memory CPD alarm ; reaches alarm time? BNE case2 LDX routine JSR 0,X ; call the alarm routine case2 RTI END
443
Example 8.9 LED Flashing. Connect 8 LEDs to port B and flash these LEDs in the
following way: 1. Light all LEDs for ¼ seconds and turn them off for ¼ seconds—repeat this pattern 4 times. 2. Light one LED at a time for one second—from the LED controlled by the most significant output port pin to the LED controlled by the least significant port pin. 3. Reverse the order of display in step 2. 4. Turn off all of the LEDs.
444
unsigned char flas_tab [25][2] = {{0xFF, 25}, {0x00, 25}, {0xFF, 25} {0x00, 25}, {0xFF, 25},
{0x00, 25}, {0xFF, 25}, {0x00, 25}, {0x80, 100}, {0x40, 100}, {0x20, 100}, {0x10, 100}, {0x08,100}, {0x04, 100}, {0x02, 100}, {0x01, 100}, {0x01, 100}, {0x02, 100}, {0x04, 100}, {0x08, 100}, {0x10, 100}, {0x20, 100}, {0x40, 100}, {0x80, 100}, {0x00,100}}; void delay (char k); void flash ( ) { int i; for (i = 0; i < 25; i++) { PORTB = flash_tab [i][0]; delay (flash_tab[i][1]); } void delay (char k) { TFLG1 = 0x40; /* clear OC2F flag */ TOC2 = TCNT ; /* start an OC2 operation */ while (k) { while (!(TFLG1 & 0x40)); TFLG1 = 0x40; -- k; TOC2 += 20000; /* start a new OC2 operation */
445
Using OC1 to Control Multiple OC Functions
- OC1 can control up to five OC pins - Specify the OC pins to be controlled by OC1 using the register OC1M. - Specify the value that any OCx (x = 1,…,5) pin to assume when the value of TOC1 equals TCNT using the OC1D register. - When a successful OC1 compare is made, each affected pin assumes the value of the corresponding bit of OC1D. - The OC1 (PA7) pin is bidirectional. For this pin to be controlled by OC1 function, it must be configured for output. The direction of PA7 pin is controlled by the bit 7 of the PACTL register. Set bit 7 of PACTL to 1 to configure PA7 pin for output.
446
Example 8.9 Write values into OC1M and OC1D so that OC2 and OC3 pins will assume
the values of 0 and 1 when the OC1 compare operation succeeds. Solution: - Set bits 6 and 5 of OC1M to 11 - Set bits 6 and 5 of OC1D to 01 regbas EQU $1000 OC1M EQU $0C OC1D EQU $0D LDX #regbas LDAA #% STAA OC1M,X LDAA #% STD OC1D … In C language OC1M = 0x60; OC1D = 0x20;
447
Example 8. 11 An application requires control of five valves
Example 8.11 An application requires control of five valves. The first, third, fifth valves should be opened for five seconds and then closed for five seconds. When these three valves are closed, the second and fourth valves are opened, and vise versa. This process is repeated forever. Pins OC1,…,OC5 are used to control these five valves. When the OCx pin is high, the corresponding valve will be opened. Write a program to perform the operation. Solution: - The OC1 pin (same as PA7) is bi-directional, to use it to control a valve, it must be configured for output. Set the bit 7 of the PACTL register to 1. - Write the value % into OC1M so that OC1 function can control all five OC pins. - Write the value % into OC1D to open only valves 1,3,and 5. - Write the value % into OC1D to open only valves 2 and 4. - Perform 200 OC1 output compare operations with each operation creating 25 ms delay. regbas EQU $1000 PACTL EQU $26 OC1D EQU $0D OC1M EQU $0C TOC1 EQU $16 TCNT EQU $0E TFLG1 EQU $23 oc1m_in EQU $F8 ; value to initialize OC1M oc1d_in1 EQU $A8 ; value to initialize OC1D to open valves 1, 3, and 5
448
oc1d_in2 equ $50 ; value to initialize OC1D to open valves 2 and 4
five_sec equ ; number of OC1 operations to be performed dly25ms equ ; the number of E clock cycles equivalent to 25 ms ORG $0000 oc1_cnt rmb 1 ; number of OC1 operations remained to be performed ORG $C000 ldx #regbas bset PACTL,X $80 ; configure PA7 pin for output ldaa #oc1m_in ; allow OC1 function to control all OC pins staa OC1M,X ; “ bclr TFLG1,X $7F ; clear OC1F flag ldaa #five_sec staa oc1_cnt ldaa #oc1d_in1 ; set pins OC1, OC3, and OC5 to high after 25 ms staa OC1D,X ldd TCNT,X ; start an OC1 operation with 25 ms delay repeat1 addd #dly25ms ; “ std TOC1,X ; “ brclr TFLG1,X $80 * ; wait for 25 ms
449
dec oc1_cnt ; decrement the output compare count
beq change ; at the end of 5 seconds change the valves setting ldd TOC1,X ; prepare to perform the next OC1 operation bra repeat1 change ldaa #oc1d_in2 ; set to open valves 2 and 4 staa OC1D,X ; “ ldaa #five_sec ; reinitialize the output compare count staa oc1_cnt ; “ repeat2 ldd TOC1,X ; start the next OC1 operation with the same addd #dly25ms ; delay std TOC1,X ; “ brclr TFLG1,X $80 * ; wait until OC1F flag is set to 1 bclr TFLG1,X $7F ; clear OC1F flag dec oc1_cnt beq switch ; five seconds expired, switch the valve setting bra repeat2 switch ldaa #five_sec ; reinitialize the OC1 count ldaa #oc1d_in1 ; change the valve setting staa OC1D,X ; ldd TOC1,X ; prepare to start the next OC1 operation end
450
#include <hc11.h> main () { unsigned int oc1_cnt; PACTL |= 0x80; /* configure PA7 for output */ OC1M = 0xF8; /* allow OC1 to control OC1-OC5 pins */ TFLG1 = 0x80; /* clear OC1F flag */ TOC1 = TCNT ; /* start an OC1 operation with 10 ms delay */ while (1) { OC1D = 0xA8; /* prepare to set PA7, PA5, and PA3 to high */ oc1_cnt = 500; /* number of OC1 operations to create 5 s delay */ while (oc1_cnt) { while (!(TFLG1 & 0x80)); TFLG1 = 0x80; /* clear OC1F flag */ TOC1 += 20000; /* start the next OC1 operation */ oc1_cnt --; } OC1D = 0x50; /* value to pull PA6 and PA4 to high */ oc1_cnt = 500;
451
OC1 function can control an output compare pin that has been controlled by another
output compare function. This allows two output compare functions to control the same pin. Example 8.12 Use OC1 and OC2 together to generate a 5KHz digital waveform with 40% duty cycle. Solution: - Use OC1 function to pull OC2 pin to high every 200 ms. - Use OC2 function to pull OC2 pin to low 80 ms later. - Enable both OC1 and OC2 interrupts - The interrupt service routines of OC1 and OC2 clear the flag and then start their associated output compare operations with 200 ms delay.
452
regbas equ $1000 TMSK1 equ $22 PORTA equ $00 OC1D equ $0D OC1M equ $0C TOC1 equ $16 TOC2 equ $18 TCTL1 equ $20 TFLG1 equ $23 tctl1_in equ $80 ; value to set the OC2 action to be pull the OC2 pin to low oc1m_in equ $40 ; value to allow OC1 function to control OC2 pin oc1d_in equ $40 ; value to be written into OC1D to pull OC2 to high fiveKHz equ ; timer count for 5 KHz (2 MHz E clock cycles) diff equ ; the count difference of two output compare functions org $00DC jmp oc2_ISR ; interrupt vector jump table entry for OC2 jmp oc1_ISR ; interrupt vector jump table entry for OC1 org $C000 lds #$DFFF ldx #regbas bclr TFLG1,X $3F ; clear OC1F and OC2F flags
453
ldaa #tctl1_in ; define OC2 action to pull OC2 pin to low
staa TCTL1,X ; “ ldaa #oc1d_in ; define OC1 action to pull OC2 pin to high staa OC1D,X ; “ ldaa #oc1m_in ; allow OC1 function to control OC2 pin staa OC1M,X ; “ bset TMSK1,X $C0 ; enable OC1 and OC2 interrupts bclr PORTA,X $40 ; pull OC2 pin to low ldd TCNT,X ; start the OC1 operation with a delay of 200 ms addd #fiveKHz ; “ std TOC1,X ; “ addd #diff ; start the OC2 operation std TOC2,X ; “ cli ; enable interrupt to the 68HC11 loop bra loop ; infinite loop to wait for OC1 and OC2 interrupts
454
* The OC1 interrupt service routine is in the following
oc1_ISR bclr TFLG1,X $7F ; clear OC1 flag ldd TOC1,X ; start the next OC1 operation with a delay of 200 ms addd #fiveKHz ; “ std TOC1,X ; “ rti * The OC2 interrupt service routine is in the following oc2_ISR bclr TFLG1,X $BF ; clear OC2 flag ldd TOC2,X ; start the next OC2 operation with a delay of 200 ms std TOC2,X ; “ end
455
C Language Program Using OC1 & OC2 to generate a waveform
#include <hc11.h> void OC1_ISR ( ); void OC2_ISR ( ); main ( ) { *(unsigned char *)0xdf = 0x7E; *(void (**)())0xe0 = OC1_ISR ( ); *(unsigned char *)0xdc = 0x7E; *(void (**)())0xdd = OC2_ISR ( ); OC1M = 0x40; /* allow OC1 to control OC2 pin */ OC1D = 0x40; /* configure OC1 to pull OC2 to high */ TCTL1 = 0x80; /* configure OC2 to pull OC2 pin to low */ PORTA &= 0xBF; /* pull OC2 pin to low */ TOC1 = TCNT + 400; /* start an OC1 operation with 400 E cycles as delay */ TOC2 = TOC ; /* start OC2 operation that succeed 160 E cycles later */ TMSK1 |= 0xC0; /* enable OC1 and OC2 interrupts */ INTR_ON ( ); while (1); /* infinite loop */ return 0; }
456
#pragma interrupt_handler OC1_ISR ( )
void OC1_ISR ( ) { TFLG1 = 0x80; TOC1 += 400; /* start the next OC1 operation */ } #pragma interrupt_handler OC2_ISR ( ) void OC2_ISR ( ) TFLG1 = 0x40; TOC2 += 400; /* start the next OC2 operation */
457
set to 1 nor the interrupt is generated.
Forced Output Compare - Useful when the user requires the output compare to succeed immediately after being started - Write a 1 to the corresponding bit of the CFORC register to force an output compare operation - The forced output compare operation only causes pin action. Neither the flag is set to 1 nor the interrupt is generated.
458
Example 8.13 Suppose that the contents of the TCTL1 register are %10011000. What
would occur on pins PA6-PA3 on the next clock cycle if the value % is written into the CFORC register? Solution: The contents of TCTL1 configure the output compare actions in Table 8.5 - CFORC specifies that OC2-OC5 are to be forced. - Pin PA6 will be pulled low - Pin PA5 will be toggled - Pin PA4 will be pulled low - Pin PA3 will not be affected
459
Real-Time Interrupt (RTI)
- Will generate periodic interrupts if enabled. - The RTI interrupt period is programmable by programming the bits 1 and 0 of the PACTL register (see table 8.6). - RTI interrupt is enabled by setting the bit 6 of the TMSK2 register - The bit 6 of the TFLG2 register will be set to 1 on a RTI interrupt Example 8.14 Use the RTI function to create a delay of 10 seconds. Solution: - Select the prescale factor of 8 that will set the interrupt period to ms - Need to enable RTI interrupt - 305 RTI interrupts will roughly create a delay of 10 seconds
460
regbas EQU $1000 TMSK2 EQU $24 TFLG2 EQU $25 PACTL EQU $26 tensec EQU ; total RTI interrupts in 10 s RTIF EQU $40 ; mask to select the RTIF flag ORG $0000 rti_cnt RMB 2 ; remaining RTI interrupts to be generated ORG $00EB ; RTI interrupt vector jump table entry JMP rti_hnd ; “ ORG $C000 LDS #$DFFF ; initialize stack pointer LDX #regbas LDD #tensec STD rti_cnt BSET PACTL,X $03 ; select RTI clock prescale factor to 8 LDAA #RTIF STAA TFLG2,X ; clear RTIF flag STAA TMSK2,X ; enable RTI function CLI ; enable interrupt to the 68HC11 loop LDD rti_cnt ; wait until rti_cnt becomes 0 BNE loop SWI
461
RTI service routine is as follows:
rti_hnd LDX #regbas BCLR TFLG2,X $BF LDX rti_cnt DEX STX rti_cnt RTI
462
C Function that Uses RTI To Create 10-Second Delay
int rti_cnt; /* number of RTI interrupts remained */ void delay_10s ( ) { rti_cnt = 305; PACTL |= 0x03; /* set RTI clock prescale factor to 8 */ TFLG2 = 0x40; /* clear RTIF flag */ TMSK2 |= 0x40; /* enable RTI interrupt */ INTR_ON ( ); /* “ */ while (rti_cnt); TMSK2 &= 0xBF; /* disable RTI interrupt */ } #pragma interrupt_handler RTI_ISR ( ) void RTI_ISR ( ) rti_cnt --;
463
The Pulse Accumulator - 8-bit pulse accumulator (PACNT) - two operation modes: event counting and gated accumulation modes - PACNT is clocked by the PAI input in event counting mode - PACNT is clocked by the E-divided-by-64 clock in gated accumulation mode - The PAI pin (PA7 pin) must be configured for input to enable pulse accumulator - There are two interrupt sources: PAI pin edge and the rollover of PACNT from $FF to $00 - Four registers are related to the operation of the PACNT: TMSK2, TFLG2, PACTL, PACNT
464
- The bits 5 and 4 of TMSK2 enables/disables PACNT overflow and PAI edge interrupt
respectively. - The bits 5 and 4 of TFLG2 are pulse accumulator overflow and PAI edge flag respectively. Pulse Accumulator Control Register (PACTL) - bit 7 (DDRA7): configure PA7 pin for input; configure PA7 for output - bit 6 (PAEN): disable PA function; enable PA function - bit 5 (PAMOD): select event-counting mode; select gated accumulation mode - bit 4 (PEDGE): its meaning depends on bit 5
465
Example 8. 15 Interrupt after N events
Example Interrupt after N events. Events are converted into signal edges and are connected to the PAI pin. N is smaller than Write a program to interrupt the 68HC11 after N event. Solution: regbas EQU $1000 TMSK2 EQU $24 TFLG2 EQU $25 PACTL EQU $26 PACNT EQU $27 PA_INI EQU $50 ; value to enable PA, select event-counting mode, ; falling edge active N EQU …. ; event count ORG $C000 LDX #regbas BCLR TFLG2,X $DF ; clear the PAOVF flag LDAA #N NEGA ; complement N STAA PACNT,X ; initialize PACNT to -N LDAA #PA_INI STAA PACTL,X BSET TMSK2,X $20 ; enable the PACNT overflow interrupt CLI ; enable interrupt to the 68HC11 END
466
C Program that Interrupts After N Events
#include <hc11.h> void PAOV_ISR ( ); main ( ) { *(unsigned char *)oxcd = 0x7E; *(void (**)())0xce = PAOV_ISR; PACNT = ~N + 1; /* place -N in PACNT */ PACTL = 0x50; /* configure PA function */ TMSK2 |= 0x20; /* enable PAOV interrupt */ INTR_on ( ); … } #pragma interrupt_handler PAOV_ISR ( ) void PAOV_ISR ( )
467
Use the PA function to measure frequency
- Set up pulse accumulator to operate in event-counting mode - Connect the unknown signal to the PAI pin - Select the active edge (rising or falling) - Use one of the output compare function to create a delay of one second - Use a memory location to keep track of the number of active edges arrived in one second. - Enable pulse accumulator interrupt on active edge. The PA interrupt service routine increments the signal count by 1. - Disable the pulse accumulator interrupt at the end of one second. Example Write a program to measure the frequency of an unknown signal connected to the PAI pin. Solution: - use OC2 function to perform 40 operations to create a delay of one second - each OC2 operation creates a delay of 25 ms - enable PAI edge interrupt - on a PAI edge interrupt, increment the frequency count by 1
468
regbas EQU $1000 TCNT EQU $0E TOC2 EQU $18 TFLG1 EQU $23 TMSK2 EQU $24 TFLG2 EQU $25 PACTL EQU $26 PACNT EQU $27 oc2dly EQU ; output compare count for 25 ms delay pa_in EQU $50 ; value to enable PA, select event-counting mode, rising * ; edge as active edge, * ; and set PA pin for input onesec EQU 40 ; number of OC2 operations to be performed stop EQU $10 ; value to disable the PA interrupt ORG $0000 oc2_cnt RMB 1 freqcy RMB 2 ; active edge count in one second ORG $CA ; interrupt vector jump table entry for PAI edge JMP pa_ISR ; “
469
ORG $C000 LDS #$DFFF LDX #regbas LDAA #onesec STAA oc2_cnt ; initialize OC2 count LDD #0 STD freqcy ; initialize frequency counter to 0 LDAA #pa_in ; initialize the PA function STAA PACTL,X ; “ BCLR TFLG2,X $EF ; clear the PAIF flag BSET TMSK2,X $10 ; enable the PAI edge interrupt CLI ; enable interrupt to the 68HC11 LDD TCNT,X ; start an OC2 operation with a delay sec_loop ADDD #oc2dly ; of 25 ms STD TOC2,X ; “ BCLR TFLG1,X $BF ; clear OC2F flag BRCLR TFLG1,X $40 * ; wait for 25 ms LDD TOC2,X DEC oc2_cnt BNE sec_loop ; if 1 second is not expired, continue. LDAA #stop ; disable PAI edge interrupt STAA TMSK2,X ; “ SWI ; return to BUFFALO monitor
470
pa_ISR LDX #regbas BCLR TFLG2,X $EF ; clear the PAIF flag LDX freqcy ; increment frequency counter INX ; “ STX freqcy ; “ RTI END
471
C Program that Uses PAI to Measure the Frequency
#include <hc11.h> #include <stdio.h> void PAI_ISR ( ); unsigned int frequency; main ( ) { unsigned int oc2_cnt; *(unsigned char *)0xca = 0x7E; *(void (**)())0xcb = PAI_ISR; frequency = 0; PACTL = 0x50; TFLG2 = 0x10; /* clear PAIF flag */ oc2_cnt = 100; /* total OC2 operations to be performed */ TOC2 = TCNT ; /* start an OC2 operation with E cycles as delay */ TFLG1 = 0x40; /* clear OC2F flag */ TMSK2 |= 0x10; /* enable PAI interrupt */ INTR_ON ( ); /* “ */ while (oc2_cnt) {
472
while (!(TFLG1 & 0x40)); /* wait for 20000 E cycles */
TOC2 += 20000; oc2_cnt --; } TMSK2 &= 0xEF; /* disable PAI interrupt */ INTR_OFF ( ); /* “ */ printf(“\n The frequency of the unknown signal is %d \n”, frequency); return 0; #pragma interrupt_handler PAI_ISR ( ) PAI_ISR ( ) { TFLG2 = 0x10; /* clear PAIF flag */ frequency ++; Drawback of Using PAI interrupt - interrupt handling overhead is too high - can only measure frequency up to about 43KHz.
473
Using the PA function to measure the duration of an unknown signal
- The gated accumulation mode can be used to measure the duration of an unknown signal. - Initialize PACNT to 0. - Select the falling edge of the PAI signal as the active edge. An interrupt will be generated on the falling edge. - Enable the PAI interrupt and wait for the arrival of the PAI active edge - Stop the PA function when the interrupt occurs. - The number of times that PACNT overflows should be kept track of in order to measure a very slow signal. pulse width = (28 × paov_cnt + pacnt) × 64 × TE where, paov_cnt is the PACNT overflow count, pacnt is the contents of the PACNT counter when interrupt occurs. Example 8.17 Write a program to measure the duration of an unknown signal connected to the PAI pin. Solution:
474
regbas equ $1000 TCNT equ $0E TMSK2 equ $24 TFLG2 equ $25 PACTL equ $26 PACNT equ $27 stop equ $00 ; value to stop the pulse accumulator pa_in equ % ; value to be written into PACTL to enable PA, select gated * ; accumulation mode, and set PAI to be active high org $00 paov_cnt rmb 2 ; keep track of PACNT overflow count pa_cnt rmb 1 ; holds the contents of the PACNT at the end of measurement edge rmb 1 ; PAI edge interrupt count org $00CA ; set up interrupt vector jump table entries for PAOV and PAI jmp pai_hnd ; “ jmp paov_hnd ; “
475
ORG $C000 LDS #$DFFF LDX #regbas LDD #0 STD paov_cnt ; initialize the PACNT overflow count to 0 LDAA #1 STAA edge ; initialize PAI signal edge count to 1 BCLR TFLG2,X $CF ; clear PAOVF and PAIF flags to 0 LDAA #pa_in STAA PACTL,X ; initialize the PA function CLR PACNT,X ; reset the PACNT counter to 0 BSET TMSK2,X $30 ; enable the PAOV and PAI edge interrupts CLI ; enable interrupt to the 68HC11 wait TST edge ; wait for the arrival of PAI falling edge BNE wait ; “ BCLR PACTL,X $40 ; disable the PA function LDAA PACNT,X ; make a copy of PACNT STAA pa_cnt ; “ SWI
476
* the PAI interrupt service routine is in the following
pai_hnd BCLR TFLG2,X $EF ; clear the PAIF flag DEC edge ; reset the edge flag to 0 RTI * The PAOV interrupt service routine is in the following paov_hnd BCLR TFLG2,X $DF ; clear the PAOVF flag LDD paov_cnt ; increment the PAOV count ADDD #1 ; “ STD paov_cnt ; “ END
477
C Program for Measuring Pulse Width Using PA Gated Accumulation Mode
#include <hc11.h> #include <stdio.h> void PAI_ISR ( ); void PAOV_ISR ( ); unsigned int paov_cnt, pai_cnt, edge; main ( ) { unsigned long pulse_width; *(unsigned char *)0xca = 0x7E; *(void (**)())oxcb = PAI_ISR; *(unsigned char *)0xcd = 0x7E; *(void (**)())0xce = PAOV_ISR; paov_cnt = 0; edge = 1; TFLG2 = 0x30; /* clear PAIF and PAOVF flags */ PACTL = 0x60; PACNT = 0; TMSK2 |= 0x30; /* enable PAI and PAOV interrupts */
478
INTR_ON ( ); while (edge); PACTL &= 0xBF; /* disable PA function */ pulse_width = paov_cnt << 8 + PACNT; printf(“\n The pulse width of the signal is %d \n”, pulse_width); return 0; } #pragma interrupt_handler PAI_ISR ( ) void PAI_ISR ( ) { TFLG2 = 0x10; /* clear PAIF flag */ edge --; #pragma interrupt_handler PAOV_ISR ( ) void PAOV_ISR ( ) TFLG2 = 0x20; /* clear PAOVF flag */ paov_cnt ++;
479
Chapter 9: 68HC11 Serial Communication Interface
The 68HC11 Microcontroller Han-Way Huang Minnesota State University, Mankato
480
Asynchronous Serial Data Communication
- Often used for data communication between a DTE and a DCE with or without a modem. - DTE stands for data terminal equipment and can be either a computer or a terminal. - DCE stands for data communication equipment. A modem is a DCE. - A basic data communication link is shown in Figure 9.1. - there are three kinds of data communication links: 1. simplex link 2. half-duplex link 3. full-duplex link
481
- specifies 25 interchange circuits for DTE/DCE use
Types of communication links configuration The RS232 Standard - was the most widely used physical level interface for data communication - specifies 25 interchange circuits for DTE/DCE use - was established in 1960 by Electronics Industry Association (EIA) - was revised into RS232C in 1969 - was revised into RS232D in 1987 - was revised to RS232E in 1992 - there are four aspects: electrical, functional, procedural, and mechanical
482
The RS232D Electrical Specifications
- the interface is rated at a signal rate of < 20 kbps - the signal can transfer correctly within 15 meters - the maximum driver output voltage (with circuit open) is -25 V to +25 V - the minimum driver output voltage (loaded output) is -25 V to -5 V and +5 V to +25 V - the minimum driver output resistance when power is off is 300 W - the maximum driver output current (short circuit) is 500 mA - the maximum driver output slew rate is 30 V/ms - the receiver input resistance is 3-7 KW - the receiver input voltage range is -25 V to +25 V - the receiver output is high when input is open circuit - a voltage more negative than -3 V at the receiver input is interpreted as a logic 1 - a voltage more positive than +3 V at the receiver input is interpreted as a logic 0
483
The EIA-232E Functional Specifications
484
EIA-232E Mechanical Specification
- Specifies a 25-bit connector - Specifies exact dimensions of each pin.
485
EIA-232E Procedural Specification
- define the sequence of events that occurs during data transmission - the procedure is easier to understand by examples Case 1. Two DTEs connected via a point-to-point link using a modem. EIA-232 signals involved: - signal ground (GND) - transmitted data (Tx) - received data (Rx) - request to send (RTS) - clear to send (CTS) - data set ready (DSR) - data carrier detect (DCD)
486
Sequence of events occurred during data transmission over dedicated link
Local Time Remote 1. DCE asserts DSR 2. DTE asserts RTS 3. DCE asserts CTS 4. DTE starts to send data (to local DCE) 5. DCE sends out a carrier and then the modulated data 6. DCE asserts DCD 7. DTE waits for arrival of data 8. DCE sends out demodulated received data 9. DEC receives demodulated data
487
Case 2. Two DTEs exchange data through a public phone line
RS232 signals involved: - signal ground (GND) - transmitted data (Tx) - received data (Rx) - request to send (RTS) - clear to send (CTS) - data set ready (DSR) - data carrier detect (DCD) - data terminal ready (DTR) - ring indicator (RING) - The signal DTR is used by the DTE to indicate its intention to make a call or accept a call. - The signal RING is used by the DCE to indicate that there is an incoming call.
488
Remote (receiving side)
Sequence of events occur during data transmission over public phone line Local time (transmission side) Remote (receiving side) Connection establishment phase 1. DTE asserts DTR 2. DCE dials the phone number 3. DCE detects the ring and asserts RING 4. DTE asserts DTR to accept the call 5. DCE sends out a carrier and asserts DSR 6. DCE asserts DSR and DCD and also sends out a carrier for full duplex operation 7. DCE asserts DCD (full duplex operation)
489
Sequence of events occur during data transmission (continued)
Local time (transmission side) Remote (receiving side) Data transmission phase 1. DTE asserts RTS 2. DCE asserts CTS 3. DTE sends out data to DCE 4. DCE modulates data and sends it out 5. DCE demodulates data and forwards the data to DTE 6. DTE receives data Disconnection phase 1. DTE drops RTS 2. DCE drops CTS and drops the carrier 3. DCE deasserts DCD & DSR 4. DTE deasserts DTR
490
Data format for asynchronous data communication
- data is transmitted character by character bit-serially - a character consists of 1. one start bit (0), 2. 7 to 8 data bits, 3. an optional parity bit, 4. one, or one and a half, or two stop bits (1) 5. least significant bit is transmitted first 6. most significant bit is transmitted last
491
Example 9. 1 The letter A is to be transmitted
Example 9.1 The letter A is to be transmitted. What is the data output transmitted out from the computer? The data format for transmission is 8 data bits, no parity, and one stop bit. Solution: The ASCII code of letter A is $41 or % This code will be followed by a stop bit. The output from the DTE should be: Example 9.2 How long does it take to transmit one character at the speed of 9600 baud? Each character is transmitted using a format with seven data bits, even parity, and two stop bits. Solution: - Each character consists 11 bits. - Each bit requires 104 ms (= 1 sec ÷ 9600). - One character requires 11 × 104 ms = ms to transmit.
492
Data transmission errors
- framing error: a character is not properly framed by a stop bit - receiver overrun: one or more characters received but not read by the CPU - parity error: odd number of bits change value Null Modem connection
493
The 68HC11 SCI Subsystem - Signal pins: TxD (PD1) and RxD (PD0) - Data formats 1. one start bit 2. 8 or 9 data bits 3. one stop bit - Wake up feature 1. address mark wakeup: the character whose msb is a 1 is an address mark 2. idle line wakeup: the RxD pin is idle (high) for at least one complete character time Wakeup feature can reduce the data communication overhead in a multidrop environment. - Start bit detection 1. the SCI uses a clock 16 times the bit rate to detect the arrival of a start bit and data bit 2. the RxD pin must be high for at least three sampling clock cycles followed by a low voltage 3. the majority of bits 3, 5, and 7 being a low is considered as the arrival of a start bit
494
- Receive process of a character
1. the receiver detects the start bit 2. the receiver shifts in 8 (or 9) data bits 3. the receiver shifts in the stop bit 4. when a correct stop bit is detected, the data bits will be loaded into the receive data register 5. the receiver sets the RDRF flag in the SCSR register and may optionally generate an interrupt to the CPU - SCI receive errors 1. framing error (FE) 2. receiver overrun (OR) 3. noise error (NE) - The transmitting process of a character 1. CPU writes the character into the transmit data register after the transmitter is enabled 2. the transmitter adds the start bit and a stop bit to the data character presented by the CPU 3. the transmitter shifts out the bit stream 4. the transmitter sets the TDRE status flag of the SCSR register after a character is shifted out and may optionally generate an interrupt to the CPU
495
SCI registers Serial Communication Data Register (SCDR) Receive data register (RDR) and transmit data register (TDR) are referred to as SCDR. Serial Communication Status Register (SCSR) TDRE: set to 1 when transmit data register is empty TC: set to 1 when transmission is complete (the whole message have been sent out) RDRF: set to 1 when receive data register is full IDLE: set to 1 when idle line condition is detected OR: set to 1 when receiver is overrun NF: set to 1 when communication line is noisy FE: set to 1 when framing error occurs
496
Serial Communication Control Register 1 (SCCR1)
R8: receive data bit 8 T8: transmit data bit 8 M: data format bit (0 selects 8 data bits, 1 selects 9 data bits) WAKE: wake up method select (0 selects idle line, 1 selects address mark wake up method)
497
Serial Communication Control Register 2 (SCCR2)
TIE: transmit interrupt enable TCIE: transmit complete interrupt enable RIE: receive interrupt enable (including receive data register full and receiver overrun) ILIE: idle line interrupt enable TE: transmit enable RE: receive enable RWU: receiver wake up (puts the receiver in sleep and enables wake up mechanism) SBK: send break A break is defined as the transmission or reception of a low for at least one complete character frame time (from the viewpoint of a DTE). An idle line is defined as a continuous logic high on the RxD line for at least a complete
498
Baud Register (BAUD) TCLR: clear baud rate counter (used in factory testing only) RCKB: SCI baud rate check (used in factory testing only) The baud rate is derived by dividing the E clock signal by two factors specified in the BAUD register.
499
Example 9.3 Give a set of baud rate prescale and baud rate select factors to set the
baud rate to 9600 with a 2-MHz E clock. Solution: - the frequency of the clock that is used to determine the bit value is 16 × 9600 = 153,000. - 13 × = » 2 MHz. - set the prescale factor to 13 (set SCP1 & SCP0 to 11) - set the baud rate select factor to 1 (set SCR2-SCR0 to 000) - write the value $30 to the BAUD register
500
- the SCI uses 0 V and 5 V to represent 0 and 1
SCI Interfacing - the SCI uses 0 V and 5 V to represent 0 and 1 - the RS232 signal Tx cannot be driven by the SCI TxD signal without translation - the RS232 signal Rx cannot drive the SCI RxD signal without translation - voltage level translation is required for the SCI signals to drive and be driven by the RS232 signals - Companies such as MAXIM and Motorola provide RS232 driver and receiver chips that perform the required voltage translation - MAX232 from MAXIM is a RS232 driver chip that operates off a single 5V power supply
501
MAX232 signals
502
Interfacing the 68HC11 SCI to the RS232 using the MAX232 chip and implements the
NULL modem connection so that this connection can talk to a PC directly.
503
Example 9.4 Write a subroutine that initialize the 68HC11 SCI subsystem to operate with
the following parameters: baud - 1 start bit, 8 data bits, and 1 stop bit - no interrupt for receive and transmit - enable receive and transmit - idle line wakeup - do not send break Solution: regbas equ $1000 baud equ $2B sccr1 equ $2C sccr2 equ $2D on_sci pshx psha ldx #regbas ldaa #$30 staa baud,X ldaa #0 staa sccr1,X ldaa #0C staa sccr2,X pula pulx rts - to choose 9600 baud write $30 into BAUD - for the remaining parameters, write $00 and $0C into SCCR1 and SCCR2
504
Example 9.5 Write a subroutine to send break to the communication port controlled by the
SCI subsystem. The duration of the transmitted break is approximately 200,000 E clock cycles. Solution: - A break can be sent by setting the bit 0 of SCCR2 to 1. As long as this bit is 1, the SCI will keep sending out break characters. regbas EQU $1000 SCCR2 EQU $2D sendbrk PSHX LDX #regbas BSET SCCR2,X $01 ; set send break bit * the following 3 instructions create a delay of about 100 ms LDY #28751 txwait DEY BNE txwait BCLR SCCR2,X $01 ; clear the SBK bit of SCCR2 PULX RTS
505
C Function to Send Break for 100 ms
void send_break ( ) { char i; SCCR2 |= 0x01; /* set the bit that triggers send break */ TFLG1 = 0x40; /* clear OC2 F flag */ TOC2 = TCNT ; /* start an OC2 operation with 10 ms delay */ for (i = 0; i < 10; i ++) { /* wait for 100 ms */ while (!(TFLG1 & 0x40)); TFLG1 = 0x40; TOC2 += 20000; } SCCR2 &= 0xFE; /* stop send break */
506
Example 9.6 Write a subroutine to output a character from the SCI subsystem
using the polling method. The character to be output is in accumulator A. Solution: The subroutine will wait until the TDRE bit is set to 1 and then send out the character. regbas EQU $1000 SCSR EQU $23 ; offset of SCSR from regbas SCDR EQU $2F ; offset of SCDR from regbas TDRE EQU $80 ; mask to select the TDRE bit of SCSR SCIputch PSHX LDX #regbas BRCLR SCSR,X TDRE * ; wait until transmit data register is empty ANDA #$7F ; clear bit 7 STAA SCDR,X ; send the character PULX RTS In C language, #define TDRE 0x80 void sci_putch (char xch) { while (!(SCSR & TDRE)); SCDR = xch & 0x7F; }
507
Example 9.7 Write a subroutine to input a character from the SCI subsystem using the
polling method. The character will be returned in accumulator A. Solution: regbas EQU $1000 SCSR EQU $23 ; offset of SCSR from regbas SCDR EQU $2F ; offset of SCDR from regbas RDRF EQU $20 ; mask to select the RDRF bit of SCSR SCIgetch PSHX LDX #regbas BRCLR SCSR,X RDRF * ; wait until RDRF bit is 1 LDAA SCDR,X ; read the character PULX RTS In C language, #define RDRF 0x20 char sci_getch ( ) { while (!(SCSR & RDRF)); /* wait until the RDRF flag is set */ return SCDR; }
508
Serial Communication Interface Chips
- A general-purpose microprocessor needs an external serial interface chip to communicate with other computer. - The 68HC11 needs external serial communication chips if it needs to talk to two or more DTEs. - The Motorola 6850 ACIA, Intel 8251, Zilog Z8530, and Rockwell R6551 are among the popular serial communication chips - Serial communication chips are also called universal asynchronous receiver and transmitter (UART) - The Motorola 6850 is used in the EVB to implement the terminal port
509
The Motorola 6850 ACIA - was designed to work with Motorola 8-bit microprocessors - can also work with the family microprocessors and also the 68HC11 - has two 8-bit data registers, one each for receive and transmit - has a programmable control register and a read-only status register - the register select input in conjunction with the R/W input to select one of the four registers 4 TxCLK 12 14 VCC Table 8.4 MC6850 Register Selection Enable 13 R/W 6 Reg Sel R/W Register Tx Data Register Rx Data Register Control Register Status Register 8 TxData CS0 10 CS1 24 9 CTS CS2 11 Reg Sel 23 DCD 7 6850 IRQ 5 22 RTS D0 D1 D2 D3 D4 D5 D6 D7 21 2 RxData 20 19 18 17 1 VSS 16 3 15 RxCLK
510
Control register
511
Status Register IRQ: interrupt request flag PE: parity error
OVRN: overrun flag FE: frame error flag CTS: clear to send flag that reflects the current level of the CTS input from a modem DCD: data carrier detect flag. This bit goes high when the DCD input from the modem goes high (indicates no carrier condition) TDRE: transmit data register empty RDRF: receive data register full
512
ACIA Transmit Operation Sequence
- the CPU reads the ACIA as a result of an interrupt or polling sequence - the CPU writes a character into the TDR if the TDRE bit of the status register is 1 - the ACIA transfers the character to the transmit shift register to serialize the character - the transmitter adds start bit, stop bit(s) and optionally parity bit to the serialized character before sending it to the TxData pin ACIA Receive Operation Sequence - the RxCLK clock which is either 1 or 16 or 64 times the bit rate is used to detect the arrival of a start bit - for the divide-by-16 or divide-by-64 counter divide factor, the start bit is detected by 8 or 32 consecutive low samples from the RxData pin - the ACIA receiver detects the start bit - the ACIA shifts in the character and discards the stop bit(s) - the ACIA records parity, receiver overrun, and framing errors in the status register ACIA Interrupts - one transmit interrupt source: transmit data register empty - three receive interrupt sources: receive data register full, receiver overrun, and data carrier detect goes high
513
Interfacing ACIA to the 68HC11
- the 68HC11 should be configured to operate in expanded mode - address space should be assigned to the ACIA - an example of circuit connection is shown in Figure 9.17
515
Example 9.9 Implement the null modem connection to the ACIA so that the 68HC11 can
talk to a PC via a straight-through RS232 cable and connector. This implementation should allow the user to select from the following baud rates: 300, 600, 1200, 2400, 4800, and 9600. Solution: - A crystal oscillator will be needed to generate an accurate and stable clock signal. A MHz crystal oscillator is used in this example. - A Schmidt-Trigger inverter circuit will be used to convert the sinusoidal output of the oscillator to a square wave. The 74HC14 is used. - A ripple counter is needed to provide a choice of baud rates. A 74HC4040 is used. By feeding the output of the 74HC14 to the 74HC4040, the frequencies of Q1-Q7 are MHz, MHz, MHz, MHz, MHz, MHz, and MHz. - Choosing 64 as the divide factor for the receive clock, baud rates of 9600, 4800, 2400, 1200, 600, and 300 are obtained.
517
- Use a MAX232 to perform voltage level translation and implement the Null modem
connection as shown in Figure 9.20.
518
Example 9.10 Write an instruction sequence to configure the ACIA in Figure 9.20 to operate
with the following parameters: - disable receive and transmit interrupts - counter divide factor is 64 - data format is 8 data bits, 1 stop bit, and no parity Solution: - To disable receive interrupts, clear the bit 7 of the ACIA control register. - To disable transmit interrupt, set bits 6 and 5 of the ACIA control register to 00 or 11. - For the chosen data format, set bits 4-2 of the control register to 101. - Set bits 1-0 of the control register to 10 to select the specified divide factor. - The address space assigned to the ACIA is $9800-$9FFF. acia_ini EQU $16 LDAA #acia_ini STAA $9800
519
A Terminal I/O Package for ACIA
ONACIA initializes the ACIA control register GETCH returns a character in accumulator A from the ACIA receive data register PUTCH writes the contents of accumulator A into the ACIA transmit data register GETSTR inputs a string that is terminated by a carriage return (CR). The string is to be stored in the buffer pointed to by Y. PUTSTR outputs a Null-terminated string pointed to by Y NEWLINE outputs a CR/LF character pair to the terminal CHPRSNT clears the Z bit in CCR to 0 if a character is present in the ACIA receive data register; otherwise sets the Z flag to 1. PUTHEX prints in 2 hex digits the 8-bit contents of A ECHOFF turns off keyboard input echoing (to the screen) ECHO turns on keyboard input echoing (to the screen) LFON expands a CR into CR/LF pair and expands a LF into LF/CR pair LFOFF turns off newline expansion
520
Constant definitions for the ACIA I/O package
ACIA equ $9800 ; base address of the ACIA CR equ $0D ; ASCII code of carriage return LF equ $0A ; ASCII code of line feed TDRE equ $02 ; mask to select the transmit data register empty flag RDRF equ $01 ; mask to select the receive data register full flag control equ $0 ; offset of the ACIA control register from its base address status equ $0 ; offset of the ACIA status register from its base address xmit equ $01 ; offset of the ACIA transmit data register from its base address rcv equ $01 ; offset of the ACIA receive data register from its base address masterst equ $03 ; value to reset ACIA control register ctl_ini equ $16 ; value to initialize the ACIA control register ONACIA pshx psha ldx #ACIA ldaa #masterst ; reset the ACIA staa control,X ; “ ldaa #ctl_ini ; set up ACIA parameters pula pulx rts
521
In C language, we need to add the following declaration to the hc11
In C language, we need to add the following declaration to the hc11.h file so that we can use symbols to access ACIA registers: #define ACIA_CTRL *(unsigned char volatile *)(0x9800) #define ACIA_STAT *(unsigned char volatile *)(0x9800) #define ACIA_XMIT *(unsigned char volatile *)(0x9801) #define ACIA_RCV *(unsigned char volatile *)(0x9801) ACIA initialization in C language void on_acia ( ) { ACIA_CTRL = 0x03; /* master reset ACIA */ ACIA_CTRL = 0x16; /* configure ACIA parameters */ }
522
Flowchart of Getch
523
GETCH PSHX PSHB LDX #ACIA * The following instruction checks framing, parity, and overrun errors retry BRCLR status,X $70 noerr JSR ONACIA ; reset ACIA BRA retry * The next instruction checks if receive data register is full noerr BRCLR status,X RDRF retry getit LDAA rcv,X ; read the character ANDA #$7F ; mask out bit 7 LDAB echo ; is echo flag on? BEQ quit ; “ JSR PUTCH ; echo the character quit PULB PULX RTS
524
C Language Version of Getch
char getchar ( ) { char xch; while (ACIA_STAT & 0x70) { on_acia ( ); } while (!(ACIA_STAT & 0x01)); /* wait until receive data register is full */ xch = ACIA_RCV & 0x7F; /* mask out parity bit */ if (ECHO_ON) putchar (xch); /* echo the character to the screen */ return xch;
525
Flowchart of PUTCH routine
526
PUTCH BSR outch TST autolf ; check auto line feed flag BEQ quit ; prepare to return if not CMPA #CR ; does A contains a CR? BNE chklf ; go and check LF LDAA #LF ; also output a LF BSR outch ; “ BRA quit chklf CMPA #LF ; does A contains a LF? BNE quit ; prepare to return if not LDAA #CR ; also output a CR BSR outch quit RTS outch LDX #ACIA BRCLR status,X TDRE * ; wait until xmit empty STAA xmit,X ; output the character RTS
527
C Function that Outputs A Character
char auto_lf; void outchar (xch) #define CR 0x0D; { #define LF 0x0A; while (!(ACIA_STAT &0x02)); void outchar (char xch); ACIA_XMIT = xch; void putchar (char xch); } { outchar (xch); if (auto_lf) { switch (xch) { case CR: outchar (LF); break; case LF: outchar (CR); default: break; }
528
GETSTR PSHA gsloop JSR GETCH ; get a character CMPA #CR ; is it a carriage return? BEQ gfinis ; if yes, then it is the end of the string STAA 0,Y ; save the character INY ; move the pointer BRA gsloop gfinis LDAA #00 ; add a Null to the end of the string STAA 0,Y ; “ PULA RTS PUTSTR PSHA psloop LDAA 0,Y BEQ pfinis ; is this the end of the string? JSR PUTCH ; if not, output the character INY ; move to the next character BRA psloop pfinis PULA
529
GETSTR Function in C void getstr (char *ptr) { char xch; while ((xch = getchar ( )) != ‘\n’) *ptr++ = xch; *ptr = ‘\0’; } PUTSTR Function in C void putstr (char *ptr) while (*ptr) { putchar (*ptr); ptr ++; } }
530
NEWLINE PSHA LDAA #$01 ; set the auto linefeed expansion flag STAA autolf ; “ LDAA #CR ; output a carriage return JSR PUTCH ; output a CR which will be expanded into CR/LF pair PULA CLR autolf ;clear the auto line feed expansion flag RTS In C language, void newline ( ) { auto_lf = 1; /* set auto-linefeed flag */ putchar (CR); auto_lf = 0; }
531
CHPRSNT PSHA PAHX LDX #ACIA LDAA status,X BITA #RDRF ; test the RDRF flag to update the Z flag of CCR PULX PULA RTS In C language, int chprsnt ( ) { if (ACIA_STAT & 0x01) return 1; else return 0; }
532
PUTHEX PSHX PSHB PSHA TAB ; make a copy of A in B LSRB ; shift the upper hex digit LSRB ; to the lower half of B LSRB ; “ LDX #hexdig ; place the address of the hex digit table in X ABX ; point X to the ASCII code of the upper hex digit in A LDAA 0,X ; get the ASCII code JSR PUTCH ; output the upper hex digit PULB ; put A in B again PSHB ; restore the stack ANDB #$0F ; mask out the upper digit LDX #hexdig ; place the address of the hex table digit in X ABX ; point X to the ASCII code of the lower hex digit in A LDAA 0,X ; get the ASCII code of the lower hex digit JSR PUTCH ; output the hex digit PULA PULB PULX RTS hexdig FCC “ ABCDEF” ; hex digits ASCII code table
533
PUTHEX Function in C Language
char hex_tab [16] = {‘0’, ‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’, ‘A’, ‘B’, ‘C’, ‘D’, ‘E’, ‘F’}; void puthex (xch) { char xx; xx = xch & 0xF0; /* mask out the lower 4 bits */ xx = xx >> 4; putchar (hex_tab[xx]); xx = xch & 0x0F; /* mask out the upper 4 bits */ }
534
ECHOFF CLR echo ; turn off input echoing
RTS ECHON LDAA #1 STAA echo ; turn on input echoing LFON LDAA #1 STAA autolf ; turn on auto line feed expansion LFOFF CLR autolf ; turn off auto line feed expansion echo RMB 1 ; input echo flag autolf RMB 1 ; line feed expansion flag END
535
Chapter 10: 68HC11 Serial Peripheral Interface
The 68HC11 Microcontroller Han-Way Huang Minnesota State University, Mankato
536
Why SPI? - The number of I/O port pins are limited on an 8-bit microcontroller. - It is desirable to implement more I/O functions on the same number of port pins. - Many I/O devices do not require high speed. - SPI allows more I/O functions to be supported on the 68HC11. A Summary of the 68HC11 SPI System - Two types of devices are involved in data transfer in the SPI format: master and slaves - Multiple SPI compliant devices can be interconnected - The master device initiates data transfer and also generates the clock signal required for data transfer synchronization - The 68HC11 SPI is often used for I/O port expansion, and interfacing with peripheral devices such as LED/LCD display drivers, phase-locked loop chips, A/D and D/A converters, serial EEPROMs, serial SRAMs, etc.
537
SPI Pins - SS/PD5: slave select - SCK/PD4: serial clock - MOSI/PD3: master out slave in - MISO/PD2: slave out master in
538
SPI-Related Registers
1. The Serial Peripheral Control Register (SPCR) SPIE: SPI interrupt enable SPE: SPI enable DWOM: port D wired-or mode select MSTR: SPI master or slave select CPOL: clock polarity. 1: SCK idle high, 0: SCK idle low CPHA: SCK clock phase. Control the clock-data relationships between the master and slave. CPHA and CPOL must be used together. See Figure 9.1. SPR1 & SPR0: SPI clock rate select
540
Serial Peripheral Status Register (SPSR)
Port D Data Direction Register (DDRD)
541
SPI Circuit Connection
1. Single master single slave
542
2. SPI Single master and multiple slaves circuit connection I
- The SPI master can selectively exchange data with any slave. - By disconnecting the MISO pin, the master can output data to one or multiple slaves at the same time.
543
3. SPI Single master and multiple slaves circuit connection II
- All slaves are connected into a large shift register chain. - The master cannot selectively exchange data with a single slave.
544
SPI Data Transfer 1. The procedure
- An SPI transfer is initiated by writing data to the shift register in the master SPI device. - Data is circuited 8 bit positions; thus data is exchange between the master and the slave. - The master SPI device sends out 8 pulses from the SCK pin to synchronize data transfer. - After 8 bits have been transferred, the SPIF flag of the SPSR register will be set to 1. 2. Error conditions - write collision: a write is performed during an SPI data transfer. The write will be unsuccessful and the WCOL bit of the SPSR register will be set to 1. - mode fault: the SS input of a master is asserted low. The SPI master that has a mode fault will: (1) generate an SPI interrupt if SPIE = 1 (2) clear SPE flag to disable the SPI (3) clear the MSTR bit forcing itself into the slave mode (4) force the DDRD bits to zeros for the four SPI pins.
545
3. The program to transfer data from the master to a slave
regbas equ $1000 ; base address of the I/O register block SPDR equ $2A ; offset of SPDR from regbas SPCR equ $28 ; offset of SPCR from regbas SPSR equ $29 ; offset of SPSR from regbas DDRD equ $09 ; offset of DDRD from regbas SPI_DIR equ $38 ; value to set SS, SCK and MOSI pins for output and MISO for input SPI_INI equ $54 ; value to initialize the SPI which will enable SPI, disable SPI * ; interrupt, configure port D pins as normal CMOS pins, select * ; master mode, choose the falling edge of SCK to shift data, and * ; sets data rate to 1 Mbits/sec at 2 MHz E clock ORG $00 data RMB $10 ; a data buffer . ldx #regbas ldaa #SPI_DIR staa DDRD,X ; set port D directions ldaa #SPI_INI staa SPCR,X ; initialize the SPI operation parameters ldaa data staa SPDR,X ; start SPI transfer wait ldab SPSR,X ; wait for data to be sent out bpl wait ; “
546
3. The program to read data from a slave
ldx #regbas ldaa #SPI_DIR staa DDRD,X ldaa #SPI_INI staa SPCR,X staa SPDR,X ; start an SPI transfer here ldab SPSR,X ; wait until 8 bits have been shifted in bpl here ; “ ldaa SPDR,X ; place the byte in A .
547
Simulating the SPI If data is shifted on the falling edge of the clock signal: Step 1: Set the clock to high. Step 2: Apply the data bit on the port pin that is connected to the serial data input pin of the peripheral device. Step 3. Pull the clock to low. Step 4. Repeat steps 1 to 3 for as many times as needed. If the rising edge is used to shift data, then - set clock to low in step 1 - set clock to high in step 3
548
Shift register HC589
549
HC589 Operation 1. The parallel data inputs (A,…,H) will be loaded into the data latch on the rising edge of the latch clock. 2. When the serial shift/parallel load signal is low, the data in the data latch will be loaded into the shift register. Otherwise, the shift register is enabled to shift. 3. When the shift register is enabled to shift, the serial data input SA will be shifted into the shift register and the data on stage H will be shifted out from pin QH. 4. The output enable signal (pin 10) must be low in order for data at stage H be driven out from pin QH. Application of HC589 - to expand the number of parallel input ports of 8-bit microcontrollers. - convert parallel data into serial format
550
Interfacing the HC589 to the SPI
Method 1.
551
Method I (continued) procedure for data transfer: Step 1. Program the DDRD register to configure SCK, TxD, and SS pins for output and the MISO pin for input. Step 2. Program the SPCR register to enable the SPI function and set up other parameters. Step 3. Set the LC pin to low and then pull it to high; this will load the external data into the data latch in parallel. Step 4. Set the SS pin to low to select the parallel load mode, which will load the contents of the data latch into the shift register. Step 5. Set the SS pin to high to select the serial shift mode. Step 6. Write a byte into the SPDR register to trigger eight SCK clock pulses to shift in 8 bits. Step 7. Repeat step 6 as many times as needed, and save the data in a buffer.
552
Example 10.1 Write a program to input 8 bytes from 8 external HC589s connected as shown
in Figure 10.6 and store the data at locations $00-$07. Solution: Configure the SS, SCK, MOSI, and TxD pins for output and MISO and RxD pins for input -- write the value % ($3A) into DDRD. Write the value % ($50) into the SPCR register to: 1. disable SPI interrupt 2. enable the SPI 3. set port D pins for normal CMOS output pins (not open drain) 4. use the rising edge of the SCK signal to shift data 5. select a 1-Mbits/sec data rate regbas equ $1000 PORTD equ $08 DDRD equ $09 SPCR equ $28 SPSR equ $29 SPDR equ $2A SPCR_INI equ $50 SPI_DIR equ $3A
553
org $C000 ldx #regbas ldaa #SPI_DIR staa DDRD,X ; configure SPI pin directions ldaa #SPCR_INI staa SPCR,X ; initialize SPI operation parameters * The following two instructions load data into HC589s in parallel bclr PORTD,X $02 ; pull TxD (LC) to low bset PORTD,X $02 ; pull TxD (LC) to high bclr PORTD,X $20 ; pull SS pin to low to select parallel load mode and load ; the contents of the data latch into the shift register bset PORTD,X $20 ; pull SS pin to high to select serial shift mode ldab #8 ; loop count for transferring 8 bytes ldy #$0000 ; set Y to point to the buffer loop staa SPDR,X ; trigger SPI data transfer brclr SPSR,X $80 * ; wait until 8 bits have been shifted ldaa SPDR,X ; get one byte staa 0,Y ; save the data decb ; decrement loop count bne loop end
554
In C language, #include <hc11.h> main ( ) { char buffer[8], i; DDRD = 0x3A; /* configure port D pins directions */ SPCR = 0x50; /* configure SPI parameters */ PORDT &= 0xFD; /* create a rising edge on the TxD pin */ PORTD |= 0x02; /* to load data into data latch */ PORTD &= 0xDF; /* transfer data from data latch to shift register */ PORTD |= 0x20; /* select serial shift mode */ for (i = 0; i < 8; i++) { SPDR = 0x00; /* shift data in from the MISO pin */ while (!(SPSR & 0x80)); /* wait for data to shift in */ buffer [i] = SPDR; } return 0;
555
Interfacing the HC589 to the SPI -- Method II
556
Procedure for data transfer (method II)
Step 1. Program the DDRD register to set the directions of the MISO, SCK, SS, and TxD pins. Step 2. Program the SPCR register to configure the SPI operation parameters. Step 3. Set the TxD pin to low and then pull it to high to load external data into the data latch in parallel. Step 4. Set the SS pin to low to select the parallel load mode, which will load the contents of the data latch into the shift register. Step 5. Pull the SS pin to high to select the serial shift mode. Step 6. Set the port B that controls the specified HC589 to low to enable the shift register to output serial data. The remaining port B pins are set to high. Step 7. Write a byte into the SPDR register to trigger eight pulses from the SCK pin to shift in the serial data. The external data is now in the SPDR register and ready for use. Step 8. Repeat steps 6 and 7 as many times as needed.
557
Shift Register HC595
558
HC595 Operation - The shift register accepts serial data and provides a serial output. - The serial data input (A) is shifted into the shift register on the rising edge of the shift clock. - The data in the shift register will be loaded into the output latch on the rising edge of the latch clock. - A low on the output enable pin allows data from the latch to be presented at the output pins QA-QH. - The serial output SQH does not have tri-state capability. - Multiple HC595s can be cascaded to expand the number of parallel output ports for the 68HC11.
559
Interfacing HC595 to the SPI -- Method I
560
Method I (continued) Data transfer procedure Step 1. Program the DDRD register to configure SPI pin directions. Step 2. Program the SPCR register to set up appropriate SPI operating parameters. Step 3. Write a byte into the SPDR register to trigger eight pulses from the SCK pin. Step 4. Repeat step 3 as many times as needed. Step 5. Set the SS pin to low and then pull it to high to transfer the byte in the shift register into the output latch. After this step, the output latch contains valid data. Example 9.2 Write a program to output three bytes to the first three HC595s in Figure 9.8. Solution: regbas equ $1000 PORTD equ $08 DDRD equ $09 SPCR equ $28 SPDR equ $2A SPSR equ $29
561
SPI_DIR equ $3A ; value to configure SPI pin directions
SPCR_IN equ $50 ; value to enables SPI, disables SPI interrupt, chooses rising * ; edge of SCK to shift data, selects normal port D pins, * ; and sets data rate to 1 Mbits/sec. K equ 3 org $00 buffer fcb $11,$22,$33 org $C000 ldx #regbas ldaa #SPI_DIR staa DDRD,X ; configure pins SS, MOSI, SCK, and TxD for output ldaa #SPCR_IN staa SPCR,X ; configure SPI operation parameters ldab #K ; set up loop count ldy #buffer ; set Y as a pointer to the buffer ch_loop ldaa 0,Y ; send out one byte via SPI function staa SPDR,X ; “ brclr SPSR,X $80 * ; wait until the byte is shifted out iny ; move the buffer pointer decb ; decrement the loop count bne ch_loop bclr PORTD,X $20 ; create a rising edge on SS pin to load data into output bset PORTD,X $20 ; latch end
562
Interfacing the HC595 to the SPI -- Method II
563
Method II: Data transfer procedure Step 1. Program the DDRD register to set up SPI pin directions. Step 2. Program the SPCR register to enable the SPI subsystem, select the data rate, select the rising edge of SCK signal for data shifting, select master mode, and disable interrupt. Step 3. Write a byte into SPDR to trigger SPI data transfer. Step 4. Set the PBi pin to low and then pull it to high to load the byte from the shift register of the HC595 i into its output latch.
564
The Seven-Segment Display Driver Chip MC14489
565
MC14489 Pins Data In: A serial data input pin. Clock: The rising edge of this signal is used to shift data into the shift register. The highest shift clock frequency is 4 MHz. Enable: External data can be entered when this signal is low. The data are loaded from the shift register into the latches on the rising edge of this signal. a thru h: Seven-segment outputs for driving seven segments and decimal point LEDs. Bank 1..5: Digit select pins. The MC14489 can drive up to five seven-segment displays, but only one seven-segment display is lighted at any time. The display to be lighted is selected by these pins. Rx: External current-setting resistor. The relationship between the segment current and Rx is shown in Figure
567
The MC14489 Operation - The configuration register controls the MC14489 operation. - Two operation modes: hex mode and special decode. The decode function is shown in Table 10.1. - Displays can be made dimmer or brighter by clearing or setting the first bit of the display data sent to the MC14489.
569
Interfacing the MC14489 to the 68HC11 SPI
570
- One byte of configuration information and 3 bytes of display data must be
sent to the MC14489 in Figure - The 4 most significant bits control the brightness and display of h segments as shown in Figure
571
Example 10. 3 Write a program to display 997
Example 10.3 Write a program to display from bank 5 to bank 1 in Figure Use the normal brightness to display these five digits. Solution: The control byte to be written into the configuration register is as follows: bit 7: no decode, set to 0 bit 6: no decode, set to 0 bit 5: bank 5 hex decode, set to 0 bit 4: bank 4 hex decode, set to 0 bit 3: bank 3 hex decode, set to 0 bit 2: bank 2 hex decode, set to 0 bit 1: bank 1 hex decode, set to 0 The display data format is
572
The Configuration of SPCR register:
bit 7 (SPIE): set to 0 to disable interrupt bit 6 (SPE): set to 1 to enable SPI function bit 5 (DWOM): set to 0 to choose normal port D pins bit 4 (MSTR): set to 1 to select master mode bit 3 & 2 (CPOL & CPHA): set to 00 to use rising edge to shift data out bit 1 & 0 (SPR1 & SPR0): set to 00 to choose 1 MHz shift rate regbas equ $1000 PORTD equ $08 DDRD equ $09 SPCR equ $28 SPDR equ $2A SPSR equ $29 SP_DIR equ $3A ; value to configure SPI pins directions SPCR_IN equ $50 ; value to set up the specified SPI operation parameters
573
ORG $00 disp_dat FCB $B9,$97,$04 ORG $C000 LDX #regbas LDAA #SP_DIR STAA DDRD,X ; configure SPI pin directions LDAA #SPCR_IN STAA SPCR,X ; initialize the SPI parameters BCLR PORTD,X $20 ; enable data shifting to MC14489 LDAA #$01 STAA SPDR,X ; send out configuration data to MC14489 BRCLR SPSR,X $80 * ; wait until configuration data has been shifted out BSET PORTD,X $20 ; latch data into configuration register BCLR PORTD,X $20 ; enable SPI data transfer to MC14489 LDY #disp_dat LDAB #3 loop LDAA 0,Y STAA SPDR,X BRCLR SPSR,X $80 * INY DECB BNE loop BSET PORTD,X $20 ; load data into display data register END
574
A C Program for Sending Data to MC14489
#include <hc11.h> main ( ) { int i; unsigned char disp_dat[3] = {0xB9, 0x97, 0x04}; DDRD = 0x3A; SPCR = 0x50; PORTD &= 0xDF; /* enable SPI data transfer to MC14489 */ SPDR = 0x01; /* send out configuration data */ while (!(SPSR & 0x80)); /* wait until data have been shifted out */ PORTD |= 0x20 /* load data into configuration register */ PORTD &= 0xDF; /* enable SPI transfer to MC14489 */ for (i = 0; i < 3; i++) { SPDR = disp_dat [i]; while (!(SPSR & 0x80)); } PORTD |= 0x20; } /* load data into display data register */
575
Cascading MC14489s - Connect the Data Out pin of one MC14489 to the Data In pin of the next MC14489. - To configure n MC14489s, we need to send out 3 × (n -1) + 1 bytes of data to the MC14489s. Only n bytes are used to configure the MC14489s. - A circuit of cascading three MC14489s is illustrated in Figure
576
Three bytes of configuration data must be sent to three MC14489s:
Example 10.8 Write a program to display the following information (temperature at 14:20 of Aug. 2nd, 1999) on the 15 seven-segment displays driven by three MC14489s as shown in Figure 10.17: 30.5oC Solution: - Use the special decode of character F to represent the character for degree. - Represent all other characters using normal decode method. - The left-most five digits are displayed by the MC14489 #1. - The middle five digits are displayed by the MC14489 #2. - The right-most five digits are displayed by the MC14489 #3.
577
Configurations of three MC14489s
C7: set to 0 to select no decode C6: set to 1 to select special decode (display degree character on bank 2) C5..C3: set to 0 to select hex decode C2: set to 1 to select special decode C1: set to 0 to select hex decode C0: set to 1 to select normal mode MC14489 #2 & #3: C7 & C6: set to 0 to select no decode C5..C1: set to 0 to select hex decode - The configuration data for the MC14489 #3 should be sent out first. - The complete configuration data is 01xxxx01xxxx45, where x strands for don’t care and should be set to 0.
578
Display Data for MC14489 #1 Display Data for MC14489 #2 Display Data for MC14489 #3
579
REGBAS EQU $1000 SPSR EQU $29 SPDR EQU $2A SPCR EQU $28 PORTD EQU $08 DDRD EQU $09 ORG $C000 LDX #REGBAS LDAA #$3A STAA DDRD,X ; configure SPI pin directions LDAA #$50 STAA SPCR,X ; configure SPI parameters LDAB #7 BCLR PORTD,X $20 ; enable SPI transfer to MC14489s LDY #conf_dat ; set Y to point to configuration data loop1 LDAA 0,Y STAA SPDR,X BRCLR SPSR,X $80 * ; wait until a byte has been shifted out INY DECB BNE loop1 BSET PORTD,X $20 ; load data into configuration registers
580
BCLR PORTD,X $20 ; enable SPI transfer to MC14489s
LDY #disp_dat LDAB #9 loop2 LDAA 0,Y STAA SPDR,X BRCLR SPSR,X $80 * INY DECB BNE loop2 BSET PORTD,X $20 ; load data into display data register … ; do something else conf_dat DB $01,$00,$00,$01,$00,$00,$45 disp_dat DB $88,$02,$99,$81,$20,$00,$C2,$55,$FC
581
In C language #include <hc11.h> main ( ) { int i; unsigned char conf_dat [ ] = {0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x45}; unsigned char disp_dat [ ] ={0x88, 0x02, 0x99, 0x81, 0x20, 0x00, 0xC2, 0x55, 0xFC}; DDRD = 0x3A; SPCR = 0x50; PORTD &= 0xDF; /* enable SPI transfer to MC14489s */ for (i = 0; i < 7; i++) { SPDR = conf_dat[i]; while (!(SPSR & 0x80)); } PORTD |= 0x20; /* load data into configuration registers */ for (i = 0; i < 9; i++) { SPDR = disp_dat [i]; while (!(SPSR 7 0x80)); PORTD |= 0x20; /* load data into display data registers */ return 0;
582
Liquid Crystal Displays (LCDs)
- LCDs are often multiplexed to save connection pins. - Motorola has LCD drivers that drives 1/4 multiplexing LCDs. - In a 1/4 multiplexing LCD, each character is represented by a multiple of four segments. - An LCD display that displays BCD digit consists of seven segments and an optional decimal point. - An LCD segment is turned on and off by controlling the backplane and frontplane voltages. - Each BCD digit is controlled by two frontplane and four backplane signals. - There is no standard for backplane and frontplane connections on multiplexed LCD displays.
583
The MC145000 and MC145001 LCD drivers
585
Operation of the MC145000 - Display data bits are shifted in on the falling edge of the data clock. - Data in the shift register are loaded into the 48-bit latch at the beginning of each frame period. - The frame period is the time during which all the LCD segments are set to the desired on or off states. - The data in the shift register of the LCD driver is loaded into the latch that drives the frontplane outputs when the frame-sync pulse is high. - New data should not be shifted in in this period to avoid flicker. - Backplane waveforms are invariant. - The frontplane and backplane waveforms, FPn and BPn, are generated using the system clock and voltages from the V/3 generator circuit. - Examples on backplane and frontplane waveforms are given in Figure 10.26, Operation of the MC145001 - This unit consists of the same circuitry as the master unit, with two exceptions: it has no backplane driver circuitry, and its shift register and latch hold 44 bits.
589
Clock Signal Issue - OSCin is the input to the system clock circuit. - OSCout is the system clock output generated by the master unit. - The OSCout signal from the master unit is connected to the OSCin input of all slave units to synchronize updating of display data. - The oscillator frequency can be obtained from an external oscillator or by connecting an resistor between OSCin and OSCout. - The relationship between oscillator frequency and resistor value is shown in Figure
591
LCD display pattern - The LCD controller multiplexes four bits to drive the same frontplane output pin. - The master unit also activates the corresponding backplane output to turn segments on and off. - The bit locations (in the latch) that control the master unit LCD segments located at each frontplane-backplane intersection are shown in Table 10.3. - The order for shifting the segment patterns into the LCD driver is a, b, c, d, e, f, g, and h. - The hexadecimal representation of BCD digits LCD display patterns are shown in Table 10.3.
593
LCD driver system configuration
- One master and one or multiple slave LCD drivers can be cascaded when more than six digits are to be displayed (shown in Figure 10.30). - Data are shifted serially first into the master unit and then into the following slave units on the falling edge of the common data clock. - At the beginning of each frame period, the master unit generates a frame-sync pulse to synchronize to the master unit’s backplane drive circuit. - The master unit generates the backplane signals for all the LCD digits in the system.
594
An LCD from LXD -- part #69
595
- The backplane signal BP1 is assigned to pins 60 and 59.
- Ai, Bi, Ci, Di, Ei, Fi, Gi, and DP stand for the segments and decimal point of the ith digit. - A pin associated with some segment letter is a frontplane pin. - Up to 8 digits can be displayed using this LCD.
596
Using an MC145000 and an eight-digit LCD from LXD to display 6 digits
- The 1 MW resistance sets the oscillator frequency to 24 KHz. - The system frequency is obtained by dividing the previous frequency by 256 and is 94 Hz.
597
Example 10.5 Write a program to display 123456 on the LCD in Figure 10.33.
Solution: - Configure pins SS, MOSI, SCK, and Tx for output and the other port D pins for input. - Configure the SPI to operate with the following parameters: 1. SPI interrupt disabled 2. SPI function enabled 3. normal port D pins 4. master mode 5. shifting data using the falling edge of the SCK signal 6. 1 Mbits/sec data rate Write the value $54 into the SPCR register - Send 48 0s to the LCD driver to clear the LCD digits.
598
regbas EQU $1000 ; base address of I/O register block
DDRD EQU $09 ; offset of DDRD from regbas SPCR EQU $28 ; offset of SPCR from regbas SPSR EQU $29 ; offset of SPSR from regbas SPDR EQU $2A ; offset of SPDR from regbas DD_INI EQU $3A ; value to set the DDRD register SPCR_INI EQU $54 ; value to be written into the SPCR register ORG $00 digits FCB 1,2,3,4,5,6 ; digits to be displayed lp_cnt RMB 1 ; loop count ORG $C000 LDS #$3F ; set up stack pointer for EVB computer LDX #regbas LDAA #DD_INI STAA DDRD,X ; configure port D pin directions LDAA #SPCR_INI STAA SPCR,X ; configure SPCR register * The following 6 instructions send out 6 0’s to clear LCDs LDAB #6 loop CLRA STAA SPDR,X BRCLR SPSR,X $80 * ; wait for 8 bits to be shifted out DECB BNE loop
599
LDY #digits ; point Y to the start of the digit table
LDAB #6 STAB lp_cnt ; initialize the loop count loop1 LDAB 0,Y ; get the digit to be displayed PSHY ; save Y in the stack LDY #lcdndp ; place LCD pattern table address in Y ABY ; index into the LCD pattern table LDAA 0,Y ; get the LCD pattern from the table STAA SPDR,X ; send out the digit pattern BRCLR SPSR,X $80 * ; wait until the digit pattern has been shifted out PULY ; restore the value of Y from the stack INY ; move the digit pointer DEC lp_cnt ; decrement the loop count BNE loop1 . * The following lines contain the LCD display patterns of hexadecimal digits lcdndp FCB $EB,$60,$C7,$E5,$6C,$AD,$2F,$E0,$EF,$EC FCB $EE,$0A,$6A,$6B,$04,$00 END
600
In C Language, #include <hc11.h> main ( ) { int i; char digits [ ] = {1, 2, 3, 4, 5, 6}; hex_pat [ ] = {0xEB, 0x60, 0xC7, 0xE5, 0x6C, 0xAd, 0x2F, 0xE0, 0xEF, 0xEC, 0xEE, 0x0A, 0x6A, 0x6B, 0x04, 0x00}; DDRD = 0x3A; /* configure SPI pin directions */ SPCR = 0x54; /* configure SPCR register */ for (i = 0; i < 6; i++) { /* send out 0s to blank the screen */ SPDR = 0; while (!(SPSR & 0x80)); } for (i = 0; i < 6; i++) { /* send out digits 1..6 */ SPDR = hex_pat [digits [i]]; return 0;
601
The MC68HC68T1 Real-Time Clock with Serial Interface
Features: - Full clock features -- seconds, minutes, hours (AM/PM), day-of-week, date, month, year, auto leap year - 32 bytes general-purpose RAM for saving critical data - power control functions -- sensing power transition, performing power up and power down - burst mode for reading/writing successive addresses in clock/RAM - selectable crystal or 50/60 Hz line input frequency - clock registers utilize BCD data - watchdog circuit similar to COP - battery backup power supply input
602
68HC68T1 signals CLK OUT: buffered clock output; 7 selectable frequencies. CPUR: CPU reset. INT: interrupt. Activated when one of the following occurs: 1. power failure 2. preset alarm time occurs. 3. periodic interrupt SCK: serial clock for data shifting. Either the rising or falling edge can be used for data shifting. MOSI: master in slave out MISO: master in slave out SS: slave select PSE: power supply enable POR: power on reset LINE: line sense. XTAL IN, XTAL OUT: crystal input/output
603
On-Chip RAM and Registers
- 32 bytes of on-chip RAM and 13 registers - to access these RAM and registers, the CPU first sends in an 8-bit address and then performs the actual access - Each read/writable register and each RAM byte has two addresses: one for read and one for write - The address map of these registers and RAM bytes are shown in Figure - All timer counters and alarm registers are in BCD format (shown in Table 10.5).
605
Clock Control Register
Start/stop: a 1 enables the counter stages of the clock circuitry Line/XTAL: a 1 selects 50/60 Hz Line input to update the time XTAL Select: select crystal frequencies. 0 = MHz 1 = MHz 2 = MHz 3 = MHz 50 Hz/60 Hz: A 1 selects 50 Hz for line input. Otherwise, 60 Hz is selected. CLK OUT2-CLK OUT0: specify one of the seven frequencies to be used as the square wave output at the CLK OUT pin. 0 = Xtal 1 = Xtal/2 2 = Xtal/4 3 = Xtal/8 4 = disable 5 = 1 Hz 6 = 2 Hz 7 = 50/60 Hz for Line operation, 64 Hz for Xtal operation
606
Interrupt Control Register
Watch dog: When set to 1, the watchdog function is enabled. Power down: When set to 1, a power down operation is initiated. Power sense: When set to 1, this bit enables the Line input pin to sense a power failure. Alarm: When set to 1, the alarm function is enabled. When the alarm time is reached, the interrupt output is activated Periodic select: The frequency of the periodic output is selected by these four bits.
608
Status Register Watchdog. Set to 1 when a CPU failure is detected. First time up. Set to 1 by a power on reset. Interrupt true. Set to 1 when one of the three interrupts is valid. Power sense INT. Set to 1 when the power sense circuit generates an interrupt Alarm INT. Set to 1 when the contents of the seconds, minutes, and hours time time counters and alarm latches are equal. Clock INT. Set to 1 on a periodic interrupt.
609
Interfacing the 68HC68T1 to the 68HC11
- The corresponding pins of the 68HC11 and 68HC68T1 are connected together. - A battery is added to the 68HC68T1 so that important information can be kept when the line power is interrupted. - An alarm transducer is added and will be ringing at 4 KHz to remind the user that the preset alarm time has reached. - Only the timer function is used. - A KHz crystal oscillator is used to generate the clock signal to be used by the 68HC68T1. - Data transfer to/from the 68HC68T1 can occur one byte at a time or in multi-byte burst mode. - Each read or write cycle causes clock/calendar register or RAM address to automatically increment by 1.
610
Constant definition for the programming of 68HC68T1
regbas equ $1000 SPDR equ $2A SPCR equ $28 SPSR equ $29 DDRD equ $09 PORTD equ $08 ram_addr equ $80 ; starting address to write the RAM second_r equ $20 ; read address for seconds minute_r equ $21 ; read address for minutes hour_r equ $22 ; read address for hours day_wk_r equ $23 ; read address for day of week date_m_r equ $24 ; read address for date of month month_r equ $25 ; read address for month year_r equ $26 ; read address for year stat_reg equ $30 ; read address for status register clk_ctlr equ $31 ; read address for clock control register int_ctlr equ $32 ; read address for interrupt control register second_w equ $A0 ; write address for seconds minute_w equ $A1 ; write address for minutes hour_w equ $A2 ; write address for hours day_wk_w equ $A3 ; write address for day of week
611
date_m_w equ $A4 ; write address for date of month
month_w equ $A5 ; write address for month year_w equ $A6 ; write address for year s_alarm equ $A8 ; write address for seconds alarm m_alarm equ $A9 ; write address for minutes alarm h_year equ $AA ; write address for hours alarm clk_ctlw equ $B1 ; write address for clock control register int_ctlw equ $B2 ; write address for interrupt control register
612
The initialization of the SPI function
- Configure pins SS, CLK, MOSI, TxD for output and MISO and RxD for input. Write the value % into the DDRD register. - Choose the following SPI operating parameters: 1. disable SPI interrupt 2. enable SPI function 3. port D normal CMOS pins 4. master mode 5. rising edge of CLK for shifting data 6. 1 Mbits/sec data shifting rate Write the value $50 into the SPCR register. The instruction sequence to initialization the SPI system: ldx #regbas ldaa #$3A staa DDRD,X ldaa #$50 staa SPCR,X
613
Data transfer to and from the 68HC68T1
- Set the SS signal to high during the data transfer process. - Send the time of day information (7 bytes) and alarm information (3 bytes) in two separate burst mode transfer because these two blocks of information are not in contiguous addresses. - Reserve 10 bytes in SRAM of the 68HC11 to hold time-of-day and alarm information. * The following instruction sequence sends the time-of-day information to the 68HC68T1 org $00 clk_mgt rmb 10 ; block of memory to store time-of-day and alarm information org $C000 ldx #regbas bset PORTD,X $20 ; enable data transfer to the 68HC68T1 ldaa #second_w staa SPDR,X ; send the write address of seconds to the 68HC68T1 brclr SPSR,X $80 * ; wait until the byte is shifted out ldab #7 ; use accumulator B as the loop count ldy #clk_mgt ; Y points to the base address of time-of-day information LP1 ldaa 0,Y staa SPDR,X ; send out one byte information to the 68HC68T1 iny decb bne LP1 bclr PORTD,X $20 ; disable SPI transfer to the 68HC68T1
614
* The following instruction sequence sends out the alarm information to the 68HC68T1
bset PORTD,X $20 ; enable SPI transfer to the 68HC68T1 ldaa #s_alarm staa SPDR,X ; send out seconds alarm address brclr SPSR,X $80 * ; wait until the address has been shifted out ldab #3 ; use accumulator B as the loop count ldy #clk_mgt+7 ; Y points to the alarm information block LP2 ldaa 0,Y staa SPDR,X ; send out one byte of alarm information brclr SPSR,X $80 * ; wait until the byte is shifted out iny ; move to the next byte decb ; decrement the loop count bne LP2 bclr PORTD,X $20 ; disable SPI transfer to the 68HC68T1 * The following instruction sequence reads the status register of the 68HC68T1 bset PORTD,X $20 ; enable data transfer from the 68HC68T1 ldaa #stat_reg staa SPDR,X ; send out the address of the status register brclr SPSR,X $80 * ; wait until the address byte is shifted out staa SPDR,X ; start an SPI transfer to read the status register brclr SPSR,X $80 * ; wait until the status register is shifted in ldaa SPDR,X ; place the status register in accumulator A
615
Clock/Calendar portion
- consists of a long string of counters that are toggled by a 1-Hz input that can be derived from one of the three sources: 1. an external crystal oscillator applied between pins XTAL IN and XTAL OUT 2. an external frequency source applied to XTAL IN 3. a 50- or 60-Hz source connected to the LINE input - an AM/PM indicator is available; once set, it toggles at 12:00 AM and 12:00 PM.
616
Alarm operation - the alarm latches consist of seconds, minutes, and hours registers. - when the contents of alarm latches equal the values of the seconds, minutes, and hours time counters, an interrupt is generated. - the CLK OUT can be used to drive an alarm transducer. - the procedure for using the alarm function is as follows: 1. disable CLK OUT when the alarm time has not been reached. 2. enable the alarm interrupt. 3. when the alarm time is reached, the alarm interrupt-service routine enables a pulse output from the CLK OUT pin for some specific amount of time. - the alarm interrupt should be enabled and its procedure is: 1. enable the periodic interrupt of the 68HC68T1 2. set up the alarm time and then set up the alarm counter. The alarm counter is used to keep track of the amount of time that the alarm transducer has been turned on. 3. stay in a wait loop while checking if the alarm counter has been decremented to 0. If yes, turn off the alarm and reinitialize the alarm counter.
617
Alarm interrupt service routine
1. checks the cause of the interrupt by reading the status register 2. returns if the interrupt is periodic and the alarm is not turned on. 3. turns on the alarm transducer if the interrupt is caused by the alarm function. 4. decrement the alarm count by 1 and then returns if the interrupt is caused by periodic interrupt and the alarm transducer is on. The interrupt control register should be set up as follows for this application: - disable watchdog interrupt (clear bit 7) - disable power down (clear bit 6) - disable power sense (clear bit 5) - enable alarm interrupt (set bit 4 to 1) - set the periodic interrupt frequency to be 1 Hz (set bits 3-0 to 1100) The value % should be written into the interrupt control register.
618
The clock control and interrupt control registers can be initialized by using the burst mode:
ldx #regbas bset PORTD,X $20 ; enable data transfer to the 68HC68T1 ldaa #clk_ctlw staa SPDR,X ; send the write address of the clock control register brclr SPSR,X $80 * ; wait until the address is shifted out ldaa #$B4 ; disable CLK OUT when alarm time has not reached staa SPDR,X ; send out the clock control byte first_bt brclr SPSR,X $80 first_bt ; wait until the clock control byte is shifted out ldaa #$1C staa SPDR,X ; send out the interrupt control byte sec_bt brclr SPSR,X $80 sec_bt ; wait until the interrupt control byte is shifted out bclr PORTD,X $20 ; disable data transfer to the 68HC68T1 A flag is needed to indicate whether the alarm transducer has been turned on. The alarm counter and the alarm flag can be set up as follows: threemin equ 180 ; let the alarm transducer be turned on for three minutes alarmcnt rmb 1 ; memory location to store the alarm count alarmflg rmb 1 ; memory location used as alarm flag set_alct ldaa #threemin staa alarmcnt ; initialize alarm count to 180 clr alarmflg ; clear the alarm flag
619
Clock interrupt service routine
clk_ISR ldx #regbas bset PORTD,X $20 ; enable SPI transfer to the 68HC68T1 ldaa #stat_reg staa SPDR,X brclr SPSR,X $80 * ; wait until the address has been shifted out staa SPDR,X ; trigger an SPI transfer to read the status register brclr SPSR,X $80 * ; wait until the status register has been shifted in bclr PORTD,X $20 ; disable SPI transfer bset PORTD,X $20 ; re-enable SPI transfer so that new address can be sent out ldaa SPDR,X ; place the status register in A anda #$02 ; check the alarm interrupt bit beq periodic ; if interrupt is periodic go and check if the alarm flag is set ldaa #clk_ctlw ; send out the write address of the clock control register staa SPDR,X ; “ ldaa #% ; send a new control byte to the clock control register to turn staa SPDR,X ; on CLK OUT brclr SPSR,X $80 * ; wait until the new control byte is shifted out ldaa #1 staa alarmflg ; set the alarm flag bra exit ; prepare to return from interrupt
620
periodic ldaa alarmflg ; check the alarm flag
beq exit ; return if the alarm is not turned on dec alarmcnt ; decrement the alarm count if the alarm has been turned on bne exit ; if alarm is not zero then return * disable CLK OUT, reinitialize the alarm count and clear the alarm flag when alarm count * has been decremented to 0 ldaa #threemin staa alarmcnt clr alarmflg ; clear the alarm flag * To disable CLK OUT, write the value % into the clock control register ldaa #clk_ctlw staa SPDR,X ; send the write address to the 68HC68T1 brclr SPSR,X $80 * ; wait until the address has been shifted out ldaa #$B4 staa SPDR,X ; send out the new clock control byte brclr SPSR,X $80 * ; wait until the new clock control byte has been shifted out exit bclr PORTD,X $20 ; disable SPI transfer to the 68HC68T1 rti
621
Example 10. 6 For the circuit in Figure 10
Example 10.6 For the circuit in Figure 10.37, write a C function to send the current time- of-day and alarm time information to the 68HC68T1. This function must also enable the 68HC68T1 to generate periodic and alarm interrupt to the 68HC11. Solution: #define second_w 0xA0 /* seconds write address */ #define s_alarm 0xA8 /* write address for seconds alarm */ #define ccr_wad /* clock-control register write address */ init_68HC68T1 (char spi_dir, char spr_ctrl, char t_of_d [ ], char alarm, char ccon [ ]) { int i; DDRD = spi_dir; /* set up SPI pin diriections */ SPCR = spr_ctrl; /* initialize SPI parameters */ PORTD |= 0x20; /* enable SPI transfer to the 68HC68T1 */ SPDR = second_w; /* send the write address for seconds */ while (!(SPSR & 0x80)); /* wait until the byte is shifted out */ for (i = 0; i < 7; i+) { SPDR = t_of_d [i]; /* send the current time to 68HC68T1 */ while (!(SPSR & 0x80)); }
622
PORTD &= 0xDF; /* disable SPI transfer so that new address can be sent */
PORTD |= 0x20; /* enable SPI transfer to the 68HC68T1 */ SPDR = s_alarm; /* send the second alarm address to the 68HC68T1 */ while (!(SPSR & 0x80)); for (i = 0; i < 3; i++) { SPDR = alarm [i]; /* send new alarm time to the 68HC68T1 */ } PORTD &= 0xDF; SPDR = ccr_wad; /* send write address of clock control register */ for (i = 0; i < 2; i++) { /* send out clock and interrupt control info. */ SPDR = ccon[i]; while (!(SPSR 0x80));
623
Example 10.7 Write a main program and an interrupt service routine for the 68HC68T1.
The main program sets up the IRQ interrupt vector, calls the function in Example 10.6 to initialize the 68HC68T1, sets up alarm count, clears alarm flag, and enable the interrupt. The IRQ interrupt service routine will perform the operations described earlier. This program is to be run on the EVB, the EVBU, or the CMD-11A8 demo board. Solution: #include <hc11.h> #define stat_reg 0x30 /* read address of the status register */ unsigned char alarm_cnt, alarm_flg; unsigned char t_of_d [7], alarm [3], ccon [2]; void IRQ_ISR ( ); main ( ) { alarm_cnt = 180; alarm_flg = 0; . /* read the current time-of-day and alarm time here */ ccon[0] = 0xB4; /* clock control byte */ ccon[1] = 0x1C; /* interrupt control byte */ init_68HC68T1 (0x3A, 0x50, t_of_d [ ], alarm [ ], ccon [ ]);
624
*(unsigned char *)0xee = 0x7E; /* set up IRQ interrupt jump vector */
*(void (**)())0xef = IRQ_ISR; INTR_ON ( ); . /* do something else */ return 0; } #pragma interrupt_handler IRQ_ISR ( ); void IRQ_ISR ( ) { /* read the status register to identify the cause of interrupt */ PORTD |= 0x20; /* enable SPI transfer to the 68HC68T1 */ SPDR = stat_reg; /* send out status register read address */ while (!(SPSR & 0X80)); SPDR = 0x00; /* read the status register */ while (!(SPSR & 0x80)); PORTD &= 0xDF; /* disable SPI transfer */ if (SPDR & 0x20) { /* interrupt is caused by alarm time */ SPDR = ccr_wad; /* send out the clock-control register write address */ SPDR = 0xB3; /* turn on alarm device */
625
while (!(SPSR &0x80)); alarm_flg = 1; /* set this flag to indicate that alarm is turned on */ PORTD &= 0xDF; /* disable SPI transfer to 68HC68T1 */ return; } if (!alarm_flg) return; /* interrupt is caused by periodic interrupt and alarm is not on */ -- alarm_cnt; if (alarm_cnt) else { alarm_cnt = 180; alarm_flg = 0; PORTD |= 0x20; SPDR = clk_ctlw; /* send clock-control register write address */ while (!(SPSR & 0X80)); SPDR = 0xB4; /* turn off alarm */ while (!(SPSR & 0x80)); PORTD &= 0xDF;
626
Other functions of the 68HC68T1 chip
1. Power sensing: - the voltage level on the LINE input pin is check - as long as the voltage is either higher or lower than a certain threshold around VDD, a power failure is indicated. - the 68HC68T1 may interrupt the CPU on a power failure for the CPU to take appropriate actions 2. Power-down: - power down is initiated by the processor - signals PSE, CLK OUT, and CPUR output will be placed low during a power-down - procedure of power down is as follows: a. set the power sense operation (set bit 5 of the interrupt control register) b. when interrupt occurs, the processor reads the status register to determine the interrupt source. c. if a power failure is sensed, the processor does the necessary housekeeping to prepare for shutdown. d. the CPU reads the status register again after several milliseconds to determine the validity of the power failure. e. the CPU sets power down and disable all interrupts when the power failure is verified. f. when the power returns and Vsys rises above Vbatt + 0.7V, power up is initiated. The CPU reset is released and serial communication is established.
627
3. Power-up - Power-up is started when the signal POR goes high - If the Vsys input also goes high, then 68HC68T1 initiates the power-up operation by placing PSE, CLK OUT, and CPUR to high so that the CPU can start to boot. 4. Watchdog function - when enabled, the SS pin must be toggled at regular intervals without a serial transfer. - if the SS pin is not toggled, the 68HC68T1 supplies a CPU reset pulse at the CPUR pin and the watchdog bit in the status register is set to 1. - the watchdog service time and CPU reset period (CPUR low) is listed in Table 9.8.
628
Chapter 11: 68HC11 Analog to Digital Converter
The 68HC11 Microcontroller Han-Way Huang Minnesota State University, Mankato
629
Basics on A/D Conversion
- Almost any measurable quantity, for example, current, voltage, temperature, speed, and time, is analog in nature. - Analog signals must be represented in digital format in order to be processed by the digital computer. - An analog to digital (A/D) converter can convert a electrical voltage to a digital value. - A non-electrical quantity must be converted into electrical voltage before it can be converted into digital value. - A transducer is normally used to convert a non-electrical quantity into a electrical voltage so that it can be further processed by a computer. - The accuracy of an A/D converter is dictated by the number of bits it used to represent the digital value. - An A/D conversion system is illustrated in Figure 10.1
631
Successive Approximation Method
632
Algorithm of Successive Approximation Method
Starting the most significant bit of SAR, for each bit 1. Guess the bit to be a 1. 2. Converts the value of the SAR to an analog voltage 3. Compares the D/A output with the analog input. 4. Clears the bit to 0 if the D/A output is larger.
633
Optimal Voltage Range for the A/D Converter
A/D converter needs a low reference voltage and a high reference voltage to operate. The low reference voltage (VLREF) is often set to 0 and the high reference voltage (VHREF) is often set to VCC. Most A/D converters are ratiometric. To take advantage the whole dynamic range of the A/D converter, we should set scale and shift the sensor output to VLREF ~ VHREF. The A/D conversion result x corresponds to an analog voltage given by Vx = VLREF + (range x) (2n – 1) where, range = VHREF – VHREF
634
Example 11.1 Assume there is a 12-bit A/D converter with VLREF = 0V and VHREF = 5V.
Find out the corresponding voltage values for A/D conversion results of 100, 400, 800, 1200, and 2400. Solution: range = VHREF – VLREF = 5 V. V(100) = 0V + (100 5) (212 – 1) = 0.12 V V(400) = 0V + (400 5) (212 – 1) = 0.49 V V(800) = 0V + (800 5) (212 – 1) = 0.98 V V(1200) = 0V + (1200 5) (212 – 1) = 1.46 V V(2400) = 0V + (2400 5) (212 – 1) = 2.93 V
635
Voltage Scaling Circuit
Example 11.2 Convert the output voltage of an A/D converter from 0-200mV to the range of 0-5V. Solution: AV = 1 + (R2/R1) = (5V/0.2V) = 25 R2/R1 = 24 Choose 10K for R1, then R2 = 240K.
636
Voltage Scaling and Shifting Circuit
Can translate a voltage from V1 - V2 to the range of 0V – 5V.
637
Example 11. 3 Use the circuit in Figure 11
Example 11.3 Use the circuit in Figure 11.5 to scale and shift the transducer output from -2.5 ~ 2.5 V to 0 ~ 5V. Solution: 0 = Rf R1 × (- 2.5) – Rf R2 × V (1) 5 = Rf R1 × (2.5) – Rf R2 × V (2) By choosing V1 = - 12V and Rf = 5KW, R1 and R2 are solved to be 5KW and 24KW. R0 is independent of other parameters, we arbitrarily set it to 5 KW.
638
An Overview of the 68HC11 A/D Converter
- Eight-channel, 8-bit, multiplexed input, successive-approximation conversion method. - A weighted array of capacitors are used to implement the successive-approximation method. - A clock signal is required to control the A/D conversion that must have a frequency no lower than 750 KHz. - Reference voltages are required for the conversion: one is high reference (VRH) voltage, the other is low reference (VRL) voltage. The difference between VRH and VRL cannot be lower than 2.5 V. - Accuracy is only guaranteed for VRL = 0 V and VRH = 5 V. - The conversion is ratiometric. The input voltage VRL converts to $00 and the input voltage VRH converts to $FF.
639
The Clock Frequency Issue
- The A/D converter requires a clock to operate. - Either the E clock or the on-chip RC clock signal can be used. - The RC clock runs at 1.5 MHz. - To choose the E clock signal, clear the bit 6 of the OPTION register to 0. - To select RC clock signal, set the bit 6 of the OPTION register to 1. This circuit requires 10 ms to start and settle. - The 68HC11 completes the conversion of one sample in 32 clock cycles. Registers Related to the A/D Operation - ADCTL: A/D control/status register - OPTION: bits 7 and 6 - ADR1-4: A/D result registers 1 to 4
640
A/D Control Register (ADCTL)
642
The OPTION Register ADPU: A/D power up. When set to 1, it enables the A/D converter. After setting this bit, the user must wait at least 100 ms before using the A/D converter. CSEL: clock select. When set to 1, the RC clock signal is selected. Otherwise, the E clock is selected. It takes 10 ms for RC clock to stabilize.
643
The Procedure for Using the A/D Converter
Step 1. Connect the hardware properly. Scale and shift the analog inputs, when necessary, so that they fall between VRH and VRL. Step 2. Set the ADPU bit of OPTION register to enable the A/D converter. Step 3. Select the appropriate clock signal by setting or clearing the CSEL bit of the OPTION register. Step 4. Wait for the A/D converter to stabilize. Step 5. Select the appropriate channel(s) and operation modes by programming the ADCTL register. Step 6. Wait until the CCF flag of the ADCTL register becomes 1 and collect the conversion results.
644
Example 11.5 Write an instruction sequence to set up the following A/D conversion
parameters: Nonscan mode Single-channel mode Select channel AN0 Choose the E clock as the clock source for the A/D converter Enable A/D converter Solution: Set bit 5 of ADCTL to 0 to select nonscan mode. Set bit 4 of ADCTL to 0 to select single-channel mode. Set bits 3-0 of ADCTL to 0000 to select channel AN0. Write the value $00 into the ADCTL register. Set the bit 7 of the OPTION register to enable A/D charge pump. Clear the bit 6 of the OPTION register to select E clock as the A/D control clock signal. Wait for 100 ms for the converter to stabilize.
645
regbas EQU $1000 ADCTL EQU $30 OPTION EQU $39 LDX #regbas BCLR OPTION,X $40 ; select E clock for the A/D clock signal BSET OPTION,X $80 ; enable the A/D charge pump LDY #30 ; delay for 105 ms for delay DEY ; the charge pump to BNE delay ; stabilize LDAB #$00 STAA ADCTL,X ; start the conversion END
646
Example 11.6 Write an instruction sequence to set up the following A/D conversion
parameters: Non-scan mode Multiple-channel mode Select channels AN4-AN7 Choose E clock as the clock source for the A/D converter Enable the A/D converter Solution: Set bit 5 of ADCTL to 0 to select non-scan mode Set bit 4 of ADCTL to 1 to select multi-channel mode Set bits 3-0 of ADCTL to 0100 to select channels AN4-AN7 Write the value $14 into the ADCTL register. Set the bit 7 of the OPTION register to enable A/D charge pump. Clear the bit 6 of the OPTION register to select E clock as the A/D control clock signal. Wait for 100 ms for the converter to stabilize.
647
regbas EQU $1000 ADCTL EQU $30 OPTION EQU $39 LDX #regbas BCLR OPTION,X $40 ; select the E clock as the A/D control clock BSET OPTION,X $80 ; enable the A/D converter LDY #30 ; wait for 105 ms delay DEY ; “ BNE delay ; ” LDAB #$14 ; start the A/D conversion STAA ADCTL,X ; “ END
648
Example 11.7 Write an instruction sequence to convert the analog signal connected to
channel AN0 into digital form. Perform four conversions and stop. Assume the frequency of the E clock is 2 MHz. Solution: 1. Circuit connection is shown in Figure 11.6. 2. Write one byte into the ADCTL register and four conversions will be performed. 3. Perform A/D conversion on the AN0 input in single-channel and nonscan mode. Write $00 into ADCTL.
649
regbas equ $1000 OPTION equ $39 ADCTL equ $30 ADR1 equ $31 ADR2 equ $32 ADR3 equ $33 ADR4 equ $34 org $00 result rmb 4 ; result four bytes to hold A/D results org $C000 ldx #regbas bset OPTION,X $80 ; enable the charge pump to start A/D conversion bclr OPTION,X $40 ; select E clock as the clock source to A/D converter ldy #30 ; delay for 105 ms to wait for the charge pump delay dey ; to stabilize bne delay ; “ ldaa #$00 staa ADCTL,X ; initialize ADCTL and start the A/D conversion again ldaa ADCTL,X ; check CCF bit bpl again ; wait until CCF flag is 1 ldaa ADR1,X ; get the first result
650
staa result ; save it ldaa ADR2,X ; get the second result staa result+1 ; save it ldaa ADR3,X ; get the third result staa result+2 ; save it ldaa ADR4,X ; get the fourth result staa result+3 ; save it end
651
In C Language, #include <hc11.h> unsigned char result [4]; main ( ) { OPTION &= 0xBF; /* select E clock as the A/D clock source */ OPTION |= 0x80; /* enable A/D converter */ TFLG1 = 0x40; /* clear OC2F flag */ TOC2 = TCNT + 200; /* start an OC2 operation with 100 ms delay */ while (!(TFLG1 & 0x40)); /* wait for 100 ms */ ADCTL = 0x00; /* start an A/D conversion */ while (!(ADCTL & 0x80)); /* wait until A/D conversion is complete */ result [0] = ADR1; /* save A/D conversion results */ result [1] = ADR2; result [2] = ADR3; result [3] = ADR4; return 0; }
652
Example 11.8 Take 20 samples from each of the A/D channels AN0 to AN3, convert them
to digital values, and store them in memory locations from $D000 to $D04F. Solution: 1. Circuit connection is shown in Figure 11.7. 2. Perform A/D conversion on channels AN0 to AN3 in multi-channel, non-scan mode. Write the value $10 into ADCTL. 3. Take samples at as regular intervals as possible. This can be achieved by starting the next conversion immediately after the previous conversion has been completed but before collecting the result.
653
N EQU 20 ; number of samples to be taken per channel
ORG $D000 result RMB 80 ; reserve 80 bytes to store A/D conversion results ORG $C000 LDX #regbas BSET OPTION,X $80 ; enable A/D charge pump BCLR OPTION,X $40 ; select E clock to control A/D conversion LDY #30 ; wait for 105 ms for charge pump to stabilize delay DEY ; “ BNE delay ; “ LDAA #$10 ; initialize ADCTL STAA ADCTL,X ; “ LDAB #N ; number of samples remained to be taken on each channel LDY #result ; Y points to the buffer that holds the result wait LDAA ADCTL,X ; wait until the current A/D conversion is completed BPL wait ; “ * Start the next conversion immediately so that samples can be taken more uniformly in time LDAA #$10 ; start the next A/D conversion
654
* The following eight instructions collect the previous results
LDAA ADR1,X ; fetch the result from channel 1 STAA 0,Y ; save the result LDAA ADR2,X ; fetch the result from channel 2 STAA 1,Y ; save the result LDAA ADR3,X ; fetch the result from channel 3 STAA 2,Y ; save the result LDAA ADR4,X ; fetch the result from channel 4 STAA 3,Y ; save the result INY ; move the result pointer INY ; “ INY ; “ DECB ; decrement the loop count BNE wait END
655
In C Language, #include <hc11.h> unsigned char result[80]; main ( ) { int i; OPTION &= 0xBF; /* select E clock as the A/D conversion clock source */ OPTION |= 0x80; /* enable A/D converter */ TFLG1 = 0x40; /* clear OC2F flag */ TOC2 = TCNT + 200; /* create 100 ms delay */ while (!(TFLG1 & 0x40)); /* “ */ ADCTL = 0x10; /* start an A/D conversion */ for (i = 0; i < 20; i++) { while (!(ADCTL & 80)); ADCTL = 0x10; result [4*i] = ADR1; result [4*i + 1] = ADR2; result [4*i + 2] = ADR3; result [4*i + 3] = ADR4; } return 0;
656
The LM35 Precision Centigrade Temperature Sensors
Pins and circuit connections Features - No external calibration required. - Very linear over the temperature range - Draws only 60 mA from power supply and has very low self-heating. - Converts the ambient temperature into voltage
657
Example 11. 9 Use the circuit shown in Figure 11
Example 11.9 Use the circuit shown in Figure 11.8b as a building block in a system to measure room temperature. Display the result in two integer digits and one fractional digit using the seven-segment displays. Assume the room temperature never goes below 0 oC and never goes above 42.5 oC so that the A/D converter of the 68HC11 can be used to perform the conversion and drive the seven-segment displays. Solution: 1. The voltage output from the circuit shown in Figure 10.6b will be between 0V and 425 mV. 2. Better precision can be obtained by scaling the voltage corresponding to 42.5 oC to 5 V. 3. Voltage scaling circuit is shown is Figure 11.9.
658
Display Circuit
659
Setting of Configuration Data for MC14489
bit 7: no decode, set to 0. bit 6: special decode, set to 1. bit 5 to 3: bank 5 to 3 hex decode, set to 0. bit 2: bank 2 special decode, set to 1. bit 1: bank 1 hex decode, set to 0. bit 0: normal mode, set to 1. Format of Display Data
660
REGBAS EQU $1000 SPCR EQU $28 SPDR EQU $2A SPSR EQU $29 DDRD EQU $09 ADR1 EQU $09 OPTION EQU $39 ADCTL EQU $30 PORTB EQU $04 PORTD EQU $08 TCNT EQU $0E TOC2 EQU $18 TFLG1 EQU $23 OC2 EQU $40 ; mask to check the OC2F flag of TFLG1 OC2M EQU $BF ; mask to clear OC2F flag for the BCLR instruction SP_DIR EQU $3A ; value to configure SPI pins directions SPCR_IN EQU $54 ; value to initialize SPCR register ADPU EQU $80 ; mask to select ADPU bit of the OPTION register ADCLK EQU $40 ; mask to select CSEL bit of the OPTION register A2D_INI EQU $00 ; value to configure A/D control register
661
ORG $00 byte1 RMB 1 ; storage for temperature data byte2 RMB 1 ; “ byte3 RMB 1 ; “ remain RMB 2 ; to hold the remainder of division oc2cnt RMB 1 ; output comparison count of OC2 ORG $C000 LDX #regbas LDAA #$C0 STAA byte1 ; store the fixed value of display data LDAA #$FC ; “ STAA byte3 ; “ * The following 4 instructions initialize the SPI system LDAA #SPDIR ; set up SPI pin directions STAA DDRD,X ; “ LDAA #SPCR_INI ; initialize SPI parameters STAA SPCR,X ; “ BCLR PORTD,X $20 ; enable SPI transfer to MC14489 LDAA #$45 ; send configuration data to MC14489 STAA SPDR,X ; “ BRCLR SPSR,X $80 * BSET PORTD,X $20 ; load data into configuration register
662
* The following 5 instructions enable the A/D converter and select E clock to control A/D
* conversion process and wait for the charge pump to stabilize BCLR OPTION,X ADCLK ; select E clock for A/D conversion BSET OPTION,X ADPU ; enable A/D converter LDY #30 ; delay 105 ms so charge pump can stabilize delay DEY ; “ BNE delay ; “ forever LDAA #A2D_INI ; start an A/D conversion STAA ADCTL,X ; “ here LDAA ADCTL,X BPL here LDAB ADR1,X ; read the A/D conversion result CLRA ; convert to temperature LDX #6 ; reading IDIV ; “ STD remain ; save the remainder XGDX ; swap integer part to D LDX #10 ; separate tens and ones digits IDIV LSLB ; shift ones digits to upper half of B LSLB ; “
663
STAB byte2 XGDX ; swap the tens temperature digit in B ADDB byte1 ; combine the decimal pointer specifier with tens digit STAB byte1 ; “ LDD remain ; get back the remainder (in B) LDAA #10 MUL LDX #6 IDIV ; compute remainder × 10 6 XGDX ADDB byte2 ; combine the ones digit and the fractional digit STAB byte2 ; “ BCLR PORTD,X $20 ; enable SPI transfer to MC14489 LDAA byte1 ; get byte1 and send it out STAA SPDR,X BRCLR SPSR,X $80 * ; wait until 8 bits have been shifted out LDAA byte2 ; send out byte2 STAA SPDR,X ; “ BRCLR SPSR,X $80 * ; “ LDAA byte3 ; send out byte3 BSET PORTD,X $20 ; load data into the display register of the MC14489
664
* Use OC2 to create 1 second delay
LDAB #100 STAB oc2cnt ; initialize OC2 count to create 1 s delay LDX #REGBAS BCLR TFLG1,X $BF ; clear OC2F flag LDD TCNT,X repeat ADDD #20000 STD TOC2,X wait BRCLR TFLG1,X $40 * ; wait for 10 ms BCLR TFLG1,X $BF ; clear the OC2F flag LDD TOC2,X DEC oc2cnt BNE repeat JMP forever END
665
C Program for Temperature Measurement
#include <hc11.h> main ( ) { unsigned char byte1, byte2, byte3, temp; byte1 = 0xC0; byte3 = 0xFC; /* store characters “degree” and “C” in byte3 */ DDRD = 0x3A; /* configure SPI pin directions */ SPCR = 0x56; /* initialize SPI function */ OPTION |= 0x80; /* start the A/D charge pump */ OPTION &= 0xBF; /* select E clock as the clock source for A/D conversion */ TFLG1 = 0x40; /* clear OC2F flag */ TOC2 = TCNT /* wait for 100 ms */ while (!(TFLG1 & 0x40)); PORTD &= 0xDF; /* enable SPI transfer */ SPDR = 0x45; /* send configuration data to MC14489 */ while (!(SPSR & 0x80)); PORTD |= 0x20; /* disable SPI transfer to MC14489 */ while (1) { ADCTL = 0x00 /* start and A/D conversion */ while (!(ADTCL & 0x80));
666
temp = ADR1/6; byte1 += temp / 10; /* place the ten’s digit in the lower half of byte1 */ byte2 = 4 << (temp % 10); /* place the one’s digit in the upper half of byte2 */ temp = (ADR1 % 6) * 10 /6; /* compute the first fractional digit */ byte2 += temp; /* combine the one’s and fractional digits */ PORTD &= 0xDF; /* enable SPI transfer to MC14489 */ SPDR = byte1; /* send out byte1 */ while (!(SPSR & 0x80)); SPDR = byte2; /* send out byte2 */ while (!(SPSR & 0x80)); /* “ */ SPDR = byte3; /* send out byte3 */ while (!(SPSR & 0x80)): /* “ */ PORTD |= 0x20; /* transfer data to the display register */ TOC2 = TCNT ; /* start OC2 operation with 10 ms delay */ TFLG1 = 0x40; /* clear OC2 flag */ for (temp = 0; temp < 100; temp -- ) { TOC2 += 20000; /* start the next OC2 operation */ TFLG1 = 0x40; /* clear the OC2 flag */ } return 0;
667
Measuring the Humidity
The IH-3605 is a humidity sensor made by HyCal Engineering, a division of Honeywell. The voltage output for relative humidity 0 to 100% is 0.8V to 3.9V. Pin assignment is shown in Figure Specifications are shown in Table 11.2.
668
Example 11.10 Construct a humidity measurement system that consists of the 68HC11, an
IH-3605 humidity sensor, and four 7-segment displays. Solution: 1. Use a signal conditioning circuit to scale and shift the voltage to 0-5V. 2. Use a 1KW resistor and a 0.16mF capacitor to construct a 1KHz low pass filter. 3. Use a MC14489 to drive four seven-segment displays. 4. Blank the most significant digit when the humidity is not 100%. - Send $91 as the configuration data to blank the most significant digit. - Send $01 as the configuration data when the most significant digit is a 1. 5. Use table lookup method to translate from A/D result to the relative humidity.
670
Relative Humidity Data Format
671
REGBAS EQU $1000 SPCR EQU $28 SPSR EQU $29 SPDR EQU $2A DDRD EQU $09 ADR1 EQU $31 OPTION EQU $39 ADCTL EQU $30 PORTB EQU $04 PORTD EQU $08 TCNT EQU $0E TOC2 EQU $18 TFLG1 EQU $23 SP_DIR EQU $3A SPCR_INI EQU $54 APDU EQU $80 ; mask to select ADPU bit of the OPTION register ADCLK EQU $40 ; mask to select CSEL bit of the OPTION register A2D_INI EQU $00 ; value to initialize the ADCTL register CONF1 EQU $91 ; configuration data that need to blank msd CONF2 EQU $01 ; configuration data that display the msd
672
ORG $00 byte1 RMB 1 ; storage for display data byte2 RMB 1 ; “ byte3 RMB 1 ; “ oc2cnt RMB 1 ORG $C000 LDX #REGBAS LDAA #$A0 STAA byte1 ; first byte of the display data is a constant LDAA #SPDIR STAA DDRD,X LDAA #SPCR_INI ; initialize the SPI system STAA SPCR,X ; “ BSET OPTION,X ADPU ; start A/D charge pump BCLR OPTION,X ADCLK ; select E clock as the clock source of the A/D LDY #30 delay DEY BNE delay forever LDAA #A2D_INI STAA ADCTL,X here LDAA ADCTL,X ; wait until A/D conversion is complete BPL here
673
LDAB ADR1,X LDY #humid_up ABY LDAA 0,Y ; lookup the upper byte of the humidity STAA byte2 LDY #humid_lo LDAA 0,Y ; lookup the lower byte of the humidity STAA byte3 JSR disp_humid JSR wait_1s JMP forever disp_humid PSHA PSHB PSHY PSHX LDX #REGBAS BCLR PORTD,X $20 ; enable SPI transfer to MC14489 LDAA byte2 ANDA #$F0 ; check the upper four bits BEQ blank LDAA $01 ; choose normal hex decode BRA send
674
blank LDAA #$91 ; choose special decode to blank display
send STAA SPDR,X BRCLR SPSR,X $80 * ; wait until the SPI transfer is complete BSET PORTD,X $20 ; load data into configuration register BCLR PORTD,X $20 ; enable SPI transfer to MC14489 LDY #byte1 LDAB #3 loop_disp LDAA 0,Y STAA SPDR,X BRCLR SPSR,X $80 * ; wait until SPI transfer is complete INY DECB BNE loop_disp BSET PORTD,X $20 ; load data into display register PULX PULY PULB PULA RTS wait_1s PSHA PSHB PSHY PSHX
675
LDX #REGBAS DES TSY LDAA #50 STAA 0,Y ; initialize OC2 count to 50 LDD TCNT,X loop_50 ADDD #40000 ; start an OC2 operation with 20 ms delay STD TOC2,X BCLR TFLG1,X $BF ; clear OC2F BRCLR TFLG1,X $40 * ; wait until OC2F is set LDD TOC2,X DEC 0,Y ; decrement OC2 count BNE loop_50 INS PULX PULY PULB PULA RTS humid_up FCB $00,$00,…,$09,$10 humid_lo FCB $00,$04,…,$96,$00
676
C Program for Humidity Measurement
#include <hc11.h> unsigned char humid_up [ ] = {…}; unsigned char humid_lo [ ] = {…}; main ( ) { unsigned bytes[3]; /* display data */ unsigned char i, conf_dat; /* loop index and configuration data */ DDRD = 0x3A; SPCR = 0x54; OPTION &= 0xBF; /* select E clock to control A/D converter */ OPTION |= 0x80; /* start the A/D charge pump */ bytes[0] = 0xA0; TOC2 = TCNT + 200; /* create a delay of 100 ms */ TFLG1 = 0x40; /* “ */ while (!(TFLG1 & 0x80)): /* “ */ while (1) { ADCTL = 0x00; /* start an A/D conversion */ while (!(ADCTL & 0x80)); /* wait until A/D conversion is complete */ if (!(humid_up [ADR1] & 0xF0)) conf_dat = 0x91; /* choose special decode mode */ else conf_dat = 0x01; /* choose normal decode mode */
677
PORTD &= 0xDF; /* enable SPI transfer to MC14489
SPDR = conf_dat; /* send out configuration data */ while (!(SPSR & 0x80)); /* wait until SPI transfer is complete */ PORTD |= 0x20; /* load data into configuration register */ bytes[1] = humid_up[ADR1]; bytes[2] = humid_lo[ADR1]; PORTD &= 0xDF; for (i = 0; i < 3; i++) { /* send out humidity data for display */ SPDR = bytes[i]; while (!(SPSR & 0x80)); } PORTD |= 0x20; /* load data into display register */ TFLG1 = 0x40; /* clear OC2F flag */ TOC2 = TCNT ; /* start an OC2 operation */ for (i = 0; i < 100; i++) { while (!(TFLG1 & 0x40)); TOC2 += 20000; return 0;
678
Vi2 Processing the Results of A/D Conversions
- The results of A/D conversion often need to be processed. - One of the most useful measurements of an AC signal is its root-mean-square (RMS) value. - The RMS value of an AC signal is defined as: 1 VRMS = T V2(t)dt 11.7 T - The following equation is used to approximate the RMS value: VRMS » 1 N-1 11.8 å Vi2 N i = 0 - To make equation 10.4 a good approximation of the real RMS value, samples must be as equally spaced in time as possible. The more samples collected, the better the result.
679
Example 11.11 Write a program to compute the average of the squared values of 64
samples stored at memory locations starting with the label sample and save the result at the memory locations starting with the label sq_ave. Solution: - Two bytes are needed to hold the square of an 8-bit value. - Three bytes are needed to hold the sum of bit values. x - Divide-by-64 can be performed by shifting the dividend to the right by 6 positions.
680
ORG $D000 samples FCB … sq_sum RMB 3 sq_ave RMB 2 org $C000 LDX #samples CLR sq_sum ; initialize the sum to 0 CLR sq_sum+1 ; “ CLR sq_sum+2 ; “ LDY #64 ; initialize the loop count loop LDAA 0,X ; get a sample TAB ; duplicate the sample in B MUL ; compute the square of the sample ADDD sq_sum+1 ; add to the running sum STD sq_sum+1 ; “ LDAB sq_sum ; add the carry to the upper byte ADCB #0 ; “ STAB sq_sum INX ; move to the next sample DEY ; decrement the loop count BNE loop LDAB #6 ; prepare to shift right 6 places
681
* the next five instructions divide the sum by 64
loop1 LSR sq_sum ROR sq_sum+1 ROR sq_sum+2 DECB BNE loop1 * transfer the result to sq_sum and sq_sum+1 LDAA sq_sum+1 STAA sq_ave LDAA sq_sum+2 STAA sq_ave+1 END
682
åi = å Computing the Square Root
- A technique for approximating the square root is based on the following equation: åi = n-1 i=0 2 n(n-1) 11.9 - Equation 10.5 can be transformed into n2 = å n-1 i=0 (2i + 1) 11.10 - The value n is the square root to be found. Suppose we want to find the square root of p, and n is the integer closest to the square root of p, then one of the following relationships is satisfied: n2 < p n2 = p n2 > p - By incrementing i from 0 to n-1, the square root can be found. For the first approximation, we will stop when the running sum is larger than p. The flowchart of the program is shown in Figure
684
Example 11.12 Write a program to compute the square root of the average value computed
in Example (stored at sq_ave) and save the square root at sq_root. Solution: sq_root rmb 2 ; to hold the value of å(2i + 1) i rmb 1 ; … CLR sq_root ; initialize å(2i + 1) to 0 CLR sq_root+1 ; “ LDAB #-1 STAB i ; initialize i to 0 repeat INC i LDAB i CLRA LSLD ; compute 2i + 1 ADDD #1 ; “ ADDD sq_root ; add 2i + 1 to accumulating STD sq_root ; sum CPD sq_ave ; compare to n2 BLO repeat ; repeat when å(2i + 1) < n2 INC i ; add 1 to i to obtain the square root LDAA i ; place the square root in sq_root STAA sq_root ; “ END
685
Example 11.13 Add a sequence of instructions to the previous program to find the closest
square root of the square sum. Solution: - If n is not the true square root, then either n or n - 1 is the closest square root. - The choice can be made by comparing the following two expressions: n2 - p (1) p - (n - 1)2 (2) - The value n is selected if the expression (1) is smaller. Otherwise, n - 1 is selected - The program on the right-hand side should be appended to the program of the previous example.
686
sq_diff1 RMB 2 temp RMB 2 LDAA i ; place n in A TAB ; also place n in B MUL ; compute n2 CPD sq_ave ; compare to p BEQ exit * We need to compare expression (1) and (2) in the following SUBD sq_ave ; compute n2 - q STD sq_diff1 LDAA i DECA ; compute n - 1 TAB MUL ; compute (n - 1)2 STD temp LDD sq_ave SUBD temp ; compute p - (n - 1)2 CPD sq_diff1 ; compare p - (n - 1)2 with n2 - p BHI exit ; n is closer to the true square root DEC i ; n - 1 is closer to the true square root exit …
687
Example 11.14 Write a C routine to compute the root-mean-square value of an array
of 8-bit unsigned integers. Solution: unsigned char root_mean_sq (unsigned char *samples, unsigned int n) { int i; unsigned int sq_ave; unsigned long int sq_sum; unsigned int temp; sq_sum = 0; for (i = 0; i < n; i++) sq_sum += samples[i] * samples [i]; sq_ave = sq_sum / n; temp = 0; i = 0; while (temp < sq_ave) { temp += 2 * i + 1; i ++; } if (temp == sq_ave) return i; if ((i * i - sq_ave) < (sq_ave - (i - 1) * (i - 1)) return i; else return (i - 1);
688
Using External A/D Converter MAX1241
- 12-bit resolution - Use successive-approximation method to perform conversion and completes one conversion in 7.5 ms. - Direct interface to SPI interface. - Analog input ranges from 0 to 5V with 5V power supply
689
MAX1241 Signal Pins CS: chip select. The falling edge of this signal initiates the conversion. DOUT: serial data output. Data changes state at SCLK’s falling edge. AIN: analog input. SCLK: serial clock input. SCLK clocks data out at rates up to 2.1 MHz. GND and VDD: device supply pins. REF: analog reference voltage. Reference voltage for A/D conversion. SHDN: Shut-down input. Pulling SHDN to low shuts the MAX1241 down to 15mA supply current. Chip Functioning - Pulling CS to low initiates the conversion. - The serial data stream consists of a high bit, signaling the end of conversion (EOC), followed by the data bits (MSB first). - End of conversion is signaled by DOUT going high.
690
Timing and Control - The CS and SCLK signals control conversion-start and data-read operations. - After DOUT goes high, it transitions on the first falling edge of the SCLK signal. The next falling clock edge shifts out the most significant bit of the conversion result at DOUT, followed by the remaining bits. - Since there are 12 data bits and one leading high bit, at least 13 clock periods are needed to shift out a conversion result. - Extra clock signals only shift out trailing zeros at DOUT.
692
Interfacing the MAX1241 with the 68HC11
Procedure for A/D conversion Step 1. Use a general-purpose I/O line (SS) to pull CS low. Keep SCLK low. Step 2. Wait for maximum conversion time. Alternately, look for DOUT rising edge to determine the end of conversion. Step 3. Activate SCLK for a minimum 13 clock cycles. When interfacing with SPI, two bytes are transferred. The first bit is a 1 followed by 12 data bits and three zeros. Step 4. Pull CS high at or after 13th falling clock edge (actually 16th clock edge) Step 5. With CS = high, wait for the minimum specified time, tCS, before initiating a new conversion by pulling CS low.
693
Reading A/D Result with two SPI Transfers
694
Example 11.15 Write a subroutine to perform an A/D conversion operation for the circuit
shown in Figure and return the result in double accumulator D. Solution: REGBAS EQU $100 DDRD EQU $09 SPCR EQU $28 SPSR EQU $29 SPDR EQU $2A CS EQU $20 ; value to select the CS pin DOUT EQU $04 ; value to select the DOUT pin get_sample PSHX PSHY LDX #REGBAS LDAA #$3A STAA DDRD,X LDAA #$50 STAA SPCR,X ; set transfer rate to 1 Mbits/s, set master mode BCLR PORTD,X CS ; start an A/D conversion BRCLR PORTD,X DOUT * ;wait until DOUT goes high STAA SPDR,X BRCLR SPSR,X $80 * ; wait until the SPI transfer is complete LDAA SPDR,X ; place the upper byte of the A/D result in A
695
STAB SPDR,X ; shift in the lower byte of the conversion result
BRCLR SPSR,X $80 * ; wait until SPI transfer is complete LDAB SPDR,X ; place the lower byte in B BSET PORTD, X CS ; prepare for the next A/D conversion LSLA ; clear the bit 7 of accumulator A LSRA ; “ LSRD ; place the 12-bit A/D result in the lower 12 bits of D LSRD ; “ PULY PULX RTS
696
In C language, unsigned int get_sample ( ) { unsigned char x1; unsigned int a2d_result; DDRD = 0x3A; SPCR = 0x50; PORTD &= 0xDF; /* start an A/D conversion */ while (!(PORTD & 0x04)); /* wait until conversion is complete */ SPDR = 0x00; /* shift in the upper byte of the A/D result */ while (!(SPSR & 0x80)); /* “ */ x1 = SPDR; SPDR = 0x00; /* shift in the lower byte */ while(!(SPSR & 0x80)); /* “ */ PORTD |= 0x20; /* disable A/D converter */ a2d_result = x1 * SPDR; /* combine upper and lower bytes */ a2d_result = a2d_result << 1; /* place the A/D result in the lower 12 bits */ a2d_result = a2d_result >> 4; /* “ */ return a2d_result; }
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.