TODOPIC
Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: pikman en 14 de Febrero de 2006, 15:39:00
-
Hola a todos, y como siempre gracias por leer, el pedazo de codigo que le muestro mas abajo, con el cual perdi un monton de tiempo porque yo necesito una condicion logica OR entre una variable y una entrada y para esto escribi:
while ((minuter!=30) || (!input(_alarm)));
y el CCS genera este ASM
0676: MOVF 58,W
0678: SUBLW 1E
067A: BNZ 0676
067C: BTFSS F81.3
067E: BRA 0676
En lugar de un OR, me genera una AND!!!,
Y ya quemado de puse esto
while ((minuter!=30) && (!input(_alarm)));
Y fijense genero el codigo de una OR!! y anda
0676: MOVF 58,W
0678: SUBLW 1E
067A: BZ 0680
067C: BTFSS F81.3
067E: BRA 0676
Si la variable minuter es igual a 30 (ó
la entrada _alarm es 1 salta
si no espera.
No se cual puede ser el problema, no veo el error mas que una fatalidad
del compilador, estoy compilando con la version 3.242, voy a probar con anteriores, pero es una locura que realmente el compilador cometa este error!!, que puede volver loco a cualquiera, en especial aquellos que no tengan conocimientos de lenguaje ASM, el microcontrolador utilizado es un PIC18F452.
saludos y espero estar equivocado o que el codigo este mal escrito.
ARIEL
-
Lo acabo de probar con v3.241 y es como dices van al revés:
.................... while (cant!=30);
005E: MOVF 06,W
0060: SUBLW 1E
0062: BNZ 005E
....................
.................... while (cant==30);
0064: MOVF 06,W
0066: SUBLW 1E
0068: BZ 0064
¡Vaya jugada del compilador!
-
Pues yo no lo veo al revés, Pocher.
De ASM no entiendo mucho, pero me parece interpretar en tus dos ejemplos que el compilador lo ha hecho correctamente.
-
BZ salta si el bit Z del Status es 0, es decir si la operación anterior (la resta) no ha sido cero ... y eso no se corresponde con el while
-
Disculpa que insista, pero en la data el 18F452, página 284 dice:
BZ Branch if Zero
Syntax: BZ n
Operands: -128 ≤ n ≤ 127
Operation: if ZERO bit is ‘1’
(PC) + 2 + 2n → PC
Status Affected: None
Encoding: 1110 0000 nnnn nnnn
Description: If the ZERO bit is ‘1’, then the program
will branch.
Por lo que sigo pensando que el compilador lo hace bien, lo cual por otra parte, es lo lógico.
-
Tienes razón Nocturno, lo había interpretado mal.
BZ k -------> Branch on Zero --------> Equivalente a: BTFSC 3,2 + GOTO k
Sin embargo lo de Pikman sigue sin cumplirse:
while ((minuter!=30) && (!input(_alarm)));
Y fijense genero el codigo de una OR!! y anda
0676: MOVF 58,W
0678: SUBLW 1E
067A: BZ 0680
067C: BTFSS F81.3
067E: BRA 0676
Si el bit Z=1 (minuter=30) ya salta y no comprueba el !input
-
Insisto, esa compilación es correcta. Fijáos que si "minuter=30" ya no es necesario que se verifique el pin de entrada para salir de la condición, puesto que se incumple una de las dos partes del AND.
De hecho, el compilador lo construye como un "OR" porque es una simplificación lógica: un AND sobre dos negaciones es equivalente a un OR sobre dos afirmaciones.
Llevado al ejemplo de Pikman, es lo mismo decir:
while ((minuter!=30) && (!input(_alarm)));
que
while ((minuter==30) || (input(_alarm));
-
Pués sí que estoy espeso hoy, no doy una. Así es Manolo.
-
Que les pasa jovenes, en el diversificado no les quedo claro esto?
por la 3era de Boole la disyuncion no es mas que la negacion de la conjuncion con sus secciones negadas, es decir a and b = not (not a or not b) por contraposicion es lo mismo decir a or b que not (not a and not b), para los compiladores es mucho mas sencillo trabajar todo en verdadero, que en falso, es decir que buscar el complemente una vez es preferible que 2 veces, por eso pasa lo que pasa.
Colocandolo en terminos mas seculares quedaria como esto:
si no has hecho la tarea o no has terminado tu almuerzo entonces no sales a jugar
es lo mismo que
haz tu tarea y termina tu almuerzo y entonces saldras a jugar
es lo mas sencillo del este mundo.
Saludos cordiales.
-
Hola, gracias a todos por la ayuda,
nocturno66 dice que
Llevado al ejemplo de Pikman, es lo mismo decir:
while ((minuter!=30) && (!input(_alarm)));
mientras ( minuter no sea igual a 30 "AND" la entrada _alarm no sea igual a 1 )
que
while ((minuter==30) || (input(_alarm));
mientras ( minuter sea igual a 30 "OR" la entrada _alarm sea igual a 1 )
Sin embargo el codigo generado para
while ((minuter!=30) && (!input(_alarm)));
es una OR
0676: MOVF 58,W
0678: SUBLW 1E ; resta para comparar si es igual
067A: BZ 0680 ; sale del bucle
; "OR"
067C: BTFSC 00.0 ; Si la entrada es 0 a cero salta y sale del bucle
067E: BRA 0676 ; si no sigue en el while
0680: BRA 0590
Por lo tanto lo que yo entiendo es que si se cumplen 30 minutos "O" que la
entrada es cero sale del bucle y salta a la linea 590, no hay dudas que se cumple
una condicion "O" y el operador empleado en el codigo es AND.
Esto seria lo mismo?, odeberia generar el mismo codigo?
while ((minuter==30) || (input(_alarm));
esto es lo que genera el compilador
0676: MOVF 58,W
0678: SUBLW 1E ; resta para comparar el valor
067A: BZ 0676 ; y se queda esperando que sea 30!!??
"AND" y
067C: BTFSC F81.3 ; espera que la
067E: BRA 0676 ; entrada se convierta en cero
0680: BRA 0590
Por lo tanto hasta que no se cumplan los 30 minutos no revisa la entrada
entonce es SI se cumplen 30 minutos "AND" la entrada es un bajo sale del
WHILE???, es correcto, entonces porque se utiliza el operador logico OR
en el codigo, ademas el comportamiento de
while ((minuter!=30) && (!input(_alarm)));
y
while ((minuter==30) || (input(_alarm));
no es el mismo, el compilador NO genera el mismo codigo.
Entonces como escribo correctamente el codigo, en la practica si yo escribo
while ((minuter!=30) && (input(!_alarm))); ( utilizo el operador Y )
y corro el programa en el micro, si se cumplen 30 minutos O sube el pin _alarm
salta a la rutina siguiente.
si en su lugar escribo
while ((minuter!=30) || (input(!_alarm))); ( utilizo el operador O )
y corro el programa en el micro, hasta que no se cumplen los treinta minutos,
el pin puede hacer lo que le de la gana que no se sale de ahi, y el ASM lo dice clarito, la verdad si que estoy epeso o soy muy bruto.
gracias de nuevo..
ARIEL
-
Escrito originalmente por pikman
Sin embargo el codigo generado para
while ((minuter!=30) && (!input(_alarm)));
es una OR
0676: MOVF 58,W
0678: SUBLW 1E ; resta para comparar si es igual
067A: BZ 0680 ; sale del bucle
; "OR"
067C: BTFSC 00.0 ; Si la entrada es 0 a cero salta y sale del bucle
067E: BRA 0676 ; si no sigue en el while
0680: BRA 0590
Por lo tanto lo que yo entiendo es que si se cumplen 30 minutos "O" que la
entrada es cero sale del bucle y salta a la linea 590, no hay dudas que se cumple
una condicion "O" y el operador empleado en el codigo es AND.
Correcto, Pikman, el compilador ha simplificado tu condición transformándola de un AND sobre dos negaciones a un OR sobre dos afirmaciones. Técnicamente es lo mismo
Escrito originalmente por pikman
Esto seria lo mismo?, odeberia generar el mismo codigo?
while ((minuter==30) || (input(_alarm));
esto es lo que genera el compilador
0676: MOVF 58,W
0678: SUBLW 1E ; resta para comparar el valor
067A: BZ 0676 ; y se queda esperando que sea 30!!??
"AND" y
067C: BTFSC F81.3 ; espera que la
067E: BRA 0676 ; entrada se convierta en cero
0680: BRA 0590
Por lo tanto hasta que no se cumplan los 30 minutos no revisa la entrada
entonce es SI se cumplen 30 minutos "AND" la entrada es un bajo sale del
WHILE???, es correcto, entonces porque se utiliza el operador logico OR
en el codigo, ademas el comportamiento de
while ((minuter!=30) && (!input(_alarm)));
y
while ((minuter==30) || (input(_alarm));
no es el mismo, el compilador NO genera el mismo codigo.
Exactamente, esa condición es la misma. De hecho, has traducido mal el salto BZ en tus comentarios del ASM, porque no se queda esperando que sea 30, sino que se queda sólo cuando es 30.
Escrito originalmente por pikman
si en su lugar escribo
while ((minuter!=30) || (input(!_alarm))); ( utilizo el operador O )
y corro el programa en el micro, hasta que no se cumplen los treinta minutos,
el pin puede hacer lo que le de la gana que no se sale de ahi, y el ASM lo dice clarito, la verdad si que estoy epeso o soy muy bruto.
gracias de nuevo..
ARIEL
Esa condición no es la misma, y no tiene nada que ver con lo que tú buscas.
-
Joe, macho, llevo todo el día dándole vueltas al problema que planteas Pikman, y finalmente tengo que decir que estaba equivocado.
Cuando dije que estas sentencias son equivalentes:
(NOT A) AND (NOT B)
y
(A OR B)
me confundí
La segunda debía ser:
NOT (A OR B)
Así que tu condición while podría ser:
while !((minuter==30) || input(_alarm))
Disculpa tanto lío, Pikman, pero entre unos y otros menuda ayuda te hemos dado...
-
OK, no hay problemas,


, gracias de todos modos.
saludos
ARIEL
-
Despues nocturno66 dice por hay que no sabe nada de .asm, pa" mí es que no nos quiere enseñar

Un saludo.
-
Que no, que no, que el asm me da repeluco...