Estoy usando un Atmega32. Quiero usar un cristal externo de 16MHz y estoy usando un programador universal (como http://www.kanda.com/products/wellon/VP-290.html ). Mi pregunta es: una vez que haya programado el chip y configurado sus bits fusibles para utilizar un oscilador externo, ¿necesitaría un oscilador externo cuando quisiera reprogramar su flash?
Respuestas
¿Demasiados anuncios?¡Sí! Cuando configure los fusibles para que el controlador funcione con un reloj externo, también necesitará ese reloj externo para la reprogramación.
Es importante notar que probé esto con un Arduino configurado como ISP (En circuito Serie Programmer), que no intenta proporcionar un reloj externo al dispositivo que se está programando. Otros programadores pueden hacerlo, pero eso dependería del programador. El ISP es la forma más común de programar estos dispositivos, pero también existen otros programadores. El hecho es que el dispositivo en sí necesita un reloj externo. No es seguro para un programador paralelo. Un programador de alto voltaje puede prescindir de un reloj externo.
No he probado esto con un ATmega, sino más bien con un ATtiny45 pero ambos AVR son muy similares en estos aspectos.
Esto es lo que hice:
- Escribí un pequeño programa para dar salida a una onda cuadrada de 1kHz (listado abajo);
- Seleccioné reloj de 2MHz y programé
.low = 0x61
Tenga en cuenta que la configuración de los fusibles puede ser específica del controlador, por lo que esta es la configuración para ATtiny45; - El controlador emite una frecuencia de 1kHz, como era de esperar;
- Seleccioné 1.8432MHz para el reloj y programé
.low = 0xe0
; - La frecuencia de salida cayó a 0Hz hasta que conecté el oscilador, entonces saltó a 1kHz, de nuevo como se esperaba;
- I Desconecto el oscilador externo (salida: 0Hz);
- Intenté programar el dispositivo, resultando en:
avrdude: Firma del dispositivo = 0xffffff
avrdude: ¡Caramba! Firma de dispositivo no válida.
Vuelva a comprobar las conexiones e inténtelo de nuevo, o utilice -F para anular esta comprobación.
- Volví a conectar el oscilador externo y programé el dispositivo para 2MHz obteniendo el siguiente resultado:
avrdude hecho. Gracias.
- y, por supuesto, la salida volvía a ser de 1 kHz.
En conclusión:
Si programa los fusibles para utilizar 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;
}
}
Depende del programador que vayas a utilizar la segunda vez que programes el chip.
Para utilizar un programador ISP ( como el USBTinyIPS ), el chip necesita estar funcionando y ser funcional para ser programado. Si configura los fusibles para utilizar el cristal/resonador externo ( CKSEL1
, CKSEL2
, CKSEL3
y CKOPT
bits), entonces el chip necesitará el cristal/resonador externo para funcionar, no hay ninguna opción alternativa del tipo "Oh, ¿no hay cristal externo? Usaré el resonador interno"). Así que necesitarás tener el cristal/resonador conectado para la programación Flash vía ISP. Esta es la razón por la que se recomienda que compruebes y vuelvas a comprobar los valores de los fusibles antes de programarlos: es una manera fácil de bloquear el chip (no sólo por configurarlo para usar un cristal/resonador externo cuando no tienes uno a mano, sino también porque puedes hacer que no responda programando algunos valores como el SPIEN
valor del fusible)
También puede programar ATmega32 mediante programación de alto voltaje (serie o paralelo) y JTAG. Para la programación de alto voltaje que no necesita el cristal externo, estoy bastante seguro: HVSP y HVPP se puede utilizar para restablecer los fusibles sin reloj externo. No estoy seguro de qué método utiliza tu programador. Si es ISP, entonces necesitarás el mecanismo de reloj externo para reprogramar una vez que hayas ajustado los fusibles para cristal externo/resonador.