Microcontrollers, timers and counters question

Discussion in 'General Electronics Chat' started by hunterage2000, Feb 11, 2013.

  1. hunterage2000

    Thread Starter Senior Member

    May 2, 2010

    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

    Code ( (Unknown Language)):
    2. #include <16F877.h>
    3. #use delay(clock=lOOOOOOO)
    4. #fuses HS,NOWDT
    5. int outs;
    6. #int_TIMERl
    7. TIMERl_isr()
    8. {
    9. }
    10. outs = outs A Oxl;
    11. output_bit(PIN_D7, outs);
    12. void main()
    13. {
    14. //interrupt occurs every 2 seconds
    15. //toggle output bit
    16. //replace this line with code to keep
    17. II track of seconds, minutes, hours, days,
    18. //etc. to implement a real clock.
    19. setup_timer_l(Tl_EXTERNALITl_DIV_BY_1IOx8);
    20. }
    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()?
  2. tshuck

    Well-Known Member

    Oct 18, 2012
    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...

    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: Feb 11, 2013
  3. SamWane

    New Member

    Feb 11, 2013
    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.
    Last edited: Feb 11, 2013
  4. tshuck

    Well-Known Member

    Oct 18, 2012
    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...
  5. hunterage2000

    Thread Starter Senior Member

    May 2, 2010
    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?
  6. tshuck

    Well-Known Member

    Oct 18, 2012
    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.
  7. hunterage2000

    Thread Starter Senior Member

    May 2, 2010
    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

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

    Well-Known Member

    Oct 18, 2012
    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...
  9. Brownout

    Well-Known Member

    Jan 10, 2012
    Your code doesn't look like working code to me. Are you sure this is working code?
  10. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    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>
  11. electron_prince

    Active Member

    Sep 19, 2012
    something is wrong there.
  12. Metalmann

    Active Member

    Dec 8, 2012
    You guys are amazing!

    I still can't seem to wrap my head around a 555.:confused:

    Thanks, and carry on.;)
  13. hunterage2000

    Thread Starter Senior Member

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

    Code ( (Unknown Language)):
    2. int millisecs, outs;
    4. #int_TIMER0
    5. void TIMER0_isr(void)
    6. {
    7.    set_timer0(100);
    8.    if(millisecs++ == 100)
    9.    {
    10.       millisecs = 0;
    11.       outs = outs ^ 0xc0;
    12.       output_d(outs);
    13.    }
    14. }
    16. void main()
    17. {
    18.    setup_adc_ports(NO_ANALOGS);
    19.    setup_adc(ADC_OFF);
    20.    setup_psp(PSP_DISABLED);
    21.    setup_timer_0(RTCC_EXT_L_TO_H|RTCC_DIV_16);
    22.    setup_timer_1(T1_DISABLED);
    23.    setup_timer_2(T2_DISABLED,0,1);
    24.    setup_comparator(NC_NC_NC_NC);
    25.    setup_vref(FALSE);
    27.    setup_counters(RTCC_EXT_L_TO_H, RTCC_DIV_16);
    28.    enable_interrupts(INT_TIMER0);
    29.    enable_interrupts(global);
    30.    outs = 0x80;
    32.    while(1)
    33.    ;
    35. }
    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
  14. ErnieM

    AAC Fanatic!

    Apr 24, 2011
  15. Brownout

    Well-Known Member

    Jan 10, 2012
    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.
  16. tshuck

    Well-Known Member

    Oct 18, 2012
    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...
  17. takao21203

    AAC Fanatic!

    Apr 28, 2012
    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.
  18. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    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.
  19. thatoneguy

    AAC Fanatic!

    Feb 19, 2009
    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.