Electronic – ATmega32 programming without external clock

atmegaavrmicrocontroller

I'm using an Atmega32. I want to use an external 16MHz crystal and I'm using a universal programmer (like http://www.kanda.com/products/wellon/VP-290.html). My question is: once I've programmed the chip and set its fuse bits to use an external oscillator, would I need an external oscillator when I'd want to reprogram its flash?

Best Answer

Yes! When you configure the fuses to make the controller run from an external clock, you also need that external clock for reprogramming.

It is important to notice that I tested this with an Arduino configured as ISP (In circuit Serial Programmer), which does not attempt to provide an external clock to the device that is being programmed. Other programmers may do this, but that would depend on the programmer. ISP is most common way of programming these devices, but there are other programmers too. Fact is that the device in itself needs an external clock. Unsure for a parallel programmer. A High Voltage programmer can do without an external clock.

I didn't test this with an ATmega, but rather with an ATtiny45, but both AVR's are very similar in these aspects.

This is what I did:

  • I wrote a small program to output a 1kHz square wave output (listing below);
  • I selected 2MHz clock and programmed .low = 0x61 Notice that the fuse settings may be controller specific, so this is the setting for ATtiny45;
  • The controller outputs a frequency of 1kHz, as expected;
  • I selected 1.8432MHz for clock and programmed .low = 0xe0;
  • Output frequency dropped to 0Hz until I connected the oscillator, then it jumped up to 1kHz, again as expected;
  • I detached the external oscillator (output: 0Hz);
  • Tried programming the device, resulting in:

avrdude: Device signature = 0xffffff

avrdude: Yikes! Invalid device signature.

Double check connections and try again, or use -F to override this check.

  • I reattached the external oscillator and programed the device for 2MHz the following result:

avrdude done. Thank you.

  • and of course the ouput was back at 1kHz.

So in conclusion:

If you program the fuses for using an external clock, then you also need an external clock to program the device.


/*
        (c) copyright 2013 by J.P. Hendrix
*/

#include <avr/io.h>
#include <util/delay.h>

#define _BS(bit) ( 1 << ( bit ) )
#define _BC(bit) ( 0 << ( bit ) )

/*
        ATtiny45

        pin     function        name    ISP     SPI     XO              I2C/TWI         comparator              ADC      pin chg
        1       !RESET          PB5                                                                             ADC0     PCINT5  dW
        2       extOscPin       PB3                     XTAL1   CLKI                                    !OC1B   ADC3     PCINT3
        3                       PB4                     XTAL2   CLKO                                    OC1B    ADC2     PCINT4
        4       GND             GND
        5                       PB0     MOSI    DI                      SDA             AIN0    OC0A    !OC1A   AREF     PCINT0
        6       outputPin       PB1     MISO    DO                                      AIN1    OC0B    OC1A    PCINT1
        7                       PB2     SCK     USCK                    SCL     T0                              ADC1     PCINT2  INT0
        8       VCC             VCC
*/

const uint8_t outputPin = _BS( PB1 );
const uint8_t extOscPin = _BS( PB3 );

#ifdef F_CPU
        #if   ( F_CPU == 1000000 )
                // 1MHz
                FUSES = { .low = LFUSE_DEFAULT  , .high = HFUSE_DEFAULT , .extended = EFUSE_DEFAULT , };
        #elif ( F_CPU == 1600000 )
                // 1.6MHz => ATtiny15 Compatibilty Mode
                #warn "ATtiny15 Compatibility Mode changes Timer1 behaviour!"
                FUSES = { .low = 0x63           , .high = HFUSE_DEFAULT , .extended = EFUSE_DEFAULT , };
        #elif ( F_CPU == 2000000 )
                // 2MHz
                FUSES = { .low = 0x61           , .high = HFUSE_DEFAULT , .extended = EFUSE_DEFAULT , };
        #elif ( F_CPU == 6400000 )
                // 6.4MHz => ATtiny15 Compatibility Mode
                #warn "ATtiny15 Compatibility Mode changes Timer1 behaviour!"
                FUSES = { .low = 0xe3           , .high = HFUSE_DEFAULT , .extended = EFUSE_DEFAULT , };
        #elif ( F_CPU == 8000000 )
                // 8MHz
                FUSES = { .low = 0xe2           , .high = HFUSE_DEFAULT , .extended = EFUSE_DEFAULT , };
        #elif ( F_CPU == 16000000 )
                // 16MHz
                FUSES = { .low = 0xe1           , .high = HFUSE_DEFAULT , .extended = EFUSE_DEFAULT , };
        #else
                // #error "F_CPU setting not recognized."
                // External oscillator selected
                FUSES = { .low = 0xe0           , .high = HFUSE_DEFAULT , .extended = EFUSE_DEFAULT , };
        #endif
#else
        #error "F_CPU not defined."
#endif

void setup( void ) {                            // Initialize all hardware
        DDRB = outputPin;                       // Data Direction Register Port B
}

int main( void ) {
        setup();                                // Initialize the hardware
        while ( 1 ) {
                _delay_us( 500 );
                PORTB ^= outputPin;
        }
}