• AVR Freaks

Hot!8bit: Timer 2 PIC16F18857

Author
plutonium
New Member
  • Total Posts : 5
  • Reward points : 0
  • Joined: 2019/10/02 02:48:42
  • Location: 0
  • Status: offline
2019/10/02 08:37:08 (permalink)
0

8bit: Timer 2 PIC16F18857

Hello!
I’m sorry to trouble you in this forum. I’m a beginner in microcontrollers. I have a compulsory homework. I have done my first task and a second partially by the instructions given by the teacher.
I have an MPLAB X IDE software with XC8 Compiler. X2C development board and a 8 bit PIC16F18857.
I successful done tasks step by step until the „Timer” section. I have loaded the example project which was provided by the teacher.

You are experts and going to understand the task. That’s why I would like to ask you to help me (not only pass this task) but understand too. After a week I'm totally desperate, I don’t understand the function of Timer 2, and after some experience and programming I don’t really know what to expect as a result of successful and correct program. How to be sure that the values are good or not.  
Task: Set the Timer 2 exactly to 200ms! In order to do this choose the 31kHz nominal signal source LFINTOSC. Solve the problem without using MCC. In the main.c there are //TODO comments, you should fill them with the appropriate values.
Calculate and set the following registers:
  • Timer 2 clock source (T2CLKCON):
  • Prescaler (T2CON):
  • Postscaler (T2CON):
  • Period Register (T2PR):
After setting up Timer 2, test the code on X2C device. In the sample program, in the main cycle there is a principle error. Search and correct it!
Answer how did you calculate the prescaler, period register and postscaler!
What kind of error did you experience?
The sample project provided by the teacher,
main.c:
#include <xc.h>
void main(void) {
/*************************************
*          CONFIG
*************************************/
/* OSC config*/
// NOSC HFINTOSC; NDIV 1;
OSCCON1 = 0x60;
// HFFRQ 4_MHz;
OSCFRQ = 0x02;
/* IO config */
//Reset IOs
LATA = 0x00;   
LATB = 0x00;   
LATC = 0x00;   
// Set LEDs to output
TRISC = 0x0F;
// Disable ANALOG func. on LEDs and Buttons
ANSELC = 0x0F;
ANSELA = 0x3F;
/* Timer2 Config*/
T2CON = ; // TODO Calculate Postscaler and Prescaler
T2PR = ;// TODO calculate period register
T2CLKCON = ;// TODO select clock source

T2TMR = 0x00;// Reset Timer 2;
PIR4bits.TMR2IF = 0;// Clearing IF flag.
T2CONbits.T2ON = 1;// Start timer
PIE4bits.TMR2IE = 1;// Enable Timer 2 int
INTCONbits.PEIE = 1; // Enable Peripheral int
INTCONbits.GIE = 0; // Enable Global interrupt
/*************************************
*          Main program
*************************************/
while(1){
if(PIR4bits.TMR2IF){// Timer overflow detected!
LATCbits.LATC4 = ~LATCbits.LATC4 ;  // invert LED1 
}
}
return;
}

 
One question regards to an unknown error.
For me suspicious this : PIR4bits.TMR2IF = 0;// Clearing IF flag.
By documentation of PIC16F18857 I found that zero means "No TMR2 events has occured"
When I changed to 1 the LED lighted.
Thank you for your help in advance!
#1

17 Replies Related Threads

    teenix
    Starting Member
    • Total Posts : 25
    • Reward points : 0
    • Joined: 2017/12/21 13:47:21
    • Location: Australia, Melbourne
    • Status: offline
    Re: 8bit: Timer 2 PIC16F18857 2019/10/04 19:06:46 (permalink)
    +2 (2)
    Hi,
     
    If you consider how TMR2 works, it will increment on every input cycle if the pre and post scalers are set to 1:1.
     
    Therefor with a 31KHz input it will increment TMR2 output every 32.26uS (1/31000)
     
    If you change the prescaler to 1:2, it will increment TMR2 every 2 cycles (64.52uS)
    If you change the postscaler to 1:2, it will increment TMR2 every 2 cycles (64.52uS)
    If you change the prescaler and postscaler to 1:2, it will increment TMR2 every 4 cycles (129.04uS)
     
    When the TMR2 register = the PR2 register, the TMR2 register will reset to 0 and the TMR2IF flag will be SET (= 1) and you can test for this event in your code.
     
    0x80 = 128 decimal.
    So if the PR2 register = 0x80, Pre/post scale = 1:1, then after 128 input cycles, the TMR2IF flag will be set.
     
    In your project, you need to set this flag every 200mS. This is 200,000uS / 32.26uS = 6200 input cycles for TMR2 to "see" before setting the flag.
     
    This is way higher than the 8 bit TMR2 can count to 0x00 - 0xFF or 0 - 255, so your task is to work out what pre/post scale value and PR2 value will set the flag after TMR2 sees 6200 counts.
     
    For example, if prescaler is set to 1:16, and PR2 is set to 0x80, TMR2 will increment after every 16 input cycles.
    By the time TMR2 = PR2, (16 x 128 cycles),  2048 cycles would have occurred = 66.068mS. Still too short
     
    Set post scaler to 1:4. Now 16 x 4 x 128 cycles need to be input = 8192 cycles = 264.273mS. Now too long.
     
    But if you reduce the PR2 value, you may get close to 200mS. If not, try to re-adjust the pre/post scaler. There would be a mathematical way to figure this out, or you can use trial and error with the simulator and the Stopwatch. Set a break point set at the code line where the TMR2IF flag is set. Each time you run the simulation, you will see how long it took.
     
    Don't forget to reset the TMR2IF flag to 0 :-)
     
    Hope this helps you find your way.
     
    cheers
     
    Tony
     
    #2
    dan1138
    Super Member
    • Total Posts : 3262
    • Reward points : 0
    • Joined: 2007/02/21 23:04:16
    • Location: 0
    • Status: offline
    Re: 8bit: Timer 2 PIC16F18857 2019/10/04 22:09:33 (permalink)
    +2 (2)
    I think you have an awful teacher.

    This may be the code you need:
    #include <xc.h>
    void main(void) {
        /*************************************
        *          CONFIG
        *************************************/
        /* OSC config*/
        // NOSC HFINTOSC; NDIV 1;
        OSCCON1 = 0x60;
        // HFFRQ 4_MHz;
        OSCFRQ = 0x02;
        /* IO config */
        //Reset IOs
        LATA = 0x00;   
        LATB = 0x00;   
        LATC = 0x00;   
        // Set LEDs to output
        TRISC = 0x0F;
        // Disable ANALOG func. on LEDs and Buttons
        ANSELC = 0x0F;
        ANSELA = 0x3F;
        /* Timer2 Config*/
        T2CON = 0b00110100;     // TODO Calculate Postscaler 1:5 and Prescaler 1:8
        T2PR = 154;             // TODO calculate period register 155, 5*155*8 = 31000 / 5 = 6200
        T2CLKCON = 0b0100;      // TODO select clock source, LFINTOSC
        T2HLT = 0x00;           // Software gate mode
        T2TMR = 0x00;           // Reset Timer 2;
        PIR4bits.TMR2IF = 0;    // Clearing IF flag.
        T2CONbits.T2ON = 1;     // Start timer
        PIE4bits.TMR2IE = 1;    // Enable Timer 2 int
        INTCONbits.PEIE = 1;    // Enable Peripheral int
        INTCONbits.GIE = 0;     // Enable Global interrupt
        /*************************************
        *          Main program
        *************************************/
        while(1){
            if(PIR4bits.TMR2IF){                    // Timer overflow detected!
                PIR4bits.TMR2IF = 0;                // Clearing IF flag.
                LATCbits.LATC4 = ~LATCbits.LATC4 ;  // invert LED1
            }
        }
        return;
    }

     
    <EDIT>
     
    WARNING:
    The MPLABX simulator does not simulate the TIMER2 behavior correctly when the clock source is not FOSC/4.
     
    Microchip has been aware of this for at least the past two releases of MPLABX but has not done anything to fix it.
    post edited by dan1138 - 2019/10/04 22:27:38
    #3
    dan1138
    Super Member
    • Total Posts : 3262
    • Reward points : 0
    • Joined: 2007/02/21 23:04:16
    • Location: 0
    • Status: offline
    Re: 8bit: Timer 2 PIC16F18857 2019/10/05 19:08:10 (permalink)
    +2 (2)
    plutonium
    You are experts and going to understand the task. That’s why I would like to ask you to help me (not only pass this task) but understand too. After a week I'm totally desperate, I don’t understand the function of Timer 2, and after some experience and programming I don’t really know what to expect as a result of successful and correct program. How to be sure that the values are good or not.

    It is understandable that you are frustrated with how the TIMER2 function block works.
     
    So this is the task you are required to complete:
    plutonium
    Task: Set the Timer 2 exactly to 200ms! In order to do this choose the 31kHz nominal signal source LFINTOSC. Solve the problem without using MCC. In the main.c there are //TODO comments, you should fill them with the appropriate values.
    Calculate and set the following registers:
    • Timer 2 clock source (T2CLKCON):
    • Prescaler (T2CON):
    • Postscaler (T2CON):
    • Period Register (T2PR):

    This is how an expert might write this code:
    /*
     * File:   main.c
     * Author: dan1138
     * Target: PIC16F18857
     * Compiler: XC8 v2.05
     * IDE: MPLABX v5.25
     *
     * Created on October 5, 2019, 4:01 PM
     *
     *                              PIC16F18857
     *                        +---------:_:---------+
     *                 RE3 -> :  1 MCLRn     PGD 28 : <> RB7
     *   TOUCH SENSOR  RA0 <> :  2           PGC 27 : <> RB6
     *        10K POT  RA1 <> :  3               26 : <> RB5
     *                 RA2 <> :  4               25 : <> RB4
     *                 RA3 <> :  5               24 : <> RB3
     *                 RA4 <> :  6               23 : <> RB2
     *                 RA5 <> :  7               22 : <> RB1
     *                 VSS -> :  8               21 : <> RB0
     *             S1  RA7 <> :  9 OSC1          20 : <- VDD
     *             S2  RA6 <> : 10 OSC2          19 : <- VSS
     *         MCP_RX  RC0 <> : 11 SOSCO         18 : <> RC7  LED4
     *         MCP_TX  RC1 <> : 12 SOSCI         17 : <> RC6  LED3
     *                 RC2 <> : 13               16 : <> RC5  LED2
     *                 RC3 <> : 14               15 : <> RC4  LED1
     *                        +---------------------+
     *                                DIP-28
     *
     * Description:
     *
     * Target hardware is the X2C development board.
     * See link: http://x2c.microstickplus.com/home/doc
     *
     * This code sets TIMER2 to assert an interrupt request every 6200 input clocks.
     * The TIMER2 clock source is the 31KHz internal low frequency oscillator (LFINTOSC).
     * The data sheet does not have a precise characterization of the LFINTOSC. The
     * typical frequency is 31KHz but this varies from about 29.1KHz to 34.2KHz depending
     * on ambient temperature and VDD voltage.
     *
     * Note: The LFINTOSC clocks source is a poor choice for critical time measurements.
     *
     */
    #pragma config FEXTOSC = OFF      /* External Oscillator mode selection bits (Oscillator not enabled) */
    #pragma config RSTOSC = HFINT32   /* Power-up default value for COSC bits (HFINTOSC with OSCFRQ= 32 MHz and CDIV = 1:1) */
    #pragma config CLKOUTEN = OFF     /* Clock Out Enable bit (CLKOUT function is disabled; i/o or oscillator function on OSC2) */
    #pragma config CSWEN = OFF        /* Clock Switch Enable bit (The NOSC and NDIV bits cannot be changed by user software) */
    #pragma config FCMEN = OFF        /* Fail-Safe Clock Monitor Enable bit (FSCM timer disabled) */
    #pragma config MCLRE = ON         /* Master Clear Enable bit (MCLR pin is Master Clear function) */
    #pragma config PWRTE = OFF        /* Power-up Timer Enable bit (PWRT disabled) */
    #pragma config LPBOREN = OFF      /* Low-Power BOR enable bit (ULPBOR disabled) */
    #pragma config BOREN = OFF        /* Brown-out reset enable bits (Brown-out reset disabled) */
    #pragma config BORV = LO          /* Brown-out Reset Voltage Selection (Brown-out Reset Voltage (VBOR) set to 1.9V on LF, and 2.45V on F Devices) */
    #pragma config ZCD = OFF          /* Zero-cross detect disable (Zero-cross detect circuit is disabled at POR.) */
    #pragma config PPS1WAY = OFF      /* Peripheral Pin Select one-way control (The PPSLOCK bit can be set and cleared repeatedly by software) */
    #pragma config STVREN = ON        /* Stack Overflow/Underflow Reset Enable bit (Stack Overflow or Underflow will cause a reset) */
    #pragma config WDTCPS = WDTCPS_31 /* WDT Period Select bits (Divider ratio 1:65536; software control of WDTPS) */
    #pragma config WDTE = SWDTEN      /* WDT operating mode (WDT enabled/disabled by SWDTEN bit in WDTCON0) */
    #pragma config WDTCWS = WDTCWS_7  /* WDT Window Select bits (window always open (100%); software control; keyed access not required) */
    #pragma config WDTCCS = SC        /* WDT input clock selector (Software Control) */
    #pragma config WRT = OFF          /* UserNVM self-write protection bits (Write protection off) */
    #pragma config SCANE = available  /* Scanner Enable bit (Scanner module is available for use) */
    #pragma config LVP = ON           /* Low Voltage Programming Enable bit (Low Voltage programming enabled. MCLR/Vpp pin function is MCLR.) */
    #pragma config CP = OFF           /* UserNVM Program memory code protection bit (Program Memory code protection disabled) */
    #pragma config CPD = OFF          /* DataNVM code protection bit (Data EEPROM code protection disabled) */
    /*
     * Target specific header file
     */
    #include <xc.h>
    /*
     * Global constant definitions
     */
    #define _XTAL_FREQ (32000000UL)
    /*
     * Initialize this PIC
     */
    void PIC_Init(void) {
        INTCON = 0;     /* Disable all interrupt sources */
        PIE0 = 0;
        PIE1 = 0;
        PIE2 = 0;
        PIE3 = 0;
        PIE4 = 0;
        PIE5 = 0;
        PIE6 = 0;
        PIE7 = 0;
        PIE8 = 0;

        ANSELA = 0xFF;  /* Enable all analog inputs */
        ANSELB = 0xFF;
        ANSELC = 0xFF;

        TRISA  = 0xFF;  /* Make all GPIOs inputs */
        TRISB  = 0xFF;
        TRISC  = 0xFF;
    }
    /*
     * Initialize X2C development board I/O
     */
    void X2C_Init(void) {

        ANSELC &= 0x0F; /* Make PORTC RC7-RC4 digital I/O */
        LATC   &= 0x0F; /* Make PORTC RC7-RC4 outputs zero */
        TRISC  &= 0x0F; /* Enable PORTC RC7-RC4 outputs */
    }
    /*
     * Initialize TIMER2 to assert interrupt every 200ms (5 Hz)
     *
     * Use the LSINTOSC (31KHz) clock source and initialize TIMER2
     * to count 6200 input clocks then assert an interrupt request.
     *
     * The value 6200 was select to yield a 5Hz rate from a 31KHz clock.
     *
     * TIMER2 is an 8-bit counter with a restart on match feature. To
     * get it to divide the input clock by 6200 requires using the input
     * prescaler and output postscaler.
     *
     * The TIMER2 prescaler can divide the input clock source
     * by 1,2,4,8,16,32,64 or 128, the postscaler can divide
     * the output be 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 or 16.
     *
     * The value 6200 is 31 * 2 * 2 * 2 * 5 * 5 so the prescaler is
     * set for 1:8, the postscaler is set for 1:5. The TIMER2 period
     * match resister (PR2) is set to 154 (31*5-1).
     */
    void TIMER2_Init(void) {
        T2CON = 0b00110100;         /* Postscaler 1:5 and Prescaler 1:8 */
        T2PR = 154;                 /* TIMER2 divides input clock by 155 */
        T2CLKCON = 0b0100;          /* TIMER2 clock source LFINTOSC */
        T2HLT = 0x00;               /* Software gate mode */
        T2TMR = 0x00;               /* Reset TIMER2 count to zero */
        PIR4bits.TMR2IF = 0;        /* Clear interrupt request */
        T2CONbits.T2ON = 1;         /* Start TIMER2  */
        PIE4bits.TMR2IE = 1;        /* Enable TIMER2 interrupt */
        INTCONbits.PEIE = 1;        /* Enable Peripheral interrupt */
    }
    /*
     * Interrupt handler
     */
    void __interrupt() ISR_Handler(void) {
        if (PIE4bits.TMR2IE && PIR4bits.TMR2IF)
        {
            PIR4bits.TMR2IF  = 0;   /* Clear TIMER2 interrupt request */
            LATCbits.LATC4  ^= 1;   /* Toggle LED4 */
        }
    }
    /*
     * Main application
     */
    void main(void) {
        PIC_Init();
        X2C_Init();
        TIMER2_Init();
        INTCONbits.GIE = 1;         /* Enable system interrupts */
        /*
         * Application loop
         */
        for(;;)
        {

        }
    }

     
    plutonium
    After setting up Timer 2, test the code on X2C device. In the sample program, in the main cycle there is a principle error.
     
    Search and correct it!

    This seems like a real cheap shot.
     
    The error is that the TIMER2 interrupt request flag in PIR4 needs to be cleared before the TIMER2 can use it to signal the end of a 200 millisecond interval.
    plutonium
    Answer how did you calculate the prescaler, period register and postscaler!

    A lot of people just hack away at the TIMER2 settings until they find values that seem to work.
     
    The experts describe the problem in clear and simple terms then use logic and arithmetic to calculate the values.
    plutonium
    What kind of error did you experience?

    Why do teachers ask ambiguous questions?
     
    One valid answer is: Hey! I found the bug you put in your code on purpose.
     
    Another answer is: The LFINTOSC clock source is not really 31KHz but it is kind of close. It is OK to have a 200 millisecond flashing interval that is only as precise as the LFINTOSC clock source? If not why not because this is what the task instructions imply.
     
    It seems to me that your teacher could do some actual teaching by getting the students to be able to read and comprehend how controller data sheets describe how the controllers function blocks work.
    #4
    plutonium
    New Member
    • Total Posts : 5
    • Reward points : 0
    • Joined: 2019/10/02 02:48:42
    • Location: 0
    • Status: offline
    Re: 8bit: Timer 2 PIC16F18857 2019/10/06 00:33:37 (permalink)
    0
    Thank you very much for all answers!

    It was a big help!
    The program works on the development board.
    Based on your answers I thought, that I want to see a blinking LED in every 5 sec. (It is easier to test and make sure, than 200 ms :) ) So the 5 sec also worked, and consistently the 200 ms too.
    Yesterday afternoon, when I tested, I also had a question.
    I know, that the T2CLKCON is LFINTOSC. But I cheated with MCC to get to know it in binary.
    But in reality, without the MCC, I can't figure out neither in binary nor in hex.
    In other .c files there is no clue.
    See below:
     
    // CONFIG1
    #pragma config FEXTOSC = OFF    // External Oscillator mode selection bits->Oscillator not enabled
    #pragma config RSTOSC = HFINT1    // Power-up default value for COSC bits->HFINTOSC (1MHz)
    #pragma config CLKOUTEN = OFF    // Clock Out Enable bit->CLKOUT function is disabled; i/o or oscillator function on OSC2
    #pragma config CSWEN = ON    // Clock Switch Enable bit->Writing to NOSC and NDIV is allowed
    #pragma config FCMEN = ON    // Fail-Safe Clock Monitor Enable bit->FSCM timer enabled

    // CONFIG2
    #pragma config MCLRE = ON    // Master Clear Enable bit->MCLR pin is Master Clear function
    #pragma config PWRTE = OFF    // Power-up Timer Enable bit->PWRT disabled
    #pragma config LPBOREN = OFF    // Low-Power BOR enable bit->ULPBOR disabled
    #pragma config BOREN = ON    // Brown-out reset enable bits->Brown-out Reset Enabled, SBOREN bit is ignored
    #pragma config BORV = LO    // Brown-out Reset Voltage Selection->Brown-out Reset Voltage (VBOR) set to 1.9V on LF, and 2.45V on F Devices
    #pragma config ZCD = OFF    // Zero-cross detect disable->Zero-cross detect circuit is disabled at POR.
    #pragma config PPS1WAY = ON    // Peripheral Pin Select one-way control->The PPSLOCK bit can be cleared and set only once in software
    #pragma config STVREN = ON    // Stack Overflow/Underflow Reset Enable bit->Stack Overflow or Underflow will cause a reset

    // CONFIG3
    #pragma config WDTCPS = WDTCPS_31    // WDT Period Select bits->Divider ratio 1:65536; software control of WDTPS
    #pragma config WDTE = OFF    // WDT operating mode->WDT Disabled, SWDTEN is ignored
    #pragma config WDTCWS = WDTCWS_7    // WDT Window Select bits->window always open (100%); software control; keyed access not required
    #pragma config WDTCCS = SC    // WDT input clock selector->Software Control

    // CONFIG4
    #pragma config WRT = OFF    // UserNVM self-write protection bits->Write protection off
    #pragma config SCANE = available    // Scanner Enable bit->Scanner module is available for use
    #pragma config LVP = ON    // Low Voltage Programming Enable bit->Low Voltage programming enabled. MCLR/Vpp pin function is MCLR.

    // CONFIG5
    #pragma config CP = OFF    // UserNVM Program memory code protection bit->Program Memory code protection disabled
    #pragma config CPD = OFF    // DataNVM code protection bit->Data EEPROM code protection disabled
     
    Tha main.c starts with the following:
     
    #include <xc.h>
    void main(void) {
        /*************************************
         *          CONFIG
         *************************************/
        /* OSC config*/
        // NOSC HFINTOSC; NDIV 1;
        OSCCON1 = 0x60;
        // HFFRQ 4_MHz;
        OSCFRQ = 0x02;
     
    It configs 4 MHz HFINTOSC oscillator instead of 31kHz LFINTOSC. Why?
    #5
    ric
    Super Member
    • Total Posts : 24278
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: 8bit: Timer 2 PIC16F18857 2019/10/06 00:48:00 (permalink)
    +2 (2)
    plutonium
    ...
    Yesterday afternoon, when I tested, I also had a question.
    I know, that the T2CLKCON is LFINTOSC. But I cheated with MCC to get to know it in binary.
    But in reality, without the MCC, I can't figure out neither in binary nor in hex.
    In other .c files there is no clue.

    The clue, as always, will be in the PIC datasheet.
    That will be one of the primary aims of this course, to prompt you to find information in datasheets.
    The T2CLKCON register will be fully documented in there.
     

       /* OSC config*/
       // NOSC HFINTOSC; NDIV 1;
       OSCCON1 = 0x60;
       // HFFRQ 4_MHz;
       OSCFRQ = 0x02;
     
    It configs 4 MHz HFINTOSC oscillator instead of 31kHz LFINTOSC. Why?

    Explain why you think writing 0x60 to OSCCON1 and 0x02 to OSCFRQ will give you "31kHz LFINTOSC".
    You already have comments there stating it will select 4MHz

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #6
    Ian.M
    Super Member
    • Total Posts : 13267
    • Reward points : 0
    • Joined: 2009/07/23 07:02:40
    • Location: UK
    • Status: offline
    Re: 8bit: Timer 2 PIC16F18857 2019/10/06 01:44:14 (permalink)
    +4 (4)
    +1 for reading the datasheet.  Everything you need to know (other than the basics of 8 bit PIC coding with XC8) to solve this effectively is in datasheet section 29.0 TIMER2/4/6 MODULE (whole chapter), TABLE 37-8: INTERNAL OSCILLATOR PARAMETERS, and graphs linked from its notes,  FIGURE 6-1: SIMPLIFIED PIC® MCU CLOCK SOURCE BLOCK DIAGRAM, and 6.5 Register Definitions: Oscillator Control .
     
    I'm going to attempt to bring some formalism to choosing the optimum pre and post scaler division ratios, once one has calculated the required number of cycles of the source clock for the desired period:
     
    6300 factorises to 7 x 52 x 32 x 22.
     
    The prescaler can only handle powers of two, so use it for the 22.
    The postscaler can divide by anything up to 16.  The main 8 bit timer can divide by anything from 2 to 256.
    There are two cycle exact ways of allocating the remaining factors: 
    7 to the postscaler, and 52 x 32 (=225) to the timer,
    5 x 3 (=15) to the postscaler, and 7 x 5 x 3 (=105) to the timer.
     
    Either will set the TMR2IF once, exactly every 6300 input clock cycles.  However, as Dan has noted, the LFINTOSC is notoriously inaccurate.   See datasheet: FIGURE 38-8: LFINTOSC Frequency, PIC16F18857/77 Only.  Provided Vdd is above 3.6V, you've got a 99.7% probability* its frequency is between 29.0 KHz and 33.6 KHz (approx, estimated from graph).   The lower limit would give you a period that's about 8.6% too long and the upper, about 6.3% too short.  :(
     
    IMHO the instruction to use LFINTOSC is bad.  MFINTOSC/16 is available as a Timer 2 clock source, and that is derived from HFINTOSC so has worst case +/-2% error over the temperature range 0 - 60 deg C, provided Vdd is above 2.3V  (Datasheet: FIGURE 37-6: PRECISION CALIBRATED HFINTOSC FREQUENCY ACCURACY OVER DEVICE VDD AND TEMPERATURE).  
     
    For MFINTOSC/16 at its nominal frequency of  31.25 KHz, we need 6250 counts for a period of 200 ms.
    6250 factorises to 55 x 2.   Unfortunately the Timer 2 divider chain cant handle that exactly - there's too high a power of five.  The main timer can handle 53, and the postscaler another 5, which only gets us to 54. Therefore  one needs to try inexact division ratios that have more favourable factors.   Ideally, we'd divide 6250 by 25 in the pre and postscalers, leaving the remaining 250 to the timer.  However the only combined pre and post scaler division ratios we can get are even numbers in the range 26 to 32, or every fourth integer from 32 to 64, or every 8th from 64 to 128 etc..  A few minutes with Excel checking the percentage error for each possible divisor once the main timer component has been rounded to an integer finds that 44 (11 x 22) in the pre and post scalers and 142 in the main timer, for a total count of 6248 only has -0.032% error, negligible compared to the inherent +/-2% accuracy of the MFINTOSC/16 source (0-60 deg C Vdd>=2.3V).  
     
    That gives you a nominal 200ms period that's more than three times more accurate than that derived from LFINTOSC. :)
     
    N.B. Don't forget that Timer 2 rolls over to 0 on the next prescaler output pulse after a PR2 match, i.e the period is PR2+1, so don't forget to subtract 1 from the desired rollover count to get PR2.
     
     

    * If you are unfamiliar with statistical limits see: https://en.wikipedia.org/...9395%E2%80%9399.7_rule
     
    post edited by Ian.M - 2019/10/06 01:52:54

    --
    NEW USERS: Posting images, links and code - workaround for restrictions.
    I also support http://picforum.ric323.com because this forum is sometimes too broken to use!
    #7
    drh
    30+ years
    • Total Posts : 1054
    • Reward points : 0
    • Joined: 2004/07/12 11:43:22
    • Location: Hemet, Calif. USA
    • Status: offline
    Re: 8bit: Timer 2 PIC16F18857 2019/10/06 06:03:11 (permalink)
    0
    At least this "teacher" isn't using a PIC16F873A.

    David
    #8
    dan1138
    Super Member
    • Total Posts : 3262
    • Reward points : 0
    • Joined: 2007/02/21 23:04:16
    • Location: 0
    • Status: offline
    Re: 8bit: Timer 2 PIC16F18857 2019/10/06 16:55:02 (permalink)
    +2 (2)
    @Ian.M,

    We may have loaded too much information on the Original Poster:
    plutonium
    Based on your answers I thought, that I want to see a blinking LED in every 5 sec. (It is easier to test and make sure, than 200 ms :) ) So the 5 sec also worked, and consistently the 200 ms too.
    Yesterday afternoon, when I tested, I also had a question.
    I know, that the T2CLKCON is LFINTOSC. But I cheated with MCC to get to know it in binary.
    But in reality, without the MCC, I can't figure out neither in binary nor in hex.
    In other .c files there is no clue.

    It configs 4 MHz HFINTOSC oscillator instead of 31kHz LFINTOSC. Why?

    It seems the OP is now lost in areas that are divergent from issues of more immediate use to the assigned task.

    The specific controller, PIC16F18857, has two internal oscillators LFINTOSC (31KHz) and HFINTOSC (32MHz).


    The controller can use these oscillators as clock sources for various peripherals or as the main system oscillator or both.

    Restrictions do apply as these oscillators are independent and not synchronized. It can be tricky to get certain features in some function blocks to work when a clock source is asynchronous with respect to the instruction cycle clock.

    This restriction does not apply to the OPs present task.

    The X2C development board the OP is using is constructed such that the EXTOSC and SOSC oscillation amplifiers cannot be used with external crystals or clock sources.
    post edited by dan1138 - 2019/10/06 17:04:00
    #9
    nigelwright7557
    Super Member
    • Total Posts : 308
    • Reward points : 0
    • Joined: 2006/11/06 08:15:51
    • Location: 0
    • Status: offline
    Re: 8bit: Timer 2 PIC16F18857 2019/10/06 17:22:50 (permalink)
    +1 (1)
    Timer 2 just counts pulses from 0 to 255.
    The prescaler allows dividing the input clock before it goes into timer2.
    The post scaler allows dividing the clock after it has left timer 2.
    If you know the input clock speed you can work out the IF speed.
    As others have said don't forget to reset IF flag after interrupt.
     
     
    #10
    Ian.M
    Super Member
    • Total Posts : 13267
    • Reward points : 0
    • Joined: 2009/07/23 07:02:40
    • Location: UK
    • Status: offline
    Re: 8bit: Timer 2 PIC16F18857 2019/10/06 22:04:37 (permalink)
    +2 (2)
    The OP's blind spot seems to be that he believes the MCU's CPU core should be clocked at the same speed as its Timer 2 peripheral.  That is L*NOT* the teacher's intention.
     
    The teacher's sample code explicitly sets Fosc, the core clock, to 4 MHz:

    /* OSC config*/
    // NOSC HFINTOSC; NDIV 1; 
    OSCCON1 = 0x60;
    // HFFRQ 4_MHz; 
    OSCFRQ = 0x02;

    Although many of us would impugn the teacher's intelligence and abilities, this is clearly intentional.   The "principle error in the main cycle" (main loop) has already been located, its the missing
     PIR4bits.TMR2IF = 0;

    not the oscillator settings, which aren't in the loop anyway.   At 4 MHz Fosc, the CPU core runs at 1 MIPS, so the main loop will respond to TMR2IF in a time that is negligible compared to the desired period.  If the CPU core was also running at 31 KHz (nominal LFINTOSC), it would execute 7750 instructions per second (more or less as LFINTOSC isn't accurate) and the main loop latancy responding to TMR2IF could easily amount to a delay of the order of 1 ms.  This is clearly undesirable, unless other constraints like a requirement for minimal power consumption apply.
     
    Dan has used LFINTOSC's nominal frequency of 31 KHz (parameter OS53) for his calculation, giving a total Timer 2 subsystem period of 6200 cycles.  I however used its typical frequency for Vdd>3.6V from Fig. 38-8, which is 31.5 Khz, giving a period of 6300, hence the divergence in our suggested prescaler, postscaler and PR2 settings.     Due to the low accuracy of LFINTOSC, there is little to choose between them - both are unlikely to give an exact 200 ms period on a real physical  PIC16F18857, and both are arguably 'correct' (for some value of 'correct')!

    --
    NEW USERS: Posting images, links and code - workaround for restrictions.
    I also support http://picforum.ric323.com because this forum is sometimes too broken to use!
    #11
    plutonium
    New Member
    • Total Posts : 5
    • Reward points : 0
    • Joined: 2019/10/02 02:48:42
    • Location: 0
    • Status: offline
    Re: 8bit: Timer 2 PIC16F18857 2019/10/20 06:03:15 (permalink)
    +1 (1)
    Thank you again for your help!
    Smile: Smile
    #12
    mpgmike
    Super Member
    • Total Posts : 324
    • Reward points : 0
    • Joined: 2014/01/23 17:27:06
    • Location: NJ
    • Status: offline
    Re: 8bit: Timer 2 PIC16F18857 2019/10/20 06:34:52 (permalink)
    0
    I read through this thread looking for mention of OSCEN.  I opened the data sheet expecting to see OSCEN options for LFINTOSC where 0=OFF, 1=ON.  To my surprise, 0=Can be enabled by another module.  I guess using LFINTOSC as TMR2CLK turns it on even without OSCEN?!?

    I don't need the world to know my name, but I want to live a life so all my great-grandchildren proudly remember me.
    #13
    plutonium
    New Member
    • Total Posts : 5
    • Reward points : 0
    • Joined: 2019/10/02 02:48:42
    • Location: 0
    • Status: offline
    Re: 8bit: Timer 2 PIC16F18857 2019/10/20 06:38:44 (permalink)
    0
    After I passed the Timers successfuly, based on the same project I have new challenges:
     
    "Modify the main program by the following:
    - If you push S1 button on the controller then Timer2 interruption should be disabled.
    - If you don't push S1 button on the controller then Timer2 interruption should be enabled.
    - If you push S2 button on the controller then global interruption should be disabled.
    - If you don't push S2 button on the controller then global interruption should be enabled."
     
    The instruction asks me to set:
    INTCONbits.GIE = 0; ---> INTCONbits.GIE = 1;
     
    The instruction asks me to delete from main.c the codes which are responsible for LED1 switching, because interrupt.c will do it. So the unnecesary codes became comments, by the little screenshot given by the teacher.
     
    while (1){
    // if (PIR4bits.TMR2IF) { //Timer overflow detected!
    // LATCbits.LATC4 = ~LATCbits.LATC4; // invert LED1
    //}
    }
     
    In the Config part, there are the two necessary codes:
    PIE4bits.TMR2IE = 1;// Enable Timer 2 int
    INTCONbits.GIE = 1; // Enable Global interrupt
     
    I did the following in main.c: (RA7=S1 button, RA6=S2 button)
    I put these rows before the empty while section:
     
    if (PORTAbits.RA7 = 0) {
    PIE4bits.TMR2IE = 0;
    }
    if (PORTAbits.RA6 = 0) {
    INTCONbits.GIE = 0;
    }
     
    But nothing happens. I tried some cominations but the LEDs are off.
     
    The interrupt.c:
     
    #include <xc.h>
    void __interrupt() INTERRUPT_InterruptManager (void)
    {
        if(PIR4bits.TMR2IF == 1)
        {
            PIR4bits.TMR2IF = 0; // Clear IF
            LATCbits.LATC5 ^= 1; //invert LED2   
        }
        
        if(PIR4bits.TMR4IF == 1)
        {
            PIR4bits.TMR4IF = 0; // Clear IF
            LATCbits.LATC6 = ~LATCbits.LATC6; //invert LED3
        }
    }
     
    post edited by plutonium - 2019/10/20 06:40:48
    #14
    bitdoctor
    Starting Member
    • Total Posts : 24
    • Reward points : 0
    • Joined: 2019/10/11 06:10:09
    • Location: 0
    • Status: offline
    Re: 8bit: Timer 2 PIC16F18857 2019/10/20 06:43:46 (permalink)
    +1 (1)
    plutonium
    I did the following in main.c: (RA7=S1 button, RA6=S2 button)
    I put these rows before the empty while section:



    Where it will run once at boot time and never again...
    #15
    pcbbc
    Super Member
    • Total Posts : 1373
    • Reward points : 0
    • Joined: 2014/03/27 07:04:41
    • Location: 0
    • Status: offline
    Re: 8bit: Timer 2 PIC16F18857 2019/10/20 09:09:40 (permalink)
    +1 (1)
    Not only that, this code...
    if (PORTAbits.RA7 = 0) {
    PIE4bits.TMR2IE = 0;
    }
    if (PORTAbits.RA6 = 0) {
    INTCONbits.GIE = 0;
    }

    a) Deals with disabling the interrupts when the buttons are pressed, assuming negative logic low indicates a button pressed. And as noted runs only once at startup.  But there’s no code to re-enable the interrupts if the button is not pressed (i.e. Subsequently released while the PIC is still running).
    b) Makes the beginners C programmers mistake of conflating the = sign (assignment operator) and == sign (comparison operator).
    #16
    plutonium
    New Member
    • Total Posts : 5
    • Reward points : 0
    • Joined: 2019/10/02 02:48:42
    • Location: 0
    • Status: offline
    Re: 8bit: Timer 2 PIC16F18857 2019/10/22 23:47:37 (permalink)
    0
    Nor outside the while section, neither inside the while section works.
    Nor with one =, neither with == works.
    I tried all the combination. Something is missing and/or the existing code is in wrong place.
    #17
    pcbbc
    Super Member
    • Total Posts : 1373
    • Reward points : 0
    • Joined: 2014/03/27 07:04:41
    • Location: 0
    • Status: offline
    Re: 8bit: Timer 2 PIC16F18857 2019/10/23 03:24:35 (permalink)
    +2 (2)
    Post your entire modified code.  We can't be guessing at how you may have modified it, or if you did so correctly.
    1. Code for switches should be inside the while section.
    2. My reading of the assignment is the code should also perform the opposite action if the button is NOT pressed.  Also inside the loop.
    3. == is overwhelming the correct operator to be using inside conditional statements (i.e. while(...) and if(...)).  As a novice C programmer, if you are using just = in there you have made a mistake.
     
    "Does not work" is not a good enough description of a problem for us to help.  How does it "not work"?
    a. Show your code you were testing with,
    b. Describe exactly what test(s) you tried,
    c. Describe what results you expected to see,
    d. Describe what results you actually observed,
    e. Sometimes you may also need to explain how you measured them (i.e. with a scope, multimeter, etc, and how it was connected).
    #18
    Jump to:
    © 2019 APG vNext Commercial Version 4.5