Timer0 problem with PIC16F1716

Discussion in 'Embedded Systems and Microcontrollers' started by hunterage2000, Mar 10, 2019.

  1. hunterage2000

    Thread Starter Senior Member

    May 2, 2010
    483
    2
    Hi all

    I want to be able to create a 1ms delay using timer0 and have tried the below code.

    Code (Text):
    1. #include <stdio.h>
    2. #include <pic16f1716.h>
    3. #include <xc.h>
    4. #include <stdlib.h>
    5. #pragma config FOSC = INTOSC
    6. #pragma config WDTE = OFF      
    7. #pragma config PWRTE = OFF
    8. #pragma config CLKOUTEN = ON  
    9.  
    10. void delay();
    11.  
    12. int main(int argc, char** argv)
    13. {
    14.    PORTB = LATB = ANSELB = TRISB = 0;
    15.    OSCCONbits.SCS = 0b10;
    16.    OSCCONbits.IRCF = 0b1111;
    17.    OPTION_REGbits.PSA = 0;
    18.    OPTION_REGbits.PS = 0b100;
    19.    OPTION_REGbits.nWPUEN = 1;
    20.    OPTION_REGbits.TMR0CS = 0;
    21.    OPTION_REGbits.TMR0SE = 0;
    22.    TMR0 = 131;
    23.    INTCONbits.TMR0IE = 1;
    24.    INTCONbits.GIE = 1;
    25.    INTCONbits.PEIE = 1;
    26.  
    27.    while(1)
    28.    {
    29.        PORTB = ~PORTB;
    30.        delay();
    31.    }
    32. }
    33.  
    34. void delay()
    35. {
    36.     if(INTCONbits.TMR0IF == 1)
    37.     {
    38.         TMR0 = 132;
    39.         INTCONbits.TMR0IF = 0;
    40.     }
    41. }
    42.  

    I have used the formula I got from https://proteustutorials.blogspot.com/2018/07/pic-timer-0-programming.html :

    TMR0 = 256-(Delay * Fosc)/(Prescalar*4))

    so for a 1ms delay, the values:
    Delay = 1ms
    Fosc = 16MHz
    Prescaler = 32
    gives a TMR0 value of 131

    Looking at the oscilloscope waveform I am getting a pulse width of 2.8us.

    Can anyone tell me why this is the case, how do i fix it or has anyone got any code that gives a correct delay please?
     
  2. BobTPH

    Senior Member

    Jun 5, 2013
    1,543
    367
    Look at your delay function. What code does it execute when you call it? Does that code create a 1 ms delay?

    Bob
     
  3. hunterage2000

    Thread Starter Senior Member

    May 2, 2010
    483
    2
    Hi Bob, the delay should toggle PORTB on and off at 1ms but it shows 2.8us. I have looked at numerous code examples which are all different and none work.

    I have used a timer0 calculator to calculate the required parameters but still doesn't work.
     
  4. AlbertHall

    AAC Fanatic!

    Jun 4, 2014
    7,521
    1,820
    'delay' doesn't wait for TMR0IF to be set, it exits immediately.
     
    sagor likes this.
  5. sagor

    Member

    Mar 10, 2019
    37
    11
    Hm, using a PIC timer calculator from MikroElektronica, a 1ms timer for TMR0 for a PIC16F at 16Mhz is:

    Code (Text):
    1. //Timer0
    2. //Prescaler 1:16; TMR0 Preload = 6; Actual Interrupt Time : 1 ms
    3. //Place/Copy this part in declaration section
    4. void InitTimer0(){
    5.   OPTION_REG     = 0x83;
    6.   TMR0         = 6;
    7.   INTCON     = 0xA0;
    8. }
    9. void Interrupt(){
    10.   if (TMR0IF_bit){
    11.     TMR0IF_bit     = 0;
    12.     TMR0         = 6;
    13.     //Enter your code here
    14.   }
    15. }
    16.  
    If your pre-scaler is not set right, you may not get proper timing... Add bits as required to INTCON for other interrupts
     
    Last edited: Mar 10, 2019
  6. Ian Rogers

    Well-Known Member

    Dec 12, 2012
    594
    155
    Remember!! With XC8 yu can still use the _XTAL_FREQ = xxx and then use the delays built in :-- __delay_ms(1); for exact delays..
    On Mikroelectronica's web site you can download their timer calc software.. You can use it for all the timers not just timer0.
     
  7. AlbertHall

    AAC Fanatic!

    Jun 4, 2014
    7,521
    1,820
  8. jpanhalt

    Expert

    Jan 18, 2008
    7,078
    1,526
    I cannot comment on any errors in the C code, but one question to address is how accurate do you want the 1 ms "ticks?"

    A preset of 131 + 1:32 prescale should give 1 ms ticks, ignoring any delays or losses for housekeeping. As sagor points out, a pre-load of 6 and a pre-scale of 1:16 (i.e., OPTION_REG <2..0> = 3) will also give a 1 ms tick, ignoring housekeeping. If you can do with a 24 us error (i.e., 1.024 ms ticks) , just counting TMR0 overflows with no pre-set will also work.
     
  9. sagor

    Member

    Mar 10, 2019
    37
    11
    Correct, his delay routine exits if the flag is not set, and also exits when it just resets the timer. There is no loop waiting for TMR0IF to be set. That is, if TMR0IF = 0 then loop and wait until it is =1...
     
  10. hunterage2000

    Thread Starter Senior Member

    May 2, 2010
    483
    2
    Thank you all, I've changed the if to a while and its now 1ms.

    __delay_ms(1) is also an option I'll look at.
     
Loading...