728x90

728x90

Tuesday, May 26, 2020

Using timer 0 module as an external pulses counter

Timer 0 module of PIC16F887 is an 8-bit read/write register. It could work as a timer, or a counter. Using this module as a timer, we can make:
  • a timing delay
  • a frequency generator
  • or a user-defined PWM signal
In counter mode, we could use it to count external input pulses fed to pin RA4/T0CKI. The counting result automatically stores in the TMR0 register of the SFR. TMR0 is used for both timer and counter mode.

Both timer and counter mode, have an 8-bit prescaler. This prescaler divide into two group, TMR0 prescaler and WDT prescaler. TMR0 prescaler ranges from 1:2 to 1:256. While WDT prescaler ranges from 1:1 to 1:128.
Using timer 0 module a an external pulse counter
Timer 0 simplified block diagram

Timer or counter 0 overflow could set an interrupt flag in the INTCON register. This flag is set when the TMR0 register rolls from 0xFF to 0x00.

These are some registers relate to timer/counter 0:
  • OPTION_REG
  • TMR0
  • INTCON
Now let see the option register:

 BIT 7





 BIT 0
 nRBPUINTEDG T0CS T0SE PSA PS2 PS1 PS0 

This 8-bit register is high by default.

  • The timer 0 clock source bit (T0CS) uses for selection between internal CPU clock source and external clock pulse fed to pin T0CKI. When '0' the Fosc/4 clock source fed the timer/counter.
  • The timer 0 source edge select bit (T0SE) uses for select the edge of clock pulse fed to T0CKI pin. When '0' a low to high transition activate the counting.
  • The prescaler assignment bit (PSA) select between two prescaler, timer 0 prescaler and the WDT one's.
  • Prescaler rate select bit (PS[2:0]) set the rate of prescaler. These 3-bit wise selector set the prescaler from 1:1 to 1:256. 
 PS[2:0]TMR0 Prescaler WDT Prescaler 
 0001:2 1:1 
 0011:4 1:2 
 0101:8 1:4 
 0111:16 1:8 
 1001:32 1:16 
 1011:64 1:32 
 1101:128 1:64 
 1111:256 1:128 

In the example below, I use T0CKI pin to count the external pulse from an external clock source. It has an application, for example a production counter at the output line in the factory.

Using the WDT prescaler, I set the prescaler rate to 1:1. So TMR0 will increase every rising edge of the T0CKI pin.

I use a three digits display to show the counts. It is 255 maximum before rolling back to 0. We can count the amount of pulse larger than this 8-bit TMR0 by using timer 0 overflow interrupt flag with some math calculations.

Using timer 0 module as an external pulse counter
Schematic diagram. Pin RA4/T0CKI counts the external input pulses.
PC817 opto coupler indirectly contact between signal source and
pin T0CKI to avoid disturbing signal or any voltage exceed +5 V.
PortC and PortD display and control the three-digit SSD.

XC8 source code is here:

#include "xc.h"
// PIC16F887 Configuration Bit Settings
// CONFIG1
#pragma config FOSC = XT
#pragma config WDTE = OFF
#pragma config PWRTE = OFF
#pragma config MCLRE = ON
#pragma config CP = OFF
#pragma config CPD = OFF
#pragma config BOREN = ON
#pragma config IESO = ON
#pragma config FCMEN = ON
#pragma config LVP = OFF
// CONFIG2
#pragma config BOR4V = BOR40V
#pragma config WRT = OFF
/*_XTAL_FREQ use for __delay*/
#define _XTAL_FREQ 4000000
void displayCounter(void){
    unsigned char ssd[16]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,
        0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71};
    PORTD=0x00;
    PORTC=ssd[TMR0/100];
    RD0=1;
    __delay_ms(15);
    PORTD=0x00;
    PORTC=ssd[(TMR0%100)/10];
    RD1=1;
    __delay_ms(15);
    PORTD=0x00;
    PORTC=ssd[TMR0%10];
    RD2=1;
    __delay_ms(15);
}
void main(){
    //Port configuration
    PORTC=0x00;
    TRISC=0x80;
    PORTD=0x00;
    TRISD=0xF8;
    /*use rising edge transition*/
    T0SE=0;
    /*use 1:1 rate*/
    OPTION_REGbits.PS=0x00;
    TMR0=0;
    while(1){
        displayCounter();
    }
}

I took a simulation screen shot of this program.

Using timer 0 module as an external pulse counter
Simulation screen shot. The content of TMR0 is 155 in decimal.




No comments:

Post a Comment

320x50

Search This Blog

tyro-728x90