You are on page 1of 21

The 68HC11 Microcontroller

The 68HC11 Microcontroller

3. Output compare functions

Chapter 8: 68HC11 Timer Functions The 68HC11 Microcontroller Han-Way Huang Minnesota State University, Mankato

A (E) series members have five (four/five) channels (OC1OC5) 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

The 68HC11 Microcontroller

The 68HC11 Microcontroller

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 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.

TOI TOF

Interrupt request

MCU E clock

Prescaler divide by 1, 4, 8, or 16

TCNT(H) TCNT(L) 16-bit free-running counter Taps for RTI, COP watchdog, and pulse accumulator

16-bit timer bus Figure 8.1 68HC11 main timer system

The 68HC11 Microcontroller

The 68HC11 Microcontroller

Registers related to Main Timer 1. Timer counter: TCNT 2. Timer flag register 2: TFLG2 3. 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.
7 value after reset TOI 0 7 value after reset TOF 0 6 RTII 0 6 5 PAOII 0 5 4 PAII 0 4 PAIF 0 0 0 0 0 3 0 0 3 2 0 0 2 1 PR1 0 1 0 PR0 0 0 TFLG2 at $1025

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.

TMSK2 at $1024

RTIF PAOVF 0 0

Figure 8.2 TMSK2 and TFLG2 registers

The 68HC11 Microcontroller

The 68HC11 Microcontroller

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.
Overflow period PR1 0 0 1 1 PR0 0 1 0 1 Prescale factor 1 4 8 16 2 MHz E clock 32.77 ms 131.1 ms 262.1.ms 524.3 ms 1 MHz E clock 65.54 ms 262.1 ms 524.3 ms 1.049 ms

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.
Rising edge or Falling edge

Table 8.1 Main timer clock frequency vs. PR1 and PR0
Figure 8.3 Events represented by signal edges

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 TCNTH TCNTL equ $1000 equ $0E equ $0F ldx #regbas ldaa TCNTH,X ldaa TCNTL,X

- 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.
ICxI Interrupt request

; read the upper byte of TCNT ; read the lower byte of TCNT

16-bittimer bus

16-bitlatch TICx

ICxF

Edge-detection logic

ICx pin

Figure 8.4 Input-capture function block diagram

The 68HC11 Microcontroller

The 68HC11 Microcontroller

- The edge to be captured is selected by programming the register TCTL2.


value after reset
EDG1B EDG1A EDG2B EDG2A EDG3B EDG3A at $1021

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.

TCTL2

0 0 0 1 1

0 0 1 0 1

EDGxB ED GxA

capture disabled capture on rising edge capture on falling edge capture on both edges

x = 1,...,3 Figure 8.5 Contents of TCTL2

For example, the following instruction sequence captures the rising edge of the signal applied at PA0 (IC3): regbas TCTL2 equ $1000 equ $21

; offset of TCTL2 from regbas

ldx #regbas bclr TCTL2,X %00000010 ; clear bit 1 to 0 bset TCTL2,X %00000001 ; set bit 0 to 1

The 68HC11 Microcontroller

The 68HC11 Microcontroller

Registers related to input capture 1. timer mask register 1 (TMSK1):


7 OC1I 0 6 OC2I 0 5 OC3I 0 4 OC4I 0 3 OC5I 0 2 IC1I 0 1 IC2I 0 0 IC3I 0

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
one period

- 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):
7 value after reset OC1F 0 6 OC2F 0 5 OC3F 0 4 OC4F 0 3 OC5F 0 2 IC1F 0 1 IC2F 0 0 IC3F 0

(a) Capture two rising edges one period

(b) Capture two falling edges

TFLG1 at $1023

Figure 8.8 Period measurement by capturing two consecutive edges

- Pulse width measurement: capture the rising and falling edges


Pulse width

Figure 8.6 The contents of the TFLG1 register

- 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

Rising edge

Falling edge

Figure 8.9 Pulse-width measurement using input capture

The 68HC11 Microcontroller

The 68HC11 Microcontroller

- 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
e1 e2 Start of interval Figure 8.10 Using an input-capture function for event counting e3 e4

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. Start Solution:
Choose to capture the rising edge

...

ei

...

ej End of interval

- two versions are available. - The polling method is shown in Figure 8.15.
no

Clear the IC1F flag

IC1F = 1? yes

- Time reference: often used in combination with an output compare function


Time t 0 Time t0 + delay no

Save the captured value of the first edge. Clear the IC1F flag.

IC1F = 1? yes Take the difference of the second and the first edges.

Time ofreference (set up by signal edge) Figure 8.11 A time reference application

Time to activate output signal (set up by output compare)

Stop Figure 8.15 Logic flow of the period-measurement program (polling method)

The 68HC11 Microcontroller

The 68HC11 Microcontroller

Duty Cycle Measurement


T T duty cycle = T T * 100%

Assembly Program for Period Measurement (Polling Method) REGBAS TLFG1 TIC1 TCTL2 IC1rise edge1 period EQU $1000 EQU $23 EQU $10 EQU $21 EQU $10 ORG $00 RMB 2 RMB 2 ORG $C000 LDX #REGBAS BCLR TFLG1,X $FB LDAA #IC1rise STAA TCTL2,X BRCLR TFLG1,X $04 * LDD TIC1,X STD edge1 BCLR TFLG1,X $FB BRCLR TFLG1,X $04 * LDD TIC1,X SUBD edge1 STD period END

Figure 8.12 Definition of duty cycle

Phase Difference Measurement


T

; clear IC1F flag ; capture rising edge ; wait for the first rising edge ; save the first edge ; clear IC1F flag ; wait for the second edge ; save the period

signal S1 T

signal S2 phase difference = T T * 360o

Figure 8.13 Phase difference definition for two signals

The 68HC11 Microcontroller

The 68HC11 Microcontroller

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; }

REGBAS TFLG1 TMSK1 TIC1 TCTL2 IC1rise IC1I IC1FM

EQU EQU EQU EQU EQU EQU EQU EQU ORG RMB RMB RMB ORG JMP ORG LDS LDX LDAA STAA BCLR LDAA

$1000 $23 $22 $10 $21 $10 $04 $FB $0000 1 2 2 $E8 IC1_ISR

; base address of the I/O register block ; offset of TFLG1 from regbas ; offset of TMSK1 from regbas ; offset of TIC1 from regbas ; offset of TCTL2 from regbas ; value to select the rising edge of IC1 to capture ; mask to select the IC1 bit in TMSK1 ; mask to clear IC1F using the BCLR instruction

edge_cnt edge1 period

; edge count ; captured first edge ; period in number of E clock cycles ; IC1 interrupt jump table entry on the EVB ;

$C000 ; starting address of the main program #$DFFF ; set up stack pointer #REGBAS #IC1rise ; select to capture the rising edge of IC1 TCTL2,X ; TFLG1,X IC1FM ; clear the IC1F flag #2

The 68HC11 Microcontroller

The 68HC11 Microcontroller

Interrupt-driven Method for Period Measurement


Start

Select to capture the rising edge of IC1

Clear IC1F flag Decrement edge_cnt


u pt

inte rr

edge_cnt 2 Clear IC1F flag Enable IC1 interrupt

edge_cnt = 1? yes Save the first edge return from interrupt

no

no

edge_cnt = 0? yes period = edge2 - edge1 Stop

Return from inte rrupt

Figure 8.16 Interrupt-driven method for period measurement

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

IC 1

The 68HC11 Microcontroller

The 68HC11 Microcontroller

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; }

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 32.67 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 TFLG1 TIC1 TCTL2 IC1rise IC1fall IC1F temp pul_width EQU $1000 EQU $23 EQU $10 EQU $21 EQU $10 EQU $20 EQU $04 EQU $00 PSHX PSHY DES DES TSY LDX #regbas ; base address of the I/O register block ; offset of TFLG1 from regbas ; offset of TIC1 from regbas ; offset of TCTL2 from regbas ; value to select the rising edge of IC1 ; value to select the falling edge of IC1 ; a mask to select the IC1F flag ; offset of temp from the top of the stack

; allocate two bytes for local variable temp

The 68HC11 Microcontroller

The 68HC11 Microcontroller

#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; }

rise

fall

LDAA STAA LDAA STAA BRCLR LDD STD LDAA STAA LDAA STAA BRCLR LDD SUBD INS INS PULY PULX RTS

#IC1rise ; configure TCTL2 to capture the rising edge of IC1 TCTL2,X ; #IC1F ; clear IC1F flag TFLG1,X ; TFLG1,X IC1F rise ; wait for the arrival of the rising edge TIC1,X ; save the first edge temp,Y ; #IC1fall ; configure to capture the falling edge of IC1 TCTL2,X ; #IC1F ; clear IC1F flag TFLG1,X ; TFLG1,X IC1F fall ; wait for the arrival of the falling edge TIC1,X ; get the captured time of the second edge temp,Y

The 68HC11 Microcontroller


Start

The 68HC11 Microcontroller

Measuring the period or pulse width of a slow signal (longer than 32.76 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 Case 2: edge2 < edge1 period (or pulse width) = (ovcnt - 1) 216 + diff The main timer overflows at least once in this case. 216 + diff
no

overflow 0 Set up to capture the rising edge. Disable all interrupts.

no

IC1F = 1? yes Timer overflow interrupt service routine

Clear IC1F flag. Save the first captured edge.

TO

in ter ru pt
R etu

Clear timer overflow flag. Enable main timer overflow interrupt.

Clear TOF flag. overflow overflow + 1.


Execute the RTI instruction.

IC1F = 1? yes

rn fr o m in te rr

up t

Compute the difference of two edges.

no

Is second edge smaller? overflow yes overflow - 1

Combine the results. Stop Figure 8.17 Logic flow for measuring period of slow signals

The 68HC11 Microcontroller

The 68HC11 Microcontroller

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.

regbas TFLG1 TIC1 TCTL2 TMSK1 TMSK2 IC1rise

EQU EQU EQU EQU EQU EQU EQU ORG RMB RMB RMB ORG JMP ORG LDS SEI CLR CLR LDX

$1000 $23 $10 $21 $22 $24 $10 $0000 2 2 2 $00D0 tov_ISR $C000 #$DFFF ov_cnt ov_cnt+1 #regbas

; base address of I/O register block ; offset of TFLG1 from regbas ; offset of TIC1 from regbas ; offset of TCTL2 from regbas ; offset of TMSK1 from regbas ; offset of TMSK2 from regbas ; value to select the rising edge of IC1

edge1 ov_cnt period

; captured time of the first edge ; main timer overflow count ; period of the unknown signal ; setup timer overflow interrupt vector jump table entry ; on EVB ; set up stack pointer ; disable all maskable interrupts to the 68HC11 ; initialize overflow count to 0 ;

The 68HC11 Microcontroller

The 68HC11 Microcontroller

LDAA #IC1rise STAA TCTL2,X BCLR TFLG1,X $FB BCLR TMSK1,X $FF BRCLR TFLG1,X $FB * BCLR TFLG2,X $7F BSET TMSK2,X $80 CLI LDD TIC1,X STD edge1 BCLR TFLG1,X $FB BRCLR TFLG1,X $04 * LDD TIC1,X SUBD edge1

; select to capture the rising edge ; ; clear IC1F flag ; disable all input capture and output compare interrupts ; wait for the arrival of the first edge ; clear TOF flag ; enable timer overflow interrupt ; enable interrupt to the 68HC11 ; save the captured time of the first edge ; ; clear IC1F flag ; wait for the arrival of the second edge ; compute the difference of edge2 and ; edge1

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 IC1s 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 */

The 68HC11 Microcontroller

The 68HC11 Microcontroller

next tov_ISR

STD BCC LDD SUBD STD LDX BCLR LDD ADDD STD RTI END

period next ov_cnt #1 ov_cnt

; ; is second edge smaller? ; decrement overflow count if second edge is smaller ; ;

#regbas TFLG2,X $7F ov_cnt #1 ov_cnt

; clear TOF flag ; increment timer overflow count ; ;

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 ++; }

The 68HC11 Microcontroller

The 68HC11 Microcontroller

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
OCxI Interrupt request

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 s high and 600 s low in one period. The flowchart to generate this waveform is shown in Figure 8.20.
Start Set OC2 pin to high Set OC2 action to toggle Clear OC2F flag Start OC2 output compare with a delay of 400 s no

OC2F = 1? yes

16-bit comparator TOCx x = 1,...,5

OCxF

Clear OC2F flag Start OC2 output compare with a delay of 600 s Pin control logic

FOCx

OCx Pin

no

OC2F = 1?

yes

Figure 8.18 Output-compare function block diagram

Figure 8.20 The program logic flow for digital waveform generation

The 68HC11 Microcontroller

The 68HC11 Microcontroller

- 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):
OM2 0 OL2 0 OM3 0 OL3 0 OM4 0 OL4 0 OM5 0 OL5 0 TCTL1 at $1020

regbas PORTA TOC2 TCNT TFLG1 toggle lotime hitime

equ equ equ equ equ equ equ equ org ldx bset bclr ldaa staa ldd addd std brclr bclr ldd addd std

$1000 $00 $18 $0E $23 $40 1200 800

; base address of I/O register block ; offset of PORTA from regbas ; offset of TOC2 from regbas ; offset of TCNT from regbas ; offset of TFLG1 from regbas ; value to select the toggle action ; value to set low time to 600 s ; value to set high time to 400 s

value after reset

OMx OLx 0 0 OCx does not afftect pin 0 1 Toggle OCx pin on successful compare 1 0 Clear OCx on successful compare 1 1 Set OCx pin on successful compare Figure 8.19 The contents of the TCTL1 register (Reprinted with permission of Motorola)

high

$C000 #regbas PORTA,X $40 ; set OC2 pint to high TFLG1,X $BF ; clear OC2F flag #toggle ; select output compare action to be TCTL1,X ; toggle TCNT,X ; start an OC2 operation which toggles the OC2 pin #hitime ; with a delay of 800 E clock cycles TOC2,X ; TFLG1,X $40 high ; wait until OC2F is set to 1 TFLG1,X $BF ; clear OC2F flag TOC2,X ; start another OC2 operation which toggles the OC2 pin #lotime ; with a delay of 1200 E cycles TOC2,X ;

The 68HC11 Microcontroller

The 68HC11 Microcontroller

low

brclr bclr ldd addd std bra end

TFLG1,X $40 low ; wait until OC2F is set to 1 TFLG1,X $BF ; clear OC2F flag TOC2,X ; start another OC2 operation which toggles the OC2 pin #hitime ; with a delay of 800 E cycles TOC2,X ; high

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.

The 68HC11 Microcontroller

The 68HC11 Microcontroller

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 s */ TFLG1 = 0x40; TOC2 += 1200; /* start next OC2 operation with 1200 E cycles as delay */ while (!(TFLG1 & 0x40)); /* wait for 600 s */ TFLG1 = 0x40; TOC2 += 800; } return 0; }

regbas TOC2 TCNT TFLG1 dly25ms onesec oc2_cnt

EQU EQU EQU EQU EQU EQU EQU

$1000 $18 $0E $23 50000 40 0

; base address of I/O register block ; offset of TOC2 from regbas ; offset of TCNT from regbas ; offset of TFLG1 from regbas ; the number of E cycles to generate 25 ms delay ; number of OC2 operations to be performed ; 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

The 68HC11 Microcontroller

The 68HC11 Microcontroller

exit

BEQ exit LDD TOC2,X BRA wait INS PULY PULX RTS

regbas TOC2 TCNT TFLG1 TMSK1 dly20ms one_min * hours minutes ticks alarm routine

equ equ equ equ equ equ equ org rmb rmb rmb rmb fdb org jmp org lds sei ldd std

$1000 $18 $0E $23 $22 40000 3000 $0000 1 1 2 2 start_alarm $00DC oc2_ISR $C000 #$DFFF #one_min ticks

; number of E cycles equivalent to 20 ms delay ; number of OC2 operations to be created to ; generate 1 minute delay

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 + 20000; /* start an OC2 operation with 20000 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 */ } }

; starting address of the alarm routine ; interrupt jump table entry for OC2 on EVB

; set up stack pointer ; disable interrupt before setup is done ; initialize the OC2 count to generate ; one minute delay

The 68HC11 Microcontroller

The 68HC11 Microcontroller

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

forever oc2_ISR

ldx #regbas bclr TFLG1,X $BF bset TMSK1,X $04 ldd TCNT,X addd #dly20ms std TOC2,X cli bra forever ldx #regbas bclr TFLG1,X $BF ldd TOC2,X addd #dly20ms std TOC2,X ldy ticks dey sty ticks bne case2 ldd #one_min std ticks ldd hours

; clear OC2F flag ; enable OC2 interrupt ; start an OC2 operation with ; 20 ms delay ; ; enable interrupt to the 68HC11 ; loop forever to wait for interrupt

; clear OC2 flag ; start the next OC2 operation with ; 20 ms delay ; ; decrement the minute count ; ; ; is one minute expired? ; reinitialize the one-minute counter ; ; load the hours and minutes

The 68HC11 Microcontroller

The 68HC11 Microcontroller

case1

case2

INCB CMPB BNE CLRB INCA CMPA BNE CLRA STD CPD BNE LDX JSR RTI END

#60 case1

#24 case1 hours alarm case2 routine 0,X

; is it time to increment the hour? ; no need to update hour digits yet ; reset minutes to 0 ; increment the hour ; it is time to reset hours to 0? ; no need to reset hour yet ; reset hours to 00 ; save the current time in memory ; reaches alarm time?

; call the alarm routine

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 + 20000; /* start an OC2 operation */ while (k) { while (!(TFLG1 & 0x40)); TFLG1 = 0x40; -- k; TOC2 += 20000; /* start a new OC2 operation */ } }

The 68HC11 Microcontroller

The 68HC11 Microcontroller

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 secondsrepeat this pattern 4 times. 2. Light one LED at a time for one secondfrom 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.
5V 68H C11A8

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.
7 value after reset M7 0 PA7 7 value after reset D7 0 6 M6 0 OC2 6 D6 0 5 M5 0 OC3 5 D5 0 4 M4 0 OC4 4 D4 0 3 M3 0 OC5 3 D3 0 2 0 0 1 0 0 0 0 0 2 0 0 1 0 0 0 0 0 pin controlled OC1D at $100D

74LS04 100 PB7 PB6 PB5 PB4 PB3 PB2 PB1 PB0 Figure 8.21 An LED-flashing circuit driven by port B

OC1M at $100C

Figure 8.22 Contents of the OC1M and OC1D registers (Reprinted with permission of Motorola)

The 68HC11 Microcontroller

The 68HC11 Microcontroller

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 OC1M OC1D EQU EQU EQU $1000 $0C $0D #regbas #%01100000 OC1M,X #%00100000 OC1D

oc1d_in2 equ five_sec equ dly25ms equ ORG rmb ORG ldx bset ldaa staa bclr ldaa staa ldaa staa ldd addd std brclr bclr

$50 200 50000

; value to initialize OC1D to open valves 2 and 4 ; number of OC1 operations to be performed ; the number of E clock cycles equivalent to 25 ms

oc1_cnt

LDX LDAA STAA LDAA STD In C language OC1M = 0x60; OC1D = 0x20;

repeat1

$0000 1 ; number of OC1 operations remained to be performed $C000 #regbas PACTL,X $80 ; configure PA7 pin for output #oc1m_in ; allow OC1 function to control all OC pins OC1M,X ; TFLG1,X $7F ; clear OC1F flag #five_sec oc1_cnt #oc1d_in1 ; set pins OC1, OC3, and OC5 to high after 25 ms OC1D,X TCNT,X ; start an OC1 operation with 25 ms delay #dly25ms ; TOC1,X ; TFLG1,X $80 * ; wait for 25 ms TFLG1,X $7F ; clear OC1F flag

The 68HC11 Microcontroller

The 68HC11 Microcontroller

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 %11111000 into OC1M so that OC1 function can control all five OC pins. - Write the value %10101000 into OC1D to open only valves 1,3,and 5. - Write the value %01010000 into OC1D to open only valves 2 and 4. - Perform 200 OC1 output compare operations with each operation creating 25 ms delay. regbas PACTL OC1D OC1M TOC1 TCNT TFLG1 oc1m_in oc1d_in1 EQU EQU EQU EQU EQU EQU EQU EQU EQU $1000 $26 $0D $0C $16 $0E $23 $F8 $A8

change

repeat2

dec beq ldd bra ldaa staa ldaa staa ldd addd std brclr bclr dec beq bra ldaa staa ldaa staa ldd bra end

oc1_cnt change TOC1,X repeat1 #oc1d_in2 OC1D,X #five_sec oc1_cnt TOC1,X #dly25ms TOC1,X TFLG1,X $80 * TFLG1,X $7F oc1_cnt switch repeat2 #five_sec oc1_cnt #oc1d_in1 OC1D,X TOC1,X repeat1

; decrement the output compare count ; at the end of 5 seconds change the valves setting ; prepare to perform the next OC1 operation ; set to open valves 2 and 4 ; ; reinitialize the output compare count ; ; start the next OC1 operation with the same ; delay ; ; wait until OC1F flag is set to 1 ; clear OC1F flag

; five seconds expired, switch the valve setting ; reinitialize the OC1 count ; ; change the valve setting ; ; prepare to start the next OC1 operation

switch

; value to initialize OC1M ; value to initialize OC1D to open valves 1, 3, and 5

The 68HC11 Microcontroller #include <hc11.h> main () { unsigned int oc1_cnt; PACTL |= 0x80; OC1M = 0xF8; TFLG1 = 0x80; TOC1 = TCNT + 20000; while (1) { OC1D = 0xA8; oc1_cnt = 500; while (oc1_cnt) { while (!(TFLG1 & TFLG1 = 0x80; TOC1 += 20000; oc1_cnt --; } OC1D = 0x50; oc1_cnt = 500; while (oc1_cnt) { while (!(TFLG1 & TFLG1 = 0x80; TOC1 += 20000; oc1_cnt --; } } }

The 68HC11 Microcontroller

/* configure PA7 for output */ /* allow OC1 to control OC1-OC5 pins */ /* clear OC1F flag */ /* start an OC1 operation with 10 ms delay */ /* prepare to set PA7, PA5, and PA3 to high */ /* number of OC1 operations to create 5 s delay */ 0x80)); /* clear OC1F flag */ /* start the next OC1 operation */

regbas TMSK1 PORTA OC1D OC1M TOC1 TOC2 TCTL1 TFLG1 tctl1_in oc1m_in oc1d_in fiveKHz diff

equ equ equ equ equ equ equ equ equ equ equ equ equ equ org jmp jmp org lds ldx bclr

$1000 $22 $00 $0D $0C $16 $18 $20 $23 $80 $40 $40 400 160 $00DC oc2_ISR oc1_ISR

; value to set the OC2 action to be pull the OC2 pin to low ; value to allow OC1 function to control OC2 pin ; value to be written into OC1D to pull OC2 to high ; timer count for 5 KHz (2 MHz E clock cycles) ; the count difference of two output compare functions ; interrupt vector jump table entry for OC2 ; interrupt vector jump table entry for OC1

/* value to pull PA6 and PA4 to high */

0x80)); /* clear OC1F flag */ /* start the next OC1 operation */

$C000 #$DFFF #regbas TFLG1,X $3F ; clear OC1F and OC2F flags

The 68HC11 Microcontroller

The 68HC11 Microcontroller

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 s. Use OC2 function to pull OC2 pin to low 80 s 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 s delay. loop
80s 120s

68HC11

ldaa staa ldaa staa ldaa staa bset bclr ldd addd std addd std cli bra

#tctl1_in TCTL1,X #oc1d_in OC1D,X #oc1m_in OC1M,X TMSK1,X $C0 PORTA,X $40 TCNT,X #fiveKHz TOC1,X #diff TOC2,X loop

; define OC2 action to pull OC2 pin to low ; ; define OC1 action to pull OC2 pin to high ; ; allow OC1 function to control OC2 pin ; ; enable OC1 and OC2 interrupts ; pull OC2 pin to low ; start the OC1 operation with a delay of 200 s ; ; ; start the OC2 operation ; ; enable interrupt to the 68HC11 ; infinite loop to wait for OC1 and OC2 interrupts

OC2

Figure 8.23 Using OC1 and OC2 to generate a 40% duty cycle waveform

The 68HC11 Microcontroller

The 68HC11 Microcontroller

* 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 s 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 s addd #fiveKHz ; std TOC2,X ; rti end

#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 */ }

The 68HC11 Microcontroller

The 68HC11 Microcontroller

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 = TOC1 + 160; /* start OC2 operation that succeed 160 E cycles later */ TMSK1 |= 0xC0; /* enable OC1 and OC2 interrupts */ INTR_ON ( ); while (1); /* infinite loop */ return 0; }

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.
7 value after reset 0 6 0 5 0 4 0 3 0 2 0 0 1 0 0 0 0 0 CFORC at $100B

FORC1 FORC2 FORC3 FORC4 FORC5

Figure 8.24 Contents of the CFORC register (Redrawn with permission of Motorola)

The 68HC11 Microcontroller

The 68HC11 Microcontroller

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 %01111000 is written into the CFORC register? Solution: The contents of TCTL1 configure the output compare actions in Table 8.5
Bit positions 7 5 3 1 6 4 2 0 Value 10 01 10 00 Action to be triggered clear OC2 pin toggle OC3 pin clear OC4 pin no effect on OC5 pin

regbas TMSK2 TFLG2 PACTL tensec RTIF rti_cnt

Table 8.5 Pin actions on OC2-OC5 pins

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 loop

EQU EQU EQU EQU EQU EQU ORG RMB ORG JMP ORG LDS LDX LDD STD BSET LDAA STAA STAA CLI LDD BNE SWI

$1000 $24 $25 $26 305 $40 $0000 2 $00EB rti_hnd $C000 #$DFFF #regbas #tensec rti_cnt PACTL,X $03 #RTIF TFLG2,X TMSK2,X rti_cnt loop

; total RTI interrupts in 10 s ; mask to select the RTIF flag ; remaining RTI interrupts to be generated ; RTI interrupt vector jump table entry ; ; initialize stack pointer

; select RTI clock prescale factor to 8 ; clear RTIF flag ; enable RTI function ; enable interrupt to the 68HC11 ; wait until rti_cnt becomes 0

The 68HC11 Microcontroller

The 68HC11 Microcontroller

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
RTR1 bit 1 0 0 1 1 RTR0 bit 0 0 1 0 1 (E/2 13) divided by 1 2 4 8

RTI service routine is as follows: rti_hnd LDX BCLR LDX DEX STX RTI #regbas TFLG2,X $BF rti_cnt rti_cnt
Start Set RTI clock prescale factor to 8 RTI_cnt 305

Table 8.6 RTI clock source prescale factor Clear RTIF flag in FLG2 Enable RTI interrupt Clear RTIF flag in TFLG2 RTI_cnt RTI_cnt - 1

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 32.67 ms - Need to enable RTI interrupt - 305 RTI interrupts will roughly create a delay of 10 seconds

I RT

e rr in t

t up

RTI_cnt = 0?
Return from interru pt

Return from interrupt

Stop Figure 8.25 Using RTI to create a 10-second delay

The 68HC11 Microcontroller

The 68HC11 Microcontroller

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 ( ) { TFLG2 = 0x40; /* clear RTIF flag */ rti_cnt --; }

- 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): bit 6 (PAEN): bit 5 (PAMOD): bit 4 (PEDGE): 0 -- configure PA7 pin for input; 1 -- configure PA7 for output 0 -- disable PA function; 1 -- enable PA function 0 -- select event-counting mode; 1 -- select gated accumulation mode its meaning depends on bit 5
PAMOD 0 0 1 1 PEDGE 0 1 0 1 Action on clock PAI falling edge increments the counter PAI rising edge increments the counter A 0 on PAI inhibits counting A 1 on PAI inhibits counting

Table 8.7 Combinations of PAMOD and PEDGE bits

The 68HC11 Microcontroller

The 68HC11 Microcontroller

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
7 Value after reset
TOI

6
RTII

5
PAOVI

4 PAII 0

3 0 0 0 0

2 0 0 0 0

1
PR1

0
PR0

0 0 0

0 0 0

TMSK2 at $1024

Example 8.15 Interrupt after N events. Events are converted into signal edges and are connected to the PAI pin. N is smaller than 255. 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 LDX BCLR LDAA NEGA STAA LDAA STAA BSET CLI END $C000 #regbas TFLG2,X $DF ; clear the PAOVF flag #N ; complement N PACNT,X ; initialize PACNT to -N #PA_INI PACTL,X TMSK2,X $20 ; enable the PACNT overflow interrupt ; enable interrupt to the 68HC11

Value after reset

TOF

RTIF

PAOVF PAIF

TFLG2 at $1025

Value after reset

DDRA7

PAEN PAMOD PEDGE

0 0

0 0

RTR1

RTR0

PACTL at $1026

Value after reset

bit 7

bit 6

bit 5

bit 4

bit 3

bit 2

bit 1

bit 0

PACNT at $1027

Figure 8.26 Registers related to the pulse accumulator function (Redrawn with permission of Motorola)

The 68HC11 Microcontroller

The 68HC11 Microcontroller

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 ( ) { }

regbas TCNT TOC2 TFLG1 TMSK2 TFLG2 PACTL PACNT oc2dly pa_in * * onesec stop

EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU

$1000 $0E $18 $23 $24 $25 $26 $27 50000 $50

EQU EQU ORG RMB RMB ORG JMP

40 $10 $0000 1 2 $CA pa_ISR

; output compare count for 25 ms delay ; value to enable PA, select event-counting mode, rising ; edge as active edge, ; and set PA pin for input ; number of OC2 operations to be performed ; value to disable the PA interrupt

oc2_cnt freqcy

; active edge count in one second ; interrupt vector jump table entry for PAI edge ;

The 68HC11 Microcontroller

The 68HC11 Microcontroller

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 8.16 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

ORG LDS LDX LDAA STAA LDD STD LDAA STAA BCLR BSET CLI LDD sec_loop ADDD STD BCLR BRCLR LDD DEC BNE LDAA STAA SWI

$C000 #$DFFF #regbas #onesec oc2_cnt #0 freqcy #pa_in PACTL,X TFLG2,X $EF TMSK2,X $10

; initialize OC2 count

; initialize frequency counter to 0 ; initialize the PA function ; ; clear the PAIF flag ; enable the PAI edge interrupt ; enable interrupt to the 68HC11 TCNT,X ; start an OC2 operation with a delay #oc2dly ; of 25 ms TOC2,X ; TFLG1,X $BF ; clear OC2F flag TFLG1,X $40 * ; wait for 25 ms TOC2,X oc2_cnt sec_loop ; if 1 second is not expired, continue. #stop ; disable PAI edge interrupt TMSK2,X ; ; return to BUFFALO monitor

The 68HC11 Microcontroller

The 68HC11 Microcontroller

pa_ISR

LDX BCLR LDX INX STX RTI END

#regbas TFLG2,X $EF ; clear the PAIF flag freqcy ; increment frequency counter ; freqcy ;

while (!(TFLG1 & 0x40)); TFLG1 = 0X40; TOC2 += 20000; oc2_cnt --;

/* wait for 20000 E cycles */

} 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.

The 68HC11 Microcontroller

The 68HC11 Microcontroller

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 + 20000; /* start an OC2 operation with 20000 E cycles as delay */ TFLG1 = 0x40; /* clear OC2F flag */ TMSK2 |= 0x10; /* enable PAI interrupt */ INTR_ON ( ); /* */ while (oc2_cnt) {

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:

The 68HC11 Microcontroller regbas TCNT TMSK2 TFLG2 PACTL PACNT stop pa_in * paov_cnt pa_cnt edge equ equ equ equ equ equ equ equ org rmb rmb rmb org jmp jmp $1000 $0E $24 $25 $26 $27 $00 %01100000 $00 2 1 1 $00CA pai_hnd paov_hnd

The 68HC11 Microcontroller

* 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
; value to stop the pulse accumulator ; value to be written into PACTL to enable PA, select gated ; accumulation mode, and set PAI to be active high ; keep track of PACNT overflow count ; holds the contents of the PACNT at the end of measurement ; PAI edge interrupt count ; set up interrupt vector jump table entries for PAOV and PAI ; ;

* 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 ; RTI END

The 68HC11 Microcontroller

The 68HC11 Microcontroller

wait

ORG LDS LDX LDD STD LDAA STAA BCLR LDAA STAA CLR BSET CLI TST BNE BCLR LDAA STAA SWI

$C000 #$DFFF #regbas #0 paov_cnt #1 edge TFLG2,X $CF #pa_in PACTL,X PACNT,X TMSK2,X $30

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 */

; initialize the PACNT overflow count to 0 ; initialize PAI signal edge count to 1 ; clear PAOVF and PAIF flags to 0

; initialize the PA function ; reset the PACNT counter to 0 ; enable the PAOV and PAI edge interrupts ; enable interrupt to the 68HC11 edge ; wait for the arrival of PAI falling edge wait ; PACTL,X $40 ; disable the PA function PACNT,X ; make a copy of PACNT pa_cnt ;

The 68HC11 Microcontroller

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 ++; }

You might also like