Tanta Higher Institute of Engineering
and Technology, THIET
االنظمة المدمجة
Embedded Systems
Course Code: ELE 413
Communication & Computer Engineering Department
Level: 400
Lec 6
PIC16F877A Microcontrollers
(I/O Ports)
General Overview of I/O Ports
The PIC16F877A microcontroller features 5 I/O ports:
Port A: 6 pins (RA0 to RA5)
Port B: 8 pins (RB0 to RB7)
Port C: 8 pins (RC0 to RC7)
Port D: 8 pins (RD0 to RD7)
Port E: 3 pins (RE0 to RE2)
Each of these ports can be configured for different
functionalities, and their respective pins can either serve as
input or output.
Configuring I/O Pins
Configuring I/O Pins
To configure the I/O pins of the PIC16F877A, you need to
manipulate various registers. The key registers for controlling
I/O are:
TRIS (Tri-State): The TRIS registers (TRISA, TRISB,
TRISC, TRISD, TRISE) control whether a pin is configured
as input (TRIS = 1) or output (TRIS = 0).
PORT: The PORT registers (PORTA, PORTB, PORTC,
PORTD, PORTE) are used to read from or write to the I/O
pins when they are configured as output.
Configuring I/O Pins
TRIS Registers Overview
• Each I/O port on the PIC16F877A has a corresponding
TRIS register that controls the direction of each individual
pin on that port.
• A TRIS bit can be set to 1 to configure the corresponding
pin as an input, or set to 0 to configure it as an output. This
configuration must be done in software, typically at the
beginning of the program or during runtime, to ensure
proper operation of the I/O pins.
• The term Tri-state refers to the three possible states of an
I/O pin: high (1), low (0), and high-impedance (Z).
Ports Direction Configuration
TRIS REGISTER PORTS
TRISA PORTA
TRISB PORTB
TRISC PORTC
TRISD PORTD
TRISE PORTE
For example, PIC16f877A has 5 ports A, B, C, D and E, these ports can be configured as
input or output using 5 TRIS registers: TRISA, TRISB, TRISC, TRISD and TRISE
PIC16F877A Microcontroller
Specifications:
• Five ports: Port A (6
pins) and Port B , C, D
(8 pins), E (3 pins)
• 8K words (14 bits) of
rewritable memory
(flash memory)
• 368 byte of RAM
• 256 bytes of EEPROM
• A/D converter
Ports Direction Configuration
A bit in the TRIS register containing 1 makes the corresponding pin
of the port register to be an input.
A bit in the TRIS register containing 0 makes the corresponding pin
of the port register to be an output.
For example, to make pins RB0 and RB1 of PORTB input and the
other bits output, we have to load the TRISB register with the bit
pattern 0 0 0 0 0 0 1 1
Output pins Input pins
TRIS Register in C++ programming
For the pervious example we want to load the TRISB register with the
bit pattern 0 0 0 0 0 0 1 1
We can use one of the following C++ assignment statements:
TRISB = 0x03; // the assigned value in hex. format
TRISB = 3; // the assigned value in decimal format
TRISB = 0b00000011; // the assigned value in binary format
Port Data Register for Reading Or Writing
After ports configuration process was done using TRIS register, we can
use this configured port to read data from its pins or out data through
its pins.
The read or write process is done by using the port data register:
PORTA
PORTB
PORTC
PORTD
PORTE
Port Data Register in C++ programming
We can use an assignment statement to read from input port or writ
to output port as in the following :
1) Write Data To PORTB
(assume that PORTB is configured as output port)
PORTB= 0x33; // the assigned value in hex. format
PORTB = 51; // the assigned value in decimal format
PORTB = 0b00110011; // the assigned value in binary format
Port Data Register in C++ programming
From theses examples we note that:
A number with a prefix ‘0b’ indicates a binary number.
A number with a prefix ‘0x’ indicates a hexadecimal number.
A number without prefix is a decimal number.
Port Data Register in C++ programming
2) Read Data From PORTB
(assume that PORTB is configured as input port and PORTC is configured as
output port)
D = PORTB // D is a pre-declared variable
PORTC = PORTB // read from PORTB and out to PORTC
PORTC.B2 = PORTB.B1 & PORTB.B2
// perform ANDING operation between the reading data from pins RB1 and RB2 //
and out the result to RC2 pin. These statement can be used in another form:
PORTC.F2 = PORTB.F1 & PORTB.F2
Write your first program using
C++ Programming Language
EX1:
Write a PIC16F877A C program to toggle bit RB0 every 10
sec, use a suitable endless loop.
void main ( )
TRISB.F0 = 0; // Makes PORTB pin RB0 Output Pin
while(1) // Infinite Loop
PORTB.F0 = 1; // RB0 ON
Delay_ms(10000); // 10 Sec Delay
PORTB.F0 = 0; // RB0 OFF
Delay_ms(10000); // 10 Sec Delay
}
EX2:
Write a PIC16F877A C program to toggle PORTB every 10
sec, use a suitable endless loop.
void main ( )
TRISB = 0; // Makes PORTB Output port
while(1) // Infinite Loop
PORTB = 0xFF; // PORTB ON
Delay_ms(10000); // 10 Sec Delay
PORTB = 0; // PORTB OFF
Delay_ms(10000); // 10 Sec Delay
}
LED and Switch Interfacing
Interfacing an LED with a switch involves connecting the LED and the
switch to a microcontroller or a simple circuit for control.
Here's a basic outline of how this can be done, to control the LED based on
the switch state.
LED and Switch Interfacing
Calculating the Resistor Value for LED Current Limiting
When connecting an LED to a microcontroller (or any power source), it is
important to limit the current through the LED to prevent damage to both
the LED and the microcontroller. This is done by placing a current-
limiting resistor in series with the LED. The resistor ensures that the
current does not exceed a safe value, which is typically specified in the
LED datasheet.
LED and Switch Interfacing
Calculating the Resistor Value for LED Current Limiting
Problem Setup
Given:
LED Current (I): 10 mA (or 0.01 A) — typical current for normal
brightness.
Output Voltage at the Microcontroller Pin (V_out): 5 V — the
microcontroller output voltage, often from a 5V power supply.
LED Voltage Drop (V_LED): 2 V — the voltage drop across the LED
when it is forward biased and emitting light.
LED and Switch Interfacing
Calculating the Resistor Value for LED Current Limiting
We need to calculate the value of the resistor required to limit the current to 10 mA.
Step-by-Step Calculation
Determine the voltage to be dropped across the resistor: The total voltage
supplied by the microcontroller pin is 5 V, and the LED has a voltage drop of 2
V. The remaining voltage, which must be dropped across the resistor, is:
VR=Vout−VLED=5V−2V=3V
So, the resistor needs to drop 3 V.
LED and Switch Interfacing
Calculating the Resistor Value for LED Current Limiting
Use Ohm's Law to calculate the resistor value: Ohm's Law states that:
R=V/I
Where:
o V is the voltage across the resistor (which we've determined to be 3 V),
o I is the current flowing through the circuit (which is 10 mA, or 0.01 A).
Substituting the known values:
R= 3V/ 0.01A =300Ω
Therefore, the value of the resistor required to limit the current to 10 mA is 300
ohms.
LED and Switch Interfacing
Understanding Pull-up and Pull-down Resistors in Microcontroller
Circuits
When interfacing switches with microcontrollers, it's crucial to ensure that the input
pin connected to the switch has a defined state (either HIGH or LOW) when the
switch is not pressed.
If the switch is left floating (i.e., not connected to a voltage level), the input pin may
randomly fluctuate between HIGH and LOW, leading to unreliable behavior.
To solve this problem, pull-up and pull-down resistors are used to ensure that the
input pin has a stable state when the switch is not activated.
LED and Switch Interfacing
Understanding Pull-up and Pull-down Resistors in Microcontroller
Circuits
1. Pull-up Resistor
A pull-up resistor is used to pull the microcontroller's input pin to a HIGH state
when the switch is not pressed. When the switch is pressed, it closes the circuit and
connects the input pin directly to ground, pulling the input to a LOW state.
Configuration: The pull-up resistor is connected between the input pin and
Vcc (the supply voltage), while the switch is connected between the input pin
and ground (GND).
Behavior:
o When the switch is not pressed, the pull-up resistor ensures the input pin is
pulled to HIGH (logic level 1).
o When the switch is pressed, the input pin is pulled directly to LOW (logic
level 0) due to the connection to ground.
LED and Switch Interfacing
Understanding Pull-up and Pull-down Resistors in Microcontroller
Circuits
1. Pull-up Resistor
LED and Switch Interfacing
Understanding Pull-up and Pull-down Resistors in Microcontroller
Circuits
2. Pull-down Resistor
A pull-down resistor, on the other hand, is used to pull the microcontroller's input
pin to a LOW state when the switch is not pressed. When the switch is pressed, it
connects the input pin directly to Vcc, pulling the input to a HIGH state.
Configuration: The pull-down resistor is connected between the input pin and
ground, while the switch is connected between the input pin and Vcc (the
supply voltage).
Behavior:
o When the switch is not pressed, the pull-down resistor ensures the input pin
is pulled to LOW (logic level 0).
o When the switch is pressed, the input pin is pulled directly to HIGH (logic
level 1) due to the connection to Vcc.
LED and Switch Interfacing
Understanding Pull-up and Pull-down Resistors in Microcontroller
Circuits
2. Pull-down Resistor
LED and Switch Interfacing
Understanding Pull-up and Pull-down Resistors in Microcontroller
Circuits
Feature Pull-up Resistor Pull-down Resistor
Default State (Switch not pressed) HIGH (logic 1) LOW (logic 0)
State when Switch Pressed LOW (logic 0) HIGH (logic 1)
Connected between the input pin and Connected between the input pin and
Resistor Connection
Vcc GND
Connected between the input pin and Connected between the input pin and
Switch Connection
GND Vcc
Typically used for active-low Typically used for active-high
Common Usage
switches switches
Example 3:
Write a suitable C program for PIC16F877A to perform the following logic
gates
Example 3:
Write a suitable C program for PIC16F877A to perform the following logic
gates
Example 3:
Solution:
void main ( )
{
TRISA = 0xFF; // Makes PORTA input port
TRISB = 0b01100000; // Makes RB5 , RB6 input pins and others pins are output pins
TRISC.F1 = 0; // Makes RC1 output pin
while(1) // Infinite Loop
{
PORTB.B2 = portA.b0 & portA.b1 & portA.b2; // AND output at pins RB2
PORTB.B3 = ~ (portA.b0 & portA.b1 & portA.b2); // NAND output at pins RB3
PORTB.B4= portA.b0 | portA.b1 | portA.b2 ; // OR output at pins RB4
PORTC.B1 = portB.f5 ^ portB.f6; // XOR output at pins RC1
}
}
Example 4:
LEDs are connected to PORT D of a PIC16F877A microcontroller. Write a
program to repeatedly control the LEDs with delay 6 sec according to the
following table:
Example 4: Solution:
void main ( ) {
TRISD = 0; // Makes PORTD Output port
while(1) // Infinite Loop
{
PORTD = 1;
Delay_ms(6000); // 6 Sec Delay
PORTD = 2* PORTD;
Delay_ms(6000); // 6 Sec Delay
PORTD = 2* PORTD;
Delay_ms(6000); // 6 Sec Delay
PORTD = 2* PORTD;
Delay_ms(6000); // 6 Sec Delay
PORTD = 2* PORTD;
Delay_ms(6000); // 6 Sec Delay
PORTD = 2* PORTD;
Delay_ms(6000); // 6 Sec Delay
PORTD = 2* PORTD;
Delay_ms(6000); // 6 Sec Delay
PORTD = 2* PORTD;
}
}
Example 4: Another Solution:
void main ( )
{
TRISD = 0; // Makes PORTD Output port
while (1) // Infinite Loop
{
PORTD = 1;
Delay_ms (6000); // 6 Sec Delay
for ( i=0 ; i<7 ; i++)
{
portd = 2*portd;
delay_ms (6000); // 6 Sec Delay
}
}
}
Example 5:
8 LEDs are connected to PORT B of a PIC16F877A microcontroller. Write
a program to repeatedly control the LEDs with delay 5 sec according to the
following table:
Example 5: Solution:
void main ( )
{
TRISB = 0; // Makes PORTD Output port
while(1) // Infinite Loop Delay_ms(5000); // 5 Sec Delay
{ PORTB = PORTB/2;
PORTB = 1; Delay_ms(5000); //5 Sec Delay
Delay_ms(5000); // 5 Sec Delay PORTB = PORTB/2;
PORTB = 2* PORTB; Delay_ms(5000); // 5 Sec Delay
Delay_ms(5000); //5 Sec Delay PORTB = PORTB/2;
PORTB = 2* PORTB; Delay_ms(5000); // 5 Sec Delay
Delay_ms(5000); // 5 Sec Delay PORTB = PORTB/2;
PORTB = 2* PORTB; Delay_ms(5000); // 5 Sec Delay
Delay_ms(5000); // 5 Sec Delay PORTB = PORTB/2;
PORTB = 2* PORTB; Delay_ms(5000); // 5 Sec Delay
Delay_ms(5000); // 5 Sec Delay PORTB = PORTB/2;
PORTB = 2* PORTB; Delay_ms(5000); // 5 Sec Delay
Delay_ms(5000); // 5 Sec Delay }
PORTB = 2* PORTB; }
Delay_ms(5000); // 5 Sec Delay
PORTB = 2* PORTB;
Example 5: Another Solution:
void main()
{
int i;
trisb = 0;
while(1)
{
portb = 1;
delay_ms(5000);
for(i=0; i<7 ; i++)
{
portb = 2*portb;
delay_ms(5000);
}
for(i=0; i<6 ; i++)
{
portb = portb/2;
delay_ms(5000);
}
}
}