Sie sind auf Seite 1von 14

8051 Ports & Programming using Embedded C

8051 has four 8 bit ports, namely P0,P1,P2 and P3. These ports can be configured as inputs or
outputs. We have to configure them, before using the ports .To configure any port as output,
write 0’s , to configure as input write 1’s to it.
Ports can be used as whole, like,
value = P0;
P1 = result;
port bits can be accessed individually also by using the sbit declarations,
sbit LED = P0 ^ 0;
sbit SENSOR = P0 ^1;
LED = 0; // configured as output
SENSOR = 1; // configured as input

Some of the ports has alternate functions, other than normal I/O, as indicated below,

P0 - requires external pull up resistors (10K), because of open drain outputs


To +5V

Ppp Port0

- Alternate function : P0 is used to send address/data (multiplexed) , when 8051/31 uses


external code or data memory
P1 - 8 bit input or output port
P2 - 8 bit input or output port
Alternate function: P2 generates most significant byte of address (A8-A15), when
8051/31 uses external code or data memory.
P3 - used as 8 bit input or output port, all the pins of Port 3 has alternate function,
P3.0 RxD
P3.1 TxD
P3.2 INT0
P3.3 INT1
P3.4 TO, (used with timer0)
P3.5 T1, (used with timer1)
P3.6 *WR
P3.7 *RD

1. Write a program to send 0x55 (01010101b) to P0 ?

void main( )
{
P0 = 0x55;
while( 1 );
}
2. Write a program to toggle all the leds connected to P0, with arbitrary delay ?

void delay(unsigned int);


void main( )
{
while(1)
{
P0 = 0x55;
delay(500);
P0 = 0xAA;
delay(500);
}
}
void delay(unsigned int x) // delay in msec
{
unsigned char i;
while(x--)
for(i=0;i<300;i++); // for a perticular microcontroller board, this
// produces 1msec delay
}

Write a Program to monitor bit P1.5, if it is high, send 55H to P0, otherwise, send AAH
to P2 ?

sbit InPin = P1 ^ 5;
void main( )
{
InPin = 1; // configure the pin as input
while( 1)
{
if(InPin == 1)
P2 = 0xAA;
else
P2 = 0x55;
}

A door sensor is connected to the P1.1 pin, and a buzzer is connected to P1.7 pin, and a buzzer
is connected to P1.7. Write an 8051 C program to monitor the door sensor, and when it opens,
sound the buzzer ?
# include <reg51.h>
sbit buzz = P2 ^ 6; // assume buzzer is connected to P2.6 (ouput)
sbit sensor = P3 ^ 7; // assume sensor is connected to this P3.7 (input)
void buzzer(unsigned char );

void main( )
{
sensor = 1; // configure the pin as input
while( 1)
{
if(sensor == 1) // let us assume sensor gives, logic 1, whenever door opens
buzzer(30);
}

}
// buzzer is made on (i.e you can here sound) by generating a square waveform
// different on and off times and durations, produce different sounds
void buzzer(unsigned char cnt)
{
unsigned char val;
while(cnt--)
{
buzz=0; // transistor is on i.e conducts
val=40; while(val--) ; // small delay
buzz=1; // transistor is off
val=10;while(val--);
}
}

Write a program to keep monitoring P0.1 until it is high, when it is high, read in data
from P1 and send low to high pulse on P0.2 to indicate data has read ?
# include <reg51.h>
sbit P0_1 = P0 ^ 1; // assume buzzer is connected to P2.6 (ouput)
sbit P0_2 = P0 ^ 2; // assume sensor is connected to this P3.7 (input)
void buzzer(unsigned char );

void main( )
{
unsigned char value;
P0_1 = 1; // configure the pin as input
P1 = 0xff; // configure the port 1 as input
while( ! P0_1); // wait till the P0_1 line become high
value = P1; // read port1 and store that in the variable
P0_2 = 0;
P0_2 = 1; // generate low to high pulse ( if reqd, we can add delay, before making it 1)
while(1);
}
8051 Timers & Programming using embedded C

8051 has inbuilt hardware timers, so that timing related jobs can be delegated to timers
instead of CPU engagement.

Features:
It has two 16 bit timers / counters – Timer 0 and Timer 1, each one can be configured as
timer or counter. Generally used as timer for generation of timing signals ( like
generating timing waveforms, pulses , timing events etc), used as counter for counting
external events

 Timer can count from 0000H to FFFFH (up counter)

 Timer ON/OFF is controlled by software (program) or hardware (external signal


T0/T1) . TR0 / TR1 bit (of TCON register) is used to make it ON/OFF through the
program

 Timers are configured using TMOD register


TMOD = 0x11; // to configure timer0 and timer1 as timers in Mode1 (16 bit timer)

TCON register bits are used to control the operation of timers

Write a Program in embedded C to generate delay of 20ms ?

Let us select Timer0, and configure this to work as timer in mode1( 16bit timer)
TMOD = 00000001B
4. Calculate the MSB and LSB values from initial value, so that it can be loaded into TH &
TL registers
45536 = B1E0h (in hexa decimal), so TH0 is loaded with B1h & TL0 with E0h

Embedded C function, to generate 20ms delay,

void delayHW( )
{
TMOD = 01h; //timer0 is used as 16 bit timer – mode 1

TH0=B1H; // load the timer with the initial count,


TL0=E0H; // when it reaches FFFFh, it indicates completion of 20ms

TR0=1; //start the timer 0, now it starts counting up

while(TF0==0); // wait till the timer0 overflows, i.e it reaches to FFFFH and TF0 is 1

TR0=0;TF0=0; // stop the timer and clears the overflow flag


}

Write a program to generate a pulse of 10ms on the port pin P0.0

---10msec--
Ans:
Calculation:
Assume crystal frequency is 12MHz, and Timer0 is used in Mode1 (16 bit timer), so
1. Input clock frequency to timer0 is,
12MHz / 12 = 1MHz ; // internally crystal freq is divided by 12 and supplied
So, T = 1µsec ( time period of input clock pulse)
Td= 10msec , required delay
So, count = 10msec / 1 µsec = 10000 ,
(number of input clock pulses required to realize 10 ms)

2. Now calculate the initial value to be loaded into the timer is,
= max. value of timer - count
= 65535 – 10000 = (55535 +1) = 55536(in decimal) = D8EFh ( in hexa decimal),
so this has to be loaded into TH0 and TL0 registers, after 10000 clocks, TF0 is set

#include <reg51.h>
sbit OutPin = P0 ^ 0;
void delay( );
void main( )
{
OutPin = 0;
OutPin = 1;
delay( );
OutPin = 0;
while(1);
}
void delay( )
{
TMOD = 01h; //timer0 is used as 16 bit timer – mode 1

TH0=D8H; // load the timer with the initial count,


TL0=EFH; // when it reaches FFFFh, it indicates completion of 10ms
TR0=1; //start the timer 0, now it starts counting up
while(TF0==0); // wait till the timer0 overflows, i.e it reaches to FFFFH and TF0 is 1

TR0=0;TF0=0; // stop the timer and clears the overflow flag


}

Write a Program to generate the square waveform of 5 KHz on P1.0


On time
Off time

Given frequency = 5 KHz, T = 1/5Khz = 0.2msec, Ton = 0.1msec , Toff=0.1msec


Delay calculation for 1msec,
Assume crystal frequency is 12MHz, and Timer0 is used in Mode1 (16 bit timer), so
1. Input clock frequency to timer0 is,
12MHz / 12 = 1MHz ; // internally crystal freq is divided by 12 and supplied
So, T = 1µsec ( time period of input clock pulse)
Td= 0.1 msec , required delay
So, count = 0.1msec / 1 µsec = 100 ,
(number of input clock pulses required to realize 0.1 ms)

2. Now calculate the initial value to be loaded into the timer is,
= max. value of timer - count
= 65535 – 100 = (65435 +1) = 65436(in decimal) = FF9Ch ( in hexa decimal),
so this has to be loaded into TH0 and TL0 registers, after 100 clocks, TF0 is set
#include <reg51.h>

sbit OutPin = P1 ^ 0;
void delay( );
void main( )
{
while(1)
{
OutPin = 0;
delay( );
OutPin = 1;
delay( );
}

}
void delay( )
{
TMOD = 01h; //timer0 is used as 16 bit timer – mode 1

TH0=FFH; // load the timer with the initial count,


TL0=9CH; // when it reaches FFFFh, it indicates completion of 10ms
TR0=1; //start the timer 0, now it starts counting up
while(TF0==0); // wait till the timer0 overflows, i.e it reaches to FFFFH and TF0 is 1

TR0=0;TF0=0; // stop the timer and clears the overflow flag


}

8051 Interrupts & Programming using embedded C

Interrupts in general,

 Prevents the microcontroller from unnecessary continuous polling (i.e it can keep doing
other works, it can attend to the task required only when it is interrupted)
 Provides mechanism for handling multiple tasks simultaneously (as many interrupts
are provided)

8051 can be interrupted from five different sources, indicated based on their priorities

1. External Interrupt 0 (through the external pin INT0, the IE0 flag )
2. Timer 0 (Timer overflow Flag – TF0)
3. External Interrupt 1 (through the pin INT1, the IE1 flag)
4. Timer 1(Timer overflow Flag- TF1)
5. Serial Port (Transmit Interrupt Flag-TI or Receive Interrupt Flag- RI)

[Note: If we include Reset also as interrupt , then six sources of interrupts)]

8051 interrupts are VECTORED and MASKABLE…

It is Vectored, because when interrupt arises from any one of the above sources, the interrupt
vector i.e starting address of ISR is predefined in 8051, their locations, are

Interrupts interrupt vectors (forms interrupt vector table)


1. External Interrupt 0 ----------------0003H
2. Timer0 ----------------000BH (0003H + 8)
3. External Interrupt 1 -----------------0013H (000BH +8)
4. Timer1 ----------------001BH (00013H+8)
5. Serial Port -----------------0023H (0001BH+8)
(For Reset -----------------0000H)

[Note: Since only 8 bytes are provided for ISR, generally one writes LCALL ISR_Proc, at the
specified vector location, to branch to the actual ISR routine (if the routine is bigger)]
All the interrupts are maskable (i.e through the instructions, they can be enabled or disabled).
8051 provides the SFR registers IE (interrupt enable register) and IP (interrupt priority register)
for masking and setting priority for the interrupts,

EA – 1 - enable all the interrupts ; 0 – disable all the interrupts


The remaining five bits – 1 for enabling corresponding interrupt, 0 – for disable, are used for
selectively enabling and disabling of interrupts

Program to enable external interrupt0 and timer0 interrupt, disable other interrupts?

IE = 0x83; // 10000011B i.e 83h

Write an interrupt service routine, to handle timer0 interrut

Let us compliment the Port0.0 bit every 10msec using timer0 using the interrupt, (take the
calculation for timer, from previous problem)
Program:

sbit OutPin = P0 ^ 0;
void main( )
{
TMOD = 0x01; // 0000 0001 timer0 as 16 bit timer
IE = 0x82; // 100 00010; enable only timer0 interrupt
TH0=D8H; // load the timer with the initial count,
TL0=EFH; // when it reaches FFFFh, it indicates completion of 10ms
TR0=1; //start the timer 0, now it starts counting up, when it overflows it generates int
while(1); // don’t do anything, since ISR takes care of complimenting the P0.0 bit
}

Timer0_ISR ( ) interrupt 1 // interrupt keyword, names fun as ISR, 1 is for timer0


{
OutPin = ~OutPin; //compliment the P0.0 pin every 10ms

// again, reload the initial values to the timer0, otherwise it will start from 0000h
TR0 = 0;
TH0=D8H; // load the timer with the initial count,
TL0=EFH; // when it reaches FFFFh, it indicates completion of 10ms
TR0=1; //start the timer 0, starts counting up, when it overflows it generates int
}
Modify the above program to, make the LED connected to P0.1,’ On’ for half a second and
‘Off’ for half a second.
Add ,
Sbit LED = P0 ^ 1;

Change in the ISR,

Timer0_ISR ( ) interrupt 1
{
Static count =0; //use static variable, as it has to retain the value
OutPin = ~OutPin; //compliment the P0.0 pin every 10ms

If(++count==50) // 10ms * 50 =500ms, i.e half a second


{
LED = ~LED;
}

// again, reload the initial values to the timer0, otherwise it will start from 0000h

TR0 = 0;
TH0=D8H; // load the timer with the initial count,
TL0=EFH; // when it reaches FFFFh, it indicates completion of 10ms
TR0=1; TF0=0;
}

The priorities of interrupts are assigned as below,


0- external int0, 1 - timer0, 2 - external int1, 3 - timer1 & 4- serial port
i.e if interrupt is generated by INT0 and Timer1 simultaneously, first ISR related to INT0 is
serviced and then ISR related to Timer1 is serviced. But the priority of the interrupts can be
changed by programming the register, IP (Interrupt Priority Register)
Each of the above interrupts can be assigned one of the two priorities,
1 – Higher priority 0 – lower priority

Write a program to assign higher priority to serial port compared to timer0?

Since by default timer0 has higher priority than serial port, we will use IP register to assign
higher priority level to serial port.

IP = 0x10 ; //00010000B

8051 first evaluates all the interrupts whose priority is set as 1, then it evaluates the interrupts
whose priority is set as 0, if more than one interrupt priority is set as 1, then the default order as
indicated in the list is followed to evaluate the interrupts in the given priority level.

An ISR routine for a high priority interrupt cannot be interrupted. An ISR routine for
a low priority interrupt can be interrupted by a high priority interrupt, but not by a low
priority interrupt. If two interrupt requests, at different priority levels, arrive at the same time
then the high priority interrupt is serviced first. If two, or more, interrupt requests at the same
priority level arrive at the same time then the interrupt to be serviced is selected based
on the order shown below. Note, this order is used only to resolve simultaneous
requests. Once an interrupt service begins it cannot be interrupted by another interrupt
at the same priority level.

[Note: external interrupts, Int0 & Int1 can be configured as edge triggered (high to low) or
level triggered (low level) using TCON register bits, TCON.0(IT0) and TCON.1(IT1), by default
they are set as level triggered.
SETB IT0 ; configures External interrupt 0, as edge triggered type(1to 0, negative)]

Special Function Registers….


SFRs are special function registers, associated with different logics of 8051, provided to access
and configure different functionalities provided inside 8051, these SFRs are allocated the
addresses in the range 80h to FFh , are part of internal RAM (only few addresses are used,
others are reserved).
Ex: P0 = sfr address 80h
P1 = sfr address 90h
P2 = sfr address A0h
P3 = sfr address B0h
SP = sfr address 81h
TCON,TMOD,SCON,IE,IP etc (pls refer 8051 datasheet/documentation)
Many of the SFRs are bit addressable (ex. P0), i.e each bit of the register can be accessed for
reading or writing using SETB and CLR instructions.
In embedded C, keywords sft and sbit are provided to associate the variable names to special
function registers, and their bits (if it is bit addressable), as shown below,
sfr P0 = 0X80; // P0 is the name we are associating to the address 0x80, which is allocated by
// the manufacturer for accessing port0

sbit LED = P0 ^ 0; // LED is the name we are associating with the individual bit of particular sfr
// only if it is bit addressable, as specified by the manufacturer

generally these declarations are put in the header file, like reg51.h, different header files are
provided by the respective manufacturers of microcontrollers, so just including these header
files in the program, enables the programmer to refer to these special function registers like
P0,TMOD and bits of the special function registers like TI,RI etc (open the reg51.h file, in the
editor and verify the same…)

Difference between sbit and bit declarations:

‘sbit’ is used with the bits of special function registers only, (80 to FFh are the addresses of
SFRs),
Ex: sbit LED = P0^0
‘bit’ is used to declare the bit variables, (they are allocated space in the bit addressable memory
area, 20h to 2Fh, total bit address space of 8051 is 128).
Ex: bit flag=0,flag1=1;

Note: use the keyword “code” in the declaration of variables, to store them in code memory
instead of data memory, ex: unsigned char code keycodes[4][4];

Das könnte Ihnen auch gefallen