Microcontrollers, timers and counters question

Thread Starter

hunterage2000

Joined May 2, 2010
487
Hi,

I have been trying to get my head around how to use timers and counters but I cant figure out what this example is saying. Heres one example

Rich (BB code):
#include <16F877.h>
#use delay(clock=lOOOOOOO)
#fuses HS,NOWDT
int outs;
#int_TIMERl
TIMERl_isr()
{
}
outs = outs A Oxl;
output_bit(PIN_D7, outs);
void main()
{
//interrupt occurs every 2 seconds
//toggle output bit
//replace this line with code to keep
II track of seconds, minutes, hours, days,
//etc. to implement a real clock.
setup_timer_l(Tl_EXTERNALITl_DIV_BY_1IOx8);
}
Q1 - For TIMER1_isr(), Can someone tell what the comments are saying? I understand the comment //interrupt occurs every second and even then I cant see what makes the interrupt every second

Q2 - What is happening in main()?
 

tshuck

Joined Oct 18, 2012
3,534
Q1 - For TIMER1_isr(), Can someone tell what the comments are saying? I understand the comment //interrupt occurs every second and even then I cant see what makes the interrupt every second
Interrupts can occur at a any point in the program execution. So, the interrupt must go to a specific place in memory. For the 16F series, I believe it is 0x0004, but is has been a while. This location is referred to as the interrupt vector, since all interrupts will force the program counter to this location. After that, typically, the user makes the program identify the interrupt that fired and takes appropriate action. This process is called the Interrupt-Service Routine(ISR). Most microcontrollers have a vectored interrupt where each interrupt will return to a different location in memory, PICs return to a single location, so you must spend processor cycles determining the source of the interrupt. One drawback of the PIC, but not a huge deal...

Q2 - What is happening in main()?
I don't know what compiler this was written for, but, from the function name, it sounds like it sets the timer up. The function isn't defined here, so it must be defined elsewhere, whether in the compiler, or another header file that wasn't #include(ed)...
 
Last edited:

tshuck

Joined Oct 18, 2012
3,534
You may want to look at my webpage http://www.fcet.staffs.ac.uk/sow1/pic_c18.htm
I explain a lot about interrupts etc.
The 'setup_timer_l(Tl_EXTERNALITl_DIV_BY_1IOx8)' is referring to an externally referenced library file. I would ditch this, and start with my website, libraries for the C18, and the datasheet.
I only saw explanations about how to set certain interrupts, and one wrong statement saying interrupts are called from either a timer or a change in an interrupt port...

Otherwise, looks pretty nice...
 

Thread Starter

hunterage2000

Joined May 2, 2010
487
I think its this interrupt thing I dont really get. Like interrupt every 0.036 seconds, not really sure what its interrupting or why interrupt.

I want to have a counter that counts while a button is not pressed and return a value of how long the button was off when pressed. When the button is pressed will this be the interrupt that sends stops the counter and returns the time it was off for?
 

tshuck

Joined Oct 18, 2012
3,534
I think its this interrupt thing I dont really get. Like interrupt every 0.036 seconds, not really sure what its interrupting or why interrupt.

I want to have a counter that counts while a button is not pressed and return a value of how long the button was off when pressed. When the button is pressed will this be the interrupt that sends stops the counter and returns the time it was off for?
An interrupt does just what it's name implies-it interrupts the processor. In fact, it interrupts the code at whatever point it is and goes to the interrupt vector. The source of an interrupt can be a timer module, CCP, ADC , UART, SPI, I2C, and many more. in your case, you would have to make the timer generate an interrupt after X clock cycles, since the microcontroller has no real concept of time, just however many clock oscillations have ocurred. If you are using a crystal, which I think you are, from your other posts, your clock's oscillations are pretty accurate, so, assuming you are using a 4MHz clock, each count in a timer represents \((4MHz/4)^{-1}\) seconds. You could generate an interrupt when a timer overflows, denoting a certain amount of time has passed. You will probably want to consult the datasheet for your device...

See the following links for more information:
Microchip Introduction to timers
Another one
Using The PIC Timers
Good read
An Online Timer Calculator
You may also find SamWane's website useful to look at how numbers are arrived at.
 

Thread Starter

hunterage2000

Joined May 2, 2010
487
I have read through the 16F877A datasheet and I cant make sense of it in a way I can understand. For example:

5.1 Timer0 Interrupt
The TMR0 interrupt is generated when the TMR0
register overflows from FFh to 00h. This overflow sets
bit TMR0IF (INTCON<2>). The interrupt can be
masked by clearing bit TMR0IE (INTCON<5>). Bit
TMR0IF must be cleared in software by the Timer0
module Interrupt Service Routine before re-enabling
this interrupt. The TMR0 interrupt cannot awaken the
processor from Sleep since the timer is shut-off during
Sleep.

I recognise the words but the paragraph as a whole makes no sense.
 

tshuck

Joined Oct 18, 2012
3,534
I have read through the 16F877A datasheet and I cant make sense of it in a way I can understand. For example:

5.1 Timer0 Interrupt
The TMR0 interrupt is generated when the TMR0
register overflows from FFh to 00h. This overflow sets
bit TMR0IF (INTCON<2>). The interrupt can be
masked by clearing bit TMR0IE (INTCON<5>). Bit
TMR0IF must be cleared in software by the Timer0
module Interrupt Service Routine before re-enabling
this interrupt. The TMR0 interrupt cannot awaken the
processor from Sleep since the timer is shut-off during
Sleep.

I recognise the words but the paragraph as a whole makes no sense.
Well, it comes with exposure to it;)

What it is saying is that the timer will create an interrupt-stop the main program flow to handle this event(timer overflow, which occurs at 0xFF -> 0x00).

You can choose to enable the interrupt by setting TMR0IE in the INTCON register(you'd also need to set the GIE bit in INTCON to enable interrupts on the whole).

The interrupt must be cleared before you can generate another interrupt(or really do anything...) as a return from the ISR(as defined previously) will go back to the main program and immediately interrupt again, since the flag was not cleared. So, you would have to clear TMR0IF explicitly.

Not all interrupts require explicit clearing.

The PIC has a sleep mode, wherein, it consumes less power, the timer0 interrupt cannot awaken the PIC from this mode...
 

ErnieM

Joined Apr 24, 2011
8,377
Perhaps an interrupt may best be explained by an example: say you are reading a book when your phone rings. You put a place holder in your book, close it, and answer the phone. When the call is complete you pick the book up, open to your bookmark, and resume reading.

The book is your main code and the phone is the interrupt. An interrupt can occur literally at anytime, and your main code needs to leave mark a trail to return to it's task. These marks consist of the return address, and the "context," which can be as simple as the contents of the W register and the status bits (and don't worry if you don't know what those are).


>5.1 Timer0 Interrupt
>The TMR0 interrupt is generated when the TMR0 register overflows from FFh to 00h.
>This overflow sets bit TMR0IF (INTCON<2>).

When the counter "rolls back" it sets a flag, and it is that flag that triggers the interrupt.

>The interrupt can be masked by clearing bit TMR0IE (INTCON<5>).

TMR0IE is the interrupt enable bit to turn the interrupt on or off (default). If you leave it off you don't get an inttrupt

>Bit TMR0IF must be cleared in software by the Timer0
>module Interrupt Service Routine before re-enabling
>this interrupt.

Part of ther interrupt routine is to clear the flag that triggered that interrupt. It's like an untimed whack-a-mole game: the mole just sits there until you smack it down, otherwise the game stalls.


>The TMR0 interrupt cannot awaken the
>processor from Sleep since the timer is shut-off during Sleep.

I would not worry about sleep for now. <grin>
 
#include <16F877.h>
#use delay(clock=lOOOOOOO)
#fuses HS,NOWDT
int outs;
#int_TIMERl
TIMERl_isr()
{
}
outs = outs A Oxl;
output_bit(PIN_D7, outs);
void main()
{
//interrupt occurs every 2 seconds
//toggle output bit
//replace this line with code to keep
II track of seconds, minutes, hours, days,
//etc. to implement a real clock.
setup_timer_l(Tl_EXTERNALITl_DIV_BY_1IOx8);
}
something is wrong there.
 

Thread Starter

hunterage2000

Joined May 2, 2010
487
I uploaded the wrong code before so heres the example I was trying

Rich (BB code):
int millisecs, outs;

#int_TIMER0
void TIMER0_isr(void)
{
   set_timer0(100);
   if(millisecs++ == 100)
   {
      millisecs = 0;
      outs = outs ^ 0xc0;
      output_d(outs);
   }
}

void main()
{
   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_psp(PSP_DISABLED);
   setup_timer_0(RTCC_EXT_L_TO_H|RTCC_DIV_16);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);

   setup_counters(RTCC_EXT_L_TO_H, RTCC_DIV_16);
   enable_interrupts(INT_TIMER0);
   enable_interrupts(global);
   outs = 0x80;

   while(1)
   ;

}
This is supposed to flash between LEDS at a 100ms rate but it isnt working. I have attached the code and circuit from the book. By the way, this was done using CCS C and PCW
 

Attachments

Brownout

Joined Jan 10, 2012
2,390
Most of the work is being done in the isr. The main sets up the controller hardware and then essentially does no more processing when it gets to the while(1) statement. All of the setup in main is performed by library functions ie "setup_timer0" etc. Assuming those routines are working correctly, timer 0 is set to run for 1ms and then overflow to assert the interrupt, which calls the isr. BTW, I can't tell where timer 0 is actually being srarted.

So anyway, in the isr, the code checks for 100 interrupts, then modifies the output to the led's. It also reloads the variable "milliseconds" to enable checking for 100 interrupts.

That's the best I can figure without seeing how the library functions are written. I'm not completely familiar with your environment. If your led's aren't changing, and assuming the hardware is set up correctly, then I'd say your isr isn't being called. Make sure the timer is actually being started.
 

tshuck

Joined Oct 18, 2012
3,534
I uploaded the wrong code before so heres the example I was trying

Rich (BB code):
int millisecs, outs;

#int_TIMER0
void TIMER0_isr(void)
{
   set_timer0(100);
   if(millisecs++ == 100)
   {
      millisecs = 0;
      outs = outs ^ 0xc0;
      output_d(outs);
   }
}

void main()
{
   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_psp(PSP_DISABLED);
   setup_timer_0(RTCC_EXT_L_TO_H|RTCC_DIV_16);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);

   setup_counters(RTCC_EXT_L_TO_H, RTCC_DIV_16);
   enable_interrupts(INT_TIMER0);
   enable_interrupts(global);
   outs = 0x80;

   while(1)
   ;

}
This is supposed to flash between LEDS at a 100ms rate but it isnt working. I have attached the code and circuit from the book. By the way, this was done using CCS C and PCW
I don't use CCS C, so this may be wrong, but I don't see a place where your interrupt flag is cleared(TMR0IF = 0). If you don't clear the flag, your controller will continue to interrupt, over and over....

Also, I don't see where your TIMER0_isr is declared as an interrupt. The compiler needs to know that this function is an ISR, and not just any ol' function...
 

takao21203

Joined Apr 28, 2012
3,702
Run the timer from the internal clock to see if it works.

If not then you have a problem with the clock source.

Normally the timer0 flag is reset this is pretty standard.
All the setup also is nonstandard.
 

ErnieM

Joined Apr 24, 2011
8,377
Are you running this on real hardware or are you simulating?

I would hope the latter, it can teach you much more about exactly what the code is doing.

So can the hardware with an in-circuit debugger but that assumes the hardware is all working.
 

thatoneguy

Joined Feb 19, 2009
6,359
What book is it?

Does the book use CCS in all of the examples?

If so, you may want to take a peek at the publisher page for any errata that came out after your book was printed.

CCS does some things differently, functions to set comparators and analog, rather than registers, etc. Unsure if the interrupt needs to be defined as interrupt or void, and if it clears the flag or not when interrupt is finished.

What does it do in CCS Simulation? Timer interrupts should simulate fine.
 
Top