Newbie Using Pic Timer0 C language question

Thread Starter

sprintfoot

Joined Mar 14, 2014
3
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.

Rich (BB code):
 #include <xc.h>
 #include <stdint.h>

#pragma config MCLRE = OFF, CP = OFF, CPD = OFF, BOREN = OFF, WDTE = OFF
#pragma config PWRTE = OFF, FOSC = INTRCIO


#define _XTAL_FREQ 4000000  //osc frequency
 //#define __delay_ms(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000.0)))

int count = 0;


void TimerBlinkLED()
{

  uint8_t  cnt_8ms;  //counter increments every 8ms

  while(1)
  {
  cnt_8ms = 0;

  while (cnt_8ms < 250)  //250 * 8ms = 2 second count
  {
    TMR0 = 0;  //clear Timer0
        
    while(TMR0 < 250)  //wait for 8ms to pass (.008ms / .000032us)
     {  //do nothing until timer is > 8ms
     }

    ++cnt_8ms;  //now timer is > 8ms so add 1 to counter variable
  }

  if (PORTC == 0b00000000)
    {
     PORTC = 0b00001000;
    }
  else
    {
     PORTC = 0b00000000;
    }
  }
}

void main()
{
    ADCON1 = 0x0F;  //deactivate A-D conveter
    //CMCON = 0x07;   //deactivate comparator module
    TRISC = 0b00000000; //set Input or 0utput bits
    PORTC = 0x00;   //clear port A

    OPTION_REGbits.T0CS = 0;  //select timer mode
    OPTION_REGbits.PSA = 0;  //assign presscaler to Timer0
    OPTION_REGbits.PS = 0b100;  //assign prescaler 32us

    while(1)
    {    
      TimerBlinkLED();
    }

}
 
Last edited by a moderator:

tshuck

Joined Oct 18, 2012
3,534
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
Rich (BB code):
ADCON1 = 0x0F;  //deactivate A-D conveter
code doesn't turn off the ADC. If you want to do that, you need to write
Rich (BB code):
ADCON0 = 0bXXXXXXX0
.
 

Papabravo

Joined Feb 24, 2006
21,159
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.
 

Thread Starter

sprintfoot

Joined Mar 14, 2014
3
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?
 

Papabravo

Joined Feb 24, 2006
21,159
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:

spinnaker

Joined Oct 29, 2009
7,830
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?
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.
 

John P

Joined Oct 14, 2008
2,025
This part of the code
Rich (BB code):
    while(TMR0 < 250)  //wait for 8ms to pass (.008ms / .000032us)
    {  //do nothing until timer is > 8ms
    }
    ++cnt_8ms;
will actually function as

Rich (BB code):
    while(TMR0 < 250)  //wait for 8ms to pass (.008ms / .000032us)
        ++cnt_8ms;
Because what is actually between the curly brackets?
 

Ian Rogers

Joined Dec 12, 2012
1,136
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!!
 

jjw

Joined Dec 24, 2013
823
This part of the code
Rich (BB code):
    while(TMR0 < 250)  //wait for 8ms to pass (.008ms / .000032us)
    {  //do nothing until timer is > 8ms
    }
    ++cnt_8ms;
will actually function as

Rich (BB code):
    while(TMR0 < 250)  //wait for 8ms to pass (.008ms / .000032us)
        ++cnt_8ms;
Because what is actually between the curly brackets?
I think OP wants to wait until TMR0 gets to 250 and then increment cnt_8ms.
So he should change to this:
Rich (BB code):
while(TMR0 < 250); // note semicolon here ! 
++cnt_8ms;
 
Last edited:

Thread Starter

sprintfoot

Joined Mar 14, 2014
3
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:

Rich (BB code):
#include <xc.h>
 #include <stdint.h>

#pragma config MCLRE = OFF, CP = OFF, CPD = OFF, BOREN = OFF, WDTE = OFF
#pragma config PWRTE = OFF, FOSC = INTRCIO


#define _XTAL_FREQ 4000000  //osc frequency
 //#define __delay_ms(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000.0)))


void TimerBlinkLED()
{

  uint8_t  cnt_8ms;  //counter increments every 8ms
  
  cnt_8ms = 0;

  while (cnt_8ms < 250)  //250 * 8ms = 2 second count
  {
    TMR0 = 0;  //clear Timer0
    
    while(TMR0 < 250);  //wait for 8ms to pass (.008ms / .000032us)
      //do nothing until timer is > 8ms

      ++cnt_8ms;  //now timer is > 8ms so add 1 to counter variable
    
  }

  
  if (PORTC == 0b00000000)
    {
     PORTC = 0b00001000;
    }
  else
    {
     PORTC = 0b00000000;
    }
}


void main()
{
    ADCON1 = 0x0F;  //deactivate A-D conveter
    //CMCON = 0x07;   //deactivate comparator module
    TRISC = 0b00000000; //set 1nput or 0utput bits
    PORTC = 0x00;   //clear port A

    OPTION_REGbits.T0CS = 0;  //select timer mode
    OPTION_REGbits.PSA = 0;  //assign presscaler to Timer0
    OPTION_REGbits.PS = 0b100;  //assign prescaler 32us

    //while(1)
   // {
     //Blink(); //works
      //LeftToRightAndBackLed();  //works
        //UseLpcButton(); //does not work
           TimerBlinkLED();
    //}

}

Any ideas???
 
Last edited by a moderator:

takao21203

Joined Apr 28, 2012
3,702
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.
 

takao21203

Joined Apr 28, 2012
3,702
OK apparently the OPTION_REG bits are set.

Rich (BB code):
void TimerBlinkLED()
{

uint8_t cnt_8ms; //counter increments every 8ms

cnt_8ms = 0;

while (cnt_8ms < 250) //250 * 8ms = 2 second count
{
TMR0 = 0; //clear Timer0

while(TMR0 < 250); //wait for 8ms to pass (.008ms / .000032us)
//do nothing until timer is > 8ms

++cnt_8ms; //now timer is > 8ms so add 1 to counter variable

}
This is really bad code.

You can for instance test bit 7:

Rich (BB code):
if(TMR0&0x80)
{
cnt_8ms++;
TMR0&=0x7e;
}
Then later:

Rich (BB code):
if(cnt_8ms==200)
{
cnt_8ms=0;
if (led_bit&0x01)led_bit&=0xfe;else led_bit|=0x01;
}
Dont forget to set cnt_8ms to zero when the program starts.

If it does not work, run in the simulator.
 
Top