Autor Tema: Lectura de puerto en orden aleatorio  (Leído 2532 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado cvargcal

  • PIC16
  • ***
  • Mensajes: 166
Lectura de puerto en orden aleatorio
« en: 30 de Enero de 2016, 11:58:38 »
Saludos,
Alguien sabe como leer la entrada del puerto en diferente orden para el compilador CCS , necesito leer 4 bits,
el puerto A tiene A0,A1,A2,A3,A4,A5,A6,A8 . Quiero obtener el binario como por ejemplo: variable= "A1A2A3A4",
en microbasic veo que lo hacen variable=porta>>2;

...y ahora algo mas complicado (creo yo) : Variable="A4A3A2A1"
necesito ese binario para sacar la tabla:

    Q4 Q3 Q2 Q1   HEX
1:  0  0  0  1  >> 01
2:  0  0  1  0  >> 02
3:  0  0  1  1  >> 03
4:  0  1  0  0  >> 04
5:  0  1  0  1  >> 05
6:  0  1  1  0  >> 06
7:  0  1  1  1  >> 07
8:  1  0  0  0  >> 08
9:  1  0  0  1  >> 09
0:  1  0  1  0  >> 0A
*:  1  0  1  1  >> 0B
#:  1  1  0  0  >> 0C
A:  1  1  0  1  >> 0D
B:  1  1  1  0  >> 0E
C:  1  1  1  1  >> 0F
D:  0  0  0  0  >> 00
*/

De antemano gracias.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Lectura de puerto en orden aleatorio
« Respuesta #1 en: 30 de Enero de 2016, 12:20:42 »
Código: C
  1. temp = input_a();  //Tomamos el valor entero del puerto y lo guardamos en una variable temporal
  2. var = 0;        // Inicializamos el registro donde vamos a guardar las cosas
  3. for ( i =1 ; i<5 ; i++ )        // preguntamos por los bits y rotamos
  4. {
  5.    if(bit_test(temp,i)) var++;
  6.    var << 1;
  7. }

Esto te va a dejar en var el valor: "A1 A2 A3 A4"
Si queres que sea "A4 A3 A2 A1" es mas simple..

Código: C
  1. var = input_a();   // Leo el puerto , var= A7 A6 A5 A4 A3 A2 A1 A0
  2. var >>= 1;       // Roto un lugar para eliminar el A0,  var= 0 A7 A6 A5 A4 A3 A2 A1
  3. var &= 0xF;    // Elimino todo lo superior, var= 0 0 0 0 A4 A3 A2 A1

Respecto a la tabla si queres que devuelva los valores *,#,A,B, etc.. Si es asi entonces usamos un array el cual el indice nos va a dar una letra como respuesta.

Código: C
  1. char tabla[16] = {'D','1','2','3','4','5','6','7','8','9','0','*','#','A','B','C'};

y haces

Código: C
  1. tabla[var]

para obtener tu letra.
« Última modificación: 30 de Enero de 2016, 12:30:19 por KILLERJC »

Desconectado cvargcal

  • PIC16
  • ***
  • Mensajes: 166
Re:Lectura de puerto en orden aleatorio
« Respuesta #2 en: 31 de Enero de 2016, 17:31:59 »
Muchas gracias, siempre eres de gran ayuda.
 :-/ ((:-))

Desconectado cvargcal

  • PIC16
  • ***
  • Mensajes: 166
Re:Lectura de puerto en orden aleatorio
« Respuesta #3 en: 31 de Enero de 2016, 19:23:43 »
Hola de nuevo,  buscando en el manual de CCS vi la función

Código: C
  1. value= input_state(pin);

Pienso algo como esto:
Código: C
  1. Q1 = input_state(DTMF_Data1); // A4
  2. Q2 = input_state(DTMF_Data2); // A3
  3. Q3 = input_state(DTMF_Data3); // A2
  4. Q4 = input_state(DTMF_Data4); // A1
  5. printf("Estados: %d%d%d%d",Q1,Q2,Q3,Q4);   //

Realmente lo que busco es leer el estado del pin y crear por decirlo de cierta forma el binario que yo quiera "####", (Ejemplo A2A5A3A1)
mi pregunta es  ¿Como concateno o  convierto "Q1Q2Q3Q4" en el hex correspondiente para luego consultarlo en la tabla?
Hex=Q1Q2Q3Q4?
« Última modificación: 31 de Enero de 2016, 19:27:29 por cvargcal »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Lectura de puerto en orden aleatorio
« Respuesta #4 en: 31 de Enero de 2016, 19:46:59 »
El tema del input_state(pin) y la diferencia de lo que yo hice:

temp = input_a();

Esta en que vos con input_state estas leyendo el puerto continuamente, mientras que yo estoy tomando todos los valores que hay en ese momento. Me intento explicar, vos estas tomando el valor pin a pin en distintos momentos temporalmente, un ejemplo de entender seria: pregunto por A1 pasan 3/4 ciclos de reloj, pregunto por A2, pasan otros 3/4 ciclos de reloj pregunto por el otro, y asi. Que puede afectar o no a tu aplicacion, obviamente.

Si no afecta podes hacer:


Código: C
  1. Q1 = input_state(DTMF_Data1); // A4
  2. Q2 = input_state(DTMF_Data2); // A3
  3. Q3 = input_state(DTMF_Data3); // A2
  4. Q4 = input_state(DTMF_Data4); // A1
  5.  
  6. Resultado = (Q1 << 3 ) + (Q2 << 2) + (Q3 << 1 ) + Q4;

Ahora esto va a llevar muchos ciclos realizarlo, ademas de requerir 4 registros para eso algo totalmente ilogico. Si queres hacerlo mas rapido

Código: C
  1. Resultado = 0;
  2. if (input_state(DTMF_Data1)) bit_set(Resultado,3);
  3. if (input_state(DTMF_Data2)) bit_set(Resultado,2);
  4. if (input_state(DTMF_Data3)) bit_set(Resultado,1);
  5. if (input_state(DTMF_Data4)) bit_set(Resultado,0);

Eso deberia crear el menor codigo de ASM posible, es decir:

Código: ASM
  1. CLRF Resultado
  2. BTFSC  PORTx, DTMF_Data1
  3. BSF   Resultado,3
  4. BTFSC  PORTx, DTMF_Data2
  5. BSF   Resultado,2
  6. BTFSC  PORTx, DTMF_Data3
  7. BSF   Resultado,1
  8. BTFSC  PORTx, DTMF_Data4
  9. BSF   Resultado,0

Solo recordar que aca imagino que DTMF_Data1 deberia ser un PIN_xx, ej, para RA1, seria PIN_A1

Y si necesitas que la infomarcion de los pines que queres ver sea tomada realmente todo al mismo tiempo, entonces

Código: C
  1. Resultado = 0;
  2. Temp = input_a();
  3. if (bit_test(Temp,DTMF_Data1)) bit_set(Resultado,3);
  4. if (bit_test(Temp,DTMF_Data2)) bit_set(Resultado,2);
  5. if (bit_test(Temp,DTMF_Data3)) bit_set(Resultado,1);
  6. if (bit_test(Temp,DTMF_Data4)) bit_set(Resultado,0);


Aca el DTMF_Datax deberia ser simplmente un numero indicando el bit, ejemplo para leer el RA1, deberia poner solo 1.
Si deseas cambiar que pin queres leer, simplemente cambias tus DTMF_Datax por el que quieras o si queres que afecte a otro bit cambias el numero del bit_set
« Última modificación: 31 de Enero de 2016, 20:16:54 por KILLERJC »

Desconectado cvargcal

  • PIC16
  • ***
  • Mensajes: 166
Re:Lectura de puerto en orden aleatorio
« Respuesta #5 en: 31 de Enero de 2016, 21:10:08 »
El tema del input_state(pin) y la diferencia de lo que yo hice:.....
Excelente!! ahora si el código trabaja como yo quiero.
Muchas gracias.
 :)

Desconectado cvargcal

  • PIC16
  • ***
  • Mensajes: 166
Re:Lectura de puerto en orden aleatorio
« Respuesta #6 en: 06 de Febrero de 2016, 23:23:41 »
Saludos!
Tengo una nueva duda, pero no se si es prudente abrir otro hilo o si preguntar aquí... en ultimas casi el mismo tema.
Estoy con otro programa que recibe una variable por el puerto serial para controlar unos relecs. Pero quiero imprimir la variable en los bit de diferentes puertos.
así:
Código: C
  1. #byte portb = 0x06     // PortB.
  2. #byte portc = 0x07     // PortC.
  3. Variable=0xFF;            // Por ejemplo, variable recibida (255=1111 1111)
  4.  
  5. //RC2,RC3,RC4,RC5 (Salida 1,2,3,4), RB0-RB3 (Salida 5,6,7,8).
  6. portc= (bits 1,2,3,4 de variable)
  7. portb =(bits 5,6,7,8 de variable)
Ya sé que lo podría hacer con:
Código: C
  1. output_low (PINx)
  2.  output_high (PINx)


Lo hice de esta forma, pero no sé si será optima:
Código: C
  1. Temp1=0xFF;
  2.  
  3.    //RC2,RC3,RC4,RC5 (Salidas 1,2,3,4),RB0-RB3 (Salidas  5,6,7,8),
  4.    if (bit_test(Temp1,0)) output_high(PIN_C2); else output_low(PIN_C2);
  5.    if (bit_test(Temp1,1)) output_high(PIN_C3); else output_low(PIN_C3);
  6.    if (bit_test(Temp1,2)) output_high(PIN_C4); else output_low(PIN_C4);
  7.    if (bit_test(Temp1,3)) output_high(PIN_C5); else output_low(PIN_C5);
  8.    
  9.    if (bit_test(Temp1,4)) output_high(PIN_B0); else output_low(PIN_B0);
  10.    if (bit_test(Temp1,5)) output_high(PIN_B1); else output_low(PIN_B1);
  11.    if (bit_test(Temp1,6)) output_high(PIN_B2); else output_low(PIN_B2);
  12.    if (bit_test(Temp1,7)) output_high(PIN_B3); else output_low(PIN_B3);





   
     
« Última modificación: 07 de Febrero de 2016, 00:17:33 por cvargcal »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Lectura de puerto en orden aleatorio
« Respuesta #7 en: 07 de Febrero de 2016, 01:14:22 »
No se a que te referis como optimo , velocidad o espacio ocupado. Si hablas de lograr la mayor velocidad ( aunque ocupe una posicion mas de RAM) entonces haria esto:


Código: C
  1. Variable=0xFF;                  // Variable recibida
  2.  
  3.         Temp=PORTC & 0xC3;              // Registro auxiliar, Solo dejo los valores que no voy a cambiar, los demas todos a 0
  4.  
  5.         //RC2,RC3,RC4,RC5 (Salidas 1,2,3,4),RB0-RB3 (Salidas  5,6,7,8),
  6.         if (bit_test(Variable,0)) bit_set(Temp,2);
  7.         if (bit_test(Variable,1)) bit_set(Temp,3);
  8.         if (bit_test(Variable,2)) bit_set(Temp,4);
  9.         if (bit_test(Variable,3)) bit_set(Temp,5);
  10.         PORTC = Temp;                   // Cambiados los bits por los nuevos procedo a ponerlos en el puerto
  11.        
  12.         Tempo = PORTB & 0xF0;           // De la misma forma que arriba
  13.         if (bit_test(Variable,4)) bit_set(Temp,0);
  14.         if (bit_test(Variable,5)) bit_set(Temp,1);
  15.         if (bit_test(Variable,6)) bit_set(Temp,2);
  16.         if (bit_test(Variable,7)) bit_set(Temp,3);
  17.         PORTB = Temp;

eso llevaria .. 26 instrucciones en ASM, poner mas seria un robo :P
El por que no un if .. else , es por 2 cosas:

- Una es cambiar uno por uno los puertos en ves de todos juntos. Un tema de seguridad en un PIC16 cuando puede haber un pin acoplado a una gran capacidad (raro )
- Y la otra es por que no hay un sistema sencillo para hacer un if .. else en los PICs y la mayoria requiere varias instrucciones y saltos, que para un if...else de 1 instruccion como tenes es insensato. Incluso si se utilizara una tabla ocuparia mas lugar de memoria.
« Última modificación: 07 de Febrero de 2016, 04:32:39 por KILLERJC »

Desconectado cvargcal

  • PIC16
  • ***
  • Mensajes: 166
Re:Lectura de puerto en orden aleatorio
« Respuesta #8 en: 07 de Febrero de 2016, 02:36:43 »
No se a que te referis como optimo , velocidad o espacio ocupado......
Gracias!
Perdona esta pregunta, tal vez es demasiado básica (Se muy poco de PIC) , pero aun no entiendo muy bien como funciona esas expresiones que usas:
Código: C
  1. Temp=PORTC & 0xF3;
  2. Tempo = PORTB & 0xF0;


Supongamos que el valor de PORTC es 0xFF=1111 1111 y  0xF3= 1111 0011
Temp=11111111 & 11110011;   ¿Cómo es eso?

Citar
El manual de CCS dice:
&=     Bitwise and assignment operator, x&=y, is the same as x=x&y
&       Address operator
&       Bitwise and operator
« Última modificación: 07 de Febrero de 2016, 02:38:55 por cvargcal »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Lectura de puerto en orden aleatorio
« Respuesta #9 en: 07 de Febrero de 2016, 04:32:25 »
Perdon cvargal, fue un error mio... es 0xC3 ese valor, es que escribi primero el de abajo 0xF0 y luego cuando pase de binario a hexa me quede pensando en la F..

Tomando tu ejemplo:
Supongamos que el valor de PORTC es 0xFF=1011 0110 y  0xC3= 1100 0011
Es decir puede haber otra parte del programa que use las salidas del puerto C, entonces yo no quiero cambiarlas. Yo solo quiero cambiar de RC2 a RC5. Entonces hago una copia y guardo la AND entre PORTC y 0xC3 en Temp.

PORTC - 1011 0110
0xC3    - 1100 0011        AND
------------------------
Temp   -  1000 0010

Es decir los bits que corresponden del PORTC a lo que estan en 1 en 0xC3 se mantienen con el mismo valor, observa PORTC,7,6,1 y 0. Con respecto a Temp, siguen con el mismo valor. Pero de RC2 a RC5 estan en 0 sea el valor que sea. Entonces solo me resta ponerlos en 1, por eso unicamente el if que hago es para ponerlos en 1.

Ahora solo resta ver "Variable" y que bits tiene, supongamos que "Variable" tiene el valor 1001 0110
Segun el programa tuyo:

RC2 deberia ser 0
RC3 deberia ser 1
RC4 deberia ser 1
RC5 deberia ser 0

Entonces a Temp le va ir cambiando bit a bit hasta dejarlo en:

1011 1010

 Y lo pongo de nuevo en PORTC. Que para ahora hacerte una diferencia del antes y despues verias:

PORTC antes : 1011 0110
PORTC ahora : 1001 1010

Como observas los bits de afuera no cambiaron. Mientras que los de adentro ( los de interes ) si lo hicieron.

De todas formas esto es muy especifico para lo que estas buscando, es como una solucion hecha a medida y que si quisieras cambiar los pines habria que cambiar el valor tambien de la AND que se realiza.

PD: Si no entendes como funciona una AND, busca : tabla de verdad AND, y vas a tener una tabla con 2 entrads ( usualmente A y B ) y segun los valores es la salida que tendrias.
« Última modificación: 07 de Febrero de 2016, 04:45:06 por KILLERJC »

Desconectado cvargcal

  • PIC16
  • ***
  • Mensajes: 166
Re:Lectura de puerto en orden aleatorio
« Respuesta #10 en: 07 de Febrero de 2016, 11:30:59 »
Perdon cvargal, fue un error mio... es 0xC3 ese valor, es que escribi primero el de abajo 0xF0 y luego cuando pase de binario a hexa me quede pensando en la F..

Listo, ahora si entendí...  Lo que pasa es que pensé que la AND era solo con  doble "&&"... lo cual me surgen dos preguntas. ¿Cuando uso "&&"? y otra pregunta. ¿Cómo sacas esos hex ? yo lo estoy haciendo con la calculadora de windows y 0xFF= 1111 1111, 0xC3=‭1100 0011‬ o el valor que escribiste es arbitrario para el ejemplo?

Muchas gracias, ahora es mas claro el panorama. :-/ ((:-))

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Lectura de puerto en orden aleatorio
« Respuesta #11 en: 07 de Febrero de 2016, 14:26:24 »
& es un bit-wise AND

Es decir es una AND bit a bit.

&& es una AND logica!.

La diferencia radica en cuando lo usas. Si vos queres hacer bit a bit usas &, si vos queres comparar true/false usas && ..
Un ejemplo para ver si queda mas claro.

Código: C
  1. a=0x30
  2. b=0x45
  3.  
  4. if ( a==0x30 && b==0x90 )
  5. {
  6. }

En ese ejemplo ese if comienza a evaluarse. Supongamos que se evalua primero el a==0x30 , esto es un operador de igualdad y el '==' significa 'igual a', ¿ A es igual a 0x30 ? Eso me devuelve un TRUE , luego pregunta por b , pero b no es igual a 0x90, asi que me da FALSE, reemplazando me queda asi:

Código: C
  1. if ( TRUE && FALSE )

true AND false = false

Por lo tanto no va a entrar al if().
Que hubiera ocurrido si ponia solo '&', podria haber funcionado. Pero no es correcto hacerlo. Ya que son 2 usos distintos. Un caso que se pueda ver eso es:

Código: C
  1. a=0b0101 0101
  2. b=0b1010 1010
  3.  
  4. if ( a & b )
  5. {
  6.    // Aca NO entra
  7. }
  8.  
  9. if ( a && b )
  10. {
  11.    // Aca SI entra
  12. }

En el primer caso si haces a AND b, te vas a encontrar que es 0. if(0) no entra. los if consideran cualquier valor distinto de 0 como verdaderos, el unico que representa el false es el 0
En el segundo caso, se evaluan primero si son verdaderos o falso ( a y b ), a tiene un valor distinto de 0, por lo tanto se evalua como True, b ocurre lo mismo y se evalua como True. Entonces True AND True = True, if (True) entra al if.

Espero que quede claro la diferencia. Hay muchos mas operandos.

Comparacion logica:

== igual , != no igual , < menor que, <= menor e igual que , > mayor que, >= mayor o igual que

= asignacion, ej: a = 10;

Luego tenes mas operandos que se forman con los de suma/multiplicacion/division/shift etc, y son para asignar:

+= , Ej a+=2; es lo mismo que poner a = a + 2;
/= , Ej a /= 2; igual que antes a = a / 2;
&= , a &= 2; ,  a = a & 2;   AND bit a bit
|= , a |= 2; , a = a | 2;    OR bit a bit

etc hay varios

https://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B

Citar
¿Cómo sacas esos hex ? yo lo estoy haciendo con la calculadora de windows y 0xFF= 1111 1111, 0xC3=‭1100 0011‬ o el valor que escribiste es arbitrario para el ejemplo?

Los saco mentalmente xD, estoy tan acostumbrado a ver el binario y pasarlo a hex que es simple, por eso lo divido en 4 bits. y se que 0xC es 1100 , y 0x3 es 0011.
Respecto a si los valores son arbitrarios no los son. Tienen un por que.

Como te explique antes La idea es cambiar unicamente los bits de PUERTOC de RC2 a RC5, pero no cambiar los otros. Al usar una AND solo pongo en 0 los bits que corresponden a RC2 a RC5 ( son los que tienen un 0 en 0xC3 y que vos pedias como salida ) y los que quiero que queden iguales como RC0,Rc1,RC6,RC7 tienen un 1.

Por que ponerlos a 0 y no ir cambiando uno por uno?, Cuestion de gusto, Yo los puse a 0 a esos bits de esa forma los if que le siguen solo deberian ponerlo a 1 si es necesario, Si no hubiera hecho esto, deberia haber realizado un if..else como lo habias hecho vos por que ademas de ponerlo a 1 tendria que ponerlos a 0, Aca directamente solo tengo que ponerlos a 1 por que ya estan en 0.

Otro ejemplo. Supongamos que esta ves querias sacar el dato por el PUERTOC pero por RC0 Rc2 RC4 Rc7, ademas de cambiar los numeros de los bits en los bit_set(), deberia hacer una AND con:

0b0110 1010 = 0x6A

------------------------------------------------------------

PD:

Respecto al & , como veras sirve para indicar la direccion de una variable. Esto tiene que ver mas con los "punteros" de C. es un poco complejo el tema y que por ahora siento que deberias dejarlo pasar, pero punteros es lo mejor de C.

Desconectado cvargcal

  • PIC16
  • ***
  • Mensajes: 166
Re:Lectura de puerto en orden aleatorio
« Respuesta #12 en: 07 de Febrero de 2016, 17:07:21 »
& es un bit-wise AND....

Excelente, todo claro!
muchas gracias.


 

anything