Example 1: 1ms timer for port A of 8255 on-board LEDs of Fig. 3. The pro-gram for a 1ms to 16-second counter is as follows:
1 2000 ORG 2000H
2 2000 90 60 03 MOV DPTR,#6003H
;POINT TO 8255 CONTROL REG.
3 2003 74 80 MOV A,#80H ;TO SET ALL PORTS AS OUTPUT 4 2005 F0 MOVX @DPTR,A
;OUTPUT TO CONTROL REG.
5 2006 7D 01 MOV R5,#01
COUNTER IN MODE 2
8 ;HERE TIMER 0 IS ALONE
USED.
9 200B 75 8C FC MOV TH0,#FCH
;FOR 1 ms, 3E8H subtract from 1000H = FC18H
10 200E 75 8A 18 MOV TL0,#18H 11 2011 43 A8 82 ORL IE,#82H
;ENABLE INTERRUPT FOR TIMER 0 12 ;INT. ENABLE BIT D7
HIGH,D1 BIT HIGH FOR ET-0 13 2014 D2 8C SETB TR0
;START TIMER 0 14 2016 C2 8D K: CLR TF0
;CLEAR TIMER -0 OVERFLOW FLG 15 2018 80 FE SJMP $ ;LOOP HERE 16
17 201A 01 08 AJMP A1
;AFTER INTERRUPT 18
19 2F2B ORG 2F2BH ;JUMP VECTOR for timer 0 interrupt
20 2F2B ISR:
21 2F2B 0D INC R5 ;Increment R5 22 2F2C ED MOV A,R5 ;move to A 23 2F2D 90 60 00 MOV DPTR,#6000H
; POINT TO 8255 PORT A 24 2F30 F0 MOVX @DPTR,A
; OUTPUT THERE 25 2F31 F5 90 MOV P1,A
;CHECKING PORT-1 IF 8255 NOT USED 26 2F33 32 RETI
; Then return from ISR.
27
28 2F34 END TABLE I
Timer/Counter Mode Control Register Bit Functions
Fig. 10: Logic states of various control bits on a timer start action
The program has to be loaded at two stretches, i.e. from 2000H to 201BH for the main program and from 2F2BH to 2F33H for timer 0 ISR. If you are assem-bling and downloading the above program after linking and ASCII-conversion into the file in a PC, you must wait for this program to download from 2000H to 2F34H after W key (downloading key) is pressed. Otherwise, the downloading up to 2F high address would not be com-pleted.
By connecting an LED or logic probe at pins 1 to 8 of the IC 89C51, it is pos-sible to see the blinking rate of the LED.
Try changing the values of TH0 and TL0 from FC18 hex to 0000H. Then we get 64 ms for each overflow. That would make the last D7 bit to blink at a rate of 256x64 ms or 16 seconds.
The program uses the timer to gener-ate 1ms timing. Register R5 increments every 1 ms. Thus, the LED on port 1 (or port A) will blink from 1 to 255 ms for its eight bits. If the D7 bit alone is observed, it will blink at 256x1x2 ms or half a second rate.
Example 2: Pulse variable control.
Here is another program which generates pulses of 15 kHz (64 μs) with gaps in between. This is a pulse-train modulated (not pulse width modulated) signal. The number of pulses in a group of 16 pulses is varied from 1 to 10. (A thumbwheel switch connected to port P1.4 (pin 5) through port P1.7 (pin 8) will vary the pulses according to the number shown by thumbwheel switch.)
The remaining periods of 64 μs are
free from pulses. These pulse trains are useful for small-model control motor drives. Here we need a short timing duration of 32 μs for the two half cycles of the rectangular pulse of 64μs duration.
As 32 is a small number, we can use an 8-bit timer. In mode 2, auto-reloading function is available, so we need not enter the values in the timer register every time, as we did in the previous program (by jumping back to A1 point). Thus timer 0 is set in mode 2. The value of E0H corresponds to –32 (E0H+20H=100 H).
The ISR is called TIM0int. A flag bit called ‘flag’ is used here. If this flag is set, pin P1.0 is set to low logic. The bit is complemented at every timer interrupt, but the number of pulses to be output is limited. The reading of bits D4 to D7 from port 1 decides the number of pulses in a group of 16 time slots of 64 μs. Thus, in 64×16 μs (=1 ms), the number of output pulses is decided by this number read from port 1 bits 4 to 7.
The program is as follows:
1 00 30 VALUE1 EQU 30H
7 2000 ORG 2000H
8 2000 MONI:
9 2000 75 81 70 ST:MOV SP,#70H 10 2003 75 B0 FF MOV P3,#FFH 11 2006 75 8A 00 MOV TL0,#00 12 2009 75 8C E0 MOV TH0,#E0H 13 200C 75 89 02 MOV TMOD,#02 ;8 BIT
TIMER-0 th AUTO RELOAD 14 200F 43 A8 82 ORL IE,#82H ;TIMER-0
BIT ENABLES INTERRUPT 15 2012 7F 18 MOV R7,#24 16 2014 E5 90 KK:MOV A,P1 17 2016 54 F0 ANL A,#F0H
18 2018 C4 SWAP A
19 2019 F5 30 MOV 30H,A 20 201B 74 10 MOV A,#16 21 201D 95 30 SUBB A,30H 22 201F F5 31 MOV 31H,A
27 2080 ORG 2080H 28
29 2080 20 32 0C TIM0INT:JB FLAG,K1 30 2083 DF 07 DJNZ R7,K2 31 2085 D2 32 SETB FLAG 32 2087 AF 30 MOV R7,30H 33 2089 B2 90 CPL P1.0
34 208B 32 RETI
35 208C C2 90 K2:CLR P1.0
36 208E 32 RETI
37 208F DF 07 K1:DJNZ R7,K3 38 2091 C2 32 CLR FLAG 39 2093 AF 31 MOV R7,31H 40 2095 C2 90 CLR P1.0
41 2097 32 RETI
42 2098 B2 90 K3:CPL P1.0
43 209A 32 RETI
44
45 209B END
Also add by hand, at 2F2BH address, the code:
2F2B 92 20 80 JMP 2080H
Example 3: Frequency counter pro-gram (Fig. 11). The 89C51 has two tim-ers or counttim-ers. If one timer is configured to repeat every 1 ms, the other timer can be made to act as a counter. The counts that would accumulate during this period (1 ms) will then indicate the frequency of the signal in kilohertz. If the timer’s window is varied to 10 ms, the count frequency will be in hundreds of hertz, and if it is varied to 100 ms, we get frequencies in tens of hertz, and so on. By varying this time, one can make an auto-ranging frequency counter that is basically useful for a range of 100 Hz to 20 kHz.
The counter pin must be fed with clean TTL pulses of the frequency being mea-sured. In digital circuits this is easy. How-ever, any analogue signal must be first converted into TTL (5V) level before it is input to the T1 (counter) pin 15 of the 89C51.
Fig. 11: Frequency counter on the 89C51 circuit
The program starts with the initialisation of the timer and the counter.
Timer 0 has the timing window. Timer 1 acts as a counter, with input to T1 (pin 15).
When the time is over, which is checked by flag TF, the value of the count in TL is passed on to the LCD. The num-ber in TL register is in binary, which is first converted into decimal form by a call to the subroutine BINBCD.
The BINBCD program is useful for converting any binary 8-bit number into BCD format. Thus FF Hex will become 255. The program uses the special instruc-tion DIV AB to divide first by 100 and then by 10 to find the BCD digits one by one. Then, the three digits are to be displayed on the LCD. Since the LCD requires ASCII coded numbers for dis-play, we convert 2 to 32, 0 to 30, and so on. Then, a three-digit number is dis-played on the LCD.
The program can be changed for a gate period of 10 ms or 100 ms by simply altering the initial values of timer regis-ters TL and TH in 4th and 5th lines of the program. For entering, the number 1000 for 1 ms (1 ms=1000 μs=1000 pulses), the preload value is FC18. (This is for a 12MHz crystal. For an 11.09MHz crystal, the number will be smaller by 11.09/12.
This gives a value of 924 for 1 ms, which is converted into hex value (39CH) and subtracted from FFFFH to get the preload value of FC64H. FC64 is to be loaded in TH0 and TL0 in lines 4 and 5, respec-tively.)
The program is as follows:
FREQCTR.ASM 1 $MOD52
2 2000 ORG 2000H
3 2000 758951 BEG: MOV TMOD, #01010001B
;TIMER 1 - MODE 1 16 BIT, TIMER-0 COUNTER MODE 1
4 2003 758CD8 MOV TH0,#0D8H ;TIMER REG.0 IS SET TO 0
5 2006 758AFE MOV TL0,#0FEH ;10 ms GATE TIME
6 2009 D28C SETB TR0 ;START TIMER 0 (COUNT ACTION) 7 200B 758B00 MOV TL1,#00H 8 200E 758D00 MOV TH1,#00H ;ctr-1 IS
START-ING FROM -1 9 2011 D28E SETB TR1 ; START COUNTER
TIMER-1 10 2013 308DFD JNB TF0,$
; COUNT OVER ? 11 2016 C28E CLR TR1 ; STOP TIM- 1 12 2018 C28D CLR TF0
13 201A C28C CLR TR0 ;STOP TIMER-0 14 201C E58B MOV A,TL1 ;read counts 15 201E 122025 CALL SHOW ; SHOWS
THE COUNTS IN 1 MILLISEC 16 2021 117A ACALL DELAY 17 2023 0100 AJMP BEG ;over 18 2025 12205D SHOW:CALL BINBCD
;RESULT IN DECIMAL IS IN
;INTERNAL RAM LOCATIONS 30-3219 2028 7401 MOV A,#1
20 202A 120090 CALL 90H ;COMMAND TO Lcd
21 202D E530 MOV A,30H 22 202F 122070 CALL HEXASCI 23 2032 12009F CALL 9FH 24 2035 12009F CALL 09FH ;Write
DDRAM of LCD 25 2038 E531 MOV A,31H 26 203A 122070 CALL HEXASCI 27 203D 12009F CALL 09FH 28 2040 E532 MOV A,32H 29 2042 122070 CALL HEXASCI 30 2045 12009F CALL 09FH 31 2048 7420 MOV A,#20H 32 204A 12009F CALL 09FH 33 204D 744B MOV A,#’K’
34 204F 12009F CALL 09FH 35 2052 7448 MOV A,#’H’
36 2054 12009F CALL 09FH 37 2057 745A MOV A,#’Z’
38 2059 12009F CALL 09FH 39 205C 22RET
40 205D 75F064 BINBCD:MOV B,#64H 41 2060 84 DIV AB
42 2061 F530 MOV 30H,A 43 2063 E5F0 MOV A,B 44 2065 75F00A MOV B,#0AH 45 2068 84 DIV AB 46 2069 F531 MOV 31H,A 47 206B E5F0 MOV A,B 48 206D F532 MOV 32H,A
49 206F 22 RET
50 2070 HEXASCI: ;CONVERTS A NIBBLE INTO ASCII CODE FOR LCD DISPLAY 51 2070 2436 ADD A,#36H
52 2072 30D602 JNB AC,SKIP 53 2075 2407 ADD A,#7 54 2077 9406 SKIP:SUBB A,#6
55 2079 22 RET
56 207A 7FFF DELAY:MOV R7,#0FFH 57 207C 7E80 S1:MOV R6,#80H 58 207E DEFE DJNZ R6,$
59 2080 DFFA DJNZ R7,S1
60 2082 22 RET
END
Note that this program uses only the polling of the timer flag. It doesn’t use the interrupt action on timer overflow, as we have not enabled the interrupts. (The program works properly in kHz.)
Example 4: Period measurement.
Signals (of course, TTL input only) of low frequency cannot be measured by using a time gate/window. In such cases the pe-riod itself can be measured to an accuracy of 1 μs. For period measurement, we can load timer 0 as above with the value ‘0’ to start with and then start it along with counter 1. Load the timer mode register TMOD with a value of 61H. This gives mode 2 for timer 1 acting as counter of pulse transitions from high level to low level (at pin 15 of 89C51). Timer 1 func-tions as an 8-bit auto-reload type of counter.
In the program for period measure-ment, we load counter 1 register with maximum count value of FFH, because we want even the very first transition to cause the register to overflow from FF to 100, which means overflow beyond eight bits. Then, we check TF1 flag (in line 12), which gets set internally. So, if we read that TF1 bit, we know the transition has occurred. Then, we start timer 0 and count the microseconds in its TH0 and TL0 registers, which are initially set to zero (in 4th and 5th lines, respectively).
Again we start counter 1. When the next transition occurs, one period is counted on timer 0. When the count is one, we can note the timer 0 register and see the value in microseconds. (With an 11.09MHz crystal, each count is 12/11.09 μs.) But this is a 16-bit number. We have no easy method to convert it into decimal (<65,536). So, for the present we just see the value in hex itself, using the monitor LCD routine. That routine shows DPH and DPL registers. So, after transferring the timer 0 low and high registers to these, the display program is called. The pro-gram repeats indefinitely, so the period of a TTL-compatible waveform can be con-tinuously observed.
Pin 15 of 89C51 is connected to the pulse output from, say, a function gen-erator. Then, after executing the program, we read the value on LCD. Let it be 7 09 Hex, giving a value of 1949 μs.
The program is as follows:
INPUT FILENAME : PERCTR.ASM 1 2000 ORG 2000H 2
3 2000 75 89 61 MOV TMOD,#01100001B
;TIMER 1-MODE 2 COUNTER,TIMR-0 TO MODE 1 4 2003 75 8C 00 BEG:MOV TH0,#0H
;TIMER REG.0 IS SET TO 0 5 2006 75 8A 00 MOV TL0,#0H
6 2009 75 8B FE MOV TL1,#FEH 7 200C 75 8D FF MOV TH1,#FFH ; ctr-1 IS
STARTING FROM -1 so that the first ;high to low transition on T1 pin 15 will cause over-flow, set TF1 9 200F C2 8F CLR TF1 ; so clear the flag
to start with 10
11 2011 D2 8E SETB TR1 ; START COUNTER -1
12 2013 30 8F FD JNB TF1,$; COUNT OVER means edge low on input detected 13 2016 D2 8C SETB TR0 ;START TIMER 0 14 2018 C2 8F CLR TF1 ;CLEAR INTR.
FLAG of counter 1 15 ;now start timer and count
microseconds till next low edge 16 201A 30 8F FD JNB TF1,$
17 201D C2 8C CLR TR0 ;STOP TIMER-0 NOW 18 201F 85 8A 82 MOV DPL,TL0 ;read counts 19 2022 85 8C 83 MOV DPH,TH0 ; TO data
pointer as 16 bit number 20 2025 12 01 30 CALL 0130H ; DISPLAY PROGRAM FOR LCD SHOWS DPH,DPL AND R2 21 2028 11 2C ACALL DELAY
22 202A 01 03 JMP BEG ;over 23 202C 7F FF DELAY:MOV R7,#FFH 24 202E 7E 80 S1:MOV R6,#80H 25 2030 DE FE DJNZ R6,$
26 2032 DF FA DJNZ R7,S1
27 2034 22 RET
28 2035 END