¡Sí! Cuando configura los fusibles para hacer que el controlador funcione desde un reloj externo, también necesita ese reloj externo para la reprogramación.
Es importante notar que probé esto con un Arduino configurado como ISP (En el circuito Serial Programador), que no intenta proporcionar un reloj externo al dispositivo que se está programando. Otros programadores pueden hacer esto, pero eso dependería del programador. ISP es la forma más común de programar estos dispositivos, pero también hay otros programadores. El hecho es que el dispositivo en sí necesita un reloj externo. No estoy seguro para un programador paralelo. Un programador de alto voltaje puede prescindir de un reloj externo.
No probé esto con un ATmega, sino con un ATtiny45 , pero ambos AVR son muy similares en estos aspectos.
Esto es lo que hice:
- Escribí un pequeño programa para generar una salida de onda cuadrada de 1kHz (listado a continuación);
- Seleccioné el reloj de 2MHz y programé
.low = 0x61
. Observe que la configuración del fusible puede ser específica del controlador, por lo que esta es la configuración para ATtiny45;
- El controlador genera una frecuencia de 1 kHz, como se esperaba;
- Seleccioné 1.8432MHz para el reloj y programé
.low = 0xe0
;
- La frecuencia de salida se redujo a 0Hz hasta que conecté el oscilador, luego salté a 1kHz, nuevamente como se esperaba;
- Desconecté el oscilador externo (salida: 0Hz);
- Intenté programar el dispositivo, lo que resultó en:
avrdude: firma del dispositivo = 0xffffff
avrdude: ¡Ay! Firma de dispositivo no válida.
Vuelva a verificar las conexiones y vuelva a intentarlo, o use -F para anular esta verificación.
- Volví a conectar el oscilador externo y programé el dispositivo para 2MHz con el siguiente resultado:
avrdude hecho. Gracias.
- y, por supuesto, la salida volvió a 1kHz.
En conclusión:
Si programa los fusibles para usar un reloj externo, también necesitará un reloj externo para programar el dispositivo.
/*
(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;
}
}