Skip to main content

Experiment No. 7: Timers and Interrupts

Background
Many microcontroller applications like generating periodic signals, measuring time interval, keeping date and time, use time as their variable. Therefore, microcontrollers need to have some internal resources to accurately measure time. The PIC16F628A has 3 timer modules which are known as Timer0, Timer1, and Timer2. The basic unit of a timer is a free-run 8-bit or 16-bit incrementing synchronous counter which can be programmed to count internal or external pulses. The count number stored by each counter can be read or modified by accessing the special function register associated with that timer. Some of the bits in these registers are also the indicators of timer overflow, which, therefore, can generate interrupt request to the microcontroller. The use of timer modules to keep record of time elapsed allows the microcontroller to carry on with its other operations like controlling outputs, reading inputs, etc.

Timers can also have another asynchronour counter, known as prescaler, which can be configured to divide the  number of pulses received by the timer register to be divided by a factor of 2, 4, 8, 16, 32, 64, 128 or 256.

1. Timer0 Module

The Timer0 module is an  8-bit timer/counter which can be configured to count machine cycles or external pulses. When counting machine cycles, it is known to operate as a timer, and when counting the external pulses, it is called to operate as a counter. The external pulses are given to RA4/T0CKI pin. The Timer0 also consists of an 8-bit prescaler which is a programmable division factor.

The operation of the timer is set up by moving a suitable control code into the OPTION register. Timer mode is selected by clearing the T0CS bit (OPTION<5>). In Timer mode, the TMR0 register value will increment every instruction cycle (without prescaler). Counter mode is selected by setting the T0CS bit. In this mode, the TMR0 register value will increment either on every rising or falling edge of pin RA4/T0CKI pin. The incrementing edge is determined by the source edge (T0SE) control bit (OPTION<4>). Clearing the
T0SE bit selects the rising edge.

Timer0 interrupt is generated when the TMR0 register timer/counter overflows from FFh to 00h. This overflow sets the T0IF bit of INTCON register. The interrupt can be masked by clearing the T0IE bit (INTCON<5>). The T0IF bit (INTCON<2>) must be cleared in software by the Timer0 module interrupt service routine before reenabling this interrupt.

The prescalar value can be set using the PSA and PS<2:0> bits of OPTION register.



2. Timer1 and Timer2
Refer to datasheet.
So in this experiment, we are going to use Timer0 to generate delay for a 4-bit up counter. Connect RB0-RB3 to the 4 LEDs on the board using jumpers.

Software:
/*
  Project Name: Use of Timer 0 and Interrupt
  * Copyright:
     (c) Rajendra Bhatt, 2009.
 * Description:
     This code is an example of using Timer 0 and Interrupt for delay.

 * Test configuration:
     MCU:             PIC16F628A
     Oscillator:      XT, 4.0 MHz
  */

  unsigned cnt, num;
  void interrupt() {   // Interrupt routine
    num ++;            // Interrupt causes Num to be incremented by 1
    if(num == 20) {
    cnt ++;           // 20 Interrupts causes cnt to be incremented by 1
    num = 0;
    }
    TMR0 = 0;        // Timer (or counter) TMR0 returns its initial value
    INTCON = 0x20;   // Bit T0IE is set, bit T0IF is cleared
  }

  void main() {
  cnt=0;
  num=0;
  OPTION_REG = 0x07; // Prescaler (1:256) is assigned to the timer TMR0
  TMR0 = 0;          // Timer T0 counts from 0 to 255
  INTCON = 0xA0;     // Enable interrupt TMR0
  TRISB = 0x00;          // set direction to be output
  PORTB = 0;         // Turn OFF LEDs on PORTB
  do {
    PORTB =cnt ;
  } while(PORTB < 0x0f);  // Till PORTB < 15
 }



Comments

  1. Hi Mr. Raj!

    I tried to do this :

    unsigned short Num;

    void interrupt(){

    if(Num == 1080) { // 1 minute
    Sound_Play(1500, 500);
    Delay_ms(500);
    count = count + 1;
    Num = 0;
    }

    TMR0 = 39; // TMR0 returns to its initial value
    INTCON = 0x20; // Bit T0IE is set, bit T0IF is cleared

    }

    void main(){

    CMCON |= 7; // Disable Comparators
    TRISB = 0x00; // Set PORTB direction to be output
    PORTB = 0xff; // Turn OFF LEDs on PORTB
    PORTA = 0x00;
    TRISA = 0x00;
    count = 0; // initialize minute to display to 7 segment display

    Num = 0;
    Num2Points = 0;
    compteur = 0;

    OPTION_REG = 0x07; // Prescaler (1:256) is assigned to the timer TMR0
    TMR0 = 39; // Timer T0 counts from 39 to 255
    INTCON = 0xA0; // Enable interrupt TMR0 and Global Interrupts
    Sound_Init(&PORTA, 5);
    segment_deux_points = 0;

    do {
    count = compteur;
    DD0 = count%10; // Extract Ones Digit
    DD0 = mask(DD0);
    DD1 = (count/10)%10; // Extract Tens Digit
    DD1 = mask(DD1);
    DD2 = (count/100)%10; // Extract Hundreds Digit
    DD2 = mask(DD2);
    DD3 = (count/1000); // Extract Thousands Digit
    DD3 = mask(DD3);

    for (i = 0; i<=50; i++) {
    PORTB = DD0;
    RA0_bit = 0; // Select Ones Digit
    RA1_bit = 1;
    RA2_bit = 1;
    RA3_bit = 1;
    delay_ms(5);
    PORTB = DD1;
    RA0_bit = 1;
    RA1_bit = 0; // Select Tens Digit
    RA2_bit = 1;
    RA3_bit = 1;
    delay_ms(5);
    PORTB = DD2;
    RA0_bit = 1;
    RA1_bit = 1;
    RA2_bit = 0; // Select Hundreds Digit
    RA3_bit = 1;
    delay_ms(5);
    PORTB = DD3;
    RA0_bit = 1;
    RA1_bit = 1;
    RA2_bit = 1;
    RA3_bit = 0; // Select Thousands Digit
    delay_ms(5);
    }
    } while(1); // endless loop
    }
    }

    Num == 1080 never occurs.. can you tell me why?

    thanks!

    ReplyDelete
  2. I'm not certain but I think it is because your are working with a 8 bit timer here. Max = 255

    ReplyDelete
  3. Sorry, missed what was going on. Num is a unsigned short 65535.

    ReplyDelete

Post a Comment

Popular posts from this blog

Contact less tachometer using PIC16F628A

Introduction Tachometer is a device that gives you the information about the rotational speed of any shaft or disc. It usually measures the speed in revolutions per minute (RPM). Today we are going to make a simple tachometer that could measure the rotation speed of a disk without making any physical contact (that's why it is contact less) with the rotating object. The range of this tachometer is 0 - 9999 RPM and displays the RPM on a multiplexed 4-digit seven-segment display. Of course, we are going to do this project on our usual PIC16F628A development board. Infrared sensor Contact-less measurement of RPM will be achieved through an IR sensor. An IR diode will send a beam of infrared towards the rotating disc, and any reflected pulse will be received by a photo diode. The resistance of a photo diode drops drastically when exposed to infrared. An infrared is reflected by a white surface and absorbed by the dark ones. The test disc for this project is shown below. You can see

Experiment No. 2 : Push Button and Seven Segment Display Interface

In this experiment, we will program the PIC16F628A as an UP/DOWN Decade Counter. The count value will be displayed on a Seven-Segment Display and will be incremented/decremented by two push buttons on the board. Experimental Setup: The board has built in interface for a multiplexed 4-digit seven segment display (HS-5461AS2 from www.futurlec.com ).We will select only one digit by connecting a Digit Select pin to Vcc, as shown in figure below. A black jumper wire is used for this purpose. The seven segments will be driven through PORTB (already wired on the board). Connect Push Buttons (PB3 and PB4) to RA1 and RA0 female headers using jumper wires.

PIC16F628A Development Board

The development board we are going to make for our experimental microcontroller PIC16F628A will look like this. Here are the features it is going to have: Access to all I/O pins through female header pins 4 Push Buttons for Input 4 LEDs for Output An LCD Interface Port A 4-digit Seven-Segment Display Interface LCD Backlight Switch and Contrast Adjustment ICSP Programming (Very Important)