Timer interrupt for pic18f4550 - Page 1
Forum section: electronics / general

author: Bibiricat
author_rank: Contributor
timestamp: March 17, 2013, 08:41:50 pm
content: Hello.I am trying to make a 50Hz pwm signal using interrupt and timer 0, however, i have tried a number of examples and i can't get the program to enter in the interrupt. I have tried a lot of configs, and i still can't get a single interrupt to work.I am using pic18f4550 with usb bootloader .I may have some extra config i don't need, and some missing config i need, so please feel free to correct me.This is my code:#include <p18f4550.h>#pragma code REMAPPED_RESET_VECTOR=0x1000 //Because of the bootloaderextern void _startup (void);void _reset (void){_asm goto _startup _endasm}void high_isr(void);#pragma code/************************************************************/#pragma code high_vector=0x08void interrupt_at_high_vector(void){_asm GOTO high_isr _endasm}#pragma code/*****************High priority ISR **************************/#pragma interrupt high_isrvoid high_isr (void){if (INTCONbits.TMR0IF){ // Interrupt CheckINTCONbits.TMR0IF = 0;TMR0H = 0xEE; //Timer0 initializareTMR0L = 0xEE;PORTBbits.RB7 = 0;}}/***********************************************************/void main(void){unsigned int second, check;// config interruptINTCON = 0x20;INTCON2 = 0x04; //TMR0 high priorityRCONbits.IPEN = 1; //enable priority levels// Timer0 configurationT0CONbits.TMR0ON = 0; // Stop the timerT0CONbits.T08BIT = 0; // Run in 16-bit modeT0CONbits.T0CS = 0; // Use system clock to increment timerT0CONbits.PSA = 0; // A prescaler is assigned for Timer0T0CONbits.T0PS2 = 1; // Use a 1:256 prescalerT0CONbits.T0PS1 = 1;T0CONbits.T0PS0 = 1;INTCONbits.GIEH = 0;INTCONbits.TMR0IE = 1; //1 = Enables the TMR0 overflow interruptINTCONbits.TMR0IF = 0;INTCONbits.INT0IF = 0; //1 = The INT0 external interrupt occurred (must be cleared in software)T0CONbits.TMR0ON = 1; // Start the timerTMR0L = 0x82; //(255-130)*4/Fosc *prescaler=0.05msTMR0H = 0x85;INTCONbits.GIEH = 1; //enable interrupts// LED configurationTRISB = 0; // Configure portb as an outputPORTBbits.RB7 = 1;while(1) // Program loop{}}

author: Psi
author_rank: Super Contributor
timestamp: March 17, 2013, 09:33:33 pm
content: Just and though.I don't really know the PIC interrupt syntax but with some micros you have to be careful using interrupts when you have a bootloader.You can end up with interrupts in a memory area assigned for bootloader code and then be unable to call them from main.Especially if you have played with the fuse bits to lockdown main code reading bootloader memory and/or vice versa.

author: DavidDLC
author_rank: Frequent Contributor
timestamp: March 17, 2013, 11:21:31 pm
content: This is working for me, but I'm using a different compiler, you can use it as a reference./*************************************************************************************************// I N T E R R U P T S E R V I C E S **********************************************************//*************************************************************************************************#pragma interrupt HighPriorityIntvoid HighPriorityInt(void){}//HighPriorityInt#pragma interruptlow LowPriorityIntvoid LowPriorityInt(void){if ( INTCONbits.TMR0IF == 1){PORTBbits.RB7 = 1;INTCONbits.TMR0IF = 0; //Need to clear timer interuption flagTMR0L = Timer_Low; //Init value for CounterTMR0H = Timer_High; //Init value for CounterPORTBbits.RB7 = 0;}}//LowPriorityInt//*************************************************************************************************// V E C T O R R E M A P P I N G ****************************************************************//*************************************************************************************************#pragma code high_vector=0x08void interrupt_at_high_vector(void){_asm goto HighPriorityInt _endasm}#pragma code low_vector=0x18void interrupt_at_low_vector(void){_asm goto LowPriorityInt _endasm}#pragma code// *** Interrupt configuration *** //INTCONbits.TMR0IF = 0; //Clear timer interuption flagRCONbits.IPEN = 0; //Enable/Disable priority levelsINTCONbits.GIEH = 0; //Enable/Disable high priority interruptINTCONbits.GIEL = 0; //Enable/Disable low priority interruptINTCONbits.TMR0IE = 0; //Enable/Disable Timer 0 interruptINTCON2bits.TMR0IP = 0; //Timer 0 is low priority interrupt// *** Timer 0 Configuration *** //T0CONbits.T08BIT = 0; //1=8 bit timer, 0=16 bit timerT0CONbits.T0CS = 0; //Use internal clock, use as TimerT0CONbits.PSA = 1; //Do not use prescalerTMR0L = Timer_Low; //Init value for Timer 0TMR0H = Timer_High; //Init value for Timer 0T0CONbits.TMR0ON = 0; //Enable Timer = 1 Disable Timer = 0

author: DavidDLC
author_rank: Frequent Contributor
timestamp: March 17, 2013, 11:23:44 pm
content: Sorry:T0CONbits.TMR0ON = 1; //Enable Timer = 1 Disable Timer = 0Should be 1, I had it temporary disabled for some testing.

author: ecat
author_rank: Frequent Contributor
timestamp: March 18, 2013, 01:26:01 am
content: At the very least...QuoteSo, to set TH & TL you MUST write the values in the correct orderTMR0H = Timer_High; // must set TH before writing to TLTMR0L = Timer_Low; // writing to TL updates TL and TH@DavidDLC,Your code may appear to work but in reality the first interrupt will be slow to appear, after that the value you set in TH will be the previous value written to the THbuffer, not necessarily the value currently in Timer_High.@Bibiricat,You have the same problem in your initialisation codeTMR0L = 0x82; //(255-130)*4/Fosc *prescaler=0.05msTMR0H = 0x85;So, TL = 0x82, the THbuffer= 0x85 but the actual TH register = ?? ie whatever happened to be in the THbufferat the time TL was written, after a reset it could well be zero.In this case you are running a 1/255 prescaler. At 8MHz: 8000000 / 4 / 256 = 7812.5Hz timer frequency, assuming 0 in TH your count to interrupt will be around 0xff00 (65280), 65280 * 1 / 7812.5 = 8.35584 secondsYou appear to be running at 2MHz (? from the TMR0L comment above), so the time to your first interrupt will be around 40 seconds, after which you will run at your 0xEEEE timings.Your code looks feasible, are you perhaps declaring the code bad before the 40 seconds are up? I've certainly done this at least once... or twice

author: JTR
author_rank: Regular Contributor
timestamp: March 18, 2013, 02:36:38 pm
content: What you are doing is useless. There is not point in trying to remap the interrupt vectors @ 0x0008 and 0x0018 if you have a bootloader installed. The bootloader is not going to write these new values. It has already remapped the vectors to 0x1008 and 0x1018 and you must pick up the vectors from these addresses. You will not be able to change this as the bootloader protects its own space and will not erase and write to it.This is the sort of system you need to use: (assuming microchip HID bootloader)#define REMAPPED_RESET_VECTOR_ADDRESS 0x1000#define REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESS 0x1008#define REMAPPED_LOW_INTERRUPT_VECTOR_ADDRESS 0x1018#pragma code REMAPPED_HIGH_INTERRUPT_VECTOR = REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESSvoid Remapped_High_ISR(void) {_asm goto InterruptHandlerHigh _endasm}#pragma code REMAPPED_LOW_INTERRUPT_VECTOR = REMAPPED_LOW_INTERRUPT_VECTOR_ADDRESSvoid Remapped_Low_ISR(void) {_asm goto InterruptHandlerLow _endasm}#pragma interrupt InterruptHandlerHighvoid InterruptHandlerHigh(void) {}#pragma interruptlow InterruptHandlerLowvoid InterruptHandlerLow(void) {}Try it and see how you go.EDIT:To make your firmware compatible in case there is no bootloader installed you can add the following code. If there is a bootloader this code will not be written into the PIC but it is harmless in that case.//set the initial vectors so this works without the bootloader too.#pragma code HIGH_INTERRUPT_VECTOR = 0x08void High_ISR(void) {_asm goto REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESS _endasm}#pragma code LOW_INTERRUPT_VECTOR = 0x18void Low_ISR(void) {_asm goto REMAPPED_LOW_INTERRUPT_VECTOR_ADDRESS _endasm}

author: DavidDLC
author_rank: Frequent Contributor
timestamp: March 18, 2013, 06:13:19 pm
content: Quote from: ecat on March 18, 2013, 01:26:01 amAhh good to know !Thank you.

author: Bibiricat
author_rank: Contributor
timestamp: March 18, 2013, 07:48:28 pm
content: Thanks all of you for the code/advice . Managed to finally get the interrupts working. Now i just have to tune it for the 50Hz signal i want.Also i am using 20MHz external crystal .The final code is this:Code:#include <p18f4550.h> // Always include the header file#define REMAPPED_RESET_VECTOR_ADDRESS 0x1000#define REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESS 0x1008#define REMAPPED_LOW_INTERRUPT_VECTOR_ADDRESS 0x1018#define Timer_Low 0x88#define Timer_High 0x88void InterruptHandlerHigh(void);void InterruptHandlerLow(void);/***************Bootloader************************************/#pragma code REMAPPED_RESET_VECTOR = REMAPPED_RESET_VECTOR_ADDRESSextern void _startup (void);void _reset (void){_asm goto _startup _endasm}#pragma code/**************************************************************///**************************************************************// V E C T O R R E M A P P I N G *****************************//**************************************************************#pragma code REMAPPED_HIGH_INTERRUPT_VECTOR = REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESSvoid Remapped_High_ISR(void) {_asm goto InterruptHandlerHigh _endasm}#pragma code#pragma code REMAPPED_LOW_INTERRUPT_VECTOR = REMAPPED_LOW_INTERRUPT_VECTOR_ADDRESSvoid Remapped_Low_ISR(void) {_asm goto InterruptHandlerLow _endasm}#pragma code/**************Interrupts*************************************/#pragma interrupt InterruptHandlerHighvoid InterruptHandlerHigh(void) {if ( INTCONbits.TMR0IF == 1){INTCONbits.TMR0IF = 0; //Need to clear timer interuption flagTMR0L = Timer_Low; //Init value for CounterTMR0H = Timer_High; //Init value for Counterif(PORTBbits.RB7 == 0) PORTBbits.RB7 = 1;else PORTBbits.RB7 = 0;}}#pragma interruptlow InterruptHandlerLowvoid InterruptHandlerLow(void) {}/*************************************************************/void main(void){// LED configurationTRISB = 0; // Configure portb as an outputPORTBbits.RB7 = 1;// *** Interrupt configuration *** //INTCONbits.TMR0IF = 0; //Clear timer interuption flagRCONbits.IPEN = 1; //Enable/Disable priority levelsINTCONbits.GIEH = 1; //Enable/Disable high priority interruptINTCONbits.GIEL = 0; //Enable/Disable low priority interruptINTCONbits.TMR0IE = 1; //Enable/Disable Timer 0 overflow interruptINTCON2bits.TMR0IP = 1; //Timer 0 is high priority interrupt// *** Timer 0 Configuration *** //T0CONbits.T08BIT = 0; //1=8 bit timer, 0=16 bit timerT0CONbits.T0CS = 0; //Use internal clock, use as TimerT0CONbits.PSA = 1; //Do not use prescalerTMR0H = Timer_High; //Init value for Timer 0TMR0L = Timer_Low; //Init value for Timer 0T0CONbits.TMR0ON = 1; //Enable Timer = 1 Disable Timer = 0while(1) // Program loop{}}