Monday, September 19, 2016

LED blinking using Pic16f877a

Circuit Diagram















Source Code

#include <xc.h> // this file contains the SFR information of the chip used
#include <delays.h> // header file for using delay functionss
//----------------------------------------------------------------------------------
#define _XTAL_FREQ     4000000L
//----------------------------------------------------------------------------------
//Function prototypes
void port_initialise(void);
void DelayMs(unsigned int msCount);
//--------------------------------------------------------------------------
//Configuaration bit setting

    #pragma config WDTE = OFF    
    #pragma config FOSC = HS
    #pragma config PWRTE = ON
    #pragma config BOREN = ON
    #pragma config LVP = OFF
    #pragma config CPD = OFF
    #pragma config WRT = OFF
    #pragma config DEBUG = ON
    #pragma config CP = OFF
//----------------------------------------------------------------------------

void main (void)
    { // main loop starts-------------
  port_initialise(); // setting up I/O lines as input and output
while(1) // Normally, every MCU programe is a never ending loop. here starts it
{ //while 1 loop starts----------
PORTD=0b11111111; // all the pins will go high
                     DelayMs(500); // This our delay function based on C18 built in delay functions
                     PORTD=0b00000000; // all the pins will go low
                     DelayMs(500); // This our delay function based on C18 built in delay functions
} //while 1 loop ends------------
} // main loop ends--------------
///*************************************************************************
void port_initialise (void)
{
TRISD = 0X00; // LED port is made as output
PORTD = 0X00; // and cleared
ADCON1 = 0X0F; // A/D module not ued.All pins digital
TRISC = 0X00;
PORTC = 0X00;
TRISB = 0B00000000;
PORTB = 0X00 ;
}
//**************************************************************************
void DelayMs(unsigned int msCount)
{
unsigned int locCnt;
for(locCnt=0;locCnt<=msCount;locCnt++)
{
__delay_ms(1); // This C18 function creates a delay of 1000 instructions= 1000uSec= 1 millisecond
} // looping this msCount times will give that much milliseconds delay
}
//****************************************************************************************************************

Explanations
This is the very first and probably the simplest program. We can compare this module to the “hello World “program which we will encounter in many of the Windows based programming language tutorials like C or C++.This program blinks eight leds. LEDs are ON for approximately 500 milliseconds and OFF for the same duration.
The logic is obvious and the program is well commented with beginners in mind. To Switch on LEDs, we will load a bit pattern in the PORT connected to LEDs. If we refer the schematics we can find that LEDs are connected to PORTD. To lit all the LEDs up ,we have top make all pins to Logic 1. So we will load 11111111 in binary form to PORTD. Now the LEDS will get +5V at its anode.
.
So what we do in this program is switch on LED, provide the controller with a task of subtracting a number till 0, then switch off it and repeat the same process of subtraction till 0 with the number loaded again. Then the whole storey is repeated again. So the program is actually a never ending loop. On -Delay –OFF – Delay- Start again.
Let us see the program in detail.
//----------------------------------------------------------------------------------------
#include <xc.h> // this file contains the SFR information of the chip used
//----------------------------------------------------------------------------------------
These are ‘pre-processor ‘directives which inform the compiler about the files to be referred (“included”) for compilation of this Source code file. In the program we will be referencing many SFRs (Special Function registers) of the concerned PIC. Different PIC ICs sometimes will be having slightly different SFR names. To handle this issue Microchip is providing some files called ‘device header’ files which can be interpreted by the concerned compiler (here XC-8) to resolve the SFR names. xc.h is that header file for PIC16F877A and we are hereby directing compiler to include that file for this process.
PORTA, PORTB, TMR0 etc are arbitrary names which are basically locations within the DATA Memory of the PIC which controls a particular peripheral or task. For example PORTA is a location which holds the control of the Pins referred as PORTA. The CPU actually operates and references them only as mere numbers which are relative positions from SFR start point. But names like PORTA and TMR0 etc are provided by the Chip vendor and the compiler designer so that we can reference them using names which are more easy for us than remembering numbers. So the compiler with the help of header files isolates us from the internal position numbering of the controller for which we are writing programs. We human beings find it easy to remember names better than we do with numbers. So compiler handles them as numbers but we can reference them as names.

//Function prototypes
voidport_initialise(void);
voidinit_variables (void);
voidDelayMs(unsigned intmsCount);

These are prototype declarations which give the compiler information about the structure of functions (signature) we are defining elsewhere in this program.

    #pragma config WDTE = OFF      
    #pragma config FOSC = HS
    #pragma config PWRTE = ON
    #pragma config BOREN = ON
    #pragma config LVP = OFF
    #pragma config CPD = OFF
    #pragma config WRT = OFF
    #pragma config DEBUG = ON
    #pragma config CP = OFF
The above statements actually configure the configuration bits of the controller so that necessary conditions for the program execution are arranged. For example the PIC as a MCU is capable of operating in different frequencies- So we need to specify which oscillator option we are going to use. Also there are options to protect the code in chip, enable or disable watch dog timer, enable Low voltage programming or not, etc. All these things need to be specified to the controller while programming. They are very critical system parameters.
But when we are working in our kit with boot loader facility most of these config bits are ignored by the boot loader. As the resident boot loader code is the one which starts up the system we need to have set the system running at high speed with PLL enabled. These bits cannot be let to the user control, so the boot loader starts the system in its own config mode – gets the data from PC and after reset we can programmatically change the oscillator options to bring the controller to our needed configurations. In all our following programs we are switching over to 4 MHz internal oscillator so that we can demonstrate examples in a more convenient and lower speed.
But the above statements will be a needed while you program this hex file into your target using a device programmer. In that case the boot loader is not there in your target and all the config info will depend on you code. You may have to edit this if you are using a different crystal in your target.

//----------------------------------------------------------------------------------------
#define _XTAL_FREQ     4000000L
//----------------------------------------------------------------------------------------
Defines actually instructs compiler to substitute the first part with second part wherever found in the program. For example when the compiler intercepts a statement which includes _XTAL_FREQ is the crystal frequency  used by the system this should be defined in the code to use the delay(eg:__delay_ms()) function in the program.
 void interrupt InterruptArea(void)
{
}
This is where and how the actual interrupt functions should go. As we are not using any interrupt driven code here in this example, thee areas are kept blank but protected. They will be filled in subsequent example modules.
The actual program is in the main() function as with any C program. After the initialization code which executes only once, the control moves to the while (1) loop, which is a never ending sequence, until power interruption, Reset or hardware failure. The effects of that code execution are the results which we experience from the device.
Now the CPU is executing initialization code and will move to the never ending code. Probably the only function we encounter in this module is Delay related. To get a delay of 650 milliseconds actually we call DelayMs(650);

This DelayMS(x) is a function we have created which uses a MPLAB XC8 delay function __delay_ms(1). This __delay_msis a routine which can create a delay of 1milliSecond. __delay_ms(2); will create a delay of 2milliSecond. In our case PIC is running at 4 Mhz Clock (internal oscillator) - So each instruction takes 1 uSec. (See data sheet).So if we call __delay_ms(1);, it will consume 1000 instructions (1 milliSecond). Our DelayMS is actually making repeated calls of this MPLAB XC8 function for 1000 instructions to create mili seconds of delay.

No comments:

Post a Comment