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

Temas similares

02/08/2011 #1

Avatar de Ajna

Interrupciones en atmega con WInavr
Hola que tal, bueno pues me paso lo siguiente.

Estoy haciendo un pequeño programa para controlar unos motores, y hago uso de las interrupciones, mas o menos pongo el ejemplo para no poner todo el codigo y aburrir

int contador; //Variable global

ISR(INT0_vect)
{
contador++; //Aqui funciona bien el incremento de la variable, cada ves que se llama se
//la incrementa
}

int main()
{
contador++; //Aqui tambien funciona bien el incremento
sei(); //Cuando entro al while ya no incrementa la variable
while(1){ //Espero a que se genere la interrupcion
contador++; //Aqui ya no incrementa la variable, pero cuando va a la interrupcion si lo hace
}
return 0;
}

Porque no se incremente la variable cuando la pongo dentro del while y si l ohace cuando va a la interrupcion, aclaro que la interrupcion se genera cada segundo, lo programe y en real no funciona lo probe en proteus y me di cuenta que no incrementa la variable en el while y luego lo probe en el mismo simulador del avr studio y lo mismo, ¿Porque no puedo incrementar la variable global cuando estoy dentro del while?
04/08/2011 #2

Avatar de StrySG

En AVR-GCC que en windows es Win-AVR, para que una varialbe tenga interaccion con las rutinas de interupcion la tienes que declarar como "volatile", por que si por ejemplo declaras

Código:
uint8_t c;
/*que es lo mismo que*/
static uint8_t c;
esta variable funcionara bien dentro el programa pero no tendra efecto de cambio dentro alguna interrupcion y viceversa, asi que tienes que hacer esto.
Código:
volatile uint8_t c; 
/*o lo que es lo mismo*/
volatile unsigned char c;
Solo asi la variable cambia en una interrupcion o en el programa principal ambos tendran evalor real de la variable esto por la naturaleza del compilador recuerda debes anteponer el keyword "volatile" para esto, existen manuales del compilador AVR-GCC disponibles si quieres mas informacion de los tipos de variable.
04/08/2011 #3

Avatar de Ajna

Si estuve leyendo y en realidad las ISR no son funciones como tal, solo son macros, y no debo modificar variables dentro de la ISR ni debo llamar a funciones desde ella, en fin ya modifique todo de nuevo procurando no modificar ningun registro estando en las ISR y funciona, lo que hice fue hacer una especie de bandera global que es la unica variable que modifica la ISR ya cuando retorne al lugar donde ocurrio dicha interrupcion lo que hago es leer esa bandera, en realidad todo el tiempo la estoy leyendo bueno imagino que habra mil formas mas pero bueno funciona gracias por tu ayuda
05/08/2011 #4

Avatar de Ajna

ME lleva el chanfle ahora ya no se que hice jajajaja no en serio que paso ya no funciona ayuda con esto porfa asi esta la cosa

volatile int flag_INT0;

void main()
{
flag_INT0 = 'N'
MCUCR = (1<<ISC01) | (0<<ISC00); //INT0 por flaco de bajada, INT1 por pulso bajo
GICR = (1<<INT0)|(1<<INT1); //Habilito interrupcion externa en INT0 y INT1
sei();
do{
if(flag_INT0 == 1)
{
RTC_leer(&tempo);
coloca_fecha_display(&tempo);
coloca_contador_display(&tA,&tB,&CarrosA,&CarrosB) ;
flag_INT0 = 0;
}
}while(1);
} //Fin main


ISR(INT0_vect)
{
flag_INT0 = 1;
}
ISR(INT1_vect)
{
flag_INT0 = 0;
}

Y pues no funciona cada ves que se genera la interrupcion el programa vuelve a comenzar desde el principio, o se vuelve loco, es como si no estubiera definiendo la ISR y el programa saltara al vector de reset, por cierto porque si declaro la variable global flag_INT0 como un uint8_t el compilador marca error diciendo que no se ha definido esa variable en la funcion ISR sale gracias por el poyo
06/08/2011 #5

Avatar de Moyano Jonathan

Hola como estás Dseda86.

En principio, tenés que revisar la lógica de tu programa para que veas si funciona logicamente.
Segundo tenés que revisar como has realizado las configuraciones del microcontrolador. En AVR-GCC el compilador no realiza nada de manera automática salvo el guardado de contexto en las interrupciones. Por lo tanto tenés que saber bien que registros estás tocando y de valores le estás asignando.

Yo personalmente tuve algunos conflictos con las interrupciones por recepción del puerto serie en un microcontrolador ATtiny2313, pero nada grave. Te paso un ejemplo usando interrupciones por eventos externos en el pin INT0.

Código:
/*************************************************
 PROGRAMAS DE EJEMPLO PARA EL ATtiny2313 - 20PU.
 EJERCICIO Nº8: Interrupciones externas.
 PROGRAMADOR: Moyano Jonathan.
 Fecha: 2011.
 Programa: Programa para demostrar el uso de las interrupciones. En este caso 
           usaremos la interrupción INT0 en el pin PD2.

 Cristal:  12Mhz.
 Programador: USBtinyISP.
 ************************************************/
#include <avr/io.h>     // Definiciones de hardware.
#include <avr/interrupt.h> // Funciones para trabajar con interrupciones.
#include <util/delay.h> // Librería para generar retardos.

SIGNAL (SIG_INT0) // Tratamos la interrupción.
{ 

  uint8_t i;
  
   for(i=0; i<=8; i++) {
   
     PORTB = i;
	 
	 _delay_ms(150);
	 
	 }

}

int main(void) // Bucle principal del programa.
{
    DDRB = 0x0F;  // PB0-PB3 salidas.
    PORTB = 0x00; // Ponemos todas las salidas a 0. 
    PCMSK |= (1<<PIND2); // PIN D2 - INT0 configurado como entrada.
    MCUCR = (1<<ISC01) | (1<<ISC00); // Interrupción en INT0, por flanco
	                             // de bajada.

    GIMSK  |= (1<<INT0); // Habilitamos la interrupción externa INT0.
    sei();                // Habilitamos todas las interrupciones.

    while(1){
	PORTB = 0xFF; // Ponemos todas las salidas en alto.
	}             // Entramos en un bucle infinito.
 }
Espero te sirva, es para el ATtiny2313.
06/08/2011 #6

Avatar de Ajna

Gracias por la ayuda, mira segun yo mi logica esta bien jajjaja "y quien soy yo no!!" bueno estube leyendo el manual del avr-gcc y no le encuentro el error, lo unico que quiero hacer es modificar una variable global desde una rutina de interrupcion, para luego usar esa misma variable en main(), pero no me anda, cada ves que ocurre una interrupcion se salta al vector de reset, segun lei no es nada recomendable hacer llamadas a funciones desde la rutina de interrupcion por ejemplo como tu que llamaste a _delay_ms(), leyendo me surgieron dos dudas mas primero exactamente para que sirve reti(); y la segunda es que hablan de acceso atomico, haciendo referencia a que se debe tener cuidado al modificar registros de 16bits en una interrupcion, pero no le entendi mas, en fin agradesco tu ayuda y ojala puedan seguir apoyandome poque me esta desesperando, ahorita voy a probar a llamar a una funcion desde la interrupcion para que esa funcion modifique la variable aver si asi funciona
06/08/2011 #7

Avatar de Moyano Jonathan

Que microcontrolador estás usando ? Acordate que cada familia tiene una designación distinta para las interrupciones.

Por favor mirá este documento de AVRlib:
06/08/2011 #8

Avatar de Ajna

Es el atmega32 ese link que pusiste es el que te digo que ya lei, y segun estoy haciendo bien todo lo que dice ahi, ya intenta cambiar la optimizacion del compilador y nada de nada

Es raro solo falla cuando intento modificar la variable global por que si hago esto:

ISR(INT0_vect)
{
LIMPIA_LCD();
}
ISR(INT1_vect)
{
LCD_IMP_CADENA("HOLA",0,0);
}

Si hago eso y genero la interrupcion INT1 se imprime bien el mensaje en la lcd y luego si genero INT0 se limpia lo que esta en la LCD y lo puedo hacer tantas veces como quiera y no falla, entonces porque cuando intento modificar esa variable global si falla

Creo que ya funciona, http://www.nongnu.org/avr-libc/user-manual/FAQ.html,
Solo que ahi dice que la variable global la declaran como volatile uint8_t flag; sin embargo si yo lo hago asi el compilador dice: variable no declarada en main(), pero me di cuenta que es de 8 bits asi que no me funciono eso de uint8_t pues la declare como char y asi si funciona que cosas no!!! entonces queda asi

volatile char flag; //Variable global que puede ser modificada por cualquier interrupcion o funcion

ISR(Vector_interrupcion)
{
flag = 1;
}

void main()
{
flag = 0;
while(1)
{
if(flag == 1)
{ //Codigo que se ejecuta en caso de genera la interrupcion
flag = 0; //Deshabilito la bandera de interrupcion
}
}
}//Fin main

Nota: si cambio a char flag, por int flag o por uint flag o cualquier otra convinacion no me funciona ¿Porque? a caso tiene que ver con el acceso atomico y si es asi como se soluciona?
06/08/2011 #9

Avatar de Moyano Jonathan

Nota: si cambio a char flag, por int flag o por uint flag o cualquier otra convinacion no me funciona ¿Porque? a caso tiene que ver con el acceso atomico y si es asi como se soluciona?
No tengo tanta experiencia con interrupciones en AVR, pero si funciona con char usá ese tipo de datos.

Yo tengo que hacer más pruebas con AVR - GCC. Si puedo hacer un ejemplo con el tipo de problemas que vos planteas lo posteo acá.
06/08/2011 #10

Avatar de Ajna

Ok sale gracias Jonathan, yo tampoco tengo experiencia con GCC pero no se porque me gusta mas jugar con avr que con pic jejeje bueno le voy a dejar el tipo char a ver si despues alguien nos explica porque?
23/12/2012 #11


Hola Moyano Jonathan, yo tuve problemas con la interrupción de recepción del puerto serie con un atme168
y combinado con el problema de Ajna que problema tuviste vos? me contas? para ver si es algo parecido y me ayudas por favor por que ya no se que puede ser.
24/12/2012 #12

Avatar de Ajna

Lo malo de dirigirse a una sola persona es que probablemente nadien mas responda y si esa persona tampoco lo hace pues no vas encontrar ayuda. O al menos asi me lo hicieron ver el dia que yo hice lo mismo, y ciertamente tienen razon.

Al ser atmega lo mas seguro es que tenga el modulo para comunicacion serie (por cierto a que comunicacion serie te refieres I2C SPI o RS232) ¿Que problema tienes? Moyano se referia al Attiny2313 que tiene un modulo muy basico para comunicaciones serie y ciertamente se complica algunos detalle, pero en el atmega es aun mas facil
24/12/2012 #13


Me dirigí a él por que comento que tuvo un problema por el rs232 y quería saber si se parecía al mío y ver si podía ayudarme.

El problema es el Siguiente:

"va para cualquiera que pueda ayudarme"

Estuve haciendo un programa en CSharp para conectarme con mi circuito y leer variables
pero por el momento estaba probando si podía cambiar de velocidad desde mi programa hecho csharp cuando le mando a que cambie a 9600 que esta por default responde bien, pero cuando le cambio a otra por ejemplo 19200 anda mal y no contesta dejo el código de los dos programa para ver si alguien puede guiarme con las modificaciones por que ya no se como arreglarlo. :(

desde ya muchas gracias espero encuentren algún problema que yo no haya visto :(

saludos gracias Ajna!
Archivos Adjuntos
Tipo de Archivo: txt codigo corto.txt (6,2 KB (Kilobytes), 4 visitas)
Tipo de Archivo: rar Analizador.rar (71,9 KB (Kilobytes), 12 visitas)
25/12/2012 #14

Avatar de Moyano Jonathan

Me dirigí a él por que comento que tuvo un problema por el rs232 y quería saber si se parecía al mío y ver si podía ayudarme.
Sinceramente hace bastante que no programo en AVRGCC y el problema específico no lo he podido solucionar para el ATtiny2313. Tampoco he probado el puerto serie en otros micros de ATMEL, todo lo que he realizado como proyecto, lo terminé haciendo con la plataforma Arduino.

Saludos !
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.