Hey Anthony! >Myko Predko: I have recently purchased your book and I love it. I >bought a copy of HiTech C and your book is a valuable reference, more >than the $35 I paid. I'm glad you like it so much (always gratifying). >My question concerns the use of TMR0 to generate interrupts. Your book >makes little or no mention of RTC, which i think means "real time >clock". Also, no further information was made available about its >proper use. I didn't notice this until I started scanning the PICLIST >and found that everyone has found writing to TMR0 in an interrupt >service routine to be very tricky. If someone is willing to provide a >detailed explanation about Timer based interrupts, please do so. Note >that this project is similar to your servo controller. So here is the >situation: > >I want an interrupt to be generated every 20mS ( the interrupt generates >the pulses ) but using the information on page 44-45 dosen't work. The >timer fires way too often during simulation. The Timer is given an >"update" at the end of the interrupt, could the prescaler be at fault? >And why does the interrupt trigger 4mS into execution? Please provide >any psuedo-code you can offer that will rid me of this ignorance I have been >suffering from. A real time clock (which is "RTC") can be produced internally in the PICMicro three different ways. The first is to use an external part which is dedicated to the task (Dallas Semiconductor have some good ones that are easy to interface to the PICMicro). The second is to use TMR1 of the PICMicro (if it has one on board) with a digital watch (32.768 kHz) crystal. The third way is to use TMR0 by loading it with a value to overflow (and interrupt) after a set period. As I indicate on pages 44-45, the formula that I use to get the overflow value is: InitTMR0 = 256 - ((Delay * Frequency) / (4 * Prescaler)) So, for the servo project (4 MHz with no prescaler), This can be calculated out as: InitTMR0 = 256 - ((20 msec * 4 MHz) / (4 * 2)) = 256 - (80x10**3 / 8) = 256 - 10,000 Which is obviously invalid - TMR0 cannot be loaded with a negative number. What has to be done is to use the prescaler to bring the "InitTMR0" value positive. When I use a OPTION register prescaler bit value of 7, I get a input divide by 256, which changes the "InitTMR0" to: InitTMR0 = 256 - ((20 msec * 4 MHz) / (4 * 256)) = 256 - (80x10**3 / 1024) = 256 - 78 = 178 Which is the value used in the Servo Application. I suspect the problem that you are having is that you are running at 20 MHz, whereas I was running at 4 MHz for my application (which would cause the interrupt to happen 5x more often as you are seeing). Plugging the new speed into the formula, we get: InitTMR0 = 256 - ((20 msec * 20 MHz) / (4 * 256)) = 256 - (400x10**3 / 1024) = 256 - 391 Which is again not a valid number to load into TMR0. So, to get around this, I would recommend that you Interrupt once every 10 msecs. In this case, the delay would be: InitTMR0 = 256 - ((10 msec * 20 MHz) / (4 * 256)) = 256 - (200x10**3 / 1024) = 256 - 195 = 61 The Interrupt code isn't that hard for this case. The shell that you would want to use would be: org 0 goto Mainline org 4 Int movwf _w ; Save Context Registers movf STATUS, w movwf _status bcf INTCON, T0IF ; Reset the Timer Interrupt Request movlw 61 ; Reset the Timer movwf TMR0 comf TMR0Flag ; Invert the Execution Flag movf TMR0Flag, f btfss STATUS, Z goto IntEnd ; If Execution Flag Register is != 0 then Skip Over : ; Execute once every 20 msec code IntEnd movf _status, w movwf STATUS swapf _w swapf _w, w retfie Mainline ; Initialize the Variables clrf TMR0Flag ; Initialize the Wait for 20 msecs Flag : ; Do other Initializations bsf STATUS, RP0 movlw 0x0D7 ; Initialize the OPTION Register movwf OPTION_REG ^ 0x080 : ; Do any other Page one Initializations bcf STATUS, RP0 movlw 61 ; Initialize TMR0 to a 10 msec delay movwf TMR0 movlw 0x0A0 ; Enable the Timer Interrupts movwf INTCON : ; Go on with the rest of the application Hmmm... Maybe I'll make this into a Template/Macro/Rentron article. >Thanks a Million, No problem - please let me know if there's anything else you are having trouble with or something that I haven't explained well enough. In the code above, note that I reset the interrupt and the timer before doing the 20 msec code check to make sure that the code is always consistent. My next Rentron article will have a macro which will set up TMR0 for just this purpose for Serial Communication. Good luck, myke