2

I am having trouble setting up high speed PWM on my ATtiny85. I need to use the PCK, at a speed of 400 kHz. I believe that I have followed the data sheet correctly, but for some reason, the timer interrupt flags are not working.

If I program the device, the output of the corresponding pin is a constant 5 V.

If I comment out the PCK setup and use the system clock instead, the flags are correctly set and PWM works fine. The code is posted. Why aren't the flags setting and the PWM isn't working?

#include <avr/io.h>
#include <avr/interrupt.h>


int main(void)
{
    PORTB = 0;        //Reset values on port B

    // After setting up the timer counter,
    // set the direction of the ports to output
    DDRB |= (1<<PB1) | (1<<PB0); // Set the direction of PB1 to an output

    // PLLCSR - PLL control and status register:
    // PLL is a clock multiplier - multiplies system     8 MHz by 8 to 64 MHz
    // PLL is enabled when:PLLE bit is enabled,
    // CKSEL fuse is programmed to 0001.  This clock is
    //   switched off in sleep modes!
    PLLCSR |= (1<<PLLE);    // PLL enable

    // Wait until the PLOCK bit is enabled
    // before allowing the PCK to be enabled
    //WaitForPLOCK();
    //unsigned int i = 0;

    while ((PLLCSR & (1<<PLOCK)) == 0x00)
    {
        // Do nothing until plock bit is set
    }

    PLLCSR |= (1<<PCKE); // Enable asynchronous mode, sets PWM clock source


    TCCR1 =
            (1<<CTC1)    | // Enable PWM
            (1<<PWM1A)   | // Set source to pck
            (1<<(CS10))  | // Clear the pin when match with ocr1x
            (1<<COM1A1);
    GTCCR =   (1<<PWM1B) | (1<<COM1B1);


    // Set PWM TOP value - counter will count and reset
    //  after reaching this value
    //            OCR1C
    // 400 kHz    159
    // 450 kHz    141
    // 500 kHz    127
    OCR1C = 159;


    // Enable Timer1 OVF interrupt
    TIMSK = (1<<OCIE1A) | (1<<TOIE1);

    sei();

    // This should set the duty cycle to about 75%
    OCR1A = 120;
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
zmink1
  • 55
  • 1
  • 8
  • Which pin is it supposed to be generated on? – Ignacio Vazquez-Abrams Feb 09 '14 at 02:55
  • PB1 which I believe is pin number 5 – zmink1 Feb 09 '14 at 03:11
  • PB1 (OC1A) is pin 6. At least on the SOIC package. From what I can tell from a quick glance, the above code looks fine. But it seems some code is missing. What is happening after the last line "OCR1A=120"? What about code in interrupt handlers? – Rev Feb 10 '14 at 08:05
  • In the while loop, I created a local counter to count how many times the interrupt flag had been set. This is all the while loop does at this point. I definitely didn't include any interrupt handlers as I thought that the timer/counter unit already took care of them. Must I have a routine for the interrupt flags? – zmink1 Feb 10 '14 at 17:34
  • I believe it might have to do with the CKDIV or the clock source of the device - should it be at 8Mhz? The CKDIV8 fuse is programmed by default. – zmink1 Feb 10 '14 at 21:08
  • I realize you solved the problem but regarding you question from the comment: It is required to have an interrupt handler routine for every interrupt that is enabled. Otherwise the controller will jump to the reset vector / restart. So judging from the aboce code you should have at least two ISR's (for OCIE1A and TOIE1). – Rev Feb 11 '14 at 07:26

2 Answers2

2

The solution involved the CKDIV8 fuse. To program this fuse correctly however, HVSP "High Voltage Serial Programming" was required. After removing this fuse so that the device operated at 8 MHz, the PWM gave a 400 kHz output. I hope other people find this useful!

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
zmink1
  • 55
  • 1
  • 8
  • But you said you did measure a constant 5V on the output. Shouldn't it just have been slower by the factor 8? – Rev Feb 11 '14 at 07:27
  • Thats correct, it was slower by a factor of 8, but I think for the PLL to work correctly, that fuse has to be removed and the device must operate at 8Mhz. This is what solved the issue. I believe that in the data sheet it mentions this for the system clock, but it never states that this is necessary for TC1 – zmink1 Feb 11 '14 at 15:47
0

The errata (section 27 of the datasheet) states 'PLL will not lock under 6 MHz'. The only workaround listed is to set the clock to 6 MHz or higher.

zmink1
  • 55
  • 1
  • 8
Zuit
  • 16