Fast PWM problem with ATMEGA8

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

Hi all,

I am playing with an ATMEGA8 and have sucessfuly used the Overflow and CTC mode of timer0 and timer1. I am now trying the fast PWM mode of timer1 and don't get it to work. I have read the datasheet, googled,... but simply can't find the error. I have an oscilloscope connected to PIN15 of the ATMEGA8 and am looking for a squarewave with duty cycle 50% but the PIn stays simply low. Here is my code:

int main (void)
{

DDRB = _BV (PB1); /* PB1 (OC1) is digital output */
DDRB = 0xff;

timer1SetPrescaler( TIMER_CLK_DIV8 );
TCNT1 = 0;
OCR1A = 0x8000;

sbi(TCCR1A,COM1A1); // set OC1 on at COMP
sbi(TCCR1A,COM1A0); // reset OC1 at TOP

sbi(TCCR1A,WGM10); // -
sbi(TCCR1A,WGM11); // - Fast PWM
sbi(TCCR1B,WGM12); // - Fast PWM
sbi(TCCR1B,WGM13); // -

sbi(TIMSK, OCIE1A);
sei();

while (1) /* loop forever */
{
}

return (0);
}

The timer1SetPrescaler funtion simply sets the CS__ bits to some value != 0. The sbi macro is defined as follows:

#define sbi(REG,BIT) REG|=(1 << BIT)

What am I missing?

Thanks a lot!!

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

You have set the PWM mode to use OCR1A as TOP. With that mode you can not also use OCR1A as the duty cycle. Either use OCR1B as the duty cycle (and therefore OC1B (PB2) as output), or switch to mode 14 and use ICR1 as TOP.

Also, you are enabling the output compare A interrupt, but not providing an ISR for it.

Regards,
Steve A.

The Board helps those that help themselves.

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

Koshchi wrote:
You have set the PWM mode to use OCR1A as TOP. With that mode you can not also use OCR1A as the duty cycle. Either use OCR1B as the duty cycle (and therefore OC1B (PB2) as output), or switch to mode 14 and use ICR1 as TOP.

Also, you are enabling the output compare A interrupt, but not providing an ISR for it.

Thanks Steve! I realized my error and changed my code as follows:

int main (void)
{
DDRB = _BV (PB5); /* PB5 is digital output */
DDRB = _BV (PB1); /* PB1 is digital output */
DDRB = _BV (PB2); /* PB2 is digital output */
DDRB = 0xff;

timer1SetPrescaler( TIMER_CLK_DIV8 );
TCNT1 = 0;
ICR1 = 0x8000;
OCR1A = 0x7000;
OCR1B = 0x6000;

sbi(TCCR1A,COM1A1); // set OC1 on at COMP
sbi(TCCR1A,COM1A0); // reset OC1 at TOP

// mode 14: OCR1A defines COMP; ICR1 defines TOP, output on (OC1A) PB1
// mode 15: OCR1B defines COMP; OCR1A defines TOP; output on (OC1B) PB2
sbi(TCCR1A,WGM10); // -
sbi(TCCR1A,WGM11); // - Fast PWM
sbi(TCCR1B,WGM12); // - Fast PWM
sbi(TCCR1B,WGM13); // -

sbi(TIMSK, OCIE1A);
sei();

while (1) /* loop forever */
{
}

return (0);
}

Mode 14 is actually working for me now. I see the expected pulses on OC1 (PB1). I also tried mode 15 again with the shown values vor OCR1A, OCR1B, ICR1 but got nothing, neither on pin PB1 nor on pin PB2!? Still an error?? The table on page 97 of the ATMEGA8 datasheet helped me a bit. Unfortuantely it shows only which register defines TOP, not which register defines COMP. I guessed from your reply that it behaves as outlined in my new code but couldn't veryfy that for mode 15!? Moreover the PB2 pin o my Arduino board has the denotation (SS) whatever the means. I see only OC1 on pin PB1 but no OC1A and OC1B on two pins. May be the ATMEGA has only one PWM pin!?

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

Quote:
it shows only which register defines TOP, not which register defines COMP.

Any compare register that is not used as TOP can be used for compare.
Quote:
I also tried mode 15 again with the shown values vor OCR1A, OCR1B, ICR1 but got nothing, neither on pin PB1 nor on pin PB2!? Still an error??

Did you change the COM bits to B?
Quote:
Moreover the PB2 pin o my Arduino board has the denotation (SS) whatever the means. I see only OC1 on pin PB1 but no OC1A and OC1B on two pins.

Look in the mega8 datasheet to see what each pin does. The Arduino documentation is likely incomplete.

Regards,
Steve A.

The Board helps those that help themselves.

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

Hi Koshchi,

Koshchi wrote:
Quote:
it shows only which register defines TOP, not which register defines COMP.

Any compare register that is not used as TOP can be used for compare.
Quote:
I also tried mode 15 again with the shown values vor OCR1A, OCR1B, ICR1 but got nothing, neither on pin PB1 nor on pin PB2!? Still an error??

Did you change the COM bits to B?
Quote:
Moreover the PB2 pin o my Arduino board has the denotation (SS) whatever the means. I see only OC1 on pin PB1 but no OC1A and OC1B on two pins.

Look in the mega8 datasheet to see what each pin does. The Arduino documentation is likely incomplete.

It seems I was standing on the line. Thanks a lot for your hints. I got it now (expected signal on PB1 and PB2). Here is the final code:

int main (void)
{
output */
        DDRB = _BV (PB1);               /* PB1 is digital output */
        DDRB = _BV (PB2);               /* PB2 is digital output */

        timer1SetPrescaler( TIMER_CLK_DIV8 );
        TCNT1 = 0;  
        ICR1 = 0x7040;
        OCR1A = 0x7000;
        OCR1B = 0x6000;
         
        sbi(TCCR1A,COM1A1);     // set OC1 on at COMP
        sbi(TCCR1A,COM1A0);     // reset OC1 at TOP

        sbi(TCCR1A,COM1B1);     // set OC2 on at COMP
        sbi(TCCR1A,COM1B0);     // reset OC2 at TOP
 
        // mode 14: OCR1A defines COMP; ICR1 defines TOP;                     
        // mode 15: OCR1B defines COMP; OCR1A defines TOP;                     
        cbi(TCCR1A,WGM10);      //  -
        sbi(TCCR1A,WGM11);      //  - Fast PWM
        sbi(TCCR1B,WGM12);      //  - Fast PWM
        sbi(TCCR1B,WGM13);      //  -
 
        sbi(TIMSK, OCIE1A);
        sei();
        
        while (1)                       /* loop forever */
        {
        }
        
        return (0);
}

Thanks a lot!