TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: johenrod en 16 de Diciembre de 2019, 11:12:51

Título: como imprimir solo una parte del puerto?
Publicado por: johenrod 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).
Título: Re:como imprimir solo una parte del puerto?
Publicado por: remi04 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);
                                                 



Título: Re:como imprimir solo una parte del puerto?
Publicado por: KILLERJC 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
Título: Re:como imprimir solo una parte del puerto?
Publicado por: elreypic2 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.
Título: Re:como imprimir solo una parte del puerto?
Publicado por: Eduardo2 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
}

Título: Re:como imprimir solo una parte del puerto?
Publicado por: johenrod 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?
Título: Re:como imprimir solo una parte del puerto?
Publicado por: johenrod 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);
                                                 




Título: Re:como imprimir solo una parte del puerto?
Publicado por: johenrod 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
Título: Re:como imprimir solo una parte del puerto?
Publicado por: KILLERJC 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.
Título: Re:como imprimir solo una parte del puerto?
Publicado por: Eduardo2 en 23 de Diciembre de 2019, 12:55:14
....
lo anterior es valido en CCS?

Lo escribí con CCS.
Título: Re:como imprimir solo una parte del puerto?
Publicado por: johenrod 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)
Título: Re:como imprimir solo una parte del puerto?
Publicado por: KILLERJC 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.
Título: Re:como imprimir solo una parte del puerto?
Publicado por: johenrod 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.
Título: Re:como imprimir solo una parte del puerto?
Publicado por: KILLERJC 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.
Título: Re:como imprimir solo una parte del puerto?
Publicado por: johenrod 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 " ((:-))