Let us see important points for programming I/O ports :
I/O Bit Manipulation Programming
AU
: May-13
Let
us see important points for programming I/O ports :
Port
0 has open drain outputs and hence to use this port as an input or an output it
is necessary to connect external pull-up resistors (value 10 K) as shown in the
Fig. 16.2.1.
Port
1, port 2 and port 3 do not require any pull-up resistors since they have
internal pull-up resistors.
On
reset, all ports are configured as an
input ports.
If
the ports are configured as an output ports, to make them input ports again, we
have to write FFH (1 to all 8-bits) on these ports.
Now
we will see simple programming examples to clearly understand the I/O concepts
discussed above.
Example
16.2.1 Write a program to toggle all bits of PO
continuously.
Solution
:
BACK
: MOV A, #0AAH ; Load AAH in the (A) accumulator
MOV
P0, A ; Send contents of A to
port 0
A
CALL Delay ; Wait for some time
MOV
A, #55H ; Load 55H in the accumulator
MOV
P0, A ; Send contents of A to port 0
A
CALL Delay ; Wait for some time
SJMP
BACK ; Repeat
The
same action can be implemented using following program code.
BACK
: MOV PO, A ; Send contents of A on port 0
CPL
A ; Complement contents of port 0
A
CALL Delay ; Wait for some time
SJMP
Back ; Repeat
Note
:
I Like port 0, we can toggle all bits of P1, P2 or P3 by replacing the corresponding
port instead of P0 in the above programs.
Example
16.2.2 Write a program to read the content of Pl and save
it in R6 and also send it to P2.
Solution
:
MOV
A, # 0FFH ; A ← FFH
MOV
Pl, A ; Make P1 as an input port by
writing all 1's to it
MOV
A, P1 ; Read data from P1
MOV
R6, A ; Save it in R6
MOV
P2, A ; Send it to P2
Example
16.2.3 Write an ALP to receive input from port P1.5 and if
it is high then an output 35H is sent to port 0.
Solution
:
SETB
P1.5 ; Configure P1.5 as an input
JNB
P1.5, LAST ; Skip next instruction if P1.5 is low
MOV
P0, #35H ; Send 35H on P0
LAST
: …
Programming
I/O Ports using 8051C
Before
going to see programming I/O ports using 8051C let us brief some important
points about 8051C.
For
8051 microcontroller we need to include the file reg51.h. This file contains
all the definitions of 8051 registers. With this information C compiler
produces hex file that can be downloaded into the ROM of the microcontroller.
It is important to note that the size of the hex file produced by the assembly
language is much smaller than the hex file produced by the C compiler. Apart
from this fact, there are many reasons for writing programs in C instead of
assembly :
1.
It is much easier and less time consuming to write programs in C than assembly.
2.
C is more flexible; it is easier to modify and update.
3.
Programming in C allows to use code available in function libraries.
4.
Program written in C for one microcontroller is portable to other
microcontrollers with little or no modifications.
Data
Types in 8051C
The
Table 16.2.1 lists the data types that are available in typical C × 51
compiler. The Table 16.2.1 gives the information about the size of the data
variable and its value range.
Using
the Appropriate Data Type
It
is necessary to keep in mind that the code space for the 8051 is limited to 64
kbytes and it has limited on-chip ROM. Thus, it is necessary to look at the
size of the created hex file. One way to keep the size of data file optimum is
to use appropriate data type. The following points must be considered while
selecting the data type.
•
The unsigned char is an 8-bit data type. Thus, it must be used to store the
value in the range of 0-255 (00-FFH). Since the 8051 is an 8-bit
microcontroller, it is one of the most widely used data type.
•
Use unsigned data type when there is no need for signed data.
•
C compiler uses the signed data type as the default. Thus when we want to use
unsigned data type, we must use unsigned keyword.
•
S bit data type should be used to access bit addressable registers. It allows
use to access single bits of the SFR registers.
•
SFR data type should be used to access the byte size SFR registers.
Logical
Operations in 8051C
One
of the most frequent operations required in embedded applications is monitoring
a single or a group of bits of a port, checking the status of a bit and
controlling an external device connected to a bit of an output port. C allows
logical operations such as AND, OR, Exclusive-OR as well as shifting a byte to the
left and right. The Table 16.2.2 shown below provides the syntax for such
operations.
Programming Examples
Example
16.2.4 Write an 8051 C program to send binary counter
values from 00-FFH to port P1.
Solution
:
#include
<reg51.h>
void
main(void)
{
unsigned
char c;
for(c=0;
c<=255; c++)
P1=c;
}
Example
16.2.5 Write an 8051 C program to send hex values for
ASCII characters of 0, 1, 2, 3, A, B, C, X, Y and Z.
Solution
:
#include
<reg51.h>
void
main (void)
{
unsigned
char mychar[]="0123ABCXYZ";
unsigned
char c;
for(c=0;
c< = 10; c++)
P1=mychar
[c];
}
Comment
:
Program displays values 30H, 31H, 32H, 33H, 41H, 42H, 43H, 58H, 59H and 5AH on
port P1.
Example
16.2.6 Write an 8051 C program to toggle all the bits
of port P0 and P1 continuously such that when P0 = FFH, P0 = 00 and vice-versa.
Solution
:
#include
<reg51.h>
void
main(void)
{
for(;;) /* repeat continuously */{
P0=0x00
; /* [0X indicates data in */
P1=0xFF
; /* hex] */
NOP
; /* [wait for some */
NOP
; /* time] */
P0=0xFF
;
P1=0x00
NOP
; /* [wait for some */
NOP
; /* time] */
}
}
Example
16.2.7 Write an 8051 C program to send the sum of values –
12 and 15 to port P1.
Solution
:
#include
<reg51.h>
void
main(void)
{
signed
char i, j;
i
= -12;
j
= 15;
P1
= i + j;
}
Example
16.2.8 Write an 8051 C program to toggle bit 0 of the
port P1 (P1.0) 20,000 times.
Solution
:
#include
<reg51.h>
shit
PORTBIT = P1 ^ 0; /* sbit is
declared outside of main function */
void
main(void)
{
unsigned
int i;
for(i
= 0; i< =20000; i++)
{
PORTBIT
= 0;
PORTBIT
= 1;
}
}
Comment:
P1 ^0 represents bit 0 of port 1.
Example
16.2.9 Write an 8051 C program to flash LEDs 10 times.
Solution
:
#include
< reg51 .h >
void
DELAY(void);
void
main(void)
{
unsigned
char N;
N=0;
do
{
P1=0xFF;
/* Turn all LEDs ON */
DELAY();
/* Wait for some time */
P1=0x00; /* Turn all LEDs OFF */
DELAY();
/* Wait for some time */
N=N+1;
}
while(N<10);
}
void
DELAY(void)
{
unsigned
char i, j;
for(i=0;
i< = 255; i=i+1)
{
for(j=0;
j< =255; j=j +1)
{
;
}
}
}
Comment
:
Program illustrates the use of do-while loop.
Equivalent
assembly language program
ORG
0
SJMP
START
ORG
30H
START:
MOV A,#00
MAIN:
MOV P1, #0FFH
CALL
DELAY
MOV
P1, #00H
CALL
DELAY
INC
A
CJNE
A, #10, MAIN
END
DELAY: MOV R0, #00H
LOOP1: MOV R1, #00H
LOOP2: INC R1
CJNE
R1, #255, LOOP2
INC
R0
CJNE
R0, #255, LOOP1
RET
Example
16.2.10 Eight LEDs are connected to port P2. Write an
8051 C program that shows the count from 0 to FFH (0000 0000 to 1111 1111 in
binary) on the LEDs.
Solution
:
#include
<reg51.h>
#define
LED P2 /* define P2 as LED */
Void
main(void)
{
LED=0;
/*clear port P2 */
for(;;)
/*repeat continuously */
{
LED++;
/*increment P2 */
}
}
Example
16.2.11 Write an 8051 C program to get a byte of data
from P1 and then send it to P2.
Solution
:
#include
<reg51.h>
#define
INP P1
#define
OUTP P2
void
main(void)
{
unsigned
char mybyte;
INP=0xFF;
/*Configure port P1 as an input port */
while(l)
{
{
mybyte
= INP; /*read a byte from P1 */
OUTP
= mybyte; } /*send it to P2 */
}
Example
16.2.12 Write an 8051 C program to read a byte
of data from P0. If it is less than 50, send it to P1; otherwise, send
it to P2.
Solution
:
#include
<reg51.h>
void
main(void)
{
unsigned
char mybyte ;
P0=0xFF;
/* Configure port P0 as an input port */
mybyte=P0;
/* read a byte from P0 */
if(mybyte<50)
P1=mybyte;
/* send it to Pl if less than 50*/
else
P2=mybyte;
* send it to P2 if more than 50*/
}
Example
16.2.13 Write an 8051 C program to read the
content of port P1. If it is greater than 200, wait for 250 msec and send the
data to port P2. otherwise wait for 150 msec and send the data to port P0.
Solution
:
#include
<reg51.h>
void
Delay (unsigned int);
void
main (void)
{
unsigned
char mybyte ;
P1=0XFF; /* Configure port Pl as an input port */
mybyte=P1; /* read a byte from P1 */
if(mybyte>200)
{
Delay
(250); /* wait for 250 msec*/
P2=mybyte;
/* send byte to port P2*/
}
else
{
Delay
(150); /* wait for 150 msec*/
P0=mybyte;
/* send byte to port P0*/
}
void
Delay (unsigned int count)
{
unsigned
int i, j;
for
(i=0; iccount; i++)
for
(j=0; j< 1200; j++)
}
}
Example
16.2.14 Write an 8051 C program to toggle only
bit P0.5 continuously.
Solution
:
/*
toggling an individual bit */
#include
<reg51.h>
sbit
portbit = P0 ^ 5; /*declaration of single bit is using sbit/
void
main(void)
{
while(l)
{
poitbit=l;
/* turn on P0.5 */
poitbit=0;
/* turn off P0.5 */
}
}
Example
16.2.15
Write
an 8051 C program to monitor bit Pl.5. If it is high, send 00H to P0; otherwise,
send 00H to P2.
Solution
:
#include
<reg51.h>
sbit
portbit = P0 ^ 5; /* declaration of single bit using sbit */
void
main(void)
{
portbit=l;
/* configure mybit an input */
if(portbit=
= l)
Pl
=0x00;
else
P2=0xFF;
}
Example
16.2.16 Write an 8051 C program to send a given
message, "My program" on the LCD connected to PO. Every time to latch
the data into the LCD, it is necessary to make its enable (En) pin from high to
low.
Solution
:
#include
<reg51.h>
#define
LCD Data P0 s
bit
En=P1^y0;
void
main(void)
{
unsigned
char message[] ="My program";
unsigned
char C;
for(C=0;
C<10; C++) /* send 10 characters */
{
LCD
Data = message [c];
En=l;
/* Make En high */
En=0;
/* Make En Low */
}
}
Example
16.2.17 Write an 8051 C program to toggle all
the bits of P0 and P2 continuously with a some delay. Use the sfr keyword to
declare the port addresses.
Solution
:
#include <reg51.h>
/*
Accessing ports as SFRs using the sfr data type */
sfr
P0 = 0x80; /* declaration of P0 using
sfr data type */
sfr
P2 = 0xA0; /*declaration of P2 using
sfr data type */
void
Delay (unsigned int);
void
main(void)
{
while(1)
/* read it continuously */
{
P0=0x55;
P2=0x55;
Delay(250);
/* delay */
P0=0xAA;
P2=0xAA;
Delay(250);
}
}
void
Delay (unsigned int count)
{
unsigned
int i, j;
for
(i=0; i<count; i++)
for
(j=0; j < 1200; j++)
}
Example
16.2.18 Write an 8051 C program to turn bit P0.5 on and
off 10,000 times.
Solution:
sbit
PORTBIT = 0x85; /* another way to declare bit P0^5 */
void
main(void)
{
unsigned
int i;
for(i=0;
i<10000; i++)
{
PORTBIT=1;
PORTBIT=0;
}
}
Example
16.2.19 Write an 8051 C program to get the status of bit
P0.0, complement it and send it to P1.5 continuously.
Solution
:
#include
<reg51.h>
sbit
inbit = P0^0;
sbit
outbit = P1^5;
bit
tempbit;
void
main(void)
{
while(1)
{
tempbit
= inbit; /* read a bit from P0.0 */
if(tempbit==1)
/* complement the bit */
tempbit=0;
else
tempbit=1;
outbit
tempbit; /*send it to P1.5 */
}
}
Example
17.2.20 To illustrate some of the above
operations, let us write a program that monitors switch S0 and when pressed, it
flashes the single LED0 ten times.
Solution
:
#include
<reg51.h>
void
DELAY (unsigned int);
sbit
S0 = P0^0; /* switch is connected to port 0.0 */
sbit
LED = P1^0; /* LED is connected to port P1.0 */
unsigned char c;
void main(void)
{
S0
= 1; /* Configure P0.0 an input */
do
/* Check whether S0 is pressed or not */
{
}
while
(S0 = = 0);
for
(c=0; c<20; c++) /* flash LED ten times */
{
LED
= ~LED;/* invert the status of LED */
DELAY(1500);
}
}
void
DELAY (unsigned int count)
{
unsigned
int i, j;
for
(i=0; i< count; i++)
for
(j=0; j < 1200; j++)
:
}
Example
16.2.21 In a home guard system, a door sensor is
connected to the P1.0 pin, window sensor is connected to the P1.1 pin, and the
a siren is connected to P2.0. Write an 8051 C program to monitor the door and
window sensor. When any one gets open, sound the siren. We can sound the siren
by sending a square wave of a few hundred Hz.
Solution
:
#include
<reg51.h>
void
DELAY (unsigned int);
shit
Dsensor = Pl ^ 0;
shit
Wsensor = Pl ^1;
shit
Siren = P2 ^ 0;
void
main (void)
{
Dsensor
=1 /* Configure P1.0 and P1.1 an input */
Wsensor
= 1
while(Dsensor=
= l Wsensor= = l)
{
siren
= ~ siren ; /* invert the status of
siren*/
DELAY(150);
}
}
void
DELAY (unsigned int count)
{
unsigned
int i,j;
for
(i=0; i<count; i++)
for
(j=0; j< 1200; j++)
;
}
Example 16.2.22 Write
an 8051 C program to toggle all the bits of P0 and P2 continuously with a some
delay. Use the Ex-OR operator.
Solution
:
#include
<reg51.h>
void
Delay (unsigned int);
void
main (void)
{
P0=0x55;
P2=0x55;
while(l)
{
P0=P0^0xFF;
P2=P2^0xFF;
Delay(250);
}
}
void
Delay(unsigned int count)
{
unsigned
int i,j;
for
(i=0; iccount; i++)
for
(j=0; j < 1200; j++)
;
}
Example
16.2.23 Write an 8051 C program to get bit P1.0
and send it to P2.7 after inverting it.
Solution
:
#include
<reg51.h>
sbit
inbit = P0^ 0;
sbit
outbit = P1 ^ 5; /*sbit is used to declare port (SFR) bits*/
bit
tempbit; /*It is bit-addressable memory*/
void
main(void)
{
while(1)
{
tempbit=inbit;
/*read a bit from P0.0 */
outbit=~tempbit;
/*invert it and send it to Pl.5 */
}
}
Example
16.2.24 Write an 8051 C program to read the P1.0
and P1.1 bits and issue an ASCII character to P0 according to the status of
bits given in the following Table 16.2.3.
Solution
:
#include
<reg51.h>
void
main(void)
{
unsigned
char c
c=P1;
/* read P1 */
c
= c & 0x3; /* mask the unused bits, i.e. ADD C with 00000011 */
switch(c)
/* make decision */
{
case
(0):
{
P0='A';
/* issue ASCII A */
break;
}
case
(1) :
{
P0='B’;
/* issue ASCII B */
break;
}
case
(2):
{
P0='C’;
/* issue ASCII C */
break;
}
case
(3):
{
P0='D';
/* issue ASCII B */
break;
}
}
}
Example
16.2.25 Write an 8051 C program to convert ASCII digits
of two keys '5' and '6' to packed BCD and display them on P1.
Solution
:
Procedure
To
convert ASCII to packed BCD, it is first converted to unpacked BCD, and then
combined to make packed BCD. For example, on pressing keys 5 and 6 keyboard
gives 35H and 36H, respectively. Let see the conversion process :
Program
#include
<reg51.h>
void
main(void)
{
unsigned
char K1 = '5';
unsigned
char K2 = '6';
K1
= K1 & 0x0F; /*Apply mask pattern to get unpacked BCD*/
K2
= K2 & 0x0F; /*Apply mask pattern to get unpacked BCD*/
K1
= K1 >> 4; /* Shift 4 times so that lower nibble ^ upper nibble */
P1
= K1 K2 ; /* Make packed BCD */
Example
16.2.26 Write an 8051 C program to convert
packed BCD 0x47 to ASCII and display
the bytes on P1 and P2.
Solution
:
Procedure
To
convert packed BCD to ASCII conversion, it is first converted to unpacked BCD,
and then ORed each BCD with 30H to get ASCII bytes. For example, 0100 0111
packed BCD can be converted to ASCII as shown in the Table 16.2.4.
Program
#include
<reg51.h>
void
main(void)
{
unsigned
char x, y, z;
unsigned
char PBCD = 0x47;
x
= PBCD & 0x0F; /* mask lower 4 bits */
P1
= x | 0x30; /* make it ASCII */
y
= PBCD & 0xF0; /* mask upper 4 bits */
y
= y > > 4; /* shift it to lower 4 bits */
P2
= y | 0x30; /* make it ASCII */
}
Example
16.2.27 Write an 8051 C program to convert 1111
1011 (FBH) to decimal and then ASCII, and display the digits on P0 sequentially
(MSD first).
Solution
:
Procedure
One
way to convert binary number to decimal is to divide it by 10 successively and
keep the remainders. This is illustrated in Fig. 16.2.3. The first remainder
gives the LSD and last remainder gives the MSD. These digits are then added
with 30H to get the ASCII equivalent.
Algorithm
1.
Divide the number by 10 and save the remainder.
2.
Save the quotient as a number.
3.
Repeat steps 1 and 2 until quotient is 0.
4.
Retrieve each remainder and add 30H to convert it to ASCII.
Program
#include
<reg51.h>
void
main (void)
{
unsigned
char Abyte, i,Q;
Example
16.2.28 a) Find the checksum byte for the
hexadecimal data : 18H, 5AH, 46H and 69H. b) Perform the checksum to ensure
data integrity, c) With an example show how checksum detects the error.
Solution
:
To ensure the data integrity of the ROM contents, one extra byte is stored at
the end of a series of data bytes called checksum byte. This byte is calculated
by performing two operations :
•
Add all data bytes without considering carry.
•
Take 2's complement of the resulted sum.
a)
Let us find the checksum byte
18H
+ 5AH + 46H + 69H = 121H
Ignoring
carry we have stun = 21H. Taking 2's complement we have checksum byte = DFH.
b)
To ensure data integrity all the bytes including checksum byte are added.
Ignoring the carry if sum is OOH then the data integrity is ensured. Let us
check this
18H
+ 5AH + 46H + 69H + DFH = 200H
Ignoring
carries we have sum equal to zero and therefore, we can say that data is valid
and not corrupted.
c)
Let us consider that the last of data is corrupted and it is now 68H instead of
69H. By adding all byte with checksum byte we get,
18H
+ 5AH + 46H + 68H + DFH = 1FFH
Ignoring
carry in the sum, result is not zero and hence we can say that data is
corrupted.
Example
16.2.29 Write an 8051 C program to find the checksum
byte of data stream 30H, 4AH, 65H and 10H. Convert the binary value of checksum
into decimal and display the value of the BCD digits on ports PO, P1 and P2.
Solution
:
#include
<reg51.h>
void
main (void)
{
unsigned
char data[] = {0X30,0X4A,0X65,0X10};
unsigned
char sum=0;
unsigned
char chksumbyte,i, d1, d2, d3;
for(i=0;
i<4; i++)
{
sum=sum+data[i];
/* since sum is declared as byte data type, carries are ignored automatically
*/
}
chksumbyte
= ~ sum+1; /*Take 2's complement*/
i
= chksumbyte / 10; /‘divide by 10*/
d1
= chksumbyte % 10; /*store the remainder (LSD)*/
d2
= i % 10; /*store middle digit*/
d3
= i/10; /*store most significant digit*/
P0
= d1; /* send LSD to P0*/
P1
= d2; *send middle digit to P1*/
P2
= d3; /*send MSD to p2*/
}
Example
16.2.30 Write an 8051 C program to send byte 24H
serially one bit at a time via P2.0. Send LSB first.
Solution
:
#include
<reg51.h>
sbit
outbit = P2 ^ 0;
sbit
ALSB = ACC ^ 0;
void
main (void)
{
unsigned
char mybyte = 0x24;
unsigned
char i;
ACC
= mybyte;
for
(i=0; i<8; i++)
{
outbit
= ALSB;
ACC
= ACC > >1;
}
}
Example
16.2.31 Write an 8051 C program to send byte 24H serially
one bit at a time via P2.0. Send MSB first.
Solution
:
#include
<reg51.h>
sbit
outbit = P2 ^ 0;
sbit
AMSB = ACC ^7;
void
main (void)
{
unsigned
char mybyte = 0x24;
unsigned
char i;
ACC
= mybyte;
for
(i=0; i<8; i++)
{
outbit
= AMSB;
ACC
= ACC<<1;
}
}
Example
16.2.32 Write an 8051 C program to receive byte
serially one bit at a time via P2.0. The first bit is LSB.
Solution
:
#include
c reg51.h>
shit
inbit = P2 ^ 0;
shit
AMSB = ACC ^7;
void
main (void)
{
unsigned
char i;
for
(i=0; i<8; i++)
{
AMSB
= inbit;
ACC
= ACC>>1;
}
}
Example
16.2.33 Write an 8051 C program to receive byte serially
one bit at a time via P2.0. The first bit is MSB.
Solution
:
#include
<reg51.h>
shit
inbit = P2 ^ 0;
shit
ALSB = ACC^0;
void
main (void)
{
unsigned
char i;
for
(i=0; ic8; i++)
{
ALSB
= inbit;
ACC
= ACC<<l;
}
}
Example
16.2.34 Write an 8051 C program to perform data
integrity check for data given in example. If data is not corrupted, send ASCII
character 'V (valid) on port P1; otherwise send 'C (corrupted) on port P1.
Solution
:
#include
<reg51.h>
void
main (void)
{
unsigned
char data[] = {0X18,0X5A,0X46,0X69,OXDF};
unsigned
char chksum=0;
unsigned
char i;
for(i=0;
i<5; i++)
{
chksum=chksum+data[i];
}
if
(chksum = =0)
P1='V';
else
P1='C’;
}
Example
16.2.35 Write an
8051 C program to toggle all the bits of P1, P2 and PO continuously with a 250
ms delay. Use SFR keyword to declare the port addresses.
Solution
:
#include
reg51.h>
void
Delay (void);
void
main (void)
{
while (1) /* Repeat continuously */
{
P0=0x
55; /* toggle all bits of P0 */
pl=0
x 55; /* toggle all bits of Pl */
P2=0x
55; /* toggle all bits of P2 */
Delay
(250); /* wait for 250 ms */
P0=0x
AA ; /* toggle all bits of P0 */
Pl=0x
AA ; /* toggle all bits of Pl */
P2=0x
AA ; /* toggle all bits of P2 */
Delay
(250) }/* wait for 250 ms */
}
void
Delay (unsigned int count)
{
unsigned
int i,j;
for
(i=0; i < count; i++)
for
(j=0; j < 1275; j ++);
}
Example
16.2.36 Write a C-program to toggle all bits of PO and
P2 continuously with 250 msec delay. Use inverting operator.
Solution
:
#include
< reg51 .h >
void
MSDelay (unsigned int);
void
main (void)
{
P0
= 0x55;
P2
= 0x55;
while
(1)
{
P0
= ~P0;
P2
= ~P2;
MSDelay
(250);
}
}
void
MSDelay (unsigned int count)
{
unsigned
int i, j;
for
(i = 0; i < count; i++)
for
(j = 0; j < 1275; j++)
}
Example
16.2.37 Write a 8051 C-program to convert a
given hex-data OFF into its equivalent decimal data and display the result
digits on P0, 1l and P2.
Solution
:
#include
< reg51 .h >
void
main(void)
{
unsigned
char x, binbyte, d1, d2, d3;
binbyte
= 0xFF;
x=binbyte/10;
d1
=binbyte%10;
d2
= x%10;
d3
= x/10;
P0=d1;
P1=d2;
P2=d3;
}
Microprocessors and Microcontrollers: Unit III: (c) 8051 I/O Ports, Timer, Serial Port & Interrupts : Tag: : - I/O Bit Manipulation Programming