Missing Timer1 ISR on first run - Problem solved

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

Hi!

My application receives a 1ms trigger pulse every 33ms. The time between each trigger pulse is called a frame. When I receive a trigger I put out a certain number of PWM pulses before waiting for the trigger to indicate the next frame.
I use a mega325. The external interrupt (PORTD1) catches the rising edge of the trigger and Timer1 puts out the PWM pulses on OC1B (PORTB6).
The external interrupt starts Timer1 and counts number of frames, and disables itself when the desired number of frames is reached.
The Timer1 interrupt counts the pulses and stops the timer when done.

And now, the problem:
On the first run, after power up or a reset, when I send a start-command no pulses appear until the last frame. The only thing I can see that changes before the last frame is that the external interrupt is turned off (CLEARBIT(EIMSK,INT0)). After this first run everything behaves as expected.
I use gcc (WinAVR-20070525), and I have tried to run the application in AVR Studio. I have put breakpoints at different places, and it looks like the timer interrupt isn't flagged before the external interrupt is disabled. Since Timer1 is configured as Fast PWM with OCR1A as TOP I've tried both overflow and compare interrupt, but it makes no difference. Still same problem.

Any suggestions?

-Jan Egil

Last Edited: Fri. Oct 26, 2007 - 06:24 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Any suggestions
?
Show us the relevant code. It will be very hard to debug without it.

Regards,
Steve A.

The Board helps those that help themselves.

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

Here is my problem explained a little easier:
First the PWM-mode is configured in an init-function:
TCCR1A = (1<<COM1B1)|(1<<WGM11)|(1<<WGM10);
TCCR1B = (1<<WGM13)|(1<<WGM12);

Then when the application is running a user input value is written to the compare-register:
OCR1A = usNewPulseDutyCycle;

When the user sends a start-command the external interrupt is enabled. At the execution of the external interrupt the PWM-timer is started:
SETBIT(TCCR1B,CS11);

The timer stops itself after a certain amount of PWM-pulses, and can be restarted by the user. The OCR1A-value can be changed by the user when the timer is stopped, but the init-function is only executed at boot/reset.

The reason this doesn't work perfectly is that the double buffering of OCR1A is enabled whenever the timer is configured in a PWM-mode. Whenever the OCR1A is changed the register won't be updated until the timer is started and reaches TOP-value. At first run, after a boot/reset, the TOP is when the timer wraps around to 0x0000.

Somehow I believed that the double buffering only was enabled when the timer was running (CS12:0 != 000).
The solution is not to configure the PWM-mode in the init-function, but when the timer is started, and to disable it when the timer is stopped.

Sorry for wasting your time.

-Jan Egil