Procblema con bucle while()

Postea aqui toda la parte de programación del lenguaje C, C++, C#...

Moderator: Junta Directiva

sdguez
Posts: 6
Joined: Fri Dec 11, 2009 1:03 pm

Procblema con bucle while()

Post by sdguez » Sun Dec 13, 2009 7:44 pm

Buenas a todos:
Os dejo un pequeño fragmento de código, pues no acabo de entender por qué a la hora de depurar el compilador hace un par de cosas, a mi juicio, un tanto raras.

Dentro de la función main(), he puesto un bucle while(1) para que se ejecute continuamente. Bien, dentro de este bucle hay básicamente dos cosas:
- Otro bucle while con la "chicha" del programa, controlada por una variable boolena
- Tres instrucciones (sei(),cli(),etc) para el control de las interrupciones.
Es decir:

Code: Select all

bool inicio = false;

void main ()
{	
        DDRA = 0xFF; // set PORTA as output
	PORTA = 0xff;
while(1)
{
	while(inicio)
	{
	if (contador_s == 20) // Han pasado 20 seg.
		{
		contador_s=0;
		if (regula== 1) salida++; // Incrementamos +1 registro del PuertoA.
		if (regula== 2) salida--; // Decrementamos	-1.....
		PORTA = salida;// escribe registro en Puerto A.
		}
	if (contador_s2 == 5400) // Han pasado 90 minutos.
		{
		contador_s2=0;
     ------->	PORTA = 0xFF;// escribe registro en Puerto A.
		}

  // más código//

	      TCNT0 = 0x00; //Poner a 0 resgistro del Timer0
	      contador_s2=0;
 	      contador_s3=0;
 	      contador_s4=0;
	      }
	 sei();
	TIMSK  |= (1 << TOIE0); // Máscara interrupción timer0
	cli();
  } //del while(inicio)
  sei();
  TIMSK  |= (1 << TOIE0); // Máscara interrupción timer0
  cli();
 }// del while (1)
} // del main
Pues bien, resulta que depurando todo paso a paso comienza con normalidad hasta alcanzar el bucle while(inicio). Como dicha variable está inicializada a "false" no se debiera ejecutar. No obstante resulta que se mete dentro del bucle, unas 10 instrucciones más abajo (la instrucción en concreto está señalada en el código con una flecha pr la izquierda) y yo creo que no llega a ejecutar dicha instrucción, le doy otro paso y vuelve al bucle while(inicio), ahora sí lo ignora y salta al final, a la instrucción sei() que está dentro de las llaves del while(1);

Acto seguido, mediante una interrupción:

Code: Select all

ISR(IO_PINS_vect)
{
inicio = !inicio;
} 
Por cierto, si escribo la instrucción así: "inicio !=;" me da error al compilar, es normal?.

El caso es que el boolean "inicio" pasa a true, se acaba la interrupción, continua con la ejecución de la función cli() y ahora entiendo que debería entrar en el bucle while(inicio), pero pasa olímpicamente del y continua ejecutando las tres últimas instrucciones cíclicamente.

Alguien sabe por qué sucede esto?.

Muchas gracias.

Bastian
Usuario Avanzado
Usuario Avanzado
Posts: 384
Joined: Wed Feb 13, 2008 9:29 pm
Nombre: David Carmona
Location: Utiel
Contact:

Re: Procblema con bucle while()

Post by Bastian » Sun Dec 13, 2009 8:55 pm

Hola!
Por cierto, si escribo la instrucción así: "inicio !=;" me da error al compilar, es normal?.
Si, es normal, por que estás asignando en ningún sitio (Donde guardas el resultado???)

Code: Select all

TCNT0 = 0x00; //Poner a 0 resgistro del Timer0
         contador_s2=0;
         contador_s3=0;
         contador_s4=0;
         }[b]//(El bucle while (inicio) lo  cierras aquí!!)[/b]
    sei();
   TIMSK  |= (1 << TOIE0); // Máscara interrupción timer0
   cli();
 [b] } //del while(inicio)[/b](En realidad lo cierras con la llave anterior!!)
El bucle while (inicio) no lo cierras donde tu crees....

Code: Select all

   TIMSK  |= (1 << TOIE0); // Máscara interrupción timer0
Ese desplazamiento a izquierdas me chirria... si no recuerdo mal estas desplazando 1, TOIE0 veces a la izquierda... quizá debería ser al revés...
Comprueba eso y luego nos cuentas... :wink:

Salu2!
Existen 10 tipos de personas...
los que saben binario y los que no.

El conocimiento es un arma poderosa... Aprende!!!


Mi blog: Robotica Lúdica Pingubot

User avatar
beamspot
Usuario Desarrollador
Usuario Desarrollador
Posts: 1132
Joined: Thu Oct 11, 2007 8:56 pm
Nombre: Guillem

Re: Procblema con bucle while()

Post by beamspot » Mon Dec 14, 2009 9:20 am

Lo del REGISTRO = (1<<VALOR) es la manera 'estándar' de GNU-GCC para AVR usada para definir posiciones de bits. Es decir, que si quiero activar el bit TCIE del registro TIMSK, lo que hago es poner TIMSK |= (1<<<TCIE). Para eso, en el header de definiciones se definen los valores de TCIE y de TIMSK, de tal manera que luego, cambiando simplemente el tipo de micro, las definiciones actualizan dichos valores y el 'portar' el código a un micro diferente es inmediado, aunque TCIE y TIMSK estén en posiciones diferentes. No olvidemos que al ser TCIE un valor #definido, el preprocesador del compilador sustituye el (1<<TCIE) por el valor en hexadecimal correspondiente. De esta manera queda mucho más legible el código.

A ver si puedo hacer un rato más para leer el código. Por cierto, ¿has probado a definir inicio como volátile? El optimizador del compilador te puede hacer muy malas pasadas si en los ISR sólo asignas valores a variables no definidas como tal, al 'optimizarlas' mediante el sencillo método de borrarlas directamente. También puedes probar a usar la optimización -O0 (o sea, nada de optimizar), malísima pero válida si tu programa es corto y quieres depurarlo en el simulador.
Beamspot.

Bastian
Usuario Avanzado
Usuario Avanzado
Posts: 384
Joined: Wed Feb 13, 2008 9:29 pm
Nombre: David Carmona
Location: Utiel
Contact:

Re: Procblema con bucle while()

Post by Bastian » Mon Dec 14, 2009 10:25 am

Hola!
beamspot wrote:Lo del REGISTRO = (1<<VALOR) es la manera 'estándar' de GNU-GCC para AVR usada para definir posiciones de bits. Es decir, que si quiero activar el bit TCIE del registro TIMSK, lo que hago es poner TIMSK |= (1<<<TCIE). Para eso, en el header de definiciones se definen los valores de TCIE y de TIMSK, de tal manera que luego, cambiando simplemente el tipo de micro, las definiciones actualizan dichos valores y el 'portar' el código a un micro diferente es inmediado, aunque TCIE y TIMSK estén en posiciones diferentes. No olvidemos que al ser TCIE un valor #definido, el preprocesador del compilador sustituye el (1<<TCIE) por el valor en hexadecimal correspondiente. De esta manera queda mucho más legible el código.
No conocía esa forma de poner a uno o a cero...los AVR los tengo en tareas pendientes :oops: . Entiendo que (1<<TCIE) activa el bit TCIE en el registro y (0<<TCIE) lo desactiva... entonces el valor #definido de TCIE debe ser su posición en el registro ¿no? :roll:

Salu2!
Existen 10 tipos de personas...
los que saben binario y los que no.

El conocimiento es un arma poderosa... Aprende!!!


Mi blog: Robotica Lúdica Pingubot

User avatar
beamspot
Usuario Desarrollador
Usuario Desarrollador
Posts: 1132
Joined: Thu Oct 11, 2007 8:56 pm
Nombre: Guillem

Re: Procblema con bucle while()

Post by beamspot » Mon Dec 14, 2009 10:51 am

Bastian, si y no. (1<<TCIE) pone a uno dicho bit, pero para ponerlo a cero, lo que se hace es TIMSK &=~(1<<TCIE). TCIE está definido, como muy bien dices tú, como la posición que el bit ocupa en el registro del modelo seleccinado de micro.

La verdad, es que este sistema es muy cómodo y práctico, aunque un poco más largo de escribir. Sin embargo, una línea como

TIMSK = 0x3C;

es difícil de interpretar, mientras que algo así como

TIMS = (1<<TCIE1)|(1<<TOVF1)|(1<<TCA1);

queda mucho más claro aunque el resultado final (en el archivo .hex) sea exactamente el mismo. Y encima, cambiar de un (pongamos por ejemplo) M16 a un M32 es tan sencillo como irse a los 'settings' del AVRStudio y cambiar la referencia. No hace falta ni cambiar el io.h, ya que este tiene un monton de #ifdef que redirigen al m16io.h o al m32.h correspondiente. Vamos, una currada de headers, pero una 'vida más fácil' para los usuarios. Nada mal para ser gratuito todo.

Añado, voviendo al meollo de la cuestión, que todas las variables que se modifican dentro de las interrupciones deben ser definidas siempre y de manera sistemática como volatile. Y mejor si estas (que suelen ser globales), se ponen dentro de un bloque de definición claramente delimitado por sus correspondientes comentarios.

Por cierto, que nadie se olvide que las teclas se deben 'filtrar' (debounce) con un antirebotes. Para eso, las interrupciones en las entradas de tecla son desaconsejables (yo suelo leerlas con la interrupción del timer de sistema).
Beamspot.

User avatar
beamspot
Usuario Desarrollador
Usuario Desarrollador
Posts: 1132
Joined: Thu Oct 11, 2007 8:56 pm
Nombre: Guillem

Re: Procblema con bucle while()

Post by beamspot » Mon Dec 14, 2009 10:57 am

Por cierto, si quereis un ejemplo de programación de AVR's, en la Wiki de este portal colgué algo de información:

http://wiki.webdearde.com/index.php/Int ... as_con_NTC" onclick="window.open(this.href);return false;

aunque no recuerdo si está para el IAR, el WinAVR, o para los dos (con algún método se selección, bien automático, bien manual).

Sin leer el código, en la misma página hay un ejemplo de iniciación del ADC donde se ve claramente cómo uso este modelo de asignación.
Beamspot.

sdguez
Posts: 6
Joined: Fri Dec 11, 2009 1:03 pm

Re: Problema con bucle while()

Post by sdguez » Mon Dec 14, 2009 8:40 pm

El bucle while (inicio) no lo cierras donde tu crees....
Mea culpa, en ese aspecto el código está bien, lo que ocurre es que por acortarlo no lo he puesto completo y la llave donde me indicas que se cierra el while pertenece a un "if" que está un poco más arriba.

Por lo demás, he probado lo que comentáis de no optimizar el código, y en efecto, a partir de ahí me ha funcionado todo correctamente. La verdad ese tipo de cosas deberían de venir en un manual o algo así porque jamás se me hubiera ocurrido que esa fuera la causa.

Una vez solventado el problema del código, me surge otro nuevo, esta vez a la hora de intentar conectar con el micro, usando el propio AVR Studio:
Image

El cable de conexión por un lado (el del micro) tiene un conector de 10 pines y por otro (el del Pc) el del puerto paralelo (25 pines). El problema es que todos los programadores del AVR emplean el USB o el Serie (como se ve en la imagen primera) y ninguno el paralelo. Sabéis cómo se puede añadir alguno al AVR Studio que utilice el paraelo?.
Detalle de conexiones del micro:
Image

User avatar
beamspot
Usuario Desarrollador
Usuario Desarrollador
Posts: 1132
Joined: Thu Oct 11, 2007 8:56 pm
Nombre: Guillem

Re: Procblema con bucle while()

Post by beamspot » Mon Dec 14, 2009 9:23 pm

¿Que programador tienes? Personalmente, no me rompería el coco mucho e iría por algo seguro: el AVRISP MkII, USB, robusto, fiable y actualizable cuesta menos de 30 €, original de Atmel. Estas navidades miraré de comprarme otro, aunque igual intento conseguir otra cosa muy diferente (JTAGICE MkII, mucho más apetitoso y caro).
Beamspot.

sdguez
Posts: 6
Joined: Fri Dec 11, 2009 1:03 pm

Re: Procblema con bucle while()

Post by sdguez » Mon Dec 14, 2009 10:32 pm

Pues en prinicipio entiendo que varios, me explico. El AVR Studio al abrir el cuadro de conexiones (la primera de las imágenes en mi post anterior) me deja escoger entre varios programadores, entre ellos el que comentas, el AVRISP MkII. Pero claro tengo el problemilla del puerto paralelo, aunque supongo que se puede resolver comprando un adaptador.
Saludos.

User avatar
beamspot
Usuario Desarrollador
Usuario Desarrollador
Posts: 1132
Joined: Thu Oct 11, 2007 8:56 pm
Nombre: Guillem

Re: Procblema con bucle while()

Post by beamspot » Tue Dec 15, 2009 12:23 am

Y ¿Cómo se llama lo que conectas al puerto paralelo para luego conectarlo al conector ISP? Es decir, ¿que programador, chisme, placa, invento, etc tienes para programar el AVR? Si pones puerto paralelo, todo tiene la pinta de ser un STK200, obsoleto y de fabricación casera, probablemente sin comprobar. Si es así, mala suerte, el AVRStudio hace tiempo que dejó de programarlo. Para eso, se usa el PonyProg. Por desgracia, no tengo más información sobre este tipo de programadores.
Beamspot.

Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest