Issues using multiple timers with PIC18F4550

Discussion in 'Embedded Systems and Microcontrollers' started by rkrutz, Jun 12, 2013.

  1. rkrutz

    Thread Starter New Member

    Dec 2, 2009
    29
    1
    Hi,
    I have been working on this issue for a week and cannot seem to get anything to work as expected. I assume I am missing a step. I want to get two LEDs flashing at different rates using two timers. I found this tutorial which was very helpful to get one LED to work. However when I tried to modify it to work with two timers both LEDs flash at the same rate and that should not be the cases since I played around with the speeds and the rates were still the same. Could anyone point out what I am doing wrong for some reason I just cannot understand timers in PIC compared to the other microcontrollers I have used.

    Also if there is a more efficient way of doing this that requires less code that would be great if someone could show me that way.

    Thanks
    I am using the 18F4550 in MPLABX with XC8
    config.h
    Code ( (Unknown Language)):
    1.  
    2. #ifndef CONFIG_H
    3. #define CONFIG_H
    4.  
    5. #ifdef  __cplusplus
    6. extern "C" {
    7. #endif
    8.  
    9.  
    10.  
    11.  
    12. #ifdef  __cplusplus
    13. }
    14. #endif
    15.  
    16. #endif  /* CONFIG_H */
    17.  
    18. #include <xc.h>
    19.  
    20. //#pragma config CONFIG1L = 0x0
    21. __CONFIG(1, PLLDIV_1 & CPUDIV_OSC1_PLL2 & USBDIV_1);
    22. //#pragma config CONFIG1H = 0x8
    23. __CONFIG(2, FOSC_INTOSCIO_EC & FCMEN_OFF & IESO_OFF);
    24. //#pragma config CONFIG2L = 0x19
    25. __CONFIG(3, PWRT_OFF & BOR_OFF & BORV_3 & VREGEN_OFF);
    26. //#pragma config CONFIG2H = 0x1E
    27. __CONFIG(4, WDT_OFF & WDTPS_32768);
    28. //#pragma config CONFIG3H = 0x83
    29. __CONFIG(5, CCP2MX_ON & PBADEN_ON & LPT1OSC_OFF & MCLRE_ON);
    30. //#pragma config CONFIG4L = 0x85
    31. __CONFIG(6, STVREN_ON & LVP_ON & ICPRT_OFF & XINST_OFF);
    32. //#pragma config CONFIG5L = 0xF
    33. __CONFIG(7, CP0_OFF & CP1_OFF & CP2_OFF & CP3_OFF);
    34. //#pragma config CONFIG5H = 0xC0
    35. __CONFIG(8, CPB_OFF & CPD_OFF);
    36. //#pragma config CONFIG6L = 0xF
    37. __CONFIG(9, WRT0_OFF & WRT1_OFF & WRT2_OFF & WRT3_OFF);
    38. //#pragma config CONFIG6H = 0xE0
    39. __CONFIG(10, WRTC_OFF & WRTB_OFF & WRTD_OFF);
    40. //#pragma config CONFIG7L = 0xF
    41. __CONFIG(11, EBTR0_OFF & EBTR1_OFF & EBTR2_OFF & EBTR3_OFF);
    42. //#pragma config CONFIG7H = 0x40
    43. __CONFIG(12, EBTRB_OFF);
    44.  
    main.c
    Code ( (Unknown Language)):
    1.  
    2. #include <xc.h>
    3. #include <plib/timers.h>
    4. #include "config.h"
    5.  
    6. #define _XTAL_FREQ 800000
    7. #define USE_AND_MASKS
    8.  
    9. int i =0;
    10. unsigned char Timer0Config;
    11. unsigned char Timer1Config;
    12. void SetupClock(void);
    13.  
    14. void main(int argc,char** argv)
    15. {
    16.     SetupClock();
    17.     TRISBbits.RB4=0;
    18.     LATB4=1;
    19.     TRISBbits.RB3=0;
    20.     LATB3=1;
    21.  
    22.     Timer0Config = TIMER_INT_ON & T0_16BIT & T0_SOURCE_INT & T0_PS_1_256 ;
    23.     T1CON=0b11110101;
    24.     Timer1Config = T1CON;
    25.     OpenTimer0(Timer0Config);
    26.     WriteTimer0(0xE17B);
    27.     OpenTimer1(Timer1Config);
    28.     WriteTimer1(0xE17B);
    29.     PIR1bits.TMR1IF = 0;
    30.     INTCONbits.TMR0IF = 0;
    31.     ei();
    32.  
    33.     while(1)
    34.     {
    35.     }
    36.  
    37. }
    38. void SetupClock()
    39. {
    40.     OSCCONbits.IRCF0 = 1;
    41.     OSCCONbits.IRCF1 = 1;
    42.     OSCCONbits.IRCF2 = 1;
    43. }
    44.  
    45. void interrupt TImerOverflow()
    46. {
    47.     if(INTCONbits.TMR0IF ==1)
    48.     {
    49.         LATB4 =~LATB4;
    50.         INTCONbits.TMR0IF = 0;
    51.         WriteTimer0(0xE17B);
    52.     }
    53.      if(PIR1bits.TMR1IF ==1)
    54.     {
    55.         LATB3 =~LATB3;
    56.         PIR1bits.TMR1IF = 0;
    57.         WriteTimer1(0xE17B);
    58.     }
    59. }
     
  2. rkrutz

    Thread Starter New Member

    Dec 2, 2009
    29
    1
    UPDATE:

    After playing around with timers I was able to get something to work. However even though I have one prescaler at 1:4 and the other at 1:8 and set both the TMR0IF and TMR1IF to overflow 10 times before their respective LEDs should come on and they seem to both come on at the same time. So my question is is there something I am missing to configure to get the two different prescalers to work and they are actually just using one timer or something else?

    The config.h file is the same as previously posted and below is the new main.c.

    Thanks
    Code ( (Unknown Language)):
    1. #include <xc.h>
    2. #include <plib/timers.h>
    3. #include "config.h"
    4. #include<stdint.h>
    5.  
    6. #define _XTAL_FREQ 800000
    7. #define USE_AND_MASKS
    8. unsigned char counter;
    9. unsigned char counter1;
    10. Init(void)
    11. {
    12.      OSCCON =01111110;
    13.      TMR1 = 0;
    14. TMR0 = 0;//Clear the TMR0 register
    15. /*Configure Timer0 as follows:
    16. - Use the internal instruction clock
    17. as the source to the module
    18. - Assign the Prescaler to the Watchdog
    19. Timer so that TMR0 increments at a 1:1
    20. ratio with the internal instruction clock*/
    21. T0CON = 0b10000001;
    22. T1CON = 0b11100101;
    23. TRISBbits.RB4=0;
    24. LATB4=0;
    25. TRISBbits.RB3=0;
    26. LATB3=0;
    27. }
    28. /*----------------------------------------------------------
    29. Subroutine: main
    30. Parameters: none
    31. Returns: nothing
    32. Synopsys: Main program function
    33. -----------------------------------------------------------*/
    34. main(void)
    35. {
    36. Init(); //Initialize the relevant registers
    37. while(1)
    38. {
    39. //Poll the T0IF flag to see if TMR0 has overflowed
    40. if (TMR0IF==1)
    41. {
    42. ++counter;//if T0IF = 1 increment the counter
    43. //variable by 1
    44. TMR0IF = 0;//Clear the T0IF flag so that
    45. //the next overflow can be detected
    46. if (counter >10)
    47. {
    48.     LATB4=1;
    49. }
    50. }
    51. if (TMR1IF==1)
    52. {
    53. ++counter1;//if T0IF = 1 increment the counter
    54. //variable by 1
    55. TMR1IF = 0;//Clear the T0IF flag so that
    56. //the next overflow can be detected
    57. if (counter1 >20)
    58. {
    59.     LATB3=1;
    60. }
    61. }
    62.  
    63. }
    64.  
     
  3. RG23

    Active Member

    Dec 6, 2010
    301
    2
    Enable the bit 5 of INTCON register in the main program before jumping to the interrupt

    INTCONbits.TMR0IF = 1
     
  4. RG23

    Active Member

    Dec 6, 2010
    301
    2
    WriteTimer0(0xE17B);??????????

    WriteTimer1(0xE17B)????????
    ___________________________________________________________
    Load different values in the timer registers so that you get different rates
     
  5. rkrutz

    Thread Starter New Member

    Dec 2, 2009
    29
    1
    Thanks that seemed to do the trick with the second code I posted. Should I also do this with the PIE1 for Timer1? I think the part that confuses me the most is how set up the timers properly. I understand I need to do the TXCON, but what other registers should I also look at? The INTCON for Timer0 and the PIE1 and PIR1 for Timers1 and 2?
     
  6. rkrutz

    Thread Starter New Member

    Dec 2, 2009
    29
    1
    Sorry that was from a test I was running, but even if I made WriteTimer1(0x70BD) so they were different by a half it came on at the same time. I will try the suggestion you made earlier on that code after dinner and hopefully that clears up the issue.

    UPDATE:
    So I changed INTCONbits.TMR0IF = 1; and made Timer1 go at 70DB and now the LEDs alternate. However no matter what I change the second timer to they still alternate at the same rate. Is this due to them being called one ofter the other in the same interrupt routine?
     
    Last edited: Jun 12, 2013
  7. RG23

    Active Member

    Dec 6, 2010
    301
    2
    Also set the bit 0 of PIE1 register in the main

    Try these changes
     
  8. rkrutz

    Thread Starter New Member

    Dec 2, 2009
    29
    1
    So I have been working with the second code I posted and it seems that no matter what I do to the if statements related to RB3 the LED at that pin always alternates with the LED on RB4. Since this even happens when I comment out those statements I am guessing there is something wrong with how I am using the timer. Could someone point out what I am doing wrong?

    Code ( (Unknown Language)):
    1.  
    2. /*
    3.  * Created on June 9, 2013, 5:13 PM
    4.  */
    5. #include <xc.h>
    6. #include <plib/timers.h>
    7. #include "config.h"
    8. #include<stdint.h>
    9.  
    10. #define _XTAL_FREQ 800000
    11. #define USE_AND_MASKS
    12. unsigned char counter;
    13. unsigned char counter1;
    14. Init(void)
    15. {
    16.      OSCCON =01011110;
    17.      TMR1 = 0;
    18. TMR0 = 0;//Clear the TMR0 register
    19. /*Configure Timer0 as follows:
    20. - Use the internal instruction clock
    21. as the source to the module
    22. - Assign the Prescaler to the Watchdog
    23. Timer so that TMR0 increments at a 1:1
    24. ratio with the internal instruction clock*/
    25. T0CON = 0b10000001;
    26. T1CON = 0b11100101;
    27. TRISBbits.RB4=0;
    28. LATB4=0;
    29. TRISBbits.RB3=0;
    30. LATB3=0;
    31. INTCONbits.TMR0IF = 1;
    32. PIR1bits.TMR1IF = 0;
    33. PIE1bits.TMR1IE = 1;
    34. INTCONbits.TMR0IF = 1;
    35. INTCONbits.TMR0IE = 1;
    36. }
    37. /*----------------------------------------------------------
    38. Subroutine: main
    39. Parameters: none
    40. Returns: nothing
    41. Synopsys: Main program function
    42. -----------------------------------------------------------*/
    43. main(void)
    44. {
    45. Init(); //Initialize the relevant registers
    46. while(1)
    47. {
    48. //Poll the T0IF flag to see if TMR0 has overflowed
    49. if (TMR0IF==1)
    50. {
    51. ++counter;//if T0IF = 1 increment the counter
    52. //variable by 1
    53. TMR0IF = 0;//Clear the T0IF flag so that
    54. //the next overflow can be detected
    55. if (counter >10)
    56. {
    57.     LATB4=1;
    58. }
    59. }
    60. /*if (TMR1IF==1)
    61. {
    62. ++counter1;//if T0IF = 1 increment the counter
    63. //variable by 1
    64. TMR1IF = 0;//Clear the T0IF flag so that
    65. //the next overflow can be detected
    66. */
    67. if (counter1 >10)
    68. {
    69.     //LATB3=1;
    70. }
    71. }
    72.  
    73. }
    74.  
     
Loading...