Sunday, 27 January 2013

TIMER and COUNTER PROGRAMMING

Timers/Counters Programming

  • The 8051 has two timers/counters, they can be used either as
    • Timers to generate a time delay or as
    • Event counters to count events happening outside the microcontroller
  • Both Timer 0 and Timer 1 are 16 bits wide
    • Since 8051 has an 8-bit architecture, each 16-bits timer is accessed as two separate registers of low byte and high byte
      • The low byte register is called TL0/TL1 
      • The high byte register is called TH0/TH1

TMOD Register

Both timers 0 and 1 use the same register, called TMOD (timer mode), to set the various timer operation modes
  • TMOD is a 8-bit register
    • The lower 4 bits are for Timer 0
    • The upper 4 bits are for Timer 1
    • In each case,
      • The lower 2 bits are used to set the timer mode
      • The upper 2 bits to specify the operation
Modes of Operation:
M0
M1
Mode
Operating mode
0
0
0
13-bit timer mode
8-bit timer/counter THx with TLx as 5-bit prescaler
0
1
1
16-bit timer mode
16-bit timer/counter THx and TLx are cascaded; there is no prescaler
1
0
2
8-bit auto reload
8-bit auto reload timer/counter; THx holds a value which is to be reloaded TLx each time it overfolws
1
1
3
Split timer mode
  • C/T : Timer or counter selected
    • Cleared for timer operation (input from internal system clock)
    • Set for counter operation (input from Tx input pin)
  • GATE:Gating control when set.
    • Timer/counter is enable only while the INTx pin is high and the TRx control pin is set
    • When cleared, the timer is enabled whenever the TRx control bit is set
Timers of 8051 do starting and stopping by either software or hardware control
  • In using software to start and stop the timer where GATE=0
  • The start and stop of the timer are controlled by way of software by the TR (timer start) bits TR0 and TR1
    • The SETB instruction starts it, and it is stopped by the CLR instruction
    • These instructions start and stop the timers as long as GATE=0 in the TMOD register
  • The hardware way of starting and stopping the timer by an external source is achieved by making GATE=1 in the TMOD register

Case of GATE = 1

  • If GATE = 1, the start and stop of the timer are done externally through pins P3.2 and P3.3 for timers 0 and 1, respectively
  • This hardware way allows to start or stop the timer externally at any time via a simple switch

Mode 1 Programming

The following are the characteristics and operations of mode1:
  • It is a 16-bit timer; therefore, it allows value of 0000 to FFFFH to be loaded into the timer’s register TL and TH
  • After TH and TL are loaded with a 16-bit initial value, the timer must be started
    • This is done by SETB TR0 for timer 0 and SETB TR1 for timer 1
  • After the timer is started, it starts to count up
    • It counts up until it reaches its limit of FFFFH
  • When it rolls over from FFFFH to 0000, it sets high a flag bit called TF (timer flag)
    •  Each timer has its own timer flag: TF0 for timer 0, and TF1 for timer 1
    •  This timer flag can be monitored
  • When this timer flag is raised, one option would be to stop the timer with the instructions CLR TR0 or CLR TR1, for timer 0 and timer 1, respectively
  • After the timer reaches its limit and rolls over, in order to repeat the process
    • TH and TL must be reloaded with the original value, and
    • TF must be reloaded to 0

Steps to Mode 1 Program

To generate a time delay
  • Load the TMOD value register indicating which timer (timer 0 or timer 1) is to be used and which timer mode (0 or 1) is selected
  • Load registers TL and TH with initial count value
  • Start the timer
  • Keep monitoring the timer flag (TF) with the JNB TFx,target instruction to see if it is raised
    • Get out of the loop when TF becomes high
  • Stop the timer
  • Clear the TF flag for the next round
  • Go back to Step 2 to load TH and TL again
Example:
In the following program, we create a square wave of 50% duty cycle (with equal portions high and low) on the P1.5 bit. Timer 0 is used to generate the time delay. Analyze the program

MOV TMOD,#01                ;Timer 0, mode 1(16-bit mode)
HERE:
MOV TL0,#0F2H                ;TL0=F2H, the low byte
MOV TH0,#0FFH               ;TH0=FFH, the high byte
CPL P1.5                               ;toggle P1.5
ACALL DELAY
SJMP HERE

In the above program notice the following step.
1. TMOD is loaded.
2. FFF2H is loaded into TH0-TL0.
3. P1.5 is toggled for the high and low portions of the pulse.

DELAY:
SETB TR0              ;start the timer 0
AGAIN:
JNB TF0,AGAIN                 ;monitor timer flag 0
        ;until it rolls over
CLR TR0                 ;stop timer 0
CLR TF0                 ;clear timer 0 flag
RET

4. The DELAY subroutine using the timer is called.
5. In the DELAY subroutine, timer 0 is started by the SETB TR0 instruction.
6. Timer 0 counts up with the passing of each clock, which is provided by the crystal oscillator. As the timer counts up, it goes through the states of FFF3, FFF4, FFF5, FFF6, FFF7, FFF8, FFF9, FFFA, FFFB, and so on until it reaches FFFFH. One more clock rolls it to 0, raising the timer flag (TF0=1). At that point, the JNB instruction falls through.
7. Timer 0 is stopped by the instruction CLR TR0. The DELAY subroutine ends, and the process is repeated.
Notice that to repeat the process, we must reload the TL and TH registers, and start the process is repeated



Example:
Find the delay generated by timer 0 in the following code, using both of the Methods of Figure 9-4. Do not include the overhead due to instruction.

CLR P2.3                            ;Clear P2.3
MOV TMOD,#01               ;Timer 0, 16-bitmode
HERE:
MOV TL0,#3EH                 ;TL0=3Eh, the low byte
MOV TH0,#0B8H              ;TH0=B8H, the high byte
SETB P2.3                          ;SET high timer 0
SETB TR0                           ;Start the timer 0
AGAIN:
JNB TF0,AGAIN                ;Monitor timer flag 0
CLR TR0                             ;Stop the timer 0
CLR TF0                              ;Clear TF0 for next round
CLR P2.3

Solution:
(a) (FFFFH – B83E + 1) = 47C2H = 18370 in decimal and 18370 × 1.085 us = 19.93145 ms
(b) Since TH – TL = B83EH = 47166 (in decimal) we have 65536 – 47166 = 18370. This means that the timer counts from B38EH to FFFF. This plus Rolling over to 0 goes through a total of 18370 clock cycles, where each clock is 1.085 us in duration. Therefore, we have 18370 × 1.085 us = 19.93145 ms as the width of the pulse.


Example:
Modify TL and TH in Example above to get the largest time delay possible. Find the delay in ms. In your calculation, exclude the overhead due to the instructions in the loop.

Solution:
To get the largest delay we make TL and TH both 0. This will count up from 0000 to FFFFH and then roll over to zero.
CLR P2.3                            ;Clear P2.3
MOV TMOD,#01               ;Timer 0, 16-bitmode
HERE:
MOV TL0,#0                       ;TL0=0, the low byte
MOV TH0,#0                      ;TH0=0, the high byte
SETB P2.3                           ;SET high P2.3
SETB TR0                            ;Start timer 0
AGAIN:
JNB TF0,AGAIN                 ;Monitor timer flag 0
CLR TR0                              ;Stop the timer 0
CLR TF0                               ;Clear timer 0 flag
CLR P2.3
Making TH and TL both zero means that the timer will count from 0000 to FFFF, and then roll over to raise the TF flag. As a result, it goes through a total Of 65536 states. Therefore, we have delay =
(65536 - 0) × 1.085 us = 71.1065ms.

Example:
The following program generates a square wave on P1.5 continuously using timer 1 for a time delay. Find the frequency of the square wave if XTAL = 11.0592 MHz. In your calculation do not include the overhead due to Instructions in the loop.

MOV TMOD,#10               ;Timer 1, mod 1 (16-bitmode)
AGAIN:
 MOV TL1,#34H                 ;TL1=34H, low byte of timer
MOV TH1,#76H                  ;TH1=76H, high byte timer
SETB TR1                            ;start the timer 1
BACK:
JNB TF1,BACK                  ;till timer rolls over
CLR TR1                             ;stop the timer 1
CPL P1.5                             ;comp. p1. to get hi, lo
CLR TF1                             ;clear timer flag 1
SJMP AGAIN                     ;is not auto-reload

Solution:
Since FFFFH – 7634H = 89CBH + 1 = 89CCH and 89CCH = 35276 clock count and 35276 × 1.085 us = 38.274 ms for half of the square wave. The frequency = 13.064Hz. Also notice that the high portion and low portion of the square wave pulse are equal. In the above calculation, the overhead due to all the instruction in the loop is not included.

Finding the Loaded Timer Values

To calculate the values to be loaded into the TL and TH registers, look at the following example
  • Assume XTAL = 11.0592 MHz, we can use the following steps for finding the TH, TL registers’ values
  1. Divide the desired time delay by 1.085 us
  2. Perform 65536 – n, where n is the decimal value we got in Step1
  3. Convert the result of Step2 to hex, where yyxx is the initial hex value to be loaded into the timer’s register
  4. Set TL = xx and TH = yy
Example:
Assume that XTAL = 11.0592 MHz. What value do we need to load the timer’s register if we want to have a time delay of 5 ms (milliseconds)? Show the program for timer 0 to create a pulse width of 5 ms on P2.3.
Solution:
Since XTAL = 11.0592 MHz, the counter counts up every 1.085 us. This means that out of many 1.085 us intervals we must make a 5 ms pulse. To get that, we divide one by the other. We need 5 ms / 1.085 us = 4608 clocks. To Achieve that we need to load into TL and TH the value 65536 – 4608 = EE00H. Therefore, we have TH = EE and TL = 00.

CLR P2.3                            ;Clear P2.3
MOV TMOD,#01               ;Timer 0, 16-bitmode
HERE:
MOV TL0,#0                      ;TL0=0, the low byte
MOV TH0,#0EEH              ;TH0=EE, the high byte
SETB P2.3                          ;SET high P2.3
SETB TR0                          ;Start timer 0
AGAIN:
JNB TF0,AGAIN               ;Monitor timer flag 0
CLR TR0                            ;Stop the timer 0
CLR TF0                            ;Clear timer 0 flag


Example:
Assume that XTAL = 11.0592 MHz, write a program to generate a square wave of 2 kHz frequency on pin P1.5.
Solution:
This is similar to Examples above, except that we must toggle the bit to generate the square wave. Look at the following steps.
(a) T = 1 / f = 1 / 2 kHz = 500 us the period of square wave.
(b) 1 / 2 of it for the high and low portion of the pulse is 250 us.
(c) 250 us / 1.085 us = 230 and 65536 – 230 = 65306 which in hex is FF1AH.
(d) TL = 1A and TH = FF, all in hex. The program is as follow.

MOV TMOD,#01               ;Timer 0, 16-bitmode
AGAIN:
MOV TL1,#1AH                ;TL1=1A, low byte of timer
MOV TH1,#0FFH              ;TH1=FF, the high byte
SETB TR1                           ;Start timer 1
BACK:
JNB TF1,BACK                 ;until timer rolls over
CLR TR1                            ;Stop the timer 1
CLR P1.5                           ;Clear timer flag 1
CLR TF1                            ;Clear timer 1 flag
SJMP AGAIN                    ;Reload timer

Example:
Assume XTAL = 11.0592 MHz, write a program to generate a square wave of 50 kHz frequency on pin P2.3.
Solution:
Look at the following steps.
(a) T = 1 / 50 = 20 ms, the period of square wave.
(b) 1 / 2 of it for the high and low portion of the pulse is 10 ms.
(c) 10 ms / 1.085 us = 9216 and 65536 – 9216 = 56320 in decimal, and in hex it is DC00H.
(d) TL = 00 and TH = DC (hex).

MOV TMOD,#10H            ;Timer 1, mod 1
AGAIN:
MOV TL1,#00                     ;TL1=00,low byte of timer
MOV TH1,#0DCH              ;TH1=DC, the high byte
SETB TR1                              ;Start timer 1
BACK:
JNB TF1,BACK                    ;until timer rolls over
CLR TR1                                ;Stop the timer 1
CLR P2.3                               ;Comp. p2.3 to get hi, lo
SJMP AGAIN                      ;Reload timer
;mode 1 isn’t auto-reload

Generating Large Time Delay

Example:

Examine the following program and find the time delay in seconds. Exclude the overhead due to the instructions in the loop.

MOV TMOD,#10H            ;Timer 1, mod 1
MOV R3,#200                    ;cnter for multiple delay
AGAIN:
MOV TL1,#08H                 ;TL1=08,low byte of timer
MOV TH1,#01H                ;TH1=01,high byte
SETB TR1                          ;Start timer 1
BACK:
JNB TF1,BACK                 ;until timer rolls over
CLR TR1                            ;Stop the timer 1
CLR TF1                            ;clear Timer 1 flag
DJNZ R3,AGAIN              ;if R3 not zero then
       ;reload timer
Solution:
TH-TL = 0108H = 264 in decimal and 65536 – 264 = 65272. Now 65272 × 1.085 μs = 70.820 ms, and for 200 of them we have 200 ×70.820 ms = 14.164024 seconds.

Mode 2 Programming

Characteriustics of Mode 2

The following are the characteristics and operations of mode 2:
  • It is an 8-bit timer; therefore, it allows only values of 00 to FFH to be loaded into the timer’s register TH
  • After TH is loaded with the 8-bit value, the 8051 gives a copy of it to TL
    • Then the timer must be started
    • This is done by the instruction SETB TR0 for timer 0 and SETB TR1 for timer 1
  • After the timer is started, it starts to count up by incrementing the TL register
    • It counts up until it reaches its limit of FFH
    • When it rolls over from FFH to 00, it sets high the TF (timer flag) When the TL register rolls from FFH to 0 and TF is set to 1, TL is reloaded automatically with the original value kept by the TH register
  • When the TL register rolls from FFH to 0 and TF is set to 1, TL is reloaded automatically with the original value kept by the TH register
    • To repeat the process, we must simply clear TF and let it go without any need by the programmer to reload the original value
    • This makes mode 2 an auto-reload, in contrast with mode 1 in which the programmer has to reload TH and TL

Steps to Mode 2 Program

To generate a time delay
  • Load the TMOD value register indicating which timer (timer 0 or timer 1) is to be used, and the timer mode (mode 2) is selected
  • Load the TH registers with the initial count value
  • Start timer
  • Keep monitoring the timer flag (TF) with the JNB TFx,target instruction to see whether it is raised
    • Get out of the loop when TF goes high
  • Clear the TF flag
  • Go back to Step4, since mode 2 is autoreload
Example:
Assume XTAL = 11.0592 MHz, find the frequency of the square wave generated on pin P1.0 in the following program

MOV TMOD,#20H            ;T1/8-bit/auto reload
MOV TH1,#5                     ;TH1 = 5
SETB TR1                          ;start the timer 1
BACK:
JNB TF1,BACK                ;till timer rolls over
CPL P1.0                           ;P1.0 to hi, lo
CLR TF1                           ;clear Timer 1 flag
SJMP BACK                     ;mode 2 is auto-reload

Solution:
First notice the target address of SJMP. In mode 2 we do not need to reload TH since it is auto-reload. Now (256 - 05) × 1.085 us = 251 × 1.085 us = 272.33 us is the high portion of the pulse. Since it is a 50% duty cycle square wave, the period T is twice that; as a result T = 2 × 272.33 us = 544.67 us and the frequency = 1.83597 kHz



Example:

Find the frequency of a square wave generated on pin P1.0.
Solution:
MOV TMOD,#2H          ;Timer 0, mod 2
   ;(8-bit, auto reload)
MOV TH0,#0
AGAIN:
MOV R5,#250                ;multiple delay count
ACALL DELAY
CPL P1.0
SJMP AGAIN
DELAY:
SETB TR0                       ;start the timer 0
BACK:
JNB TF0,BACK             ;stay timer rolls over
CLR TR0                        ;stop timer
CLR TF0                        ;clear TF for next round
DJNZ R5,DELAY
RET
T = 2 ( 250 × 256 × 1.085 us ) = 138.88ms, and frequency = 72 Hz 

COUNTER PROGRAMMING


Timers can also be used as counters counting events happening outside the 8051

  • When it is used as a counter, it is a pulse outside of the 8051 that increments the TH, TL registers
  • TMOD and TH, TL registers are the same as for the timer discussed previously

C/T Bit in TMOD Register

  • The C/T bit in the TMOD registers decides the source of the clock for the timer
    • When C/T = 1, the timer is used as a counter and gets its pulses from outside the 8051
    • The counter counts up as pulses are fed from pins 14 and 15, these pins are called T0 (timer 0 input) and T1 (timer 1 input)
Example:
Assuming that clock pulses are fed into pin T1, write a program for counter 1 in mode 2 to count the pulses and display the state of the TL1 count on P2, which connects to 8 LEDs.
Solution:
MOV TM0D,#01100000B     ;counter 1, mode 2,
;C/T=1 external pulses
MOV TH1,#0                          ;clear TH1
SETB P3.5                               ;make T1 input
AGAIN:
SETB TR1                               ;start the counter
BACK:
MOV A,TL1                            ;get copy of TL
MOV P2,A                              ;display it on port 2
JNB TF1,Back                         ;keep doing, if TF = 0
CLR TR1                                 ;stop the counter 1
CLR TF1                                 ;make TF=0
SJMP AGAIN                         ;keep doing it
Notice in the above program the role of the instruction SETB P3.5. Since ports are set up for output when the 8051 is powered up, we make P3.5 an input port by making it high. In other words, we must configure (set high) the T1 pin (pin P3.5) to allow pulses to be fed into it. 

TCON Register

TCON (timer control) register is an 8- bit register

  • The upper four bits are used to store the TF and TR bits of both timer 0 and 1
  • The lower 4 bits are set aside for controlling the interrupt bits





Saturday, 26 January 2013

ARITHMETIC & LOGIC INSTRUCTIONS AND PROGRAMS

Addition of Numbers

ADD A,source         ;A = A + source
The instruction ADD is used to add two operands
  • Destination operand is always in register A
  • Source operand can be a register, immediate data, or in memory
Example:
Write a program to add two 16-bit numbers. Place the sum in R7 and R6; R6 should have the lower byte.
Solution:
CLR C                   ;make CY=0
MOV A, #0E7H    ;load the low byte now A=E7H
ADD A, #8DH      ;add the low byte
MOV R6, A          ;save the low byte sum in R6
MOV A, #3CH     ;load the high byte
ADDC A, #3BH   ;add with the carry
MOV R7, A          ;save the high byte sum

Subtraction of Numbers

  •  In many microprocessor there are two different instructions for subtraction:
  • SUB and SUBB (subtract with borrow)
    • In the 8051 we have only SUBB
    • The 8051 uses adder circuitry to perform the subtraction


SUBB when CY = 0
  1. Take the 2’s complement of the subtrahend (source operand)
  2. Add it to the minuend (A)
  3. Invert the carry
CLR C
MOV A,#4C        ;load A with value 4CH
SUBB A,#6EH     ;subtract 6E from A
JNC NEXT             ;if CY=0 jump to NEXT
CPL A                     ;if CY=1, take 1’s complement
INC A                     ;and increment to get 2’s comp
NEXT:    MOV R1,A           ;save A in R1


SUBB when CY = 1
  • This instruction is used for multi-byte numbers and will take care of the borrow of the lower operand
CLR C
MOV A,#62H      ;A=62H
SUBB A,#96H     ;62H-96H=CCH with CY=1
MOV R7,A           ;save the result
MOV A,#27H      ;A=27H
SUBB A,#12H     ;27H-12H-1=14H
MOV R6,A           ;save the result
Solution:
We have 2762H - 1296H = 14CCH.

Multiplication

MUL AB           ;AxB, 16-bit result in B, A
Example:
MOV A,#25H      ;load 25H to reg. A
MOV B,#65H      ;load 65H to reg. B
MUL AB              ;25H * 65H = E99 where
     ;B = OEH and A = 99H

Division

DIV AB         ;divide A by B, A/B


Example:
Write a program to get hex data in the range of 00 – FFH from port 1 and convert it to decimal. Save it in R7, R6 and R5.

Solution:
MOV A,#0FFH
MOV P1,A           ;make P1 an input port
MOV A,P1           ;read data from P1
MOV B,#10         ;B=0A hex
DIV AB                  ;divide by 10
MOV R7,B           ;save lower digit
MOV B,#10
DIV AB                  ;divide by 10 once more
MOV R6,B           ;save the next digit
MOV R5,A           ;save the last digit

2's Complement 


To make the 2’s complement of a number

CPL A                     ;1’s complement (invert)
ADD A,#1             ;add 1 to make 2’s comp.

 LOGIC AND INSTRUCTIONS


ANL destination,source     ;dest = dest AND source
  • This instruction will perform a logic AND on the two operands and place the result in the destination
  • The destination is normally the accumulator
  • The source operand can be a register, in memory, or immediate
MOV A,#35H      ;A = 35H
ANL A,#0FH        ;A = A AND 0FH


LOGIC OR INSTRUCTIONS


ORL destination,source
;dest = dest OR source
  • The destination and source operands are ORed and the result is placed in the destination
  • The destination is normally the accumulator
  • The source operand can be a register, in memory, or immediate
MOV A,#04H ;A = 04
ORL A,#68H ;A = 6C

XOR INSTRUCTIONS

XRL destination,source
;dest = dest XOR source
  • This instruction will perform XOR operation on the two operands and place the result in the destination
  • The destination is normally the accumulator
  • The source operand can be a register, in memory, or immediate
MOV A,#54H
XRL A,#78H

Example:
Read and test P1 to see whether it has the value 45H. If it does, send 99H to P2; otherwise, it stays cleared.
Solution:
MOV P2,#00            ;clear P2
MOV P1,#0FFH       ;make P1 an input port
MOV R3,#45H         ;R3=45H
MOV A,P1               ;read P1
XRL A,R3
JNZ EXIT                 ;jump if A is not 0
MOV P2,#99H
EXIT: ...


Complement Accumulator


CPL A ;complements the register A
  • This is called 1’s complement
MOV A, #55H
CPL A ;now A=AAH
        ;0101 0101(55H)
        ;becomes 1010 1010(AAH)
  • To get the 2’s complement, all we have to do is to to add 1 to the 1’s complement

Compare Instruction

CJNE destination,source,rel. addr.
  • The actions of comparing and jumping are combined into a single instruction called CJNE (compare and jump if not equal)
  • The CJNE instruction compares two operands, and jumps if they are not equal
  • The destination operand can be in the accumulator or in one of the Rn registers
  • The source operand can be in a register, in memory, or immediate
  • The operands themselves remain unchanged
  • It changes the CY flag to indicate if the destination operand is larger or smaller
CJNE R5,#80,NOT_EQUAL ;check R5 for 80
...                         ;R5 = 80
NOT_EQUAL:
JNC NEXT                 ;jump if R5 > 80
...                         ;R5 < 80
NEXT: ...

Example:

Write a program to read the temperature and test it for the value 75. According to the test results, place the temperature value into the registers indicated by the following.
If T = 75 then A = 75
If T < 75 then R1 = T
If T > 75 then R2 = T
Solution:
MOV P1,#0FFH                                 ;make P1 an input port
MOV A,P1                           ;read P1 port
CJNE A,#75,OVER             ;jump if A is not 75
SJMP EXIT                           ;A=75, exit
OVER:
JNC NEXT                             ;if CY=0 then A>75
MOV R1,A                           ;CY=1, A<75, save in R1
SJMP EXIT                           ; and exit
NEXT:
MOV R2,A                           ;A>75, save it in R2
EXIT: ...

Rotate Right

RR A        ;rotate right A
  • In rotate right
  • The 8 bits of the accumulator are rotated right one bit, and
  • Bit D0 exits from the LSB and enters into MSB, D7

MOV A,#36H         ;A = 0011 0110
RR A                       ;A = 0001 1011
RR A                       ;A = 1000 1101
RR A                       ;A = 1100 0110
RR A                       ;A = 0110 0011
.

Rotate Left

RL A      ;rotate left A
  • In rotate left
  • The 8 bits of the accumulator are rotated left one bit, and
  • Bit D7 exits from the MSB and enters into LSB, D0


MOV A,#72H         ;A = 0111 0010
RL A                       ;A = 1110 0100
RL A                       ;A = 1100 1001


Rotate Left through Carry


RLC A       ;rotate left through carry
  • In RLC A
  • Bits are shifted from right to left
  • They exit the MSB and enter the carry flag, and the carry flag enters the LSB

Example:
Write a program that finds the number of 1s in a given byte.
MOV R1,#0
MOV R7,#8         ;count=08
MOV A,#97H
AGAIN:
RLC A
JNC NEXT             ;check for CY
INC R1                   ;if CY=1 add to count
NEXT:
DJNZ R7,AGAIN


Serializing Data

Serializing data is a way of sending a byte of data one bit at a time through a single pin of microcontroller
  • Using the serial port, discussed in Chapter 10
  • To transfer data one bit at a time and control the sequence of data and spaces in between them
Example:
Write a program to transfer value 41H serially (one bit at a time) via pin P2.1. Put two highs at the start and end of the data. Send the byte LSB first.
Solution:
MOV A,#41H
SETB P2.1             ;high
SETB P2.1             ;high
MOV R5,#8
AGAIN:
RRC A
MOV P2.1,C        ;send CY to P2.1
DJNZ R5,AGAIN
SETB P2.1             ;high
SETB P2.1             ;high

Example:
Write a program to bring in a byte of data serially one bit at a time via pin P2.7 and save it in register R2. The byte comes in with the LSB first.
Solution:
MOV R5,#8
AGAIN:
MOV C,P2.7 ;bring in bit
RRC A
DJNZ R5, AGAIN
MOV R2,A ;save it

Single-bit Operations with CY

Example:
Assume that bit P2.2 is used to control an outdoor light and bit P2.5 a light inside a building. Show how to turn on the outside light and turn off the inside one.
Solution:
SETB C                   ;CY = 1
ORL C,P2.2            ;CY = P2.2 ORed w/ CY
MOV P2.2,C           ;turn it on if not on
CLR C                     ;CY = 0
ANL C,P2.5            ;CY = P2.5 ANDed w/ CY
MOV P2.5,C           ;turn it off if not off

Example: 
Write a program that finds the number of 1s in a given byte.
Solution:
MOV R1,#0                         ;R1 keeps number of 1s
MOV R7,#8                         ;counter, rotate 8 times
MOV A,#97H                      ;find number of 1s in 97H
AGAIN:
RLC A                                  ;rotate it thru CY
JNC NEXT                           ;check CY
INC R1                                 ;if CY=1, inc count
NEXT:
DJNZ R7,AGAIN                  ;go thru 8 times

SWAP

SWAP A
  • It swaps the lower nibble and the higher nibble
  • In other words, the lower 4 bits are put into the higher 4 bits and the higher 4 bits are put into the lower 4 bits
  • SWAP works only on the accumulator (A)

Using a Lookup Table for ASCII

Example:
Assume that the lower three bits of P1 are connected to three switches. Write a program to send the following ASCII characters to P2 based on the status of the switches.
000 ‘0’
001 ‘1’
010 ‘2’
011 ‘3’
100 ‘4’
101 ‘5’
110 ‘6’
111 ‘7’
Solution:
MOV DPTR,#MYTABLE
MOV A,P1                           ;get SW status
ANL A,#07H                        ;mask all but lower 3
MOVC A,@A+DPTR          ;get data from table
MOV P2,A                           ;display value
SJMP $                                 ;stay here
;------------------
ORG 400H
MYTABLE DB ‘0’,‘1’,‘2’,‘3’,‘4’,‘5’,‘6’,‘7’
END








ADDRESSING MODES

Addressing Modes:


The CPU can access data in various ways, which are called addressing modes

  • Immediate
  • Register
  • Direct
  • Register indirect
  • Indexed

IMMEDIATE ADDRESSING MODE

The source operand is a constant
  • The immediate data must be preceded by the pound sign, “#”
  • Can load information into any registers, including 16-bit DPTR register
    • DPTR can also be accessed as two 8-bit registers, the high byte DPH and low byte DPL
Examples:
MOV A,#25H                      ;load 25H into A
MOV R4,#62                       ;load 62 into R4
MOV B,#40H                      ;load 40H into B
MOV DPTR,#4521H         ;DPTR=4512H
MOV DPL,#21H                                 ;This is the same
MOV DPH,#45H                ;as above
;illegal!! Value > 65535 (FFFFH)
MOV DPTR,#68975

We can use EQU directive to access immediate data

Count EQU 30
... ...
MOV R4,#COUNT            ;R4=1EH
MOV DPTR,#MYDATA    ;DPTR=200H
ORG 200H
MYDATA: DB “Student”

We can also use immediate addressing mode to send data to ports
MOV P1,#55H


REGISTER ADDRESSING MODE

  • Use registers to hold the data to be manipulated
MOV A,R0           ;copy contents of R0 into A
MOV R2,A           ;copy contents of A into R2
ADD A,R5             ;add contents of R5 to A
ADD A,R7             ;add contents of R7 to A
MOV R6,A           ;save accumulator in R6

  • The source and destination registers must match in size
    • MOV DPTR,A will give an error

MOV DPTR,#25F5H
MOV R7,DPL
MOV R6,DPH

  • The movement of data between Rn registers is not allowed
    • MOV R4,R7 is invalid


 Direct Addressing Mode


It is most often used the direct addressing mode to access RAM locations 30 – 7FH
  • The entire 128 bytes of RAM can be accessed
  • The register bank locations are accessed by the register names
MOV A,4              ;is same as
MOV A,R4           ;which means copy R4 into A

Contrast this with immediate addressing mode
  • There is no “#” sign in the operand
MOV R0,40H      ;save content of 40H in R0
MOV 56H,A        ;save content of A in 56H

SFR Registers and Their Addresses

The SFR (Special Function Register) can be accessed by their names or by their addresses
MOV 0E0H,#55H               ;is the same as
MOV A,#55h                      ;load 55H into A
MOV 0F0H,R0                    ;is the same as
MOV B,R0                           ;copy R0 into B

The SFR registers have addresses between 80H and FFH
  • Not all the address space of 80 to FF is used by SFR
  • The unused locations 80H to FFH are reserved and must not be used by the 8051 programmer

Stack and Direct Addressing Mode

Only direct addressing mode is allowed for pushing or popping the stack
  • PUSH A is invalid
  • Pushing the accumulator onto the stack must be coded as PUSH 0E0H
Show the code to push R5 and A onto the stack and then pop them
back them into R2 and B, where B = A and R2 = R5

Solution:
PUSH 05               ;push R5 onto stack
PUSH 0E0H          ;push register A onto stack
POP 0F0H            ;pop top of stack into B
;now register B = register A
POP 02                  ;pop top of stack into R2
;now R2=R6

Register Indirect Addressing Mode

  • A register is used as a pointer to the data
    • Only register R0 and R1 are used for this purpose
    • R2 – R7 cannot be used to hold the address of an operand located in RAM
  • When R0 and R1 hold the addresses of RAM locations, they must be preceded by the “@” sign
MOV A,@R0       ;move contents of RAM whose
;address is held by R0 into A
MOV @R1,B       ;move contents of B into RAM
;whose address is held by R1

Example:

Write a program to copy the value 55H into RAM memory locations 40H to 41H using
(a) direct addressing mode, (b) register indirect addressing mode without a loop, and (c) with a loop
Solution:
(a)
MOV A,#55H                      ;load A with value 55H
MOV 40H,A                        ;copy A to RAM location 40H
MOV 41H.A                        ;copy A to RAM location 41H
(b)
MOV A,#55H                      ;load A with value 55H
MOV R0,#40H                    ;load the pointer. R0=40H
MOV @R0,A                      ;copy A to RAM R0 points to
INC R0                                ;increment pointer. Now R0=41h
MOV @R0,A                      ;copy A to RAM R0 points to
(c)
MOV A,#55H                      ;A=55H
MOV R0,#40H                    ;load pointer.R0=40H,
MOV R2,#02                       ;load counter, R2=3
AGAIN: MOV @R0,A                    ;copy 55 to RAM R0 points to
INC R0                                ;increment R0 pointer
DJNZ R2,AGAIN                ;loop until counter = zero



  • The advantage is that it makes accessing data dynamic rather than static as in direct addressing mode
    •  Looping is not possible in direct addressing mode
Example:
Write a program to clear 16 RAM locations starting at RAM address 60H
Solution:
CLR A                 ;A=0
MOV R1,#60H    ;load pointer. R1=60H
MOV R7,#16       ;load counter, R7=16
AGAIN:
MOV @R1,A       ;clear RAM R1 points to
INC R1                 ;increment R1 pointer
DJNZ R7,AGAIN ;loop until counter=zero

Example:
Write a program to copy a block of 10 bytes of data from 35H to 60H
Solution:
MOV R0,#35H    ;source pointer
MOV R1,#60H    ;destination pointer
MOV R3,#10       ;counter
BACK:
MOV A,@R0       ;get a byte from source
MOV @R1,A       ;copy it to destination
INC R0                   ;increment source pointer
INC R1                   ;increment destination pointer
DJNZ R3,BACK   ;keep doing for ten bytes

  • R0 and R1 are the only registers that can be used for pointers in register indirect addressing mode


 Indexed Addressing Mode and On-chip ROM Access



Indexed addressing mode is widely used in accessing data elements of look-up table entries located in the program ROM

  • The instruction used for this purpose is 

MOVC A,@A+DPTR

  • Use instruction MOVC, “C” means code
  • The contents of A are added to the 16-bit register DPTR to form the 16-bit address of the needed data


Example Program:
In this program, assume that the word “ABC” is burned into ROM locations starting at 200H. And that the program is burned into ROM locations starting at 0. Analyze how the program works and state where “ABC” is stored after this program is run.
Solution:
ORG 0000H                         ;burn into ROM starting at 0
MOV DPTR,#200H            ;DPTR=200H look-up table addr
CLR A                                     ;clear A(A=0)
MOVC A,@A+DPTR         ;get the char from code space
MOV R0,A                           ;save it in R0
INC DPTR                             ;DPTR=201 point to next char
CLR A                                     ;clear A(A=0)
MOVC A,@A+DPTR         ;get the next char
MOV R1,A                           ;save it in R1
INC DPTR                             ;DPTR=202 point to next char
CLR A                                     ;clear A(A=0)
MOVC A,@A+DPTR         ;get the next char
MOV R2,A                           ;save it in R2
Here:
SJMP HERE                          ;stay here
;Data is burned into code space starting at 200H
ORG 200H
MYDATA:DB “ABC”
END                                                       ;end of program

Look-up Table

The look-up table allows access to elements of a frequently used table with minimum operations
Example:
Write a program to get the x value from P1 and send x2 to P2, continuously

Solution:
ORG 0
MOV DPTR,#300H           ;LOAD TABLE ADDRESS
MOV A,#0FFH                  ;A=FF
MOV P1,A                         ;CONFIGURE P1 INPUT PORT
BACK:
MOV A,P1                         ;GET X
MOV A,@A+DPTR           ;GET X SQAURE FROM TABLE
MOV P2,A                         ;ISSUE IT TO P2
SJMP BACK                      ;KEEP DOING IT
ORG 300H
XSQR_TABLE:
DB 0,1,4,9,16,25,36,49,64,81
END

BIT ADDRESSES

  • Many microprocessors allow program to access registers and I/O ports in byte size only
    • However, in many applications we need to check a single bit
  • One unique and powerful feature of the 8051 is single-bit operation
    • Single-bit instructions allow the programmer to set, clear, move, and complement individual bits of a port, memory, or register
    • It is registers, RAM, and I/O ports that need to be bit-addressable
      • ROM, holding program code for execution, is not bit-addressable

Example:
A switch is connected to pin P1.7. Write a program to check the status of the switch and make the following decision.
(a) If SW = 0, send “0” to P2
(b) If SW = 1, send “1“ to P2
Solution:
SW EQU P1.7
MYDATA EQU P2
HERE:    MOV C,SW
JC OVER
MOV MYDATA,#’0’
SJMP HERE
OVER: MOV MYDATA,#’1’
SJMP HERE
END

Example:
Assume that the on-chip ROM has a message. Write a program to copy it from code space into the upper memory space starting at address 80H. Also, as you place a byte in upper RAM, give a copy to P0.
Solution:
ORG 0
MOV DPTR,#MYDATA
MOV R1,#80H                    ;access the upper memory
B1:      CLR A
MOVC A,@A+DPTR         ;copy from code ROM
MOV @R1,A                       ;store in upper memory
MOV P0,A                           ;give a copy to P0
JZ EXIT                                  ;exit if last byte
INC DPTR                             ;increment DPTR
INC R1                                   ;increment R1
SJMP B1                               ;repeat until last byte
EXIT: SJMP $                       ;stay here when finished
;---------------
ORG 300H
MYDATA: DB “The Promise of World Peace”,0
END