Si además quieres enviarnos un Artículo para el Blog y redes sociales, pulsa el siguiente botón:
Buenas tardes, hoy tengo el día raro.
Veamos, tengo una interrupcion que salta cuando entra algo por el puerto serie. Esta interrupcion escribe en la variable Keypress el valor ASCII recibido, y en el bucle principal hay una rutina que se ejecuta si Keypress es distinto de 0, y al final lo vuelve a poner a 0.
Esto funciona correctamente y nunca me ha dado problemas.
He añadido otro IF más adelante en el Main (encerrando una rutina que antes ya estaba y no daba problemas) y ahora se ejecuta la rutina del Keypress cuando Keypress vale 0 (no todas las veces, pero a intervalos regulares).
Pego código relevante:
int Keypress=0x00;
int ready=0;
#int_rda //interrupcion puerto serie
void rda_isr() {
Keypress=0x00;
if(kbhit()){
Keypress=getc();
}
}
#int_TIMER1
void TIMER(){
ready=1;
}
void main() {
setup_timer_1(T1_INTERNAL | T1_DIV_BY_2);
enable_interrupts(int_rda);
enable_interrupts(global);
enable_interrupts(INT_TIMER1);
set_TIMER1(0);
do {
// CONTROL DESDE LA RS-232
if(Keypress!=0) //ESTE ES EL BUCLE QUE HACE COSAS RARAS. ENTRA Y EL PRINTF IMPRIME QUE KEYPRESS=0
{
printf("%d",Keypress);
Keypress=0;
}
if (ready==1) //ESTE ES EL IF QUE FASTIDIA TODO. EL CODIGO QUE SE EJECUTA YA ESTABA, ES SOLO AL AÑADIR LA CONDICION
{
if (angl>6.28)
{
angl=0;
}
angl+=0.01;
tservo0=2000*sin(angl)+3800;
tservo1=2000*cos(angl)+3800;
ready=0;
}
}
while (TRUE);
}
Lo que pasa es que cuando meto la condicion de ready==1, entra en la rutina de Keypress!=0. Es curioso ver que justo despues de evaluar la condicion, escribe el valor de Keypress y es 0. Muy raro. He comprobado (poniendo printf por todas partes) que la interrupcion rda_isr se ejecuta solo cuando pulso una tecla. es el if(keypress!=0) el que la lía.
Esto es lo más contradictorio que me ha pasado... Si elimino el if(ready==1) el otro IF funciona bien. Si lo vuelvo a poner, el otro IF entra cuando le da la gana.
Alguna idea??
Hola jcobreros
Intenta hacer esto. Declara la variable "ready" como volatile. volatile int ready = 0;
De esta forma le dices al compilador que la variable puede tomar distinto valor a 0 en una interrupción o por causas externas al programa.
Un saludo...
Safareig, he intendado lo que dices, tanto volatile int ready como volatiel int keypress, pero sigue exactamente igual.
He probado a crear otra variable como keypress (por darle redundancia al asunto), y cuando pongo "if (keypress!=0 && keypress2!=0)" todo funciona como tiene que funcionar.... pero me jode.
Voy a seguir mirando por ahi, a ver si hay suerte.
Muchas gracias!
A veces los compiladores utilizan técnicas de optimizado de memoria o velocidad que pueden contradecir la lógica del programa. Por ejemplo el utilizar memoria Overlay para las variables locales de las funciones (ahorro de memoria al utilizar las mismas posiciones de memoria para distintas variables locales) puede provocar que una interrupción nos cambie el valor de una variable local de la función interrumpida.
Seguramente no sea este tu caso pero mira las opciones de compilación (si las hay, no conozco es CSS) por si las pudieras cambiar. Tambien ayuda mucho ver el código ensamblador que te genera para buscar errores fantasma de este tipo.
Suerte.
Puede que, al hacer operaciones trigonométricas en punto flotante, main() tarde tanto en ejecutarse que se produce overrun en la interrupción del puerto serie y getc() devuelve 0x00. Recuerda que, además, 0x00 es un caracter legal que puede ser enviado y recibido por el puerto serie.
Prueba a quitar de main los sin() y cos() y poner otras funciones menos pesadas...
Mira en el manual si esas funciones de librería deshabilitan las interrupciones.