Wednesday, September 4, 2013

Using PIC18 Timer Module for delay – C Code with Proteus Simulation

title_image
In our LED Blinking tutorial we used the PIC18 library function for delay which doesn’t use timer for delay. The built-in function we used for delay just insert’s NOP instruction to obtain the required delay. Today we will use the PIC18’s Timer Module to obtain the delay for  LED Blinking Example.

Introduction to PIC18 Timers

The number of timers a PIC18 has depends on its family. They ranges from 2 to 5 in PIC18. PIC18 Timers can be used as timers to generate delays or as counters. In the counter mode it is used to count events which occur outside of the Microcontroller. PIC18 Timers are referred by the names Timer0, Timer1, Timer3, and so on. In our Example Program we will be using Timer0 in timer mode to obtain the required delay. Timer can be 8-bit, 16-bit or even 32-bit on some newest PICs. In the PIC18F8722 Timer0 can be used in 8-bit or 16-bit mode selectable via software. In the 8-bit mode the timer increments an 8-bit register on each clock cycle and ranges from 0 – 255 while in 16-bit mode the range is 0 – 65535.

Timer Clock Source

A Timer or any other Microcontroller peripheral requires clock source for its operation referred to as the Peripheral Clock. The clock can be internal or external. In the internal clock mode Timer0 operates as timer and uses the internal(FCPU) clock with or without pre-scalar. Pre-Scalar is an integer value which divides the CPU clock to give Timer Clock i.e Timer Clock = FCPU/pre-scalar.  When the Pre-scalar is set to one or bypassed then the timer runs on the same clock as the CPU is running. In the external clock mode Timer0 operates as counter and counts on every rising or falling edge of the clock connected to the Timer's clock pin. In this example we will be using Timer0 with the internal clock(timer mode) configuration and pre-scalar bypassed or 1. T0CON – Timer0 Control Register is used to control all these settings, details can be found in the Timer0 Module section of the datasheet.

Difference Between FOSC and FCPU

Oscillator Frequency (FOSC) is the frequency of the crystal we have connected to the PIC. in our case we are using 20MHz crystal so FOSC = 20MHz. The PIC internally divides FOSC by 4 to get FCPU. Based on this we have clock cycle and instruction cycle. the clock cycle is simply 1/FOSC while instruction cycle is 1/FCPU. An instruction cycle is the time required for the PIC to execute a single assembly language instruction( excluding jump and loop instructions which requires more than on instruction cycles).

Delay Calculation

After initializing Timer0 in 8-bit mode with internal clock by setting the relevant bits in T0CON Register we turn on the Timer. As the Timer is turned on it increments the TMR0 register every clock cycle starting from 0. What happens when it reaches 255? glad you asked. PIC18 has the ability to generate interrupt on overflow – meaning that a  bit called Timer0 Interrupt Flag(TMR0IF) which is set when TMR0 makes  transition from 255 to 0. We can check TMR0IF either by polling or using Interrupt Service Routine(ISR). In this example we will used polling method and will cover Interrupts in another post. 
Assuming the PIC is operating with FOSC = 20MHz or FCPU = 5MHz, a single overflow of Timer0 will give us 256 * 1/5MHz = 51.2usec delay. So if we need delay more than 51.2usec we maintain a counter and increment it each time Timer0 overflows.
For a delay of 1sec
1sec = 10^6usec the timer overflows after 51.2usec So number of TImer0 overflows required to get a 1sec delay can be calculated as 10^6/51.2 = 19531.25 rounded to 19531 will give approximately 1sec delay.
So after starting Timer0 we poll for TMR0IF if set a variable called counter is incremented. The counter value is compared to 19531 if equal it means approximately 1sec is elapsed and an LED toggles to indicate this.

C Code

Below is the C code for this example with comments, copy it and generate the hex file for Proteus simulation.
/* 

   ################################################################################ 

   **** PIC18 Timer Example

   **** IDE      : MPLAB Ver 8.91

   **** Compiler : Microchip C18 Ver 3.43

   ################################################################################

*/

 

// Includes

#include <p18cxxx.h>

#include <delays.h>

 

// Configurations

#pragma config WDT = OFF                // Watchdog Timer Disabled

#pragma config OSC = HS                // OSC Mode - High Speed Crystal/Resonator

#pragma config XINST = OFF            // Extended Instructions Disabled

 

// LEDs

#define LED1    LATCbits.LATC0

 

// main

void main(void)

{   

    unsigned int counter = 0;    // variable that holds timer overflow count

 

    // Initialize Timer0

    // T0CON bits

    //   7    |   6    |   5  |   4   |  3  |   2   |   1   |   0 

    // TMR0ON | T08BIT | T0CS |  T0SE | PSA | T0PS2 | T0PS1 | T0PS0

    // See datasheet for details

    // 8-bit timer mode 

    // internal clock, pre-scaler = 1

    // TMR0ON = 0 at this point we don't start the timer

    T0CON = 0b01001000;

 

    TRISCbits.TRISC0 = 0;     // Set as output for LED

 

    // infinite loop    

    while(1)

    {

        T0CONbits.TMR0ON = 1;           // Start Timer

        while(!INTCONbits.TMR0IF)      // wait until Timer0 overflows - polling

            INTCONbits.TMR0IF = 0;    // clear interrupt flag

        if(counter != 19531)

            counter++;

        else

        {

            counter = 0;              // reset counter

            LED1 = ~LED1;            // toggle LED

            T0CONbits.TMR0ON = 0;   // Stop Timer0      

        }

    }

}

unsigned int counter = 0;    // variable that holds timer overflow count

this line of code declares the counter as unsigned int which ranges from 0 – 65535. So if you want delay other than 19531(calculated for 1sec) and greater than 65535 then you may declare the counter as unsigned long int instead.

Simulation

Here is the gif animation of the Proteus simulation

Timer_Ex_animation

Conclusion


In this post we used PIC18F8722’s Timer0 in 8-bit timer mode to obtain a delay of approximately 1sec. Besides this the timer can also be used to find the execution time of a function – for example. In which case we have to use Timer Interrupt to take care of the timer overflow. In the beginning of the function Timer is started and after the function finishes it is stopped. To calculate the time we use our counter variable value as well as TMR0 value as
time taken = (counter * 0.0000512) + (TMR0 * 1/5MHz) sec or more generally

time taken = ((counter * 256) + TMR0) *  1/FCPU in seconds.

Please comment you questions and suggestions and subscribe for updates.
Read More

Monday, September 2, 2013

Acquiring Button Inputs in PIC18 using C with Proteus Simulation

ButtonAnimation In this Tutorial we will demonstrate how  to acquire User Push Button Input  connected to one of the PIC18 digital  IO. As the user pushes the Button an  LED connected to a different IO will  glow as long as the button is kept      pressed.

 

 

 


A Little About Port Registers

There are three Registers associated with each Port of PIC18, LATx, PORTx, and TRISx. where ‘x’ represents A,B,C depending upon the number of Ports in a specific device. The TRISx register is used for setting a Port pin either input or output by writing a binary 1 or 0 respectively. The PORTx register is used to read the state of a Port pin,  and writing to it will write to the Port latch. The LATx register is the output latch register and it keeps the latched output value for PORTx.
For reading an input port pin we use PORTx register as it gives the current status of the port pin. For writing or reading the state of an output pin either LATx or PORTx is used. Both LATx and PORTx are read/write registers.

C Code for the Project

Below as an example code of the project in C which needs to be compiled using Microchip C18 Compiler and the MPLAB IDE environment. The code is almost the same as the previous tutorial with a little difference.  In the previous tutorial we used two pins as digital outputs, here one pin is used as digital input-to which the user button is connected, and the other is used as digital output and an LED is connected to it.
The input pin is polled in the main loop for button state, if the button is pressed the LED connected to another pin turns on as long as the the button is kept pressed. This is demonstrated with the Proteus simulation.
Copy the code below and compile it to generate .hex file.
/* 
   ################################################################################ 
   **** PIC18 Button Input Example
   **** IDE      : MPLAB Ver 8.91
   **** Compiler : Microchip C18 Ver 3.43
   ################################################################################
*/
 
// Includes
#include <p18cxxx.h>
#include <delays.h>
 
// Configurations
#pragma config WDT = OFF            // Watchdog Timer Disabled
#pragma config OSC = HS                // OSC Mode - High Speed Crystal/Resonator
#pragma config XINST = OFF            // Extended Instructions Disabled

// LED
#define LED1    LATDbits.LATD0
// Button
#define BUTTON1 PORTCbits.RC0

// main
void main(void)
{   
    // As the LED1 pin is also an analog input pin we have to declare it as
    // digital by writing the port configuration control bits(PCFG<3:0>) in 
    // ADCON1 Register - Refer to the datasheet for more details
       ADCON1 = 0x00001111;    
 
    // Set PORTD bit 0 as digital output, LED1 is connected on this pin
    TRISDbits.TRISD0 = 0;

    TRISCbits.TRISC0 = 1;     // Set the Button Pin as input

    // infinite loop    
    while(1)
    {
        if(BUTTON1 == 0)    // Poll for Button Press    
            LED1 = 1;    // Turn ON LED
        else
            LED1 = 0;    // Turn OFF LED
    }
}

Proteus Simulation

The Proteus circuit is also not so much different from the previous tutorial. the only change is one LED is replaced with a button.

circuit

After adding the hex file to the Proteus project click the play button to run the simulation, while the simulation is running push the button and the LED will glow release it and it will turn off.

This is a simple tutorial demonstrating the use of a push button with PIC18 for beginners hope you learn something from it.
Please comment for feedback.
Read More

Popular Posts

Followers

Like Us

Follow me on Twitter