Haz una pregunta
  Foros de Electrónica » Diseño digital » Microcontroladores y sistemas embebidos
Foros Registrarse ¿Olvidaste tu contraseña?

Temas similares

15/02/2012 #1


Ayuda Interrupción AVR
Wenas estoy empezando a programar un atmega8 y estoy con el ADC, e exo un programa para que se encienda un led u otro dependiendo de la tension que cae a la salida de un potenciometro.
El codigo es este:

#include <avr/io.h>
#include <avr/iom8.h>
#include <util/delay.h>
# define F_CPU 1000000UL

int main(void)
{

int adc;
DDRB=0xFF;//Activo toda la parte B como salida
ADMUX=(0<<ADLAR) | (0<<MUX3) | (0<<MUX2) | (0<<MUX1) | (0<<MUX0) | (0<<REFS1) | (1<<REFS0);
ADCSRA=(1<<ADEN) | (1<<ADPS1) | (1<<ADPS0);
while(1)
{
ADCSRA=(1<<ADSC) | (1<<ADEN);

ADC=(ADCH<<8) | ADCL; //Primero desplazo la parte alta 8 bits para ponerlo en la parte alta de ADC

if((ADCSRA & (0<<ADSC))== 0)
{

if(ADC < 614) //Vin 3V
{
PORTB=(1<<PB0);
}

else if(ADC > 614)
{
PORTB=(1<<PB1);
}
}
_delay_ms(20);
}
}


Ahora estoy intentando hacer lo mismo pero con interrupciones pero no me funciona no entra dentro de la interrupcion, el codigo es este:

#include <avr/io.h>
#include <avr/iom8.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#define F_CPU 1000000UL

int main(void)
{

DDRB=0xFF;//Activo toda la parte B como salida
ADMUX=(0<<ADLAR) | (0<<MUX3) | (0<<MUX2) | (0<<MUX1) | (0<<MUX0) | (0<<REFS1) | (1<<REFS0);
ADCSRA=(1<<ADEN) | (1<<ADPS1) | (1<<ADPS0) | (1<<ADIE);

sei();

while(1)
{
ADCSRA=(1<<ADSC);
}
}

ISR(ADC_vect)
{

int adc;
adc=(ADCH<<8) | ADCL;

if(adc < 614) //Vin 3V
{
PORTB=(1<<PB0);
}

else if(adc > 614)
{
PORTB=(1<<PB1);
}
_delay_ms(20);

ADCSRA=(1<<ADIE) | (1<<ADIF);
}

Haber si alguien sabe porque no entra dentro de la interrupcion.
Muchas gracias por adelantado
15/02/2012 #2

Avatar de Ajna

Usar el edito de codigo, bueno cuando pones ADCSRA=(1<<ADSC); estas modificando todo el registro no solo el bit ADSC, para eso deberias hacer ADCSRA|=(1<<ADSC);
Ademas cuando recien entres a la interrupcion deshabilita todas las demas con cli(); y cuando salgas de la misma vuelve a activarlas con sei() porque asi solo se ejecuta una ves, veamos que mas ven los demas
15/02/2012 #3


Muchas gracias por la respuesta ahora mirare si funciona, muchas gracias por lo de ADCSRA|=(1<<ADSC); no había pensado que cambiaba todo el codigo de ADCSRA gracias

Edito: Ahora si entra en la interrupcion pero no sale.
Edito2: Estoy haciendo pruebas y si sale de la interrupcion pero nose porque no me cambia el valor del resultado del ADC nunca, solo se queda el primer valor del ADC y luego siempre tiene ese numero
17/02/2012 #4

Avatar de Ajna

Perdon no habia podido responder, bueno te cuento algunas cosillas que me han pasado, mira en general creo que no es buena idea poner mucho codigo en las interrupciones, al menos a mi me ha dado mucha lata hacer eso, algo que hace y me ha dado buenos resultados es esto:

volatile char bandera_de_adc = 0;

ISR(ADC_vect)
{
bandera_de_adc = 1;
{

while(1)
{
ADCSRA=(1<<ADSC);
if(bandera_de_adc == 1)
{
//Aqui pongo el codigo que tu pusiste en la interrupcion
bandera_de_adc == 0;
}
}

No se a mi tambien me da lata eso de usar las interrupciones asi, porque tienes que considerar varias cositas como usar variable del tipo volatile "cosa no muy recomendable" y tambien tienes que asegurarte de realizar accesos atomicos cuando trabajas valores del 16 bits etc, etc" entonces la solucion mas practica que he usado es esa.

Creo que en
ADCSRA=(1<<ADIE) | (1<<ADIF);

ADIF se limpia automaticamente cuando entras a la interrupcion

Otra cosa esto que se supone que hace

if(adc < 614) //Vin 3V
{
PORTB=(1<<PB0);
}

else if(adc > 614)
{
PORTB=(1<<PB1);
}

a como lo veo siempre pone en 1 el puerto PB1 y acuerdate que se haceasi PORTB|=(1<<PB1);, recuerda que en C no esta implementada la manipulacion de bits entonces tienes que usar algunos metodos

Ejemplo
Para poner a uno un bit de un registro se hace asi
PORTB|=(1<<PB1);
si quieres poner mas de un bit a uno se hace asi
PORTB|=(1<<PB1)|(1<<PB2)|........;
Si quieres poner a cero un bit entonces haces asi
PORTB&=~(1<<PB1);
Ya te imaginaras el caso para varios bits
Si lo que quieres es cambiar el estado de un bit independientemente de su estado actual entonces se hace asi:
PORTB^=(1<<PB1);
Respuesta
¿Tienes una mejor respuesta a este tema? ¿Quieres hacerle una pregunta a nuestra comunidad y sus expertos? Registrate

Foros de Electrónica » Diseño digital » Microcontroladores y sistemas embebidos

Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO ©2011, Crawlability, Inc.