You are on page 1of 50

Contents

Use Input Output Ports of PIC18F452 Microcontroller................................................................................ 3


Pic Microcontroller GPIO Pins Introduction ............................................................................................ 3
PortA ..................................................................................................................................................... 3
PortB ..................................................................................................................................................... 3
PortC ..................................................................................................................................................... 3
PortD ..................................................................................................................................................... 3
PortE ..................................................................................................................................................... 3
GPIO Pins Configuration Registers .......................................................................................................... 3
1. TRIS Register.................................................................................................................................... 3
2. PORT Register .................................................................................................................................. 4
3. LAT Register ..................................................................................................................................... 4
Setting a PORT in Binary .................................................................................................................. 7
Setting a PORT in Hexadecimal ...................................................................................................... 7
CHASING LEDS .............................................................................................................................................. 8
COMPLEX FLASHING LED .............................................................................................................................. 8
RANDOM FLASHING LEDS ............................................................................................................................ 9
LED BLINKING ............................................................................................................................................. 10
PUSH BUTTON ............................................................................................................................................ 10
LED PROBE .................................................................................................................................................. 11
Read Modify Write Problem ................................................................................................................ 12
PIC16Fxxx family of MCUs ............................................................................................................... 12
PIC18Fxxxx family of MCUs ............................................................................................................. 13
LED DICE ...................................................................................................................................................... 15
BUZZERS ............................................................................................................................................. 15
ACTIVE BUZZERS ............................................................................................................................. 15
PASSIVE BUZZERS ............................................................................................................................ 16
BUZZER........................................................................................................................................................ 16
Generating Sound ..................................................................................................................................... 17
PLAYING MELODY ............................................................................................................................... 17
ABCsound .................................................................................................................................................. 19
7 Segment Display ...................................................................................................................................... 21
7 Seg Dice .................................................................................................................................................... 22
7 Seg Cascading .......................................................................................................................................... 23
Interrupt with PIC Microcontroller - Mikroc ............................................................................................... 25
Timer 0 .................................................................................................................................................... 26
Register required for Timer 0 .................................................................................................................. 26
Load register ....................................................................................................................................... 27
FLAG bit ............................................................................................................................................. 28
Timmer 0 Interrupt ..................................................................................................................................... 30
7 Seg Second Counter ................................................................................................................................. 31
External Interrupt ....................................................................................................................................... 33
Types of interrupts .............................................................................................................................. 33
POLLING ........................................................................................................................................... 33
INTERRUPT SOURCES in microcontrollers .................................................................................... 33
INTERRUPT TYPES in pic microcontrollers .................................................................................... 33
INTERRUPTS IN PIC18F452 ............................................................................................................ 33
REGISTER CONFIGURATION for external interrupt ...................................................................... 34
External Interrupt1 ...................................................................................................................................... 36
External Interrupt2 ...................................................................................................................................... 37
External Interrupt3 ...................................................................................................................................... 39
ADC analogue to digital conversion ........................................................................................................... 41
ADC1 .......................................................................................................................................................... 45
ADC2 .......................................................................................................................................................... 46
LM35 Temperature sensor .......................................................................................................................... 47
Ultrasonic sensor with 16x2 LCD display ............................................................................................... 49
Use Input Output Ports of PIC18F452 Microcontroller
We will learn how to use GPIO pins of Pic microcontroller. We will see how to configure
general purpose pins either as a digital input and digital output. For demonstration, we will use
PIC18F452 microcontroller but you can also any other Microchip microcontroller also.

Pic Microcontroller GPIO Pins Introduction


The PIC18F452 microcontroller uses a number of input/output pins for connection with
external devices. It has a total of 40 pins, out of which 34 can serve as input/output pins. These
pins are grouped into five ports, which are Port A, Port B, Port C, Port D, and Port E. This
article will teach you how to utilize the I/O ports of the PIC18F452 microcontroller.
PortA
Port A consists of seven pins named as RA0-RA6.
PortB
Port B consists of eight pins named as RB0-RA7.
PortC
Port C consists of eight pins named as RC0-RC7.
PortD
Port D consists of eight pins named as RD0-RD7.
PortE
Port E consists of three pins named as RE0-RE2.

GPIO Pins Configuration Registers


Each port has three registers for its operation. These registers are:

1. TRIS register (data direction register)


2. PORT register (reads the levels on the pins of the device)
3. LAT register (output latch)
1. TRIS Register
TRIS is a data direction register. Setting the TRIS bit for the corresponding port determines the
data direction (read or write) of the microcontroller. Each port has its own TRIS register. For
example, to make Port A an output port, we can use the following code:

TRISA = 0; // making port as output port (write)

To make a specific bit of the port as input or output, we can use the following code:

TRISA.RA2 = 1; // configure PORTA pin RA2 as input


2. PORT Register
The PORT register is to read the levels on the pins of the device and assign logic values (0/1) to
the ports.

Input Mode of Port A

In the input mode of Port A, the status of the pins can be read by reading the PORTA register.
First, we need to set the direction of data by setting the TRISA bit to 1, which makes the
corresponding PORTA pin an input and puts the corresponding output driver in a Hi-Impedance
mode. Example code:

TRISA = 1; // making port as input port (read)


PORTA = 0xFF; // reading the status of the pins (input mode)

Output Mode of Port A

In the output mode of Port A, we need to set the direction of data using the TRISA register and
assign a value to the port for output. A write to the PORT register writes the data value to the
port latch. Example code:

TRISA = 0; // making port as output port (write)


PORTA = 0x03; // assigning high logic to RA0 and RA1

3. LAT Register
The LAT (Latch) register is associated with an I/O pin and eliminates the problems that could
occur with read-modify-write instructions.

Latch Read

A read of the LAT register returns the values held in the port output latches instead of the values
on the I/O pins.

Latch Write

A write to the LAT register has the same effect as a write to the PORT register. A write to the
PORT register writes the data value to the port latch.
ANSEL and ANSELH
There are several registers that affect the operation of the digital I/O pins. If you look at the pin
diagram you will see that pin 3 is called RA4/AN3. This is because it can serve as digital I/O port
RA4, or analog input pin AN3. The two registers ANSEL and ANSELH control whether or not
AN0 through AN11 are operational. Each bit in the register controls one pin as outlined in the
register tables shown below. A '0' sets the pin to digital mode and a '1' sets the pin to analog mode.
For example, if you make ANSEL equal to 0b10000001 (binary), then AN7 will be enabled and
RC3 will be disabled because they share the same pin (pin 7). AN0 will also be in analog mode
(RA0 disabled). Reading a pin that is set to analog mode will return a '0'.

ANSEL = 0x81; //AN7 and AN0 enabled


ANSELH = 0x05; //AN8 and AN10 enabled
Setting a PORT in Binary
So we will first show how to set a PORT in binary values.

We will set the bits on PORTA and PORTB.

We will make the first 2 bits of PORTA as inputs and the next 6 bits as outputs.

We will make the first 5 bits of PORTB as outputs and the last 3 bit as inputs.

The code to do this is shown below.

TRISA= 0b00000011;

TRISB= 0b11100000;

Remember that the first bits appear to the rightmost, since the most significant bit (RA7 or RB7) is
leftmost.

As another example, to make all bits in PORTA inputs and all bits in PORTB outputs, we use the
following code below.

TRISA= 0b11111111;
TRISB= 0b00000000;

Setting a PORT in Hexadecimal


Now we show how to set a PORT in hexadecimal values.

The advantage of setting a PORT with hexadecimal values is that the number used is shorter than if
using other number formats.

The disadvantage is that many times it requires calculation or some type of converter to know the value
that must be used, but with practice, a programmer may know what codes correspond to what

We will set the bits on PORTA and PORTB.

We will make the first 2 bits of PORTA as inputs and the next 6 bits as outputs.

We will make the first 5 bits of PORTB as outputs and the last 3 bit as inputs.

The code to do this is shown below.

TRISA= 0x3;
TRISB= 0xE0;

To make all bits in PORTA inputs and all bits in PORTB outputs, we use the following code below.
TRISA= 0xFF;
TRISB= 0x00;

Now all bits in PORTA are inputs and all bits in PORTB are outputs.
PIC is a Peripheral Interface Microcontroller which was developed in the year 1993 by the General
Instruments Microcontrollers. It is controlled by software and programmed in such a way that it
performs different tasks and controls a generation line. PIC microcontrollers are used in different
new applications such as smartphones, audio accessories, and advanced medical devices.

CHASING LEDS
============
In this project 8 LEDs are connected to PORTC of a PIC18F45K22 microcontroller and the
microcontroller is operated from an 8 MHz crystal.
The program turns ON the LEDs in an an�clockwise manner with 1 s delay between
each output. The net result is that LEDs seem to be chasing each other.

**************************************************************************/
void main()
{
unsigned char J = 1;
ANSELC = 0; // Configure PORTC as digital
TRISC = 0; // Configure PORTC as output
for(;;) // Endless loop
{
PORTC = J; // Send J to PORTC
Delay_ms(1000); // Delay 1 s
J = J << 1; // Shi�_ le�_ J
if(J == 0) J = 1; // If last LED, move to first one
}
}
If you are using the EasyPIC V7 development board, then make sure that the following
jumper is configured:
DIP switch SW3: PORTC ON

COMPLEX FLASHING LED


===================
In this project an LEDs is connected to port pin RC0 of a PIC18F45K22 microcontroller and the
microcontroller is operated from an 8 MHz crystal.
The program flashes the LED con�nuously with the following patern:
3 flashes with 200 ms delay between each flash
2 s delay
*****************************************************************************/
void main()
{
unsigned char i;
ANSELC = 0; // Configure PORTC as digital
TRISC = 0; // Configure PORTC as output
for(;;) // Endless loop
{
for(i = 0; i < 3; i++) // Do 3 _mes
{
PORTC.RC0 = 1; // LED ON
Delay_ms(200); // 200 ms delay
PORTC.RC0 = 0; // LED OFF
Delay_ms(200); // 200 ms delay
}
Delay_ms(2000); // 2 s delay
}
}
DIP switch SW3: PORTC ON

RANDOM FLASHING LEDS


====================

In this project 8 LEDs are connected to PORTC of a PIC18F45K22 microcontroller and the
microcontroller is operated from an 8 MHz crystal.
The program uses a pseudorandom number generator to generate a number between 0 and
32767. This number is then divided by 128 to limit it between 1 and 255. The resultant number
is sent to PORTC of the microcontroller. This process is repeated every second.
*****************************************************************************/
void main()
{
unsigned int p;
ANSELC = 0; // Configure PORTC as digital
TRISC = 0; // Configure PORTC as output
srand(10); // Ini�alize random number seed
for(;;) // Endless loop
{
p = rand(); // Generate a random number
p = p / 128; // Number between 1 and 255
PORTC = p; // Send to PORTC
Delay_ms(1000); // 1 s delay
}
}
DIP switch SW3: PORTC ON
LED BLINKING
====================

In this project 8 LEDs are connected to PORTB of a PIC18F45K22 microcontroller and the
microcontroller is operated from an 8 MHz crystal.
The program toggles the outputs at every second.
*****************************************************************************/

void main() {
// set PORTB to be digital output
TRISB = 0;
// Turn OFF LEDs on PORTB
LATB = 0;
while(1) {
// Toggle LEDs on PORTB
LATB = ~LATB;
// Delay 1000 ms
Delay_ms(1000);
}
}
DIP switch SW3: PORTB ON

PUSH BUTTON
====================

In this project RC0 of PORTC is connected to a push buton switch, RB0 of PORTB is connected
to an LED through a resistor. and the PIC18F45K22 microcontroller is operated from an 8 MHz
crystal. While and whenever the switch is pressed, the LED goes high.
*****************************************************************************/

void main() {
TRISC.RC0 = 1; //Configure 1st bit of PORTC as input
TRISB.RB0 = 0; //Configure 1st bit of PORTB as output
PORTB.RB0 = 0; //LED OFF
do
{
if(PORTC.RC0 == 1) //Check whether the switch is pressed
PORTB.RB0 = 1; //LED ON
else
PORTB.RB0 = 0; //LED OFF
}while(1);
}
DIP switch SW3: PORTB and PORTC ON, and PULLDOWN RC0
LED PROBE
====================

This is a logic probe project. In this project 2 colored LEDs are connected to PORTC pins RC6 (RED)
and RC7 (GREEN). In addi�on, RC0 is used as the probe input. If the logic probe is at logic 1 then
the RED LED is turned ON. Otherwise, the GREEN LED is turned ON.
*****************************************************************************/
#define PROBE PORTC.RC0
#define RED_LED PORTC.RC6
#define GREEN_LED PORTC.RC7
void main()
{
ANSELC = 0; // Configure PORTC as digital
TRISC0_bit = 1; // Configure RC0 as input
TRISC6_bit = 0; // Configure RC6 as output
TRISC7_bit = 0; // Configure RC7 as output
for(;;) // Endless loop
{
if(PROBE == 1) // If the signal is HIGH
{
GREEN_LED = 0; // Turn OFF GREEN LED
RED_LED = 1; // Torn ON RED LED
}
else
{
RED_LED = 0; // Turn OFF RED LED
GREEN_LED = 1; // Turn ON GREEN LED
}
}
}

DIP switch SW3: PORTC ON and PULLDOWN RC0


Read Modify Write Problem
PIC16Fxxx family of MCUs
The Microchip mid-range PIC microcontrollers use a sequence known as Read-Modify-Write (RMW)
when changing an output state (1 or 0) on a pin. This can cause unexpected behavior under certain circumstances.
When your program changes the state on a specific pin, for example RB0 in PORTB, the PIC
microcontroller first READs all 8 bits of the PORTB register which represents the states of all 8 pins in PORTB
(RB7-RB0).
The PIC microcontroller then stores this data in the MCU. The bit associated with RB that you've
commanded to MODIFY is changed, and then the PIC microcontroller WRITEs all 8 bits (RB7-RB0) back to
the PORTB register.
During the first reading of the PORT register, you will be reading the actual state of the physical pin.
The problem arises when an output pin is loaded in such a way that its logic state is affected by the load.
Instances of such loads are LEDs without current-limiting resistors or loads with high capacitance or inductance.
For example, if a capacitor is attached between pin and ground, it will take a short while to charge when the pin
is set to 1.
On the other hand, if the capacitor is discharged, it acts like a short circuit, forcing the pin to '0' state, and,
therefore, a read of the PORT register will return 0, even though we wrote a 1 to it.
Lets analyze the following example :
PORTB.B0 = 1;
PORTB.B1 = 1;
Assume that the PORTB is initially set to zero, and that all pins are set to output. Let's say we connect a discharged
capacitor to RB0 pin.
The first line, PORTB.B0 = 1; will be decoded like in this way :
The second line, PORTB.B1 = 1; will be decoded like in this way :

To correct the problem in the code, insert a delay after each PORTB.Bx = 1 line, or modify the entire
PORTB register in a single line PORTB = 0b00000011.

PIC18Fxxxx family of MCUs


On a PIC18Fxxxx device, this problem can be avoided by using LATx register when writing to ports,
rather than using PORTx registers.
Writing to a LATx register is equivalent to writing to a PORTx register, but readings from LATx
registers return the data value held in the port latch, regardless of the state of the actual pin.
For example, lets analyze the following example :
LATB.B0 = 1;
LATB.B1 = 1;
The first line, LATB.B0 = 1; will be decoded like in this way :
The second line, LATB.B1 = 1; will be decoded like in this way

When to use LATx instead of PORTx


Depending on your hardware, one may experience unpredictable behavior when using PORTx bits for
driving output.
Displays (GLCD, LCD), chip select pins in SPI interfaces and other cases when you need fast and reliable
output, LATx should be used instead of PORTx.
LED DICE
====================

This is a LED dice project. In this project 6 LEDs are connected to PORTB to represent the number
1 to 6. In addi�on, RC0 is used as the roll switch. If the dice is rolled, that means switch at RC0 is
pressed, the random number 1 through 6 is generated and corresponding output will appear at
the PORTB.
*****************************************************************************/

void main()
{
unsigned char digit;
unsigned char Dice[]={0,0x01, 0x03, 0x07,0x0F,0x1F,0x3F};
ANSELB = 0; // Configure PORTD as digital
ANSELC = 0; // Configure PORTC as digital
TRISB = 0; // Configure PORTD as outputs
TRISC = 0x01; // Configure RC.0 of PORTC as input
srand(10);
for(;;)
{
if(PORTC.RC0 == 1)
{digit=rand()%6+1;
PORTB=Dice[digit];
Delay_Ms(3000);
PORTB=0;}
}
}
DIP switch SW3: PORTB and PORTC ON and PULLDOWN RC0

BUZZERS
Buzzers can be categorized into two different types – active buzzers and passive buzzers. An active
buzzer has a built-in oscillator so it can produce sound with only a DC power supply.

A passive buzzer does not have a built-in oscillator, so it needs an AC audio signal to produce
sound.

ACTIVE BUZZERS
Active buzzers are the simplest to use. They are typically available in voltages from 1.5V to 24V.
All you need to do is apply a DC voltage to the pins and it will make a sound.
Active buzzers have polarity. The polarity is the same as an LED and a capacitor – the longer pin
goes to positive. One downside of active buzzers is that the frequency of the sound is fixed and
cannot be adjusted.
PASSIVE BUZZERS
Passive buzzers need an AC signal to produce sound. the downside to this is that they will need
more complex circuitry to control them, like an oscillating 555 timer or a programmable
microcontroller like the Arduino.
Passive buzzers have the advantage that they can vary the pitch or tone of the sound. Passive
buzzers can be programmed to emit a wide range of frequencies or musical notes.

BUZZER
============

void main() {
ANSELC=0;
TRISC=0;
PORTC=0;
for(;;)
{unsigned int i,j,k;
for(i=0;i<80;i++)
{PORTC.RC2=1;
Delay_ms(1);
PORTC.RC2=0;
Delay_ms(1);}

for(j=0;j<80;j++)
{ PORTC.RC2=1;
Delay_ms(2);
PORTC.RC2=0;
Delay_ms(2);}

}
}
J21: Select RC2
Generating Sound
====================
This project shows how sound with different frequencies can be generated using a simple
buzzer. The project shows how the simple melody “Happy Birthday” can be played using a
buzzer.
Normally, buzzers are excited using square wave signals, also called Pulse Width
Modulated (PWM) signals. The frequency of the signal determines the pitch of the generated
sound, and duty cycle of the signal can be used to increase or decrease the volume. Most
buzzers operate in the frequency range 2-4 kHz. The PWM signal required to generate sound
can be using the PWM module of the PIC microcontrollers.
When playing a melody, each note is played for a certain duration and with a certain
frequency. In addition, a certain gap is necessary between two successive notes. The
frequencies of the musical notes starting from middle C (i.e. C4) are given below. The harmonic
of a note is obtained by doubling the frequency. For example, the frequency of C5 is 2 x 262 =
524 Hz.
mikroC Pro for the PIC compiler provides a sound library with the following two functions:
Sound_Init This function is used to specify to which port and which pin the sound device is
connected to
Sound_Init(char *snd_port, char snd_pin)
Eg., Sound_Init(&PORTC, 3);

Sound_Play This function generates a square wave signal with the specified frequency
(hertz) and duration (milliseconds) from the port pin specified by the
initialization function. The frequencies given in the above table are
approximated to their nearest integers since this function accepts only integer
frequencies.
Sound_Play(unsigned freq_in_hz, unsigned duration_ms);
Eg., Sound_Play(698, 250); // Frequency = 698Hz, duration = 250ms

Notes C4 C4# D4 D4# E4 F4 F4# G4 G4# A4 A4# B4

Hz 261.63 277.18 293.66 311.13 329.63 349.23 370 392 415.3 440 466.16 493.88

PLAYING MELODY
================
In this project a buzzer is connected to port pin RC2 of a PIC18F45K22 microcontroller,
operating with an 8 MHz crystal.
The program plays the classical "Happy Birthday" melody.
**************************************************************/
#define Max_Notes 25
void main()
{
unsigned char i;
unsigned int Notes[Max_Notes] =
{
262, 262, 294, 262, 349, 330, 262, 262, 294, 262, 392,
349, 262, 262, 524, 440, 349, 330, 294, 466, 466, 440,
349, 392, 349
};
unsigned char Durations[Max_Notes] =
{
1, 1, 2, 2, 2, 3, 1, 1, 2, 2, 2, 3, 1, 1, 2, 2, 2, 2, 2,
1, 1, 2, 2, 2, 3
};
ANSELC = 0; // Configure PORTC as digital
Sound_Init(&PORTC, 2); // Initialize the Sound library
for(;;) // Endless loop
{
for(i = 0; i < Max_Notes; i++) // Do for all notes
{
Sound_Play(Notes[i], 400*Durations[i]); // Play the notes
Delay_ms(100); // Note gap
}
Delay_Ms(3000); // Repeat after 3 s
}
}
J21: Select RC2
ABCsound
=========
In this project a buzzer is connected to port pin RC2 of a PIC18F45K22 microcontroller,
operating with an 8 MHz crystal.
The program plays the classical "ABC" melody.
**************************************************************/

void main()
{
unsigned char i;
unsigned int fst[7] ={262,262,392,392,440,440,392};
unsigned int snd[7]={349,349,330,330,294,294,262};
unsigned int thd[3]={392,392,349};
unsigned int fot[3]={330,330,294};
unsigned int fit[7]={262,262,392,392,440,440,392};
unsigned int sit[7]={349,349,330,330,294,294,262};

ANSELC = 0; // Configure PORTC as digital


Sound_Init(&PORTC, 2); // Initialize the Sound library
for(;;) // Endless loop
{
for(i = 0; i < 7; i++) // Do for all notes
{
Sound_Play(fst[i], 400); // Play the notes
Delay_ms(100); // Note gap
}
Delay_ms(400);
for(i = 0; i < 7; i++) // Do for all notes
{
Sound_Play(snd[i], 400); // Play the notes
Delay_ms(100); // Note gap
}
Delay_ms(400);

for(i = 0; i < 3; i++) // Do for all notes


{
Sound_Play(thd[i], 400); // Play the notes
Delay_ms(100); // Note gap
}
Delay_ms(400);
for(i = 0; i < 3; i++) // Do for all notes
{
Sound_Play(fot[i], 400); // Play the notes
Delay_ms(100); // Note gap
}
Delay_ms(400);
for(i = 0; i < 3; i++) // Do for all notes
{
Sound_Play(thd[i], 400); // Play the notes
Delay_ms(100); // Note gap
}
Delay_ms(400);
for(i = 0; i < 3; i++) // Do for all notes
{
Sound_Play(fot[i], 400); // Play the notes
Delay_ms(100); // Note gap
}
Delay_ms(400);
for(i = 0; i < 7; i++) // Do for all notes
{
Sound_Play(fit[i], 400); // Play the notes
Delay_ms(100); // Note gap
}
Delay_ms(400);
for(i = 0; i < 7; i++) // Do for all notes
{
Sound_Play(sit[i], 400); // Play the notes
Delay_ms(100); // Note gap
}
Delay_Ms(3000); // Repeat after 3 s
}
}
7 Segment Display
====================

#define DIGIT1 PORTA.RA0


unsigned char Display(unsigned char i)
{unsigned char segment[]={0x3F, 0x06, 0x5B,0x4F,0x66,0x6D,0x7D,0X07, 0x7F,0x6F};
unsigned char patern;
patern=segment[i];
return (patern);}

void main()
{
unsigned char digit;
ANSELA = 0; // Configure PORTA as digital
ANSELD = 0; // Configure PORTD as digital
TRISA = 0; // Configure PORTA as outputs
TRISD = 0; // Configure PORTD as outputs
DIGIT1 = 0; // Disable digit 1
for(;;)
{ for(digit=0; digit<10;digit++)
{PORTD=Display(digit);
DIGIT1=1;
Delay_Ms(1000);
DIGIT1=0;}
}
}

7 Seg Dice
====================
#define DIGIT1 PORTA.RA0
unsigned char Display(unsigned char i)
{unsigned char segment[]={0x3F, 0x06, 0x5B,0x4F,0x66,0x6D,0x7D,0X07, 0x7F,0x6F};
unsigned char patern;
patern=segment[i];
return (patern);}

void main()
{
unsigned char digit;
ANSELA = 0; // Configure PORTA as digital
ANSELD = 0; // Configure PORTD as digital
ANSELC = 0; // Configure PORTC as digital
TRISA = 0; // Configure PORTA as outputs
TRISD = 0; // Configure PORTD as outputs
TRISC = 0x01; // Configure RC.0 of PORTC as input
DIGIT1 = 0; // Disable digit 1
srand(10);
for(;;)
{
if(PORTC.RC0 == 1)
{digit=rand()%6+1;
PORTD=Display(digit);
DIGIT1=1;
Delay_Ms(1000);
DIGIT1=0;}
}
}

7 Seg Cascading
====================

#define DIGIT1 PORTA.RA0


#define DIGIT2 PORTA.RA1
unsigned char Display(unsigned char i)
{unsigned char segment[]={0x3F, 0x06, 0x5B,0x4F,0x66,0x6D,0x7D,0X07, 0x7F,0x6F};
unsigned char patern;
patern=segment[i];
return (patern);}
void main()
{
unsigned char digit=0;
int lsb=0,msb=0,i=0,flag=0; // variable i is for counter & flag for delay
ANSELA = 0; // Configure PORTA as digital
ANSELD = 0; // Configure PORTD as digital
TRISA = 0; // Configure PORTA as outputs
TRISD = 0; // Configure PORTD as outputs
DIGIT1 = 0; // Disable digit 1
DIGIT2=0;
PORTD=0X00;
for(;;)
{ lsb=digit%10;
msb=digit/10;
PORTD=Display(msb);
DIGIT2=1;
Delay_Ms(5);
DIGIT2=0;
PORTD=Display(lsb);
DIGIT1=1;
Delay_Ms(5);
DIGIT1=0;
if(flag==100)
{digit++;
flag=0;
if(digit==100) digit=0;}
flag++;
}
}
Interrupt with PIC Microcontroller - Mikroc
Interrupt is a very important concept in microcontroller. It notifies the microcontroller of an
external/internal event or that a device needs its service.
There are 2 ways that a device can notify the microcontroller for its service;
• Polling.
• Interrupt.
In polling the microcontroller keeps monitoring the status of a particular device, when the
condition is met, it services the given device. After that it moves to next device until all the devices
are serviced.
This method is not efficient as it wastes much of the microcontroller time polling devices that do
not need service.
In interrupt, when a device needs service,
• The device will send an interrupt signal to the microcontroller to notify it of its
service.
• The microcontroller interrupts whatever it is doing to serve the device on
receiving of the interrupt signal.

*** Every interrupt request have an interrupt handler otherwise called Interrupt Service Routine
(ISR). The microcontroller runs the ISR on every interrupt request.

*** For every interrupt, there is a fixed location in memory that holds the ADDRESS of its ISR.
These group of memory location is called INTERRUPT VECTOR TABLE.
Interrupts can occur either ASYNCHRONUOSLY (External Events) or SYNCHRONUOSLY
(usually Timer Interrupt).

STEPS INVOLVED IN EXECUTING AN INTERRUPT


• When an interrupt request is made, the microcontroller goes through the following steps:
• It finishes the instruction it is executing and saves the address of the next instruction
(program counter) on the stack.
• It jumps to Interrupt Vector Table (IVT), the IVT directs the microcontroller to the address of
the ISR.
• The microcontroller gets the address of the ISR from IVT and jumps to it. It starts to execute
the ISR until it reaches the last instruction which is Return from Interrupt Exist.
• Upon executing the Return from Interrupt Exist instruction, the microcontroller returns to the
place where it was interrupted and resumes its normal flow of execution.
There are several sources of interrupt for PIC 16/18 microcontrollers. Most commonly used are
the:
• Timer Interrupt.
• External Interrupt
• PORTB change Interrupt etc.

The PIC18 timer is divided into 4 types


1. Timer 0
2. Timer 1
3. Timer 2
4. Timer 3
PIC18 timers can be used to generate a time delay or as a counter to count external event
happening outside the microcontroller.
In this article, we will see how to generate a time delay by programming the PIC18 timer.

Timer 0

The timer 0 module has the following features


• Software is scalable as an 8 bit or 16-bit timer/counter.
• Readable and writable
• Dedicated 8 bit software programmable Prescaler
• Clock source selectable to be internal or external
• Edge select for external clock
Register required for Timer 0

Control register
Each timer has a control register called TCON to set the various timer operation modes.
T0CON is an 8-bit register used for control of timer 0.
TMR0ON (Timer0 on/off control bit)
1 = Enable timer 0
0 = Disable timer 0
T08BIT (Timer0 8-bit/16-bit control bit)
1 = Configured as an 8-bit timer/counter
0 = Configured as an 16-bit timer/counter
T0CS (Timer0 clock source select bit)
1 = Transition on T0CKL pin
0 = Internal instruction cycle clock (CLK0) [It means Fosc/4]
T0SE (Timer0 Source Edge select bit)
1 = High to Low transition on T0CKL pin
0 = Low to High transition on T0CKL pin
PSA (Timer0 Prescaler assignment bit)
1 = Timer 0 Prescaler is not assigned
0 = Timer 0 Prescaler is assigned
T0PS2 - T0PS0 (Timer0 prescaler select bit)
111 - 1:256 prescaler value
110 - 1:128 prescaler value
101 - 1:64 prescaler value
100 - 1:32 prescaler value
011 - 1:16 prescaler value
010 - 1:8 prescaler value
001 - 1:4 prescaler value
000 - 1:2 prescaler value

Load register

TMR0H (higher byte)


TMR0L (lower byte)
FLAG bit

TMR0IF (present in INTCON register)

*** For the same interrupt to re-occur, the completion status has to be cleared that is; T0IF=0
(Timer 0 Interrupt Flag) and the Timer Value reloaded into the timer register.

Note: By loading TMR0 Register we can control the count until an overflow occurs (interrupt
takes place)

How to Calculate Value to be loaded into the Timer 0 Register


TMRO value = 256 - t / (T * prescaler value)

t = Overflow Time or Time Interrupt Occurs (in microseconds)

T (Oscillator Period in Microseconds) = 1 / (Internal Oscillator Frequency)

Internal Oscillator Frequency = Crystal clock / 4

*** In PIC microcontroller instruction takes 4 clock cycles, that’s why you see crystal clock being
divided by 4.
Assuming we have PIC 16F877A microcontroller using an external clock of 8 MHz and we are
required to generate 200 microseconds interrupt with a Prescaler value of 2. The TMRO Value
will be 56 using the above formula.
Internal Oscillator Frequency = 8MHz / 4 = 2MHz

T (Oscillator Period in Microseconds) = 1 / 2MHz = 0.5microseconds

t = Overflow Time or Time Interrupt Occurs (in microseconds) = 200microseconds

TMRO value = 256 - 200microsec / (0.5microsec * 2) = 256-200 = 56


Prescaler is a name for the part of a microcontroller which divides oscillator clock before it will
reach logic that increases timer status. The range of the prescaler id is from 1 to 256 and the value
of the Prescaler can be set using the OPTION Register (The same one that we used for pull up
resistors). For example if the value of prescaler is 64, then for every 64th pulse the Timer will be
incremented by 1.

As the timer increments and when it reaches to its maximum value of 255, it will trigger an
interrupt and initialize itself to 0 back again. This interrupt is called as the Timer Interrupt. This
interrupt informs the MCU that this particular time has lapped.
Timmer 0 Interrupt
====================

vola�le unsigned int count1 = 0 ;


vola�le unsigned int count2= 0 ;
void Interrupt(){
if (TMR0IF_bit){
TMR0IF_bit = 0;
TMR0L = 0x06;
++count1 ; // �mer configured to generate 1ms periodic �cks
++count2 ; }
}
void InitTimer0(){
T0CON = 0xC2;
TMR0L = 0x06;
GIE_bit = 1;
TMR0IE_bit = 1;
}
void task_1 (){
if (count1 ==200) //blinks led every 200ms
{
count1 = 0;
LATD = ~ LATD;
}
}
void task_2 () {
if (count2 == 1000) // blinks every second
{
count2 = 0;
LATB = ~ LATB;
}
}
void main() {

TRISD = 0x00;
TRISB = 0x00;
// clear output bit
LATD = 0x00;
LATB = 0x00;

InitTimer0();

while (1) {
task_1 (); //blinks every 200ms
task_2 (); // blinks every 1 sec

}
}

7 Seg Second Counter


==========================

vola�le unsigned int digit = 0 ;


void InitTimer0(){
T0CON = 0x84;
TMR0H = 0x0B;
TMR0L = 0xDC;
GIE_bit = 1;
TMR0IE_bit = 1;
}

void Interrupt(){
if (TMR0IF_bit){
TMR0IF_bit = 0;
TMR0H = 0x0B;
TMR0L = 0xDC;
digit++; //Enter your code here
if(digit==60) digit=0;
}
}
#define DIGIT1 PORTA.RA0
#define DIGIT2 PORTA.RA1
unsigned char Display(unsigned char i)
{unsigned char segment[]={0x3F, 0x06, 0x5B,0x4F,0x66,0x6D,0x7D,0X07, 0x7F,0x6F};
unsigned char patern;
patern=segment[i];
return (patern);}

void main()
{int lsb=0,msb=0,i=0,flag=0; // variable i is for counter & flag for delay
ANSELA = 0; // Configure PORTA as digital
ANSELD = 0; // Configure PORTD as digital
TRISA = 0; // Configure PORTA as outputs
TRISD = 0; // Configure PORTD as outputs
DIGIT1 = 0; // Disable digit 1
DIGIT2=0;
PORTD=0X00;
InitTimer0();
for(;;)
{ lsb=digit%10;
msb=digit/10;
PORTD=Display(msb);
DIGIT2=1;
Delay_Ms(5);
DIGIT2=0;
PORTD=Display(lsb);
DIGIT1=1;
Delay_Ms(5);
DIGIT1=0;
}
}

Arduino TimmerInterrupt
https://deepbluembedded.com/arduino-timer-interrupts/
External Interrupt
=====================

Types of interrupts
There are two methods of communication between the microcontroller and the external device:
• By using Polling
• By using Interrupts

POLLING
In this method, the external devices are not independent. We fix the time interval in which
microcontroller has to contact the external device. The microcontroller accesses that device at the
exact time interval and gets the required information. Polling method is just like picking up our
phone after every few seconds to see if we have a call. The main drawback of this method is the
waste of time of microcontroller. It needs to wait and check whether the new information has
arrived not.

INTERRUPT SOURCES in microcontrollers


The request to the microcontroller to stop to perform the current program temporarily can come
from various sources:
• Through external hardware devices like pressing specific key on the keyboard, which sends
Interrupt to the microcontroller to read the information of the pressed key.
• During execution of the program, the microcontroller can also send interrupts to itself to report
an error in the code. For example, division by 0 will causes an interrupt.
• In the multi-processor system, the microcontrollers can send interrupts to each other to
communicate. For example, to divide the work between them they will send signals between
them.

INTERRUPT TYPES in pic microcontrollers


There are 2 types of interrupts for PIC microcontroller that can cause break.
Software Interrupt: It comes from a program that is executed by microcontroller or we can say
that it is generated by internal peripherals of the microcontroller and requests the processor to hold
the running of program and go to make an interrupt.
Hardware Interrupt: These interrupts are sent by external hardware devices at certain pins
of microcontroller.

INTERRUPTS IN PIC18F452
Following interrupts sources are present in PIC18F452
• Timer over interrupt
• Pins RB0, RB1, RB2 for external hardware interrupts (INT0, INT1, INT2)
• PORTB Change interrupts (any one of the upper four Port B pins. RB4-RB7)
• ADC (analog-to-digital converter) Interrupt
• CCP (compare capture pulse-width-modulation) Interrupt
• Serial communication’s USART interrupts (receive and transmit)
• Reset, Brown-Out Reset, Watch-dog Reset, Power On Reset
• Parallel Port Read/Write Interrupt
• Master Synchronous Serial Port Interrupt
• Data EEPROM Write Complete Interrupt

REGISTER CONFIGURATION for external interrupt


These are the registers for interrupt operation and minimum 1 register can be used to control the
interrupt operation in PIC18F452 which are:
• RCON (Reset Control Register)
• INTCON, INTCON2, INTCON3 (Interrupt Control Registers)
• PIR1, PIR2 (Peripheral Interrupt Request Registers)
• PIE1, PIE2 (Peripheral Interrupt Enable Registers)

RCON Register:
• Reset control register
• IPEN bit to enable interrupt priority scheme, 1= enable priority level on interrupts
• Other bits used to indicate the cause of reset
RI (Reset Instruction flag), TO (Watchdog Time Out flag), PD (Power on Detection flag), POR
(Power on Reset status) and BOR (Brown Out Reset status bit)

INTCON Register:
• 3 Interrupt control registers INTCON, INTCON2, INTCON3
• Readable and writable register which contains various enable and flag bits
• Interrupt flag bits get set when an interrupt condition occurs
• Contain enable, priority and flag bits for external interrupt, port B pin change and TMR0
overflow interrupt
PIE Register:
• Peripheral Interrupt Enable register
• May be multiple register (PIE1, PIE2), depending on the number of peripheral interrupt sources
• Contain the individual bits to enable/disable Peripheral interrupts for use

PIR Register:
• Peripheral Interrupt Flag register
• May be multiple register (PIR1, PIR2), depending on the number of peripheral interrupt
sources
• Contain bits to identify which interrupt occurs (flags)
• Corresponding bits are set when the interrupt occurred

EXTERNAL INTERRUPT registers setting


INTCON registers are just used to configure the external PIC interrupts. This article also deals
with external interrupts of PIC18F452 so we will discuss it in detail here.

FOR PERIPHERAL INTERRUPT:


The PIE (Peripheral Interrupt Enable) and PIR (Peripheral Interrupt Request) registers are used to
configure the Peripheral (Internal) Interrupts.

INTCON REGISTER:
GIE: Global Interrupt Enable
This bit is set high to enable all interrupts of PIC18F452.
1 = Enable all interrupts
0 = Disable all interrupts

PEIE: Peripheral Interrupt Enable


This bit is set high to enable all the peripheral interrupts (Internal interrupts) of the microcontroller.
1 = Enable all peripheral interrupts
0 = Disable all peripheral interrupts

T0IE: TMR0 Overflow Interrupt Enable


This bit is set high to enable the External Interrupt 0.
1 = Enable TMR0 overflow interrupt
0 = Disable TMR0 overflow interrupt

INTE: INT External Interrupt Enable


This bit is set high to enable the external interrupts.
1 = Enables the INT external interrupt
0 = Disables the INT external interrupt

RBIE: RB Interrupt Enable


This bit is set high to enable the RB Port Change interrupt pin.
1 = Enables the RB port change interrupt
0 = Disables the RB port change interrupt

T0IF: TMR0 Overflow Interrupt Flag


1 = TMR0 register has overflowed (it must be cleared in software)
0 = TMR0 register has not overflowed

INTF: INT External Interrupt Flag


1 = The INT external interrupt occurred (it must be cleared in software)
0 = The INT external interrupt did not occur

RBIF: RB Port Change Interrupt Flag


1 = At least one of the RB7:RB4 pins changed the state (must be cleared in software)
0 = None of RB7:RB4 pins have changed the state

INTCON2 REGISTER:

RBPU: Port B Pull up Enable


1 = All port B pull ups are disabled
0 = All port B pull ups are enabled by individual port latch values

INTEDG0, INTEDG1, INTEDG2: External Interrupt Edge select


These bits are used to select the triggering edge of the corresponding interrupt signal on which the
microcontroller is to respond.
1 = Interrupt on rising edge
0 = Interrupt on falling edge

Bit 3, Bit 1: Unimplemented


t is always read as 0

TMR0IP: TMR0 overflow priority


1 = High priority
0 = Low priority

RBIP: RB Port change Interrupt Priority


1 = High priority
0 = Low priority

INTCON3 REGISTER:

INT1IP, INT2IP:
These bits are used to set priority of the interrupts 1 and 2, respectively.
1 = High priority
0 = Low priority

Bit 5, Bit 2:
Both are unimplemented and read as 0.
INT1IE, INT2IE:
These bits enable/disable the External Interrupt 1 and 2, respectively.
1 = Enables the External Interrupt x
0 = Disables the External Interrupt x

INT1IF, INT2IF:
These are External Interrupt 1 and 2 flag bits, respectively.
1 = The INTx External Interrupt occurred (must be cleared in software)
0 = The INTx External Interrupt did not occur

External Interrupt1
Working Principal:
PORT D LEDs will on as 10101010. When button at RB1 is pushed, interrupt service routine will
start. It will invert (or toggle) the output at PORTD. After 1 sec while loop will again start.

Code:

void interrupt() // Interrupt Service Routine


{ if(INT1F_bit == 1 )
{ INT1F_bit = 0; // Clear the interrupt 0 flag
LATD=~LATD; //toggle PORTD
delay_ms(1000); //Delay 1 second;
}
}

void main()
{
ANSELB = 0; // Configure PORT B pins as digital
ANSELD = 0; // Configure PORT D pins as digital
TRISB = 2; // Set PORT B (only RB1) as input
TRISD = 0; // Set PORT D as output
LATD = 0x00; // Set all pin on PORT D Low

INTEDG1_bit = 1; // Set interrupt on rising edge


INT1IF_bit = 0; // Clear INT1 flag
INT1IE_bit = 1; // Enable INT1 interrupts
GIE_bit = 1; // Enable GLOBAL interrupts
while(1)
{
LATD=0xAA; //Set some value at PortD

}
}

External Interrupt2
Working Principal:
This is a simple interrupt demonstration project. All LEDs on PORTD will flash until interrupt
occurs (RB0 is pressed).Interrupt will set local flag, which will cause Flashing routine to be
executed.
/* NOTES:
- Put J17 in VCC position.
- Turn ON the PORT D LEDs at SW3.4.
- Put PORTB dip switch RB0 in PullDown position
*/

bit flag;
void Delay250() {
Delay_ms(250);
}

void Delay150() {
Delay_ms(150);
}

void FlashD1() { // Flashing routine


LATD.F1 = 1;
Delay150();
LATD.F1 = 0;
Delay250(); Delay250();
LATD.F1 = 1;
Delay150();
LATD.F1 = 0;
Delay250(); Delay250();
}

void interrupt(){ // Interrupt rutine


if(INT0F_bit == 1 ) { // Checks Receive Interrupt Flag bit
flag = 1; // Set local interrupt flag
INT0F_bit = 0; // Clear Interrupt Flag
}
}

void main() {
flag = 0; // Varialbe initialisation
ANSELB = 0; // Configure PORT B pins as digital
ANSELD = 0; // Configure PORT D pins as digital
TRISB = 1; // Set PORT B (only RB0) as input
TRISD = 0; // Set PORT D as output
LATD = 0x00; // Set all pin on PORT D Low

INTEDG0_bit = 1; // Set interrupt on rising edge


INT0IF_bit = 0; // Clear INT0 flag
INT0IE_bit = 1; // Enable INT0 interrupts
GIE_bit = 1; // Enable GLOBAL interrupts

while(1) {
LATD = 0xFF; // Set all pin on PORT D High
Delay250(); // Wait for some time
LATD = 0x00; // Set all pin on PORT D Low
Delay150(); // Wait for some time
if(flag) { // Checks local interrupt flag
FlashD1(); // Do something
flag = 0; // Resert local interrupt flag
}
}
}

External Interrupt3
Working Principal:
All LEDs on PORTD will remain LOW at the beginning. To initialize the program, the interrupt
signal must appear at RB1. After that, three flashing patterns can be changed from one to another
by pressing switch connected to RB1.

int count;
void interrupt() // Interrupt Service Routine
{ if(INT1F_bit == 1 )
{ count+=1;
delay_ms(200);
INT1F_bit = 0; // Clear the interrupt 0 flag
if(count==4) count=1; //Assign flag as 1;
}
}

void main()
{ char J=1;
int i=0;
char L[]={0x01,0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF};
char R[]={0x7F,0x3F,0x1F,0x0F,0x07,0x03,0x01,0x00};
count=0;
ANSELB = 0; // Configure PORT B pins as digital
ANSELD = 0; // Configure PORT D pins as digital
TRISB = 2; // Set PORT B (only RB1) as input
TRISD = 0; // Set PORT D as output
LATD = 0x00; // Set all pin on PORT D Low

INTEDG1_bit = 1; // Set interrupt on rising edge


INT1IF_bit = 0; // Clear INT1 flag
INT1IE_bit = 1; // Enable INT1 interrupts
GIE_bit = 1; // Enable GLOBAL interrupts
while(1)
{ while(count==1)
{LATD=0x00;
delay_ms(100);
LATD=~LATD;
delay_ms(500);
}
while(count==2)
{PORTD=J;
delay_ms(100);
J=J<<1;
if(J==0) J=1;
}
while(count==3)
{for(i=0;i<8;i++)
{PORTD=L[i];
delay_ms(100);}
for(i=0;i<8;i++)
{PORTD=R[i];
delay_ms(100);}
}
}
}
ADC analogue to digital conversion
=========================================

Digital signals have two discrete states, which are decoded as high and low, and interpreted
as logic 1 and logic 0. Analog signals, on the other hand, are continuous, and can have any value
within defined range. A/D converters are specialized circuits which can convert analog signals
(voltages) into a digital representation, usually in form of an integer number. The value of this
number is linearly dependent on the input voltage value. Most microcontrollers nowadays
internally have A/D converters connected to one or more input pins. Some of the most important
parameters of A/D converters are conversion time and resolution. Conversion time determines how
fast can an analog voltage be represented in form of a digital number. This is an important
parameter if you need fast data acquisition. The other parameter is resolution. Resolution
represents the number of discrete steps that supported voltage range can be divided into. It
determines the sensitivity of the A/D converter.
ADC1
Working Principle:
This program reads the analogue value from RB0 and display the corresponding value.

#define DIGIT1 PORTA.RA0


#define DIGIT2 PORTA.RA1
#define DIGIT3 PORTA.RA2
#define DIGIT4 PORTA.RA3
unsigned char Display(unsigned char i)
{unsigned char segment[]={0x3F, 0x06, 0x5B,0x4F,0x66,0x6D,0x7D,0X07, 0x7F,0x6F};
unsigned char pattern;
pattern=segment[i];
return (pattern);}
void main()
{
int Readvalue, first, second, third, fourth, temp1, temp2;
ANSELA = 0; // Configure PORTA as digital
ANSELD = 0; // Configure PORTD as digital
TRISA = 0; // Configure PORTA as outputs
TRISD = 0; // Configure PORTD as outputs
ADCON2 = 0x80; // Right justify the result
TRISB = 1; // Configure RB0 as input
ANSELB = 1; // Configure RB0 as analog
DIGIT1 = 0; // Disable digit 1
DIGIT2=0;
DIGIT3=0;
DIGIT4=0;
PORTD=0X00;
for(;;)
{ Readvalue = Adc_Read(12); // Read from channel 12 (AN12)
first=Readvalue%10;
temp1=Readvalue/10;
second=temp1%10;
temp2=temp1/10;
third=temp2%10;
fourth=temp2/10;
PORTD=Display(first); //display first digit
DIGIT1=1;
Delay_Ms(5);
DIGIT1=0;
PORTD=Display(second); //display second digit
DIGIT2=1;
Delay_Ms(5);
DIGIT2=0;
PORTD=Display(third); //display third digit
DIGIT3=1;
Delay_Ms(5);
DIGIT3=0;
PORTD=Display(fourth); //display fourth digit
DIGIT4=1;
Delay_Ms(5);
DIGIT4=0;
}
}

ADC2
Working Principle:
This program reads the analogue value from RB0 and convert to the corresponding voltage.
Finally, display the result.

#define DIGIT1 PORTA.RA0


#define DIGIT2 PORTA.RA1
#define DIGIT3 PORTA.RA2
#define DIGIT4 PORTA.RA3
unsigned char Display(unsigned char i)
{unsigned char segment[]={0x3F, 0x06, 0x5B,0x4F,0x66,0x6D,0x7D,0X07, 0x7F,0x6F};
unsigned char pattern;
pattern=segment[i];
return (pattern);}
void main()
{
float Readvalue, Volt;
int value, temp1=0;
int first,second,third;
ANSELA = 0; // Configure PORTA as digital
ANSELD = 0; // Configure PORTD as digital
TRISA = 0; // Configure PORTA as outputs
TRISD = 0; // Configure PORTD as outputs
TRISB = 1; // Configure RB0 as input
ANSELB = 1; // Configure RB0 as analog
ADCON2 = 0x80; // Right jusfy the result
DIGIT1 = 0; // Disable digit 1
DIGIT2=0;
DIGIT3=0;
DIGIT4=0;
PORTD=0X00;
for(;;)
{ Readvalue = Adc_Read(12); // Read from channel 12 (AN12)
Volt=(Readvalue*5)/1023; //Calculate voltage
value=Volt*100;
first=value%10;
temp1=value/10;
second=temp1%10;
third=temp1/10;

PORTD=Display(first); //display first digit


DIGIT1=1;
Delay_Ms(5);
DIGIT1=0;
PORTD=Display(second); //display second digit
DIGIT2=1;
Delay_Ms(5);
DIGIT2=0;
PORTD=0x80; //display decimal point
DIGIT3=1;
Delay_Ms(5);
DIGIT3=0;
PORTD=Display(third); //display third digit
DIGIT4=1;
Delay_Ms(5);
DIGIT4=0;
}
}

LM35 Temperature sensor


The LM35 Linear Temperature Sensor module is useful in detecting ambient air temperature.
Sensitivity is 10mV per degree Celsius. The output voltage is proportional to the temperature.
LM35 is a precision IC temperature sensor with its output proportional to the temperature (in °C).

Working Principle:
This program senses the surrounding temperature with the help of LM35 sensor. Finally, display
the result in degree Celsius.

#define DIGIT1 PORTA.RA0


#define DIGIT2 PORTA.RA1
#define DIGIT3 PORTA.RA2
#define DIGIT4 PORTA.RA3
float Temperature = 0.00;
float Readvalue = 0.00;
float mV = 0.00;
unsigned int Celsius = 0, lsb = 0, middle = 0, msb = 0, temp = 0;
void main() {
unsigned char integer[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0X07,0x7F,0x6F};
unsigned char decimal[]={0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF};
ANSELA = 0; // Configure PORTA as digital
ANSELD = 0; // Configure PORTD as digital
TRISA = 0; // Configure PORTA as outputs
TRISD = 0; // Configure PORTD as outputs
TRISE = 2; // Configure RE1 as input
ANSELE = 2; // COnfigure RE1 as analog
ADCON2 = 0x80; // Right justify the result
DIGIT1 = 0; // Disable digit 1
DIGIT2=0;
DIGIT3=0;
DIGIT4=0;
PORTD=0X00;
while(1) {
Readvalue = ADC_Read(6); // Read analog value
mV = (Readvalue*5000)/1023; // convert to mV
Temperature = mV/10; // convert to degree celsius
Celsius = Temperature * 10; // Filterring 3 digits
lsb = Celsius%10;
temp = Celsius/10;
middle = temp%10;
msb = temp/10;
PORTD=0x39;
DIGIT1=1;
Delay_Ms(5);
DIGIT1=0;
PORTD=integer[lsb];
DIGIT2=1;
Delay_Ms(5);
DIGIT2=0;
PORTD=decimal[middle];
DIGIT3=1;
Delay_Ms(5);
DIGIT3=0;
PORTD=integer[msb];
DIGIT4=1;
Delay_Ms(5);
DIGIT4=0;
}
}
// End of code
Ultrasonic sensor with 16x2 LCD display
In this project an ultrasonic sensor is connected to PORTC of a PIC18F45K22 microcontroller,
operating with an 8 MHz crystal for measuring the distance. Then the result is sent to 16x2 LCD
display.
**************************************************************/

// LCD module connections


sbit LCD_RS at RB4_bit;
sbit LCD_EN at RB5_bit;
sbit LCD_D4 at RB0_bit;
sbit LCD_D5 at RB1_bit;
sbit LCD_D6 at RB2_bit;
sbit LCD_D7 at RB3_bit;
sbit LCD_RS_Direction at TRISB4_bit;
sbit LCD_EN_Direction at TRISB5_bit;
sbit LCD_D4_Direction at TRISB0_bit;
sbit LCD_D5_Direction at TRISB1_bit;
sbit LCD_D6_Direction at TRISB2_bit;
sbit LCD_D7_Direction at TRISB3_bit;
// End LCD module connections
void Trigger_Pulse_10us();
#define Trigger_Pulse LATC.RC6 /* Define Trig pin of HC-SR04 */
void main()
{
float Distance;
int Time;
char Total_distance[4];
TRISC = 0x80; /* Make PORTC as Output port*/
TMR1IF_bit = 0;
/* Enable 16-bit TMR1 Register, prescale 1:1, internal clock, Timer OFF */
T1CON = 0x04;
TMR1L=0; TMR1H=0; /* Load Timer1 with 0 */
ANSELB = 0; // Configure PORTB as digital
ANSELC = 0; // Configure PORTC as digital
ANSELD = 0; // Configure PORTD as digital
LCD_Init();
while(1)
{ Trigger_Pulse=0; /*Clear RD0*/
Delay_us(3);
Trigger_Pulse_10us(); /* Transmit 10us pulse to HC-SR04 */
while(PORTC.RC7==0); /* Wait for rising edge at Echo pin */
TMR1ON_bit=1; /* Turn ON Timer1*/
while(PORTC.RC7==1 || !TMR0IF);/* Wait for falling edge */
TMR1ON_bit=0; /* Turn OFF Timer1 */
TMR1IF_bit=0;
Time = TMR1L+(TMR1H*256);
TMR1L=0;TMR1H=0;
Distance = (float)Time*0.0343/4; /* Distance =(velocity x Time)/2 */
floatToStr(Distance,Total_distance);
Lcd_cmd(_LCD_CLEAR); // Clear LCD
Lcd_out(1,1,"Measurement");
LCD_out(2,1,Total_distance);
LCD_out(2,10,"cm");
delay_ms(500);
}
}
void Trigger_Pulse_10us()
{
Trigger_Pulse = 1;
delay_us(10);
Trigger_Pulse = 0;
}

You might also like