Estoy jugando con un ATMega328P que funciona con un USBtiny 1.0 y tengo la siguiente configuración:
Luego, mi programa refleja ADC0 en PWM en PB0, por lo que la posición del potenciómetro controla directamente el brillo del LED.
Esto funciona cuando se hace dentro del ciclo infinito al final de main(), pero si lo muevo a la interrupción ADC, parece que no pasa nada (vea el comentario "Eliminarme").
Estoy basándome parcialmente en un tutorial en http://www.avr-tutorials.com/adc/utilizing-avr-adc-interrupt-feature , pero usando 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 experimenté con la interrupción INT0 en otro programa, pero aparentemente tampoco activa 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 falta alguna configuración, pero no he podido encontrar nada que no haya hecho. ¿Alguien puede ver lo que estoy haciendo mal? Gracias.
Esto parece haber sido un problema con las bibliotecas avr-gcc/libraries incluidas con WinAVR, o cómo se configuró. La creación de la misma aplicación con Atmel Studio funciona como se esperaba.
versión avr-gcc:
Puedo confirmarle que su código funciona bajo mi winavr, una versión antigua de 2009.
ed rey
CLEAR(ADMUX, MUX0)
si ese es el que te interesa? Además, ¿está seguro de que la interrupción no se activa en absoluto, ni siquiera una vez? Si una vez, borra el indicador de interrupción dentro del ISR, ¿puede evitar que se vuelva a disparar?jameswilddev
ed rey
jameswilddev
jimmyb