Академический Документы
Профессиональный Документы
Культура Документы
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,
Ppp Port0
void main( )
{
P0 = 0x55;
while( 1 );
}
2. Write a program to toggle all the leds connected to P0, with arbitrary 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
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
void delayHW( )
{
TMOD = 01h; //timer0 is used as 16 bit timer – mode 1
while(TF0==0); // wait till the timer0 overflows, i.e it reaches to FFFFH and TF0 is 1
---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
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
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)
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
[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,
Program to enable external interrupt0 and timer0 interrupt, disable other interrupts?
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
}
// 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;
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
// 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;
}
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)]
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…)
‘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];