Cuidado con los "fuses"
Los fuses (¿fusibles?) son 3
bytes de memoria permanente que determinan ciertas partes del comportamiento del microcontrolador.
Esta semana he estado trabajando con los ATtiny84, que es un microcontrolador de la subfamilia tiny de AVR
. Es un MCU
más pequeńo que el que viene con el Arduino Uno
, y tiene algunas diferencias en cuanto a funcionalidad (ya hablaré de eso en otro momento).
Estos microcontroladores vienen de casa configurados para usar un oscilador RC
interno a 8 MHz
, pero tienen activado el flag CKDIV8
que divide por 8
la velocidad del oscilador, con lo que el MCU
funciona a solo 1 MHz
.
Como para mi proyecto quiero usar los 8 MHz
(que además es una frecuencia soportada para 3v
que puedes conseguir con dos pilas AAA
), tengo que cambiar los fuses para desactivar ese flag.
Estoy usando un programador muy barato llamado USBasp que utiliza el interfaz SPI
del microcontrolador sin la necesidad de un bootloader (como usa el Arduino
), y nos deja disponible así toda la memoria para nuestro programa.
USBasp
está soportado por avrdude, así que es bastante fácil reprogramar el MCU
.
En primer lugar hay que usar la opción -B
de avrdude
a un valor de al menos 10
porque sino no será capaz de compunicarse con el MCU
a 1 MHz
.
Podemos confirmar que los fuses están como esperamos con:
avrdude -c usbasp -p attiny84 -P usb -v -B 10
Y cambiamos el low fuse para desactivar CKDIV8
:
avrdude -c usbasp -p attiny84 -P usb -v -B 10 -U lfuse:w:0xe2:m
Muy fácil. A partir de ahora ya no es necesario usar la opción -B
porque el MCU
funcionará a 8 MHz
.
La documentación del microcontrolador explica los fuses en detalle, pero hay que ir con mucho ojo porque podemos inutilizar el MCU
(sin la ayuda del microcontrolador, USBasp
es incapaz de programarlo).
Por ejemplo yo me equivoqué probando un cristal externo, confundiendo reloj externo
con cristal externo
; y no es lo mismo. De hecho no tengo un reloj externo y básicamente inutilicé el MCU
porque no arrancaba sin el reloj :(.
Bueno, realmente no ;). Teniendo un Arduino
a mano se puede generar una señal de reloj, lo que me permitió recuperar el microcontrolador y configurar los fuses correctamente.
Este es mi código de rescate:
// Generate a clock pulse with Aduino (digital port 5) #define F_CPU 16000000 #include <avr/io.h> #include <avr/interrupt.h> int main() { cli(); DDRD |= _BV(DDD5); TCCR0A = _BV(WGM00) | _BV(WGM01) | _BV(COM0B1); TCCR0B = _BV(CS00); TCNT0 = 0; TIFR0 = 0; OCR0B = 127; sei(); while(1); }
Ese código genera una señal de reloj en el pin 5
como la que espera el ATtiny84
configurado para usar un reloj externo, así que por esta vez... he podido salvar la situación fácilmente ;).
Los comentarios están cerrados: los comentarios se cierran automáticamente una vez pasados 30 días. Si quieres comentar algo acerca de la anotación, puedes hacerlo por e-mail.