You are on page 1of 3

; Timer test

;
;
;
;
;
;
;

This 8051 program does nothing but exercise the 2 internal timers
of an 8051. Note that you must not only write to TMOD and TCON
to activate the internal timers, but you must also request that
8051.EXE support them by going to the View/Options menu choice
and adding checkmarks in the "Internal Timers" checkboxes. By
default, 8051.EXE does not support the internal timers because
doing so slows the 8051 program by about 20 % per enabled timer.
ORG 0x00
LJMP Start

; jump over the prog mem locations reserved for ISVs


; (interrupt service vectors)

ORG 0x03
EXT0INT: LJMP Int0Isr

; the ISV for the EXT 0 interrupt starts at 0x0003

ORG 0x0B
TMR0INT: LJMP Tmr0Isr

; the ISV for the TMR 0 interrupt starts at 0x000B

ORG 0x13
EXT1INT: LJMP Int1Isr

; the ISV for the EXT 1 interrupt starts at 0x0013

ORG 0x1B
TMR1INT: LJMP Tmr1Isr

; the ISV for the TMR 1 interrupt starts at 0x001B

ORG 0x23
23
SERINT: LJMP SerIsr

; the ISV for the Serial Port interrupt starts at 0x00

INCLUDE "FontData.txt"
ORG

0x100

; the interrupt service vectors consume program memory


; locations 0x03 thru 0x25 = 37 and the DB statement

s
;
;
;

in FontData.txt consume another 27*8 = 216 bytes


(remember there is a space character after Z).
Hence this program memory address of 0x100 = 256 i

safely past these items.

s
Start:

MOV

DPTR,#StartOfImageData
; We initialize the DPTR ("data pointer"), a 16 bit
; SFR ("special function register"), to point to
; the first column of font data (the first column
; of the letter 'A') in program memory. The DPTR
; register continues to hold this same value
; throughout this program.

MOV

TMOD, #0x22 ;
;
;
;
IE, #0x8A ;
;
TCON,#0x55 ;
;
;
;
;

MOV
MOV

the MSNibble controls TMR #1, the LSNibble TMR #0,


both timers are set into "8 bit auto-reload" mode
clocked internally (rather than from an external
pin).
10001010B, MSBit is the global intr enable,
we enable the TMR0 and TMR1 interrupts
01010101B hence both timers are enabled to run
and both ext intr are configured for edge trigger
MSBit TF1 tmr #1 overflow flag (set by hardware)
TR1 tmr #1 run bit
TF0 tmr #0 overflow flag (set by hardware)

MOV
MOV
MOV
loop:

;
TR0 tmr #0 run bit
;
IE1 intr #1 flag (set by hardware)
;
IT1 intr #1 type bit (1 for edge trigger)
;
IE0 intr #0 flag (set by hardware)
; LSBit IT0 intr #0 type bit (1 for edge trigger)
TH1,#0x40 ; causes TMR #1 to overflow faster than TMR #0
TH0,#0
; not necessary since this is the default value
A, #0x01 ; we walk this 1 bit across the PO SFR while waiting
; for an interrupt

RL
A
MOV P0,A
SJMP loop

Tmr0Isr:
PUSH
MOV
LCALL
POP
RETI
Tmr1Isr:
PUSH
MOV
LCALL
POP
RETI

; loop while waiting for an interrupt

; interrupt service routine for TMR 0 interrupt


ACC
; protect the prior ACC value since we need to use ACC
A,#0
; load ACC with index of letter 'A'
Draw1Char
ACC
; restore prior ACC value
; return and re-enable interrupts
; interrupt service routine for TMR 1 interrupt
ACC
A,#1
; load ACC with index of letter 'B'
Draw1Char
ACC

Int0Isr:

; interrupt service routine for EXT 0 interrupt


SJMP Int0Isr

Int1Isr:

; interrupt service routine for EXT 1 interrupt


SJMP Int1Isr

SerIsr:

; interrupt service routine for serial port interrupt


SJMP SerIsr

Draw1Char:
; This is a subroutine which is responsible for outputting exactly 8
; columns (hence 1 character) of font data to the electric sign board.
; Before you call this subroutine initialize the ACC with the index
; of the desired character. That is, if you want the letter 'C'
; output to the sign board then call this subroutine with ACC = 2.
; We first need to convert the letter index (ranging from 0 to 26)
; to a column index (ranging from 0 to 208). This column index
; will describe the byte offset to that letter's column data.
MOV
MUL

B,#8
AB

; the ACC presently holds an alphabet index


; each letter has 8 columns
; This computes the byte offset beyond
; StartOfImageData where the letter starts. This
; product is guaranteed to be < 256 since the
; entire alphabet only has 216 (27*8) columns
; (remember there is a space char after Z),
; hence we only need to keep (deal with) the
; LSByte of the product. The LSByte is found
; in the ACC following the "MUL AB" instr.

; Within this subroutine we use R0 as a temporary storage location

;
;
;
;
;
;

for the accumulator's value (we need this because the "MOVC A,@A+DPTR"
instruction keeps perturbing the accumulator). And we use the
R1 register to control the loop (that is, decide how many times
we iterate). Note that R0 is synonymous with data memory location 0
and R1 is synonymous with data memory location 1 (at least while
the 8051 remains in its default configuration).
MOV

R0,A

MOV

R1,#0

CharLoop: MOV
MOVC
MOV
INC
INC
CJNE
RET

; preserve this starting column # since the


; upcoming "MOVC A,@A+DPTR" instruction
; replaces the value in the ACC
; we use R1 to control the looping

A,R0
; prepare for upcoming "MOVC A,@A+DPTR" instruction
A,@A+DPTR ; the ACC now holds one column of font data
P0,A
; write that column to the sign board
R0
; advance to the next column
R1
; increment the loop counter
R1,#8,CharLoop
; we loop 8 times in order to output 8 columns

You might also like