Timer 0 in 16 Bit Mode Working Code

Discussion on projects that are created by users and posted on mikroElektronika website.
Post Reply
Author
Message
Bill Legge
Posts: 235
Joined: 28 Oct 2007 03:16
Location: West Australia

Timer 0 in 16 Bit Mode Working Code

#1 Post by Bill Legge » 30 May 2023 07:49

Nothing special but using Timer 0 in 16 bit mode you need to:
1. When writing to Timer 0 registers you MUST write to TMR0H first then TMR0L
2. When reading from the registers you must read TMR0L first then TMR0H

3. Set the timer on by T0CON = 0b10000xxx; Where xxx is the prescale value, between 1:2 and 1:256

Code: Select all

////////////////////////////////////////////////////////////////////////////////
// Project:         Timer 0 in 16 bit mode                                    //
// File:            Main.c                                                    //
// Function:        Use interrupt as a delay timer                            //
// MCU:             P18F8722 with 2 RS232 and 2 SPI/I2C peripheral            //
// Board:           BIGPIC5                                                   //
// Oscillator:      10MHz Xtal X 4 = 40MHz.  Max is 48MHz                     //
// Power            5.5V                                                      //
// Compiler:        mikroC PRO version 7.6.0                                  //
// Programmer:      Onboard                                                   //
// Author:          WVL                                                       //
// Date:            May 2023                                                  //
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// WARNING                                                                    //
// UART on RC6/Tx1 RC7/Rx1 and RG1/Tx2 RG2/Rx2                                //
// SCl1/RC3 SDA1/RC4 and SCL2/RD6 SDA2/RD5 - use I2C1 to avoid RD5 clash      //
// GLCD pins on ports J0,1,2,3,4,5 and D0 to D7 inclusive                     //
// Mikro LCD adaptor on port H2,3,4,5,6,7                                     //
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// Global variables                                                           //
bit TIMER0_FLAG;     // set in Timer 0 interrupt, cleared in delay function   //
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// Timer0 in 6 bit mode. One Tick = 4/(40MHz Xtal) = 0.1uS                    //
//          Prescale 1:2   0b000 Tick =   2*0.1 =  0.2[uS]                    //
//          Prescale 1:4   0b001 Tick =   4*0.1 =  0.4[uS]                    //
//          Prescale 1:8   0b010 Tick =   6*0.1 =  0.8[uS]                    //
//          Prescale 1:16  0b011 Tick =  16*0.1 =  1.6[uS]                    //
//          Prescale 1:32  0b100 Tick =  32*0.1 =  3.2[uS]                    //
//          Prescale 1:64  0b101 Tick =  64*0.1 =  6.4[uS]                    //
//          Prescale 1:128 0b110 Tick = 128*0.1 = 12.8[uS]                    //
//          Prescale 1:256 0b111 Tick = 256*0.1 = 25.6[uS]                    //
// Turn Timer 0 on, 16 bit mode and prescale 1:256 so each tick is 25.6[uS]   //
// Minimum delay = 25.6[uS] Max delay = 65535*25.6 = 1.677[S]                 //
void Timer0_init(){                                                           //
    T0CON  = 0b10000111;                                                      //
    TMR0H  = 0;         // MUST write TMR0H first in 16 bit mode              //
    TMR0L  = 0;         // MUST write TMR0L second in 16 bit mode             //
    TMR0IF_bit = 0;     // clear interrupt flag                               //
    TMR0IE_bit = 1;     // enable Timer 0 interrupt                           //
}                                                                             //
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// Timer 0. 16 bit mode interrupts when counter rolls from 0xFFFF to 0x0000   //
// Delay before interrupt = (0xFFFF - (TMR0H<<8 + TMR0L))*25.6[uS]            //
void Timer0_Interrupt() iv 0x0008 ics ICS_AUTO {                              //
    if(TMR0IF_bit){                                                           //
        TMR0IF_bit  = 0;    // flag off                                       //
        TMR0IE_bit  = 0;    // disable Timer 0 interrupt                      //
        TIMER0_FLAG = 1;    // flag on, cleared in Main function              //
    }                                                                         //
}                                                                             //
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// Function. Delay using Timer 0                                              //
// Timer 0. Tick = 25.6[uS]*Prescale value                                    //
char V_us_delay(unsigned int ticks){                                          //
    unsigned int count = 0xFFFF - ticks;                                      //
    TMR0H = (count&0xFF00)>>8; // MUST write TMR0H first in 16 bit mode       //
    TMR0L = count & 0x00FF;    // MUST write TMR0L second in 16 bit mode      //
    T0CON = 0b10000111;        // timer 0 on                                  //
    TIMER0_FLAG = 0;           // clear the flag, set in interrupt            //
    TMR0IP_bit = 1;            // make Timer 0 IP high                        //
    TMR0IF_bit = 0;            // clear interrupt flag                        //
    TMR0IE_bit = 1;            // enable Timer 0 interrupt                    //
}                                                                             //
////////////////////////////////////////////////////////////////////////////////

void main() {
    unsigned int   t = 10;  // ADC result
    unsigned int   x = 0;   // reusable
    // Init MCU
    INTCON2 = 0;            // PORTB pullups enabled
    ADC_Init();             // 10 bit ADC 0-1023 or 0-3FF
    // Init ports
    TRISA0_bit   = 1;       // input for  ADC
    TRISG0_bit   = 0;       // for LEDE flash
    LATG0_bit    = 0;
    delay_ms(100);
    // Set interrupts
    IPEN_bit   = 1;         // enable priority interrupt levels low and high
    GIEH_bit   = 1;         // enable all high priority interrupts
    GIEL_bit   = 1;         // enable all low  priority interrupts

    while(1){
        t = 30*ADC_Read(1);    // (0-1023)*30=30,697. Full delay 65535 = 1.575 Seconds
        V_us_delay(t);
        while(TIMER0_FLAG==0);
        LATG0_bit = ~LATG0_bit;
    }
}
10 bit ADC has a highest value of 1023 whereas the function will accept an unsigned int 0xFFFF or 65535 that gives a delay of 1.575 Seconds
Good uck. Regards Bill Legge in Australia

User avatar
filip
mikroElektronika team
Posts: 11874
Joined: 25 Jan 2008 09:56

Re: Timer 0 in 16 Bit Mode Working Code

#2 Post by filip » 07 Jun 2023 07:45

Hi,

Thanks for the tip! :)

Regards,
Filip.

Post Reply

Return to “User Projects”