Autor Tema: como imprimir solo una parte del puerto?  (Leído 4446 veces)

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

Desconectado johenrod

  • PIC18
  • ****
  • Mensajes: 276
como imprimir solo una parte del puerto?
« en: 16 de Diciembre de 2019, 11:12:51 »
Cordial saludo, les agradezco la ayuda que puedan brindarme para despejar lo siguiente,,,
estoy trabajando con un pic 12f508  solo tiene un puerto de 6 bits, tengo una variable, de la cual solo me interesan  los primeros 3 bits (0,1 y 2) que son salidas los demás entradas
Código: [Seleccionar]
set_tris_b(0B111000);   // configuro i_o
int8 val=7;
portb=val;

Para este ejemplo no tengo problemas ya que al sacar la información no toma en cuenta los bits 3,4 y5 ya que están como entradas (bueno al menos en la practica no me causan problemas) si fueran salidas podría estar reescribiendo alguna salida que la tenga para otro fin, ya que se colocarían a "0"  (000111). si val, fuera = a 7
podría tratar de discriminar uno a uno los bits del puerto pero creo que seria mucho código y no es pereza, pero creo debe haber alguna forma para hacerlo mejor. (he leido y creo que una forma seria enmascaralo con & pero aun no se implementarlo)
gracias de antemano (lo estoy haciendo en CCS).
« Última modificación: 16 de Diciembre de 2019, 12:17:49 por johenrod »
Si algo parece complicado... es por que esta mal explicado.

Desconectado remi04

  • PIC24F
  • *****
  • Mensajes: 657
Re:como imprimir solo una parte del puerto?
« Respuesta #1 en: 16 de Diciembre de 2019, 14:17:21 »
yo obtendría primero un modulo a 7 del numero que le vas a enviar al puerto b
Luego haces XOR al valor actual del puerto b con el modulo obtenido.

por ejemplo:

Código: C
  1. int8 numero;                                          
  2. portb = 0b111000 ^ (numero % 7);
                                                 




Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:como imprimir solo una parte del puerto?
« Respuesta #2 en: 16 de Diciembre de 2019, 15:39:17 »
El problema del codigo anterior es que borra todo lo que tenia. A vos te interesa dejar lo que tiene el PORTB, imagino que debido a que posiblemente tengas varias salidas

Pero tambien y lo mas comun  es hacer esto:

Código: C
  1. int8 numero;                                          
  2. portb = (portb & 0b111000) | (numero & 0b000111);

Si estas seguro de que numero no supera los 3 bits, entonces se reduce a:

Código: C
  1. portb = (portb & 0b111000) | numero;

Respecto a que sea por CCS, tendras que leer con input_b() y output_b() para escribir, siempre y cuando uses el FAST_IO, sino el mismo compilador te lo cambia a entrada o salida por mas que explicites con el set_tris_x

Desconectado elreypic2

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1297
Re:como imprimir solo una parte del puerto?
« Respuesta #3 en: 16 de Diciembre de 2019, 15:45:57 »
Justo estaba excribiendo mi sugerencia cuando KILLERJC se me adelantó.
Y mi sugerencia era exactamente la que de aplicar un operación AND y luego una OR, tal como lo explica KILLERJC.

Saludos.

elreypic.

Desconectado Eduardo2

  • PIC24H
  • ******
  • Mensajes: 1004
Re:como imprimir solo una parte del puerto?
« Respuesta #4 en: 16 de Diciembre de 2019, 17:03:03 »
Otra manera es por medio de estructuras.

Código: [Seleccionar]
struct { int8 b02:3 ; int8 b35:3 ;} port ;   // Declaro la estructura de "port"
#byte port = 6                                             //  La mapeo en la dirección de PORTB

void main(void)
{
    int8 p = 0x93 ;


    port.b02 = 0x93  ; // Escribe 3 en b0,b1,b2
                       // ignora el resto

    port.b35 = 0x93  ; // Escribe 3 en b3,b4,b5
                       // ignora el resto

    port.b02 = p     ; // Se generan las instrucciones
                       // necesarias para escribir
                       // 3 en b0,b1,b2

    port.b35 = p     ; // Se generan las instrucciones
                       // necesarias y los desplazamientos
                       // para escribir 3 en b3,b4,b5
}


Desconectado johenrod

  • PIC18
  • ****
  • Mensajes: 276
Re:como imprimir solo una parte del puerto?
« Respuesta #5 en: 23 de Diciembre de 2019, 11:10:40 »
cordial saludo, muchas gracias por las respuestas.
Otra manera es por medio de estructuras.

Código: [Seleccionar]
struct { int8 b02:3 ; int8 b35:3 ;} port ;   // Declaro la estructura de "port"
#byte port = 6                                             //  La mapeo en la dirección de PORTB

void main(void)
{
    int8 p = 0x93 ;


    port.b02 = 0x93  ; // Escribe 3 en b0,b1,b2
                       // ignora el resto

    port.b35 = 0x93  ; // Escribe 3 en b3,b4,b5
                       // ignora el resto

    port.b02 = p     ; // Se generan las instrucciones
                       // necesarias para escribir
                       // 3 en b0,b1,b2

    port.b35 = p     ; // Se generan las instrucciones
                       // necesarias y los desplazamientos
                       // para escribir 3 en b3,b4,b5
}



lo anterior es valido en CCS?
« Última modificación: 23 de Diciembre de 2019, 11:53:36 por johenrod »
Si algo parece complicado... es por que esta mal explicado.

Desconectado johenrod

  • PIC18
  • ****
  • Mensajes: 276
Re:como imprimir solo una parte del puerto?
« Respuesta #6 en: 23 de Diciembre de 2019, 11:38:11 »
...este simbolo "^" a que equivaldria en ccs?
% seria residuo?



yo obtendría primero un modulo a 7 del numero que le vas a enviar al puerto b
Luego haces XOR al valor actual del puerto b con el modulo obtenido.

por ejemplo:

Código: C
  1. int8 numero;                                          
  2. portb = 0b111000 ^ (numero % 7);
                                                 




« Última modificación: 23 de Diciembre de 2019, 11:49:29 por johenrod »
Si algo parece complicado... es por que esta mal explicado.

Desconectado johenrod

  • PIC18
  • ****
  • Mensajes: 276
Re:como imprimir solo una parte del puerto?
« Respuesta #7 en: 23 de Diciembre de 2019, 11:47:56 »
aquí seria hacer una and y luego una or? así lo entiendo cual seria el objetivo de hacer primero una and al puerto?

entiendo que al declarar #fast_io, no importa como se pregunte o escriba en un pin, no cambia el tris como lo haría en standard_io. o estoy equivocado?


El problema del codigo anterior es que borra todo lo que tenia. A vos te interesa dejar lo que tiene el PORTB, imagino que debido a que posiblemente tengas varias salidas

Pero tambien y lo mas comun  es hacer esto:

Código: C
  1. int8 numero;                                          
  2. portb = (portb & 0b111000) | (numero & 0b000111);

Si estas seguro de que numero no supera los 3 bits, entonces se reduce a:

Código: C
  1. portb = (portb & 0b111000) | numero;

Respecto a que sea por CCS, tendras que leer con input_b() y output_b() para escribir, siempre y cuando uses el FAST_IO, sino el mismo compilador te lo cambia a entrada o salida por mas que explicites con el set_tris_x
« Última modificación: 23 de Diciembre de 2019, 12:12:49 por johenrod »
Si algo parece complicado... es por que esta mal explicado.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:como imprimir solo una parte del puerto?
« Respuesta #8 en: 23 de Diciembre de 2019, 12:33:30 »
...este simbolo "^" a que equivaldria en ccs?
% seria residuo?

En CCS es lo mismo, ya que es un operador de C.

el ^ es la XOR
el % es el residuo, por ejemplo 18 % 5 , quedaria 3.

Citar
aquí seria hacer una and y luego una or? así lo entiendo cual seria el objetivo de hacer primero una and al puerto?

A veces tenes mas de una salida, y vos buscas cambiar solo un par, sin que te modifique las demas.
Entonces necesito dejar esos valores, es por eso que tomo el valor del PORTB y le hago la AND, dejando unicamente los bits que no quiero modificar, en este caso seria el bit 3,4 y 5

Código: C
  1. (portb & 0b111000)

Suponete que en el PORTB tenia 0b101011 , al pasarlos por esa AND me quedaria 0b101000 conservando los valores que deseo no modificar.
Del otro lado tengo el numero a cargar en los bits 0 , 1 y 2

Código: C
  1. (numero & 0b000111)

Todo lo demas que supere esos bits deseo que NO esten, por lo tanto al hacer la AND, si numero era 0b111101 me va a quedar: 0b000101

Finalmente la OR que une los 2 numeros y actualizo el PORTB con el nuevo valor

0b101000  OR 0b000101  = 0b101101

PORTB viejo:   0b101011
PORTB nuevo: 0b101101

Como ves la primer parte se mantuvo.

Citar
entiendo que al declarar #fast_io, no importa como se pregunte o escriba en un pin, no cambia el tris como lo haría en standard_io. o estoy equivocado?

Es correcto.

Desconectado Eduardo2

  • PIC24H
  • ******
  • Mensajes: 1004
Re:como imprimir solo una parte del puerto?
« Respuesta #9 en: 23 de Diciembre de 2019, 12:55:14 »
....
lo anterior es valido en CCS?

Lo escribí con CCS.

Desconectado johenrod

  • PIC18
  • ****
  • Mensajes: 276
Re:como imprimir solo una parte del puerto?
« Respuesta #10 en: 23 de Diciembre de 2019, 14:28:39 »
muchas gracias por las respuestas, a ver si me quedo claro...

 inicialmente hago una and del puerto b (colocando en 1 lo que quiero conservar)
(portb & 0b111000)

luego hago otra and a numero con el  puerto b, pero colocando 1 los bits que si deseo modificar.
(numero & 0b000111)

y al obtener esos 2 resultados les hago una "OR"
(lo asumo asi porque primero se realizan las & de los paréntesis y luego hace la OR)
Si algo parece complicado... es por que esta mal explicado.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:como imprimir solo una parte del puerto?
« Respuesta #11 en: 23 de Diciembre de 2019, 14:53:45 »
Todo bien solo te corrijo una parte que resalto en negrita:

Citar
luego hago otra and a numero con el  puerto b, pero colocando 1 los bits que si deseo modificar.
(numero & 0b000111)

Solo haces una AND con el valor 0b000111 a numero. Justamente como decis colocando en 1 los bits que deseas modificar.

Y finalmente la OR para "unir" esos dos resultados.

Desconectado johenrod

  • PIC18
  • ****
  • Mensajes: 276
Re:como imprimir solo una parte del puerto?
« Respuesta #12 en: 23 de Diciembre de 2019, 15:01:34 »
cordial saludo,
aquí me confundo si lo hago "XOR" me dan las tablas de verdad pero con "OR" no
Código: [Seleccionar]
Todo lo demas que supere esos bits deseo que NO esten, por lo tanto al hacer la AND, si numero era 0b111101 me va a quedar: 0b000101

Finalmente la OR que une los 2 numeros y actualizo el PORTB con el nuevo valor

0b101000  OR 0b000101  = 0b101101

PORTB viejo:   0b101011
PORTB nuevo: 0b101101
.

por ultimo  a continuación,, me dicen que si estoy seguro de no superar los 3 bits lo haga así resumido, entonces cuando se debe hacer con los demás pasos.
Código: [Seleccionar]
Código: C
int8 numero;                                           
portb = (portb & 0b111000) | (numero & 0b000111);

Si estas seguro de que numero no supera los 3 bits, entonces se reduce a:

Código: C
portb = (portb & 0b111000) | numero;

Respecto a que sea por CCS, tendras que leer con input_b() y output_b() para escribir, siempre y cuando uses el FAST_IO, sino el mismo compilador te lo cambia a entrada o salida por mas que explicites con el set_tris_x
,
les agradezco la paciencia al respecto.
« Última modificación: 23 de Diciembre de 2019, 15:07:53 por johenrod »
Si algo parece complicado... es por que esta mal explicado.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:como imprimir solo una parte del puerto?
« Respuesta #13 en: 23 de Diciembre de 2019, 22:37:20 »
Citar
cordial saludo,
aquí me confundo si lo hago "XOR" me dan las tablas de verdad pero con "OR" no

La tabla de verdad de la OR es muy sencilla, si tenes algun 1, queda 1.

0b101000
0b000101
-----------
0b101101

Si observas donde existia un 1, queda el 1.... O... unicamente es 0 si ambos bits de esa posicion son cero.

Citar
por ultimo  a continuación,, me dicen que si estoy seguro de no superar los 3 bits lo haga así resumido, entonces cuando se debe hacer con los demás pasos.

Cuando sabes que numero jamas va a ser 8 o mayor... ya que el 8 en binario es 0b1000. Si tu programa permite que esto ocurra necesitas usar la AND para limitarlo a los bits que deseas cambiar... Si vos sabes que no vas a pasar de 7, es decir de 0 a 7. No necesitas la AND porque siempre vas a tener maximo 3 bits con 1, y todos los demas de mayor peso serian 0.

Desconectado johenrod

  • PIC18
  • ****
  • Mensajes: 276
Re:como imprimir solo una parte del puerto?
« Respuesta #14 en: 24 de Diciembre de 2019, 11:49:49 »
cordial saludo,,

Citar
cordial saludo,
aquí me confundo si lo hago "XOR" me dan las tablas de verdad pero con "OR" no

La tabla de verdad de la OR es muy sencilla, si tenes algun 1, queda 1.

0b101000
0b000101
-----------
0b101101

Si observas donde existia un 1, queda el 1.... O... unicamente es 0 si ambos bits de esa posicion son cero.

Citar
por ultimo  a continuación,, me dicen que si estoy seguro de no superar los 3 bits lo haga así resumido, entonces cuando se debe hacer con los demás pasos.

Cuando sabes que numero jamas va a ser 8 o mayor... ya que el 8 en binario es 0b1000. Si tu programa permite que esto ocurra necesitas usar la AND para limitarlo a los bits que deseas cambiar... Si vos sabes que no vas a pasar de 7, es decir de 0 a 7. No necesitas la AND porque siempre vas a tener maximo 3 bits con 1, y todos los demas de mayor peso serian 0.

si, te entiendo perfectamente y tengo claro las tablas de verdad, lo preguntaba porque en una respuesta me dieron una solución con "XOR" y pensé que había un error pero ahora veo es otro método.

...este simbolo "^" a que equivaldria en ccs?
% seria residuo?



yo obtendría primero un modulo a 7 del numero que le vas a enviar al puerto b
Luego haces XOR al valor actual del puerto b con el modulo obtenido.

por ejemplo:

Código: C
  1. int8 numero;                                          
  2. portb = 0b111000 ^ (numero % 7);
                                                 





ya he realizado las pruebas y trabaja perfecto, muchas gracias a todos por la ayuda me ha sido muy útil,..
"Feliz navidad para todos y un nuevo año lleno de programación " ((:-))
« Última modificación: 24 de Diciembre de 2019, 12:31:37 por johenrod »
Si algo parece complicado... es por que esta mal explicado.