• AVR Freaks

Hot!Generating 1.0 second delay using Timer1 (PIC16F877A) with Fosc=4.0MHz, Prescaler 1:1

Author
hersham1980
New Member
  • Total Posts : 3
  • Reward points : 0
  • Joined: 2019/06/26 07:19:32
  • Location: 0
  • Status: offline
2019/07/20 14:02:54 (permalink)
0

Generating 1.0 second delay using Timer1 (PIC16F877A) with Fosc=4.0MHz, Prescaler 1:1

Dear All 
The following code has been optimized to generate 1.0 second time-delay using TIMER-1 (16-BIT) module. I used Proteus (simulation software) to check if the resulting time interval is exactly 1.0 second. but unfortunately it appears to be in terms of micro-seconds. 
Bellow you will find the relevant formulas to calculate the pre-loading decimal value which has to be loaded into TIMER-1
------------------------------------------------------------------------------------------------------------- 
 To calculate the initial preloaded value for TMR-1 [Taking into consideration Fosc=4.0MHz, (X=20 overflows) , Prescaler 1:1, Time-Delay = 1.0s]
------------------------------------------------------------------------------------------------------------- 
                                                      TMR1=65535 -([Tout x Fosc] / (X * [4 x Prescaler])
                                                      TMR1=65535-([1 x 4MHz] / (20 * [4 x 1])
                                                      TMR1=[15535 Decimal 0x3CAF Hexa-Decimal]
-------------------------------------------------------------------------------------------------------------- 
I would appreciate if someone could take a close look at my code and let me what I have to do
Thanks Very Much in Advance.
Adam
//---------------------------------Configuration Bit Settings-------------------- 
#pragma config FOSC = HS    
#pragma config WDTE = OFF   
#pragma config PWRTE = OFF   
#pragma config BOREN = OFF     
#pragma config LVP = OFF   
#pragma config CPD = OFF
#pragma config WRT = OFF
#pragma config CP = OFF
//--------------------------------------Variable Declaration---------------------- 
#include <xc.h>
#define _XTAL_FREQ 4000000 
void main(void) 
{
ADCON1=7;            // To Disable All Internal Analogue Channel
CMCON=7;             // To Disable The Intenal Comparator
TRISBbits.TRISB1=0;
PORTBbits.RB1=0;
//-------------------------------------Timer TMR0 SetUp-------------------------- 
 PIR1bits.TMR1IF=0;                           //  Clear Interrupt Flag bit
TMR1=15535;                                     //   Load Count Value Into TMR-1
T1CONbits.TMR1CS=0;                        //    Assign the Internal Clock Source
T1CONbits.T1CKPS1=0;                       //     Select the Prescaler Rate 1:1
 T1CONbits.T1CKPS0=0;  
 PIE1bits.TMR1IE=1;                           // Enable Interrupt Upon Overflow
INTCONbits.GIE=1;                             // Enable Global Interrupt 
INTCONbits.PEIE=1;                            // Enable Peripheral Interrupt  
T1CONbits.TMR1ON=1;                        // Enable Peripheral Interrupt    
//----------------------------------Main Program-------------------------------------- 
while(1)
  { 
      if (!PIR1bits.TMR1IF) 
           { 
                 PORTBbits.RB1=~PORTBbits.RB1;
                 PIR1bits.TMR1IF=0;                        //Clear Interrupt Flag of TMR0
                 TMR1=15535;    
             }
         }
}
//-------------------------------------End of Code------------------------------------ 
post edited by hersham1980 - 2019/07/20 14:40:25
#1

4 Replies Related Threads

    ric
    Super Member
    • Total Posts : 24544
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: Generating 1.0 second delay using Timer1 (PIC16F877A) with Fosc=4.0MHz, Prescaler 1:1 2019/07/20 15:45:37 (permalink)
    +1 (1)
    You have your test back to front.
    Change
          if (!PIR1bits.TMR1IF)
    to
          if (PIR1bits.TMR1IF)
     
    Also, you will get occasional errors because you are writing to the timer without stopping it.
    Actually, I think you might get away with it, as neither byte is near 0xFF, and you don't have interupts enabled, so there's no risk if a pause between writing the lower byte and the upper byte.
     
    post edited by ric - 2019/07/20 15:50:08

    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!
    #2
    ric
    Super Member
    • Total Posts : 24544
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: Generating 1.0 second delay using Timer1 (PIC16F877A) with Fosc=4.0MHz, Prescaler 1:1 2019/07/20 15:51:53 (permalink)
    +1 (1)
    The more precise way of doing this would be to use one of the CCP peripherals to reset TMR1 to zero at a specified count.
    See: "6.6 Resetting Timer1 Using a CCP Trigger Output" in the datasheet.

    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!
    #3
    cea
    Junior Member
    • Total Posts : 92
    • Reward points : 0
    • Joined: 2006/02/17 00:01:25
    • Location: 0
    • Status: offline
    Re: Generating 1.0 second delay using Timer1 (PIC16F877A) with Fosc=4.0MHz, Prescaler 1:1 2019/07/22 18:47:43 (permalink)
    +1 (1)
    hersham1980
    Dear All

    The following code has been optimized to generate 1.0 second time-delay using TIMER-1 (16-BIT) module. I used Proteus (simulation software) to check if the resulting time interval is exactly 1.0 second. but unfortunately it appears to be in terms of micro-seconds.

    Bellow you will find the relevant formulas to calculate the pre-loading decimal value which has to be loaded into TIMER-1

    -------------------------------------------------------------------------------------------------------------

    To calculate the initial preloaded value for TMR-1 [Taking into consideration Fosc=4.0MHz, (X=20 overflows) , Prescaler 1:1, Time-Delay = 1.0s]

    -------------------------------------------------------------------------------------------------------------
    TMR1=65535 -([Tout x Fosc] / (X * [4 x Prescaler])
    TMR1=65535-([1 x 4MHz] / (20 * [4 x 1])
    TMR1=[15535 Decimal 0x3CAF Hexa-Decimal]
    --------------------------------------------------------------------------------------------------------------

    I would appreciate if someone could take a close look at my code and let me what I have to do

    Thanks Very Much in Advance.

    Adam
    //---------------------------------Configuration Bit Settings--------------------
    #pragma config FOSC = HS
    #pragma config WDTE = OFF
    #pragma config PWRTE = OFF
    #pragma config BOREN = OFF
    #pragma config LVP = OFF
    #pragma config CPD = OFF
    #pragma config WRT = OFF
    #pragma config CP = OFF
    //--------------------------------------Variable Declaration----------------------
    #include <xc.h>
    #define _XTAL_FREQ 4000000
    void main(void)
    {
    ADCON1=7; // To Disable All Internal Analogue Channel
    CMCON=7; // To Disable The Intenal Comparator
    TRISBbits.TRISB1=0;
    PORTBbits.RB1=0;
    //-------------------------------------Timer TMR0 SetUp--------------------------
    PIR1bits.TMR1IF=0; // Clear Interrupt Flag bit
    TMR1=15535; // Load Count Value Into TMR-1
    T1CONbits.TMR1CS=0; // Assign the Internal Clock Source
    T1CONbits.T1CKPS1=0; // Select the Prescaler Rate 1:1
    T1CONbits.T1CKPS0=0;
    PIE1bits.TMR1IE=1; // Enable Interrupt Upon Overflow
    INTCONbits.GIE=1; // Enable Global Interrupt
    INTCONbits.PEIE=1; // Enable Peripheral Interrupt
    T1CONbits.TMR1ON=1; // Enable Peripheral Interrupt
    //----------------------------------Main Program--------------------------------------
    while(1)
    {
    if (!PIR1bits.TMR1IF)
    {
    PORTBbits.RB1=~PORTBbits.RB1;
    PIR1bits.TMR1IF=0; //Clear Interrupt Flag of TMR0
    TMR1=15535;
    }
    }
    }
    //-------------------------------------End of Code------------------------------------


    This is your code fixed:
    /* https://www.microchip.com/forums/FindPost/1105835
    *
    * The following code has been optimized to generate 1.0 second
    * time-delay using TIMER-1 (16-BIT) module. I used Proteus (simulation software)
    * to check if the resulting time interval is exactly 1.0 second.
    * but unfortunately it appears to be in terms of micro-seconds.
    *
    * Bellow you will find the relevant formulas to calculate
    * the pre-loading decimal value which has to be loaded into TIMER-1
    * ------------------------------------------------------------
    * To calculate the initial preloaded value for TIMER1
    * [Taking into consideration Fosc=4.0MHz, (X = 16 overflows) ,
    * Prescaler 1:1, Time-Delay = 1.0s]
    * -----------------------------------------------------------
    * TMR1=65536 - ([Tout x Fosc] / (X * [4 x Prescaler])
    * TMR1=65536 - ([1 x 4MHz] / (16 * [4 x 1])
    * TMR1=[3036 Decimal 0x0BDC Hexa-Decimal]
    * ------------------------------------------------------------
    */
    #define RELOAD_VALUE (3036u)
    #define RELOAD_OVERHEAD (7u)
    #define START_OVERHEAD (52u)
    #define RELOADS_PER_SECOND (16u)
    //---------------------------------Configuration Bit Settings--------------------
    #pragma config FOSC = HS
    #pragma config WDTE = OFF
    #pragma config PWRTE = OFF
    #pragma config BOREN = OFF
    #pragma config LVP = OFF
    #pragma config CPD = OFF
    #pragma config WRT = OFF
    #pragma config CP = OFF
    //--------------------------------------Variable Declaration----------------------
    #include <xc.h>
    #define _XTAL_FREQ 4000000
    void main(void)
    {
    unsigned char PeriodCount;

    ADCON1=7; // To Disable All Internal Analogue Channel
    CMCON=7; // To Disable The Intenal Comparator
    TRISBbits.TRISB1=0;
    PORTBbits.RB1=0;
    //-------------------------------------Timer TMR0 SetUp--------------------------
    PIE1bits.TMR1IE=0; // Disable Interrupts
    PIR1bits.TMR1IF=0; // Clear Interrupt Flag bit
    T1CONbits.TMR1ON=0; // Stop TIMER1
    TMR1=RELOAD_VALUE+START_OVERHEAD;
    T1CONbits.TMR1CS=0; // Assign the Internal Clock Source
    T1CONbits.T1CKPS=0b00; // Select the Prescaler Rate 1:1
    PeriodCount=RELOADS_PER_SECOND-1;
    T1CONbits.TMR1ON=1; // Start TIMER1
    //----------------------------------Main Program--------------------------------------
    while(1)
    {
    if (PIR1bits.TMR1IF)
    {
    PIR1bits.TMR1IF=0;
    T1CONbits.TMR1ON=0; // Stop TIMER1
    TMR1 += RELOAD_VALUE+RELOAD_OVERHEAD;
    T1CONbits.TMR1ON=1; // Start TIMER1
    if (!PeriodCount)
    {
    PORTBbits.RB1=~PORTBbits.RB1;
    PeriodCount = RELOADS_PER_SECOND;
    }
    PeriodCount--;
    }
    }
    }
    //-------------------------------------End of Code------------------------------------

    You will need to figure out why I changed what I did in your code to make it do what you asked for.

    Good luck with your other homework.

    <EDIT>
    Sorry ric I was having a hard time getting the forum to post this in a useful format.
    I think it is fixed now,
    post edited by charles@socketcom - 2019/07/22 19:33:36
    #4
    ric
    Super Member
    • Total Posts : 24544
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: Generating 1.0 second delay using Timer1 (PIC16F877A) with Fosc=4.0MHz, Prescaler 1:1 2019/07/22 19:05:32 (permalink)
    0
    cea's code is hidden down the end of the code block
    charles@socketcom
    This is your code fixed:
    /* https://www.microchip.com/forums/FindPost/1105835
     
     *
     * The following code has been optimized to generate 1.0 second
     * time-delay using TIMER-1 (16-BIT) module. I used Proteus (simulation software)
     * to check if the resulting time interval is exactly 1.0 second.
     * but unfortunately it appears to be in terms of micro-seconds.
     *
     * Bellow you will find the relevant formulas to calculate
     * the pre-loading decimal value which has to be loaded into TIMER-1
     * ------------------------------------------------------------
     * To calculate the initial preloaded value for TIMER1
     * [Taking into consideration Fosc=4.0MHz, (X = 16 overflows) ,
     * Prescaler 1:1, Time-Delay = 1.0s]
     * -----------------------------------------------------------
     *     TMR1=65536 - ([Tout x Fosc] / (X * [4 x Prescaler])
     *     TMR1=65536 - ([1 x 4MHz] / (16 * [4 x 1])
     *     TMR1=[3036 Decimal 0x0BDC Hexa-Decimal]
     * ------------------------------------------------------------
     */
    #define RELOAD_VALUE     (3036u)
    #define RELOAD_OVERHEAD     (7u)
    #define START_OVERHEAD     (52u)
    #define PERIODS_PER_SECOND (16u)
    //---------------------------------Configuration Bit Settings--------------------
    #pragma config FOSC = HS
    #pragma config WDTE = OFF
    #pragma config PWRTE = OFF
    #pragma config BOREN = OFF
    #pragma config LVP = OFF
    #pragma config CPD = OFF
    #pragma config WRT = OFF
    #pragma config CP = OFF
    //--------------------------------------Variable Declaration----------------------
    #include <xc.h>
    #define _XTAL_FREQ 4000000
    void main(void)
    {
        unsigned char PeriodCount;
     
     
     
     
     
     
     
        ADCON1=7;            // To Disable All Internal Analogue Channel
        CMCON=7;             // To Disable The Intenal Comparator
        TRISBbits.TRISB1=0;
        PORTBbits.RB1=0;
    //-------------------------------------Timer TMR0 SetUp--------------------------
        PIE1bits.TMR1IE=0;          // Disable Interrupts
        PIR1bits.TMR1IF=0;          // Clear Interrupt Flag bit
        T1CONbits.TMR1ON=0;         // Stop TIMER1
        TMR1=RELOAD_VALUE+START_OVERHEAD;
        T1CONbits.TMR1CS=0;         // Assign the Internal Clock Source
        T1CONbits.T1CKPS=0b00;      // Select the Prescaler Rate 1:1
        PeriodCount=PERIODS_PER_SECOND-1;
        T1CONbits.TMR1ON=1;         // Start TIMER1
    //----------------------------------Main Program--------------------------------------
        while(1)
        {
            if (PIR1bits.TMR1IF)
            {
                PIR1bits.TMR1IF=0;
                T1CONbits.TMR1ON=0;         // Stop TIMER1
                TMR1 += RELOAD_VALUE+RELOAD_OVERHEAD;
                T1CONbits.TMR1ON=1;         // Start TIMER1
                if (!PeriodCount)
                {
                    PORTBbits.RB1=~PORTBbits.RB1;
                    PeriodCount = PERIODS_PER_SECOND;
                }
                PeriodCount--;
            }
        }
    }
    //-------------------------------------End of Code------------------------------------

    You will need to figure out why I changed what I did in your code to make it do what you asked for.
     
    Good luck with your other homework.




    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!
    #5
    Jump to:
    © 2019 APG vNext Commercial Version 4.5