- •Acknowledgments
- •About the Author
- •1.1 Basic Computer Structure
- •1.3 A Few Instructions and Some Simple Programs
- •2 The Instruction Set
- •3.1 Op Code Byte Addressing Modes
- •4.2 Assembler Directives
- •4.3 Mechanics of a Two-Pass Assembler
- •4.6 Summary
- •5.1 Cross Assemblers and Downloaders
- •5 Problems
- •6.3 Passing Arguments by Value, Reference, and Name
- •7 Arithmetic Operations
- •7.2 Integer Conversion
- •8 Programming in C and C++
- •8.1 Compilers and Interpreters
- •9 Implementation of C Procedures
- •9.2 Expressions and Assignment Statements
- •9.4 Loop Statements, Arrays, and Structs
- •10 Elementary Data Structures
- •10.1 What a Data Structure Is
- •11.4 Synchronization Hardware
- •12.4 The 68300 Series
- •A2.1 Loading HiWare Software
- •A2.2 Opening the HiWare Toolbox
- •A2.3 Running Examples From the ManualProgramFolder
- •A2.6 POD-Mode BDM Interface
- •Index
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
