need timer interrupt help

Go To Last Post
9 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hi
im trying to teach myself how to do interrupts correctly, easiest sounding one was making an LED flash according to timer interrupts. i wrote this code for the mega162 running at 13.5 MHz;

#include
#include
#include

#define bit0 0b00000001

int volatile cntr;

int main(void)
{
DDRB = 0b00000001;

///timer register init
TCCR0 = (1<<CS00)|(1<<CS02);//prescaler set to 1024
TCCR0 |= (1<<WGM01);//clear timer on compare

OCR0 = 0x83;//set output compare number

TIMSK = (1<<OCIE0);//o/p capture interrupt enabled

sei();//enable interrupts

while(1)
{
cntr = 0;
while(cntr < 100);
PORTB ^= bit0;//toggle bit 0
}
return 0;
}

SIGNAL(SIG_OVERFLOW0)//interrupts when overflow reached
{
cntr++;
return;
}

which i cant find a problem with. everything seems to work except cntr never gets incremented when i run it on the simulator. this leads me to believe i messed up somewhere in the interrupt code. anyone got any ideas?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This is not GCC code, but it works. Perhaps the #pragma is what is missing in your code?

#include 
#include 

#pragma interrupt_handler timer:11 timer:12

void timer1_init(void);
void init_devices(void);

//**************************************************************************
// M A I N    
//**************************************************************************	    
void main (void)
{
	init_devices();
	timer1_init();
	while (1);
}

//**************************************************************************
// NAME:		timer1_init											
// PARAMETERS:	None												
// RETURNS:		Nothing												
// PURPOSE:		Initialize Timer/Counter 1 to interrupt every .01 seconds
// Warnings:	Untested	 			   	 			  				
// Notes:
//**************************************************************************	    
void timer1_init(void)
{
	TCCR1A = 0x00;
	TCCR1B = 0x00; //stop
	TCCR1C = 0x00;
	OCR1AH = 0x13;
	OCR1AL = 0x88;
	TCCR1B = 0x0A;					 	 	
}
//*****************************************************************
// Timer A Interrupts Every 100Ms
//*****************************************************************
void timer(void)
{
unsigned char i;
++i;
}
//**************************************************************************
// NAME:          init_devices						
// PARAMETERS:    None												
// RETURNS:		  Nothing									
// PURPOSE:		  Initialize everything							 
// Warnings:	  App Builder generated code							
// Notes:		  Call this routine to initialize all peripherals at power-up
//**************************************************************************	    
void init_devices(void)
{
								//stop errant interrupts until set up
	CLI(); 					//disable all interrupts
	timer1_init();
	
	MCUCR = 0x00;
	EICRA = 0x00; 			//extended ext ints
	EIMSK = 0x00;
 
	TIMSK0 = 0x00; 			//timer 0 interrupt sources
	TIMSK1 = 0x00; 			//timer 1 interrupt sources
	TIMSK2 = 0x00; 			//timer 2 interrupt sources
 
	PCMSK0 = 0x00;			//pin change mask 0 
	PCMSK1 = 0x00;			//pin change mask 1 
	PCMSK2 = 0x00;			//pin change mask 2
	PCICR = 0x00;			//pin change enable 
	PRR = 0xE1;				//power controller
	SEI();
	TIMSK1 = (1<<OCIE1A);	// OCIE1A Compare A Interrupt enable
}

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

what does #pragma do ? i looked into my K&R and can't realy figure it out.what im trying to figure out with this program is how to use interrupts to change variables used in the main() code. i can single step to "while(cntr < 100);" but it never gets out of this loop because apparently cntr which is supposed to be incremented every interrupt (10mS) never changes. ive read about stuff like this happening if you dont declare the variable volatile but i did that so im stuck.oh forgot to mention that i set the prescaler to 1 while debugging.but i only did that after stuff failed to happen with the real code.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This line:

#pragma interrupt_handler timer:11 timer:12 

tells the compiler that the "timer()" function is an interrupt routine so the code is built with the correct interrupt pointers and the interrupt routine ends with a "reti" rather than a "ret" instruction.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

it doesnt look like it ever actualy enters the interrupt routine, otherwise cntr would get stuck at 1 instead of zero. ive checked out other interrupt code on this forum and they didnt use pragma either so i dont think thats it. could the problem be with simulator maybe? the posts ive mainly looked at are:
http://8515.avrfreaks.net/index....
and
http://8515.avrfreaks.net/index....
both of these have at least partialy working interrupt code. it looks to me at least like i followed the same form....i also used avr130 as adapted by me to the mega162.i think its likely that i missed something but i have no idea what it could be.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You have set Timer0 for clear on output compare so it will never overflow.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

:oops: yeah just caught that. singlestepped past 0x83 and wondered why the code executed all the way from the top again. didnt catch it before cause i was using autostepping. thanks for the time guys. i swear ill get better at this programming thing one day....btw if i want to have interrupts enabled at the start of the ISR do i call it like
INTERRUPT(SIG_OUTPUT_COMPARE0)
{
//stuff
}
?

anyway heres the fixed code

//flashes LED on port b bit 0 at about 1Hz
//F_CPU = 13.5MHz

#include
#include
#include

#define bit0 0b00000001

int volatile cntr;

int main(void)
{
DDRB = 0b00000001;

///timer register init
TCCR0 = (1<<CS00)|(1<<CS02);//prescaler set to 1024
TCCR0 |= (1<<WGM01);//clear timer on compare

OCR0 = 0x83;//set output compare number

TIMSK = (1<<OCIE0);//o/p capture interrupt enabled

sei();//enable interrupts

while(1)
{
cntr = 0;
while(cntr < 50); //wait for ~ 1 second
PORTB ^= bit0;//toggle bit 0
}
return 0;
}

SIGNAL(SIG_OUTPUT_COMPARE0) /* interrupts when compare reached with interrupts initialy disabled */
{
cntr++;
return;
}

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yup, difference between INTERUPT() and SIGNAL() is the former executes with an implied sei() at the top.

By the way #pragma is a way for compiler writers to add their own special functions to a compiler that will be ignored by others. So that "#pragma interrupt_handler timer:11 timer:1" is just one compilers way of specifying that a certain interrupt is "alive" and has a handler supplied. The GCC way of doing this is actually "cleaner" in that it's all hidden within your use of SIGNAL() or INTERRUPT() - there's nothing else needed to define an interrupt handler for GCC.

Cliff

Last Edited: Fri. Sep 16, 2005 - 12:54 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I had the same problem "with starting up from above"

#include  

helped in my case...

(To check, if you have the same problem, check in the *.lst file, if your ISR (or its entry address) entered is in the Vector Table

#pragmas won't do it for GCC.