Newbie Using Pic Timer0 C language question

Discussion in 'Embedded Systems and Microcontrollers' started by sprintfoot, Mar 14, 2014.

  1. sprintfoot

    Thread Starter New Member

    Mar 14, 2014
    3
    0
    Hello All,

    I am completely new to programming PIC and C language. I am having trouble using the Timer0 on my pic16f690. I am using the MPLAB X IDE and compiler.

    I am simply trying to get an LED to blink on and off at 2 second intervals. My code is below. If someone could please advise me as to what i am doing wrong, I would be most appreciative.

    Code ( (Unknown Language)):
    1.  
    2.  #include <xc.h>
    3.  #include <stdint.h>
    4.  
    5. #pragma config MCLRE = OFF, CP = OFF, CPD = OFF, BOREN = OFF, WDTE = OFF
    6. #pragma config PWRTE = OFF, FOSC = INTRCIO
    7.  
    8.  
    9. #define _XTAL_FREQ 4000000  //osc frequency
    10.  //#define __delay_ms(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000.0)))
    11.  
    12. int count = 0;
    13.  
    14.  
    15. void TimerBlinkLED()
    16. {
    17.  
    18.   uint8_t  cnt_8ms;  //counter increments every 8ms
    19.  
    20.   while(1)
    21.   {
    22.   cnt_8ms = 0;
    23.  
    24.   while (cnt_8ms < 250)  //250 * 8ms = 2 second count
    25.   {
    26.     TMR0 = 0;  //clear Timer0
    27.        
    28.     while(TMR0 < 250)  //wait for 8ms to pass (.008ms / .000032us)
    29.      {  //do nothing until timer is > 8ms
    30.      }
    31.  
    32.     ++cnt_8ms;  //now timer is > 8ms so add 1 to counter variable
    33.   }
    34.  
    35.   if (PORTC == 0b00000000)
    36.     {
    37.      PORTC = 0b00001000;
    38.     }
    39.   else
    40.     {
    41.      PORTC = 0b00000000;
    42.     }
    43.   }
    44. }
    45.  
    46. void main()
    47. {
    48.     ADCON1 = 0x0F;  //deactivate A-D conveter
    49.     //CMCON = 0x07;   //deactivate comparator module
    50.     TRISC = 0b00000000; //set Input or 0utput bits
    51.     PORTC = 0x00;   //clear port A
    52.  
    53.     OPTION_REGbits.T0CS = 0;  //select timer mode
    54.     OPTION_REGbits.PSA = 0;  //assign presscaler to Timer0
    55.     OPTION_REGbits.PS = 0b100;  //assign prescaler 32us
    56.  
    57.     while(1)
    58.     {    
    59.       TimerBlinkLED();
    60.     }
    61.  
    62. }
    63.  
     
    Last edited by a moderator: Mar 14, 2014
  2. tshuck

    Well-Known Member

    Oct 18, 2012
    3,531
    675
    You need to clear the ANSEL register(pg. 98), in order for the analog options to not override the digital I/O functionality of the pin. The reset value is a 1, or, analog input.

    Also, your
    Code ( (Unknown Language)):
    1. ADCON1 = 0x0F;  //deactivate A-D conveter
    code doesn't turn off the ADC. If you want to do that, you need to write
    Code ( (Unknown Language)):
    1. ADCON0 = 0bXXXXXXX0
    .
     
  3. Papabravo

    Expert

    Feb 24, 2006
    10,140
    1,789
    You have two while(1) loops. One is in main and the other is in the function. You do realize that only one of the while loops is required. As it stands the function "timerBlinkLED" will never return just as main will never return.
     
  4. takao21203

    Distinguished Member

    Apr 28, 2012
    3,577
    463
  5. sprintfoot

    Thread Starter New Member

    Mar 14, 2014
    3
    0
    I removed the while loop in BlinkLED function and still not working. The led on RC3 lights up and remains lit. I still cant seem to get it to blink.

    Any other thoughts?
     
  6. Papabravo

    Expert

    Feb 24, 2006
    10,140
    1,789
    Does Timer0 run automatically or is there a control bit to start and stop it?
    Is TIMER0 declared as signed or unsigned? You need to look in the standard header files for this one.
     
    Last edited: Mar 14, 2014
  7. spinnaker

    AAC Fanatic!

    Oct 29, 2009
    4,884
    1,002
    What have you done to debug the problem? Set a breakpoint inside your timer routine. See in Timer 0 is actually running.

    Also I would simplify my code. Just setup a simple while loop to wait for the timer to expire. Set a breakpoint outside the loop. If it gets there then you know the timer is running.
     
  8. John P

    AAC Fanatic!

    Oct 14, 2008
    1,634
    224
    This part of the code
    Code ( (Unknown Language)):
    1.  
    2.     while(TMR0 < 250)  //wait for 8ms to pass (.008ms / .000032us)
    3.     {  //do nothing until timer is > 8ms
    4.     }
    5.     ++cnt_8ms;
    6.  
    will actually function as

    Code ( (Unknown Language)):
    1.  
    2.     while(TMR0 < 250)  //wait for 8ms to pass (.008ms / .000032us)
    3.         ++cnt_8ms;
    4.  
    Because what is actually between the curly brackets?
     
  9. Ian Rogers

    Member

    Dec 12, 2012
    158
    29
    2 seconds in MPLABX is an awfully long time to simulate... For simulation purposes you would be better off using 2mS as a delay... Just to see if its working!!
     
  10. jjw

    Member

    Dec 24, 2013
    173
    31
    I think OP wants to wait until TMR0 gets to 250 and then increment cnt_8ms.
    So he should change to this:
    Code ( (Unknown Language)):
    1.  
    2. while(TMR0 < 250); // note semicolon here !
    3. ++cnt_8ms;
    4.  
     
    Last edited: Mar 15, 2014
  11. sprintfoot

    Thread Starter New Member

    Mar 14, 2014
    3
    0
    I have updated code as suggested by previous posters, but now no leds light up. I cant figure out what i am doing wrong.

    Here is my updated code:

    Code ( (Unknown Language)):
    1.  
    2. #include <xc.h>
    3.  #include <stdint.h>
    4.  
    5. #pragma config MCLRE = OFF, CP = OFF, CPD = OFF, BOREN = OFF, WDTE = OFF
    6. #pragma config PWRTE = OFF, FOSC = INTRCIO
    7.  
    8.  
    9. #define _XTAL_FREQ 4000000  //osc frequency
    10.  //#define __delay_ms(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000.0)))
    11.  
    12.  
    13. void TimerBlinkLED()
    14. {
    15.  
    16.   uint8_t  cnt_8ms;  //counter increments every 8ms
    17.  
    18.   cnt_8ms = 0;
    19.  
    20.   while (cnt_8ms < 250)  //250 * 8ms = 2 second count
    21.   {
    22.     TMR0 = 0;  //clear Timer0
    23.    
    24.     while(TMR0 < 250);  //wait for 8ms to pass (.008ms / .000032us)
    25.       //do nothing until timer is > 8ms
    26.  
    27.       ++cnt_8ms;  //now timer is > 8ms so add 1 to counter variable
    28.    
    29.   }
    30.  
    31.  
    32.   if (PORTC == 0b00000000)
    33.     {
    34.      PORTC = 0b00001000;
    35.     }
    36.   else
    37.     {
    38.      PORTC = 0b00000000;
    39.     }
    40. }
    41.  
    42.  
    43. void main()
    44. {
    45.     ADCON1 = 0x0F;  //deactivate A-D conveter
    46.     //CMCON = 0x07;   //deactivate comparator module
    47.     TRISC = 0b00000000; //set 1nput or 0utput bits
    48.     PORTC = 0x00;   //clear port A
    49.  
    50.     OPTION_REGbits.T0CS = 0;  //select timer mode
    51.     OPTION_REGbits.PSA = 0;  //assign presscaler to Timer0
    52.     OPTION_REGbits.PS = 0b100;  //assign prescaler 32us
    53.  
    54.     //while(1)
    55.    // {
    56.      //Blink(); //works
    57.       //LeftToRightAndBackLed();  //works
    58.         //UseLpcButton(); //does not work
    59.            TimerBlinkLED();
    60.     //}
    61.  
    62. }
    63.  

    Any ideas???
     
    Last edited by a moderator: Mar 18, 2014
  12. tshuck

    Well-Known Member

    Oct 18, 2012
    3,531
    675
    Yes.

    1.) Use code tags ( [CODE ] & [/CODE ] - without the spaces) to encapsulate your code. Click the '#' button while posting and it will add them for you.

    2.) Configure your outputs as digital outputs. See post # 2.
     
  13. takao21203

    Distinguished Member

    Apr 28, 2012
    3,577
    463
    because you need to turn on the timer + configure it.
    Besides, your program is not so good. There are a number of issues.

    Well you dont have to visit my link and examine my solution.
    But how about consulting the datasheet, the chapter for the timer?

    -You have to turn on the timer
    -You have to choose the clock source
    -You have to set the divider

    Sometimes on the 16F, it is done with OPTION_REG, and the divider bits go at the bottom, and the rest can be set to 0.

    Hope you get it working + clear up the mess + use code tags.
     
  14. takao21203

    Distinguished Member

    Apr 28, 2012
    3,577
    463
    OK apparently the OPTION_REG bits are set.

    Code ( (Unknown Language)):
    1.  
    2. void TimerBlinkLED()
    3. {
    4.  
    5. uint8_t cnt_8ms; //counter increments every 8ms
    6.  
    7. cnt_8ms = 0;
    8.  
    9. while (cnt_8ms < 250) //250 * 8ms = 2 second count
    10. {
    11. TMR0 = 0; //clear Timer0
    12.  
    13. while(TMR0 < 250); //wait for 8ms to pass (.008ms / .000032us)
    14. //do nothing until timer is > 8ms
    15.  
    16. ++cnt_8ms; //now timer is > 8ms so add 1 to counter variable
    17.  
    18. }
    This is really bad code.

    You can for instance test bit 7:

    Code ( (Unknown Language)):
    1. if(TMR0&0x80)
    2. {
    3. cnt_8ms++;
    4. TMR0&=0x7e;
    5. }
    Then later:

    Code ( (Unknown Language)):
    1.  
    2. if(cnt_8ms==200)
    3. {
    4. cnt_8ms=0;
    5. if (led_bit&0x01)led_bit&=0xfe;else led_bit|=0x01;
    6. }
    Dont forget to set cnt_8ms to zero when the program starts.

    If it does not work, run in the simulator.
     
  15. spinnaker

    AAC Fanatic!

    Oct 29, 2009
    4,884
    1,002
    Get down to the basics. Forget about your timing loop for now. Just get an LED to turn on and off.


    You set Latches you don't set Ports, you read ports. You should be using the LAT registers.


    LEARN to use your debugger. It will tell you a lot.
     
Loading...