Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Introduction to Microcontrollers. Architecture, Programming, and Interfacing of the Motorola 68HC12 (G.J. Lipovski, 1999).pdf
Скачиваний:
191
Добавлен:
12.08.2013
Размер:
29.57 Mб
Скачать

11,4 Synchronization Hardware

325

Arrays or strings can be used with buffers to input or output many numbers in a similar way. Queues are implemented in buffers to input or output data when the program needs them in the same order that they are input or when the device needs them in the same order that they are provided by the program, but at different times than they are provided. Generally, data structures are used to maintain order in the data that are being transferred between the MPU and an input-outputdevice.

11.4 Synchronization Hardware

The previous section illustrated the use of a delay loop to synchronize the output to a traffic light controller. In the next sections, we consider the use of gadfly loops and interrupts to synchronize input and output. These use hardware to indicate when I/O is to be done. The most commonly used hardware is an edge-triggered flip-flop that is set when an output is needed or when an input is available. In this section, we introduce the ' A4 or 'B32 basic counter/timer device to illustrate edge-triggered sensing of I/O status signals. (See Figure 11.7.) We also briefly discuss PORTT and its direction bits.

Figure 11.7. The Counter/Timer Subsystem

I! .5 Gadfly Synchronization

327

LDAB

#$80

; Put one in leftmost bit of accumulator B

STAB

TSCR

; Put it into the control register TSCR

LDD

#$201

; Generate 2 in Accumulator A, 1 in Accumulator B

STAA

$8B

; Write 2 in rightmost bit of control register TCTLE

STAB

$8E

; Write one in rightmost bit of control register TFLG1

In place of a delay loop, the gadfly loop itself is used whenever input or output is done: do ; while{(TFLG1 & 1) == 0); TFLG1 = 1;. The loop waits until an edge sets the flag bit, and the next statement clears the flag bit. This is optimally compiled to assembly languageas

L:

BRCLR

$8E,#1,L

; Wait for one in TFLG1 bit 0

 

LDAB

#1

; Put one in rightmost bit of accumulator B

 

STAB

$8E

; Write it into control register TFLG1

We illustrate the use of gadfly synchronization for counting pulses from a Geiger counter. Each time a pulse occurs, PORTT bit 0 sees a rising edge. To count the pulses, execute the C procedure:

void main() { int i = 0;

TSCR = 0x80; TFLG1 = 1;TCTLE = 1;

do {while({TFLG1 & 1) == 0); TFLG1 = 1; i++; }while(1);

}

An optimized assembly language program segment for the body of the C procedure is

LDAB

#$80

; Put one in leftmost bit of accumulator B

STAB

$86

; Write it into control register TSCR

LDD

#$102

; Generate one in Accumulator A, 2 in Accumulator B

STAA

$8E

; Write one in rightmost bit of control register TFLG1

STAB

$8B

; Write 2 in rightmost bit of control register TCTLE

CLRA

 

; Clear msbyte of local variable i

CLRB

 

; Clear next byte of i

LOOP: BRCLR

$8E,#1, LOOP ; Wait for one in TFLG1 bit 0

MOVE

#1, $8E

; Write 1 into control register TFLG1 to clear bit 0

ADDD

#1

; Increment count

BRA

LOOP

; Loop forever

You can stop this program after it has counted the pulses and examine accumulator D.

332

Chapter 1! Input/ Output

unsigned char i; void main() {

TSCR = 0x80; TTMSKl = TFLG1 = TCTLE = 1; asm CLI

do ; while(l);

}

void interrupt 8 hndlr(void){ TFLG1=1; /*clrreqst*/ i++; /* inc count */}

An optimized assembly-language program segment for the body of the C procedure is

i:

DS. B

1

; Global storage for 8-bit count i

 

LDAB

#$80

; Put one in leftmost bit of accumulator B

 

STAB

$86

; Write it into control register TSCR

 

LDAA

#$ 1

; Generate one in Accumulator A

 

STAA

$8E

; Write one in rightmost bit of control reg. TFLG1

 

STAA

$8C

; Write one in rightmost bit of control reg. TMSK1

 

STAA

$8B

; Write 1 in rightmost bit of control reg. TCTLE

 

CLI

 

; Enableinterrupt

LOOP:

BRA

LOOP

; loop forever

An optimized assembly-language program segment for the handler is

HNDLR: MOVE

#1, TFLG1

; Write one in rightmost bit of control register TFLG1

INC

i

; Increment count

RTI

 

; Return to interrupted routine

The main procedure above initializes the control registers and loops forever. The I condition code bit is generally clear after the 6812 is reset and must be cleared to enable interrupts to occur. A high-level language like C generally does not have a way to enable interrupts, except by inserting embedded assembly language. The statement asm CLI inserts CLI into the assembly-language program. Each time another vector element is to be output, a switch is closed, and PORTT bit 0 sees a rising edge. This causes an interrupt, and the handler is entered. This handler increments the count.

We further illustrate an interrupt-based traffic light controller that is essentially the same as the gadfly-based traffic light controller example. The main procedure initializes the control registers, waits for all elements to be output, and then disables the interrupt. Each time another vector element is to be output, a switch is closed, and PORTT bit 0 sees a falling edge. See Figure 11.9. This causes an interrupt, and the handler is entered. This handler outputs an element from the vector. To output the vector, execute

char buffer[0x80],

i

= 0x80;

void main{) {

 

 

DDRA = OxFF;

TSCR = 0x80; TFLG1 = TMSK1 = 1; TCTLE = 2; asm CLI

do ; while ( i

);

/* wait until all are output */ TMSK1 = 0; /* disable interrupt*/

}

void interrupt 8 hndlr (void) (TFLGl=l;PORTA=buff erf—i ];/* output data*/}

PROBLEMS

:H5

get: BRCLR SC1SR,$20,get LDAB SC1DR

RTS

* void main() { char i;

PSHA

* SC1BD = 52; 7*9600 baud*/ SC1CR = OxC; /* enable Xmt, Rev devices */

MOVW #52,SC1BD

MOVE #$C,SC1CR

* i = SC1SR; i = SC1DR; i = SClSR; i = SC1DR; /* clear RDRF */

LDAB SClSR

LDAB SC1DR

LDAB SClSR

LDAB SC1DR

* for(i = 0; i < 9; i++) put(str[i]);

 

CLR

0,SP

 

LDX

#str

11:

LDAB

B, X

 

BSR

put

 

INC

0,SP

 

LDAB

0,SP

 

CMPB

#9

 

BLT

11

* do j = get(); while( j != ' \ r ' ) ;

12:BSR get

STAB j CMPB #13

BNE 12

PULA

RTS

Figure 11.18. Program with Disassembly

346

Chapter 11 Input/ Output

unsigned char

hi = 0,

lo = 0;

HI:

DC.B

0

LO:

DC.B

0

unsigned char

PORTB61,DDRB@3,ATDCTL2@Ox62,ATDCTL5@Qx65,ATDSTATO@Ox66, ADR380x76;

PORTS:

EQU

 

1

 

 

DDRB:

EQU

 

3

 

 

ATDCTL2:

EQU

 

$62

 

 

ATDCTL5:

EQU

 

$65

 

 

ATDSTATO:

EQU

 

$66

 

 

ADR3:

EQU

 

$76

 

 

void main()

{ unsigned

char i, j, k;

DDRB - Oxff;

 

 

ORG

 

$850

 

 

MAIN:

LDD

 

#$FF80

 

 

 

STAA

 

DDRB

;DDRB=OXFF

ATDCTL2 = 0x80; for(j = 1;

j != 0x80; j++) ;

 

STAB

 

ATDCTL2

;ATDCTL2=Ox80

 

LDY

 

#$800

;for(j=l ;

j!=0x80; j++)

LOOP1:

DBNE

 

Y, LOOPl

 

 

for(i = 0;

i

!= Oxff; i++){ PORTB « i; ATDCTL5 = 3;

 

LDD

 

#03

 

 

LOOP2:

STAA

PORTB

;PORTB =

i

 

STAB

 

ATDCTL5

;ATDCTL5

= 3

 

do ;

while(!(ATDSTATO

& 0x80)) ; k = ADR3;

 

PSHA

 

 

 

 

LOOP3:

BRCLR

ATDSTATO, #$80, LOOP3

 

;do-while(iATDSTATO & 0x80)

 

 

 

k = ADR3;

 

 

 

LDAB

 

ADR3

;k = ADR3

 

if((k > i) && (( j = (k ~ i ) ) > hi )) hi = j;

PROBLEMS

347

 

SUBB

0,SP

;j-k-i

 

BEQ

LOOP4

 

 

BLO

LOOP5

 

 

CMPB

HI

?j>hi?

 

BLS

LOOP4

 

 

STAB

HI

;hi=j

 

BRA

LOOP4

 

 

if((k < i) && (( j = ( i - k) ) > lo )) lo - j;

LOOPS:

NEGB

 

;j=i-k

 

CMPB

LO

 

 

BLS

LOOP4

;j>lo?

 

STAB

LO

 

 

for(i = 0; i != Oxff; i++){

 

LOOP4:

PULA

 

 

 

INCA

 

;i++

 

CMPA

#$FF

;j!=0x

 

BNE

LOOP2

 

LOOP6-.

BRA

LOOP6

;do-while(l)

Figure 11.19. Another Program with Disassembly