Estoy jugando con un ATMega328P ejecutándose desde un USBtiny 1.0, y tengo la siguiente configuración:
- Potenciómetro para ADC0.
- Corriente de fuente PB0 para un LED.
Mi programa luego refleja ADC0 al PWM en PB0, por lo que la posición del potenciómetro controla directamente el brillo del LED.
Esto funciona cuando se realiza dentro del bucle infinito al final de main (), pero si lo muevo a la interrupción ADC, no parece que ocurra nada (consulte el comentario "Quitarme").
Parcialmente estoy basando esto en un tutorial en enlace , pero utilizando el modo de ejecución libre.
#define __AVR_ATmega328P__
#define F_CPU 1000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#define SET(register, bit) register |= _BV(bit)
#define CLEAR(register, bit) register &= ~_BV(bit)
int main(void) {
// Set up ADC0 as a 8-bit potentiometer input.
// -------------------------------------------------------------------------
// Switch from 10-bit to 8-bit mode.
// Our output is 8-bit anyway.
SET(ADMUX, ADLAR);
// Use AVCC as the reference for the ADC.
SET(ADMUX, REFS0);
CLEAR(ADMUX, REFS1);
// Specify that we are only interested in ADC0.
CLEAR(ADMUX, MUX0);
CLEAR(ADMUX, MUX1);
CLEAR(ADMUX, MUX2);
CLEAR(ADMUX, MUX3);
// Set the clock divider to 128x.
// TODO: Experiment with reducing the divider when logic is in.
SET(ADCSRA, ADPS0);
SET(ADCSRA, ADPS1);
SET(ADCSRA, ADPS2);
// Set to free-running mode; the ADC will run continuously.
CLEAR(ADCSRB, ADTS0);
CLEAR(ADCSRB, ADTS1);
CLEAR(ADCSRB, ADTS2);
// Enable auto-triggering of the ADC by the above.
SET(ADCSRA, ADATE);
// Fire the ADC interrupt when a sample is ready.
SET(ADCSRA, ADIE);
// Enable the ADC now it has been configured.
SET(ADCSRA, ADEN);
// Start the free-running timer.
SET(ADCSRA, ADSC);
// Set up LED output on PB1.
// -------------------------------------------------------------------------
// Set the pin up as an output.
SET(DDRB, PB1);
// We'll be comparing a timer (sawtooth) to a value (OCR1A);
// the pin will be high or low depending upon whether the timer is greater
// or lower than the value (OCR1A).
SET(TCCR1A, COM1A1);
// Switch to fast PWM.
// This doubles the frequency, but means that phase shifts when OCR1A is
// changed. Doesn't matter for us.
SET(TCCR1A, WGM10);
SET(TCCR1B, WGM12);
// Disable the timer divider; as fast as possible.
SET(TCCR1B, CS10);
// Enable interrupts now everything is configured.
// -------------------------------------------------------------------------
sei();
while (1) {
// Remove me to have the ADC interrupt set the LED brightness instead.
OCR1A = ADCH;
}
}
// This ADC interrupt handler is called every time a potentiometer sample is ready.
ISR(ADC_vect) {
OCR1A = ADCH;
}
También he experimentado con la interrupción INT0 en otro programa, pero eso tampoco parece activar el controlador de interrupciones.
versión avr-gcc:
Using built-in specs.
Target: avr
Configured with: ../gcc-4.3.3/configure --enable-win32-registry=WinAVR-20100110 --with-gmp=/usr/local --with-mpfr=/usr/local --prefix=/c/WinAVR --target=avr --enable-languages=c,c++,objc --with-dwarf2 --enable-doc --disable-shared --disable-libada --disable-libssp --disable-nls --with-pkgversion='WinAVR 20100110' --with-bugurl='URL:http://sourceforge.net/tracker/?atid=520074&group_id=68108&func=browse'
Thread model: single
gcc version 4.3.3 (WinAVR 20100110)
Probablemente me esté faltando algo de configuración, pero no he podido encontrar nada que no haya hecho. ¿Alguien puede ver lo que estoy haciendo mal? Gracias.