TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: dogflu66 en 05 de Octubre de 2015, 13:11:17

Título: Asignar variable de 3bits a puerto
Publicado por: dogflu66 en 05 de Octubre de 2015, 13:11:17
Quisiera saber si es posible, dentro de una estructura poder vincular directamente una variable de 3bits a los 3bits menos significativos de un puerto, gracias.
Título: Re: Asignar variable de 3bits a puerto
Publicado por: KILLERJC en 05 de Octubre de 2015, 17:30:46
Para que este vinculado directamente asi, la variable deberia estar alojada en la direccion exacta del registro.
Eso lograria que los bits sean los correspondientes. Pero los demas bits del byte deberian estarian creado en otro espacio.
No se exactamente como se maneja con los bitfields C, pero no creo que creando bitfields cree punteros a X espacio de memoria. Ya que ocuparia mucho mas que lo expresado por la declaracion de la estructura
Ademas si es un puntero ya no ocupa 3 bits. Ni menos un puntero a una funcion.

Pensando no se me ocurre ni una forma de hacerlo. Al menos para que quede algo asi:

int lsbbits : 3

Pense en un volatile int (REGx & 3) : 3
Estarias guardado exactamente el valor una ves, al inicio de la estructura si no estoy equivocado. Si aun asi esto funcionara serviria solo para leerlo, para escribirlo el registro no.

La que quedaria seria usar un puntero, pero aun asi no cumpliria con tu bitfield de 3 bits

Yo siempre evite el bit-fields por el tema de portabilidad. Si alguno posee una solucion que hable :P


Título: Re: Asignar variable de 3bits a puerto
Publicado por: RALF2 en 05 de Octubre de 2015, 18:36:39
Lo puedes hacer asi:

Citar
#include <18f252.h>

#fuses XT, nowdt
#use delay(clock= 4000000)
#use RS232(baud= 9600, xmit= pin_b0, rcv= pin_b1)

#define data(n) (output_bit(pin_c0, bit_test(n, 0)),output_bit(pin_c1, bit_test(n, 1)),output_bit(pin_c2, bit_test(n, 2)))

void main()
{
   int i;
   output_c(0xef);
   delay_ms(1000);
   
   for(i=0; i< 16; i++)
   {
      data(i);
      delay_ms(500);
   }
   while(true);
}   
:mrgreen:


Saludos
Título: Re: Asignar variable de 3bits a puerto
Publicado por: acabello en 05 de Octubre de 2015, 20:32:29
 Hola, de que si se puede, claro que si se puede, pero no se si vale el esfuerzo.  :lol: El codigo esta en C18.
Código: C
  1. struct MyPort           // Se define la estructura
  2.   {
  3.         unsigned HIGH:5;
  4.         unsigned LOW:3;
  5.   };
  6.   struct MyPort *pMyPortD;  // se crea un puntero para el tipo de estructura
  7.  
  8. void main() {
  9.  
  10.   TRISB=0xFF;
  11.   TRISD=0x00;          
  12.   ADCON1 = 0x0F;
  13.        
  14.   pMyPortD = (struct MyPort *) &(PORTD);        // se inicializa el puntero con la direccion del puerto D
  15.  
  16.  
  17.   do {
  18.  
  19.     pMyPortD->HIGH = 0x0;        // Turn OFF HIGH LEDs on PORTD
  20.     pMyPortD->LOW = 0x7;        // Turn ON LOW LEDs on PORTD
  21.         Delay10KTCYx(250);                      //  delay
  22.  
  23.     pMyPortD->HIGH = 0x1F;        // Turn ON HIGH LEDs on PORTD
  24.     pMyPortD->LOW = 0x0;        // Turn OFF LOW LEDs on PORTD
  25.         Delay10KTCYx(250);                      // delay
  26.  
  27.   } while(1);
  28. }

Título: Re: Asignar variable de 3bits a puerto
Publicado por: PalitroqueZ en 05 de Octubre de 2015, 20:32:38
con el operador or lo puedes hacer,

ejemplo:

(1)   portb=0b10001111;
(2)   pepe=0b01110000;
(3)   portb=portb | pepe;

el resultado en portb sería: portb=0b11111111

insertas los bits de la variable pepe en portb, sin alterar el estado del resto de los bits en portb

Título: Re: Asignar variable de 3bits a puerto
Publicado por: KILLERJC en 06 de Octubre de 2015, 00:27:38
Creo que todos entendimos una cosa distinta xD

Yo pensaba que el intentaba hacer algo asi:

Código: [Seleccionar]
  struct MyPort
  {
unsigned pepito:2;
unsigned jaimito:3;
unsigned bits_del_puerto:3;
  };

en el que pepito y jaimito sean 2 datos cualquiera que se me ocurra y esten en la RAM (no pertenezcan al puerto), pero que cuando quiera escribir o leer los bits del puerto SI o SI sea de PORTx y que los demas sean datos mios y no pertenecientes al puerto.

Entonces si hago:

Código: [Seleccionar]
struct MyPort a;
a.jaimito = 7;   //Esto no me modifica el puerto,
a.pepito = 0;   // Esto tampoco
a.bits_del_puerto = 4; // Esto si

Sino todo esto es un simple

Código: [Seleccionar]
x = PORTx & 7;
Ni te hace falta crear una estructura para eso, simplemente haces 2 macros y listo.

Al menos eso es lo que entendi yo.
Título: Re: Asignar variable de 3bits a puerto
Publicado por: dogflu66 en 06 de Octubre de 2015, 05:27:44
Bueno, el tema estaba en crear un tipo de dato nuevo (3bits), que la modificación de sus bits afectara directamente a los 3 bits menos significativos del puerto, en mi caso del PORTA. Estos 3bits controlan el multiplexado de 3digitos de 7segmentos led. La implementación que tengo hecha funciona perfectamente con lógica tradicional, lo que es cambiar los tres bits del puerto sin afectar al resto aplicando lógica booleana.

En particular yo uso programación tradicional, no me gusta utilizar funciones especificas del lenguaje, en este caso CCS. De todas maneras ya puesto es interesante ver la cantidad de variantes que están saliendo.  :mrgreen:
Título: Re: Asignar variable de 3bits a puerto
Publicado por: KILLERJC en 06 de Octubre de 2015, 05:55:11
Dejo una mas ya que ahora se lo que queres hacer y no tenia nada que ver con lo que habia pensado xD, no se si sera correcta, pero la dejo. Aunque no ganas nada y estamos en la misma siempre, solo es facilitar el uso.

Código: C
  1. #define activar_display(pin)    _activar_display(A,pin,0x07)
  2. #define _activar_display(puerto,bit,andvalue) PORT ## puerto = ( PORT ## puerto & ~( andvalue ) )|(1 << bit)
  3.  
  4. activar_display(1); // Activo display en el bit 0
  5. activar_display(0); // Activo display en el bit 1
  6. activar_display(2); // Activo display en el bit 2

Equivalente a hacer:

Código: C
  1. PORTA = ( PORTA & ~(0x07) )|(1 << 1);
  2. PORTA = ( PORTA & ~(0x07) )|(1 << 0);
  3. PORTA = ( PORTA & ~(0x07) )|(1 << 2);

Suponiendo que PORTA este definido lo cual CCS... digamos que tenes que definirlo.
Si queres cambiar de puerto o usar otro cambias por esto:

#define   activar_display(port,pin)   _activar_display(port,pin,0xF8)

Y podes usarlo como

activar_display(A,1);
activar_display(B,2);
activar_display(C,0);

Nuevamente definir todos ports en CCS.

PD: A elgarbe le gusta esto :P

Y lo que sigo sin entender es por que necesitas una estructura para eso.
Sino ahi acabello lo hizo, practicamente todo el header de cada pic esta realizado de esa manera, bit a bit en XC8.
Es la unica forma que hay con estructuras.
Título: Re: Asignar variable de 3bits a puerto
Publicado por: acabello en 06 de Octubre de 2015, 08:38:02
ya veo que todos comprendimos cosas diferentes. Pero lo que entendio primero Killer también se puede hacer, pero por ser zonas diferentes de memoria yo lo haría agregando el puntero al puerto a la estrutura de la siguiente manera.

Código: C
  1. struct MyPort {
  2.         unsigned HIGH:5;
  3.         unsigned LOW:3;
  4. };     
  5.  
  6.  struct Registro
  7.  {
  8.         unsigned char pepito;
  9.         unsigned char jaimito;
  10.         struct MyPort *pMyPortD; // puntero del tipo estructura MyPort
  11.  }RegA;                         //Se crea la instancia de la estructura Registro
  12.  
  13.  
  14. void main() {
  15.  
  16.   TRISB=0xFF;
  17.   TRISD=0x00;          
  18.   PORTD = 0x00;
  19.   ADCON1 = 0x0F;
  20.  
  21.   RegA.pMyPortD = (struct MyPort *) &(PORTD);   // se inicializa el puntero con la direccion del puerto D
  22.  
  23.   do {
  24.         RegA.pepito = 'a';
  25.         RegA.jaimito = 'b';
  26.     RegA.pMyPortD->HIGH = 0x0;        // Turn OFF LEDs on PORTD
  27.     RegA.pMyPortD->LOW = 0xFF;        // Turn ON LEDs on PORTD
  28.         Delay10KTCYx(250);                      //  delay
  29.  
  30.         RegA.pepito = 'c';
  31.         RegA.jaimito = 'd';
  32.     RegA.pMyPortD->HIGH = 0xFF;        // Turn ON LEDs on PORTD
  33.     RegA.pMyPortD->LOW = 0x0;        // Turn OFF LEDs on PORTD
  34.         Delay10KTCYx(250);                      // delay
  35.  
  36.   } while(1);
  37. }
 

PD: Observen que a pesar de que se asigna 0xFF intencionalmente a los bits, solo toma los que se definieron en la estructura.
Título: Re: Asignar variable de 3bits a puerto
Publicado por: dogflu66 en 06 de Octubre de 2015, 08:56:48
Se entiende que solo un bit puede estar puesto a 1 a la vez. El activar uno solo de los bits implica la puesta a 0 de los otros dos y si, si pueden tomar todos el valor 0 en el caso de querer apagar los tres dígitos, téngase en cuenta el caso de querer hacer parpadear los 3 dígitos, pero bueno esto ya es tema de control.

Y el tema de usar un struct, es porque se supone, si no estoy equivocado, que no se pueden dar dirección de memoria a un grupo de bits inferior  1byte. Por lo que tenia curiosidad  en saber como se pueden asociar a una dirección de memoria determinada 3bits, en este caso a un grupo de bits de un puerto que trabajaran solo como salidas.

La verdad es que hay variaciones casi para cada tipo de programador.
Título: Re: Asignar variable de 3bits a puerto
Publicado por: KILLERJC en 06 de Octubre de 2015, 09:06:52
Citar
Pero lo que entendio primero Killer también se puede hacer, pero por ser zonas diferentes de memoria yo lo haría agregando el puntero al puerto a la estrutura de la siguiente manera.

Lo que pensaba yo , no es lo que interpretaste. Esa es la misma solucion que ofreciste antes.
Yo hablaba de una estructura partida en bits pero que 3bits correspondan a el Puerto y lo demas a otro lado. Me autoquoteo, exactametente asi:

Código: C
  1. struct MyPort          
  2.   {
  3.         unsigned pepito:2;  // Esto no pertenece al puerto
  4.         unsigned jaimito:3; // Esto tampoco
  5.         unsigned bits_del_puerto:3;  // Esto si pertenece al puerto
  6.   };

Y eso si que es imposible xD

Agregado el apagar:
Código: C
  1. #define encender_display(pin)   _display(A,pin,0x07,1,0)
  2. #define apagar_display()        _display(A,pin,0x07,0,0)
  3. #define _display(puerto,bit,andvalue,set,ofs) PORT ## puerto = ( PORT ## puerto & ~( andvalue ) )|( set << ( bit + ofst ))
Título: Re: Asignar variable de 3bits a puerto
Publicado por: acabello en 06 de Octubre de 2015, 09:21:14
Pienso tambíen que es imposible así como lo planteas. Para lo que plantea dogflu se puede hacer así.

Código: [Seleccionar]
struct Digitos
{
unsigned HIGH:5;
unsigned dig3:1;
unsigned dig2:1;
unsigned dig1:1;
};
struct Digitos *pDigitos = (struct Digitos *) &(PORTD); // se inicializa el puntero con la direccion del puerto D
void main() {

  TRISB=0xFF;
  TRISD=0x00;         
  PORTD = 0x00;
  ADCON1 = 0x0F;


  do {
pDigitos->dig1 = 1;
pDigitos->dig2 = 0;
pDigitos->dig3 = 1;
Delay10KTCYx(250); //  delay

pDigitos->dig1 = 0;
pDigitos->dig2 = 1;
pDigitos->dig3 = 0;
Delay10KTCYx(250); // delay

  } while(1);
}
Título: Re: Asignar variable de 3bits a puerto
Publicado por: acabello en 06 de Octubre de 2015, 10:00:42
Claro que para los que usan el compilador C18 ya estas estructuras en los puertos estan definidas, para el PORTA es PORTAbits, para LATA es LATAbits, etc.

Código: [Seleccionar]

 LATAbits.LATA0=1;        // bit 0
 LATAbits.LATA1=0;        // bit 1
 LATAbits.LATA2=1;        // bit 2



Me imagino que para el CCS posiblemente estan también definidas pero no estoy seguro porque no lo uso.
Título: Re: Asignar variable de 3bits a puerto
Publicado por: dogflu66 en 10 de Octubre de 2015, 08:55:43
Lo puedes hacer asi:

Citar
#include <18f252.h>

#fuses XT, nowdt
#use delay(clock= 4000000)
#use RS232(baud= 9600, xmit= pin_b0, rcv= pin_b1)

#define data(n) (output_bit(pin_c0, bit_test(n, 0)),output_bit(pin_c1, bit_test(n, 1)),output_bit(pin_c2, bit_test(n, 2)))

void main()
{
   int i;
   output_c(0xef);
   delay_ms(1000);
   
   for(i=0; i< 16; i++)
   {
      data(i);
      delay_ms(500);
   }
   while(true);
}   
:mrgreen:


Saludos

Este método mediante macro incorporado a mi función y probado -> OK

Código: [Seleccionar]
//Selecciona el Display de 7Segmentos activo e imprime el digito.
//_numero a imprimir, _power = 1 display on
Void _Display(Int16 _numero, int1 _power) {

   #define data(n) (output_bit(pin_A0, bit_test(n, 0)),output_bit(pin_A1, bit_test(n, 1)),output_bit(pin_A2, bit_test(n, 2)))
   
   Static Int8 n = 0;
   Int8 i = 1;
   Int8 _digito = 0;

   If (_numero > 999) _numero = 999; //Acota superior el numero
   //Descompone en digitos para numero >= 100
   If (_numero >= 100) {
      If (n == 2) _digito = _numero / 100;
      else If (n == 1) _digito = ((_numero / 10) % 10);
      else If (n == 0) _digito = _numero % 10;
   }
   else If (_numero >= 10) { //Descompone en digitos para numero >= 10
      If (n == 1) _digito = _numero / 10;
      else If (n == 0) _digito = _numero % 10;
   }
   else If (n == 0) _digito = _numero; //Extrae el digito para numero < 10
   
   If (n == 1) PORTB = _get7seg1(_digito); //Asigna la mascara del digito con punto decimal 
   else PORTB = _get7seg(_digito); //Asigna la mascara del digito sin punto decimal

   If (_power == 0) i = 0; //Apaga el display
   data(i << n);
   //PORTA = (PORTA & 0b11111000) | (i << n); //Selecciona el digito a iluminar.
   if (n < 2) n++; //Proximo digito a iluminar (digitos 0 to 2)
   else n = 0; //Reinicia el ciclo de refresco
}
Título: Re: Asignar variable de 3bits a puerto
Publicado por: dogflu66 en 10 de Octubre de 2015, 09:29:38
ya veo que todos comprendimos cosas diferentes. Pero lo que entendio primero Killer también se puede hacer, pero por ser zonas diferentes de memoria yo lo haría agregando el puntero al puerto a la estrutura de la siguiente manera.

Código: C
  1. struct MyPort {
  2.         unsigned HIGH:5;
  3.         unsigned LOW:3;
  4. };     
  5.  
  6.  struct Registro
  7.  {
  8.         unsigned char pepito;
  9.         unsigned char jaimito;
  10.         struct MyPort *pMyPortD; // puntero del tipo estructura MyPort
  11.  }RegA;                         //Se crea la instancia de la estructura Registro
  12.  
  13.  
  14. void main() {
  15.  
  16.   TRISB=0xFF;
  17.   TRISD=0x00;          
  18.   PORTD = 0x00;
  19.   ADCON1 = 0x0F;
  20.  
  21.   RegA.pMyPortD = (struct MyPort *) &(PORTD);   // se inicializa el puntero con la direccion del puerto D
  22.  
  23.   do {
  24.         RegA.pepito = 'a';
  25.         RegA.jaimito = 'b';
  26.     RegA.pMyPortD->HIGH = 0x0;        // Turn OFF LEDs on PORTD
  27.     RegA.pMyPortD->LOW = 0xFF;        // Turn ON LEDs on PORTD
  28.         Delay10KTCYx(250);                      //  delay
  29.  
  30.         RegA.pepito = 'c';
  31.         RegA.jaimito = 'd';
  32.     RegA.pMyPortD->HIGH = 0xFF;        // Turn ON LEDs on PORTD
  33.     RegA.pMyPortD->LOW = 0x0;        // Turn OFF LEDs on PORTD
  34.         Delay10KTCYx(250);                      // delay
  35.  
  36.   } while(1);
  37. }
 

PD: Observen que a pesar de que se asigna 0xFF intencionalmente a los bits, solo toma los que se definieron en la estructura.

Esta implementación me ha costado un poco más de adaptar, pero también funciona -> OK:

Código: [Seleccionar]
//Selecciona el Display de 7Segmentos activo e imprime el digito.
//_numero a imprimir, _power = 1 display on
Void _Display(Int16 _numero, int1 _power) {
   struct MyPort {
      unsigned BIT3 : 3;
   }Port = 1;
   struct Registro {
      struct MyPort *pMyPortA;
   } RegA;
   RegA.pMyPortA = (struct MyPort *) &(PORTA);
 
   Static Int8 n = 0;
   //Int8 i = 1;
   Int8 _digito = 0;

   If (_numero > 999) _numero = 999; //Acota superior el numero
   //Descompone en digitos para numero >= 100
   If (_numero >= 100) {
      If (n == 2) _digito = _numero / 100;
      else If (n == 1) _digito = ((_numero / 10) % 10);
      else If (n == 0) _digito = _numero % 10;
   }
   else If (_numero >= 10) { //Descompone en digitos para numero >= 10
      If (n == 1) _digito = _numero / 10;
      else If (n == 0) _digito = _numero % 10;
   }
   else If (n == 0) _digito = _numero; //Extrae el digito para numero < 10
   
   If (n == 1) PORTB = _get7seg1(_digito); //Asigna la mascara del digito con punto decimal 
   else PORTB = _get7seg(_digito); //Asigna la mascara del digito sin punto decimal

   //If (_power == 0) i = 0; //Apaga el display
   If (_power == 0) Port.BIT3 = 0;
   RegA.pMyPortA -> BIT3 = Port.BIT3 << n;
   //PORTA = (PORTA & 0b11111000) | (i << n); //Selecciona el digito a iluminar.
   if (n < 2) n++; //Proximo digito a iluminar (digitos 0 to 2)
   else n = 0; //Reinicia el ciclo de refresco
}

Título: Re:Asignar variable de 3bits a puerto
Publicado por: dogflu66 en 10 de Octubre de 2015, 09:39:48
Según tenga más tiempo seguiré probando las otras implementaciones.
Título: Re: Asignar variable de 3bits a puerto
Publicado por: dogflu66 en 11 de Octubre de 2015, 07:51:42
Hola, de que si se puede, claro que si se puede, pero no se si vale el esfuerzo.  :lol: El codigo esta en C18.
Código: C
  1. struct MyPort           // Se define la estructura
  2.   {
  3.         unsigned HIGH:5;
  4.         unsigned LOW:3;
  5.   };
  6.   struct MyPort *pMyPortD;  // se crea un puntero para el tipo de estructura
  7.  
  8. void main() {
  9.  
  10.   TRISB=0xFF;
  11.   TRISD=0x00;          
  12.   ADCON1 = 0x0F;
  13.        
  14.   pMyPortD = (struct MyPort *) &(PORTD);        // se inicializa el puntero con la direccion del puerto D
  15.  
  16.  
  17.   do {
  18.  
  19.     pMyPortD->HIGH = 0x0;        // Turn OFF HIGH LEDs on PORTD
  20.     pMyPortD->LOW = 0x7;        // Turn ON LOW LEDs on PORTD
  21.         Delay10KTCYx(250);                      //  delay
  22.  
  23.     pMyPortD->HIGH = 0x1F;        // Turn ON HIGH LEDs on PORTD
  24.     pMyPortD->LOW = 0x0;        // Turn OFF LOW LEDs on PORTD
  25.         Delay10KTCYx(250);                      // delay
  26.  
  27.   } while(1);
  28. }

En realidad este y el anterior son el mismo, pero se me paso el ejemplo.

Este es el mismo que el anterior pero una versión algo más simplificada. Hace lo mismo mediante el mismo método (en este caso algo más simple) pero se adapta mejor a la función, porque va mejor con la simplicidad de la función.

Código: [Seleccionar]
//Selecciona el Display de 7Segmentos activo e imprime el digito.
//_numero a imprimir, _power = 1 display on
Void _Display(Int16 _numero, int1 _power) {
   struct MyPort {
      unsigned BIT3 : 3;
   }Port = 1;
   struct MyPort *pMyPortA;
   pMyPortA = (struct MyPort *) &(PORTA);
 
   Static Int8 n = 0;
   //Int8 i = 1;
   Int8 _digito = 0;

   If (_numero > 999) _numero = 999; //Acota superior el numero
   //Descompone en digitos para numero >= 100
   If (_numero >= 100) {
      If (n == 2) _digito = _numero / 100;
      else If (n == 1) _digito = ((_numero / 10) % 10);
      else If (n == 0) _digito = _numero % 10;
   }
   else If (_numero >= 10) { //Descompone en digitos para numero >= 10
      If (n == 1) _digito = _numero / 10;
      else If (n == 0) _digito = _numero % 10;
   }
   else If (n == 0) _digito = _numero; //Extrae el digito para numero < 10
   
   If (n == 1) PORTB = _get7seg1(_digito); //Asigna la mascara del digito con punto decimal 
   else PORTB = _get7seg(_digito); //Asigna la mascara del digito sin punto decimal

   //If (_power == 0) i = 0; //Apaga el display
   If (_power == 0) Port.BIT3 = 0;
   pMyPortA -> BIT3 = Port.BIT3 << n;
   //PORTA = (PORTA & 0b11111000) | (i << n); //Selecciona el digito a iluminar.
   if (n < 2) n++; //Proximo digito a iluminar (digitos 0 to 2)
   else n = 0; //Reinicia el ciclo de refresco
}
Título: Re:Asignar variable de 3bits a puerto
Publicado por: KILLERJC en 11 de Octubre de 2015, 08:00:00
El mio no se si funciona. Para XC8 creo que funcionaria directo. Y para CCS habria que definir PORTx para que funcione, luego cambiarle el puerto en el #define. La verdad es que no lo probe.

Y todo eso si es que funciona xD, nunca probe ese metodo, lo vi y bueno, pense ponerlo aca. Me refiero a este:

Código: C++
  1. #define encender_display(pin)   _display(A,pin,0x07,1,0)
  2.     #define apagar_display()        _display(A,pin,0x07,0,0)
  3.     #define _display(puerto,bit,andvalue,set,ofs) PORT ## puerto = ( PORT ## puerto & ~( andvalue ) )|( set << ( bit + ofst ))

Y luego usarias encender_display(n) y apagar_display() , incluso se podria complicar un poco mas el #define para que directamente solo tome de 0 a 3, y que 0 apague, 1 encienda el 1 y asi. y tener solo una definicion de funcion. Luego en el codigo se reemplaza por una AND + OR y listo.
y n en encender_display(n) toma el valor de 0,1,2, si es que no se agrega un offset.
Título: Re:Asignar variable de 3bits a puerto
Publicado por: dogflu66 en 11 de Octubre de 2015, 08:15:32
El tuyo también lo voy a experimentar, en el caso de que no consiga ponerlo en marcha lo indico, para así atacarle hasta adaptarlo a la función.

Nota:
   struct MyPort {
      unsigned BIT3 : 3;
   }Port = 1;
   struct MyPort *pMyPortA;
   pMyPortA = (struct MyPort *) &(PORTA);

Tenia curiosidad por saber si el CCS entendería que pMyPortA espera la asignación de una dirección de memoria y realmente es así:

   struct MyPort {
      unsigned BIT3 : 3;
   }Port = 1;
   struct MyPort *pMyPortA;
   pMyPortA = &(PORTA);

Acepta la modificación y no genera avisos.

Incluso esta: struct MyPort *pMyPortA = &(PORTA);

Título: Re:Asignar variable de 3bits a puerto
Publicado por: acabello en 11 de Octubre de 2015, 20:48:11
 Una forma mas.

Código: [Seleccionar]
#define display(n) LATAbits.LATA0 =(n & 1); LATAbits.LATA1 = (n & 2)>>1; LATAbits.LATA2 = (n & 4)>>2;

display(0); // Apaga todos
display(1); // Enciende el 1
display(2); // Enciende el 2
display(3); // Enciende el 1 y el 2


Título: Re:Asignar variable de 3bits a puerto
Publicado por: KILLERJC en 12 de Octubre de 2015, 03:08:37
Bueno despues de corregir un par de cosas, probe mi forma en XC8

Código: C++
  1. #include "xc.h"
  2.  
  3. #define display(pin)   _display(A,pin,0x07)
  4. #define _display(puerto,bit,andvalue) PORT ## puerto = ( PORT ## puerto & ~( andvalue ) )|( (bit?1:0) << ( bit-1 ))
  5.  
  6. int main() {
  7.    
  8.     TRISB = 0x0F;
  9.     ANSEL = 0;
  10.     ANSELH = 0;
  11.     PORTB = 0;
  12.  
  13.     while(1){
  14.         display(1); //Enciende display 1 (RA0)
  15.         display(2); //Enciende display 2 (RA1)
  16.         display(3); //Enciende display 3 (RA2)
  17.         display(0); //Apaga los displays
  18.     }
  19.    
  20. }

Resultado en ASM

Código: ASM
  1. !        display(1);
  2. 0x7E8: MOVF PORTA, W
  3. 0x7E9: ANDLW 0xF8
  4. 0x7EA: IORLW 0x1
  5. 0x7EB: MOVWF PORTA
  6. !        display(2);
  7. 0x7EC: MOVF PORTA, W
  8. 0x7ED: ANDLW 0xF8
  9. 0x7EE: IORLW 0x2
  10. 0x7EF: MOVWF PORTA
  11. !        display(3);
  12. 0x7F0: MOVF PORTA, W
  13. 0x7F1: ANDLW 0xF8
  14. 0x7F2: IORLW 0x4
  15. 0x7F3: MOVWF PORTA
  16. !        display(0);
  17. 0x7F4: MOVF PORTA, W
  18. 0x7F5: ANDLW 0xF8
  19. 0x7F6: MOVWF PORTA

Es decir el minimo numero de instrucciones posibles para llevar a cabo lo que se debe hacer.
Lo malo es el de no estar limitado a solo 3, pero que seguro dandole vueltas al define se podria hacer.
Y esta realizado para los primeros 3 bits, nada que no se pueda modificar
Título: Re:Asignar variable de 3bits a puerto
Publicado por: dogflu66 en 12 de Octubre de 2015, 08:21:44
Tengo que dejar el tema unos cuantos días, seguramente el "finde" que viene retomare el tema.
Título: Re:Asignar variable de 3bits a puerto
Publicado por: acabello en 12 de Octubre de 2015, 12:19:38

Solo para verificar el codigo que produce genere el asm, pero no se cuantos ciclos dura cada instruccion

Código: C++
  1. #define display(n) LATAbits.LATA0 =(n==1?1:0); LATAbits.LATA1 =(n==2?1:0); LATAbits.LATA2 =(n==3?1:0);
  2.  
  3.         display(1);
  4.         display(2);
  5.         display(3);
  6.         display(0);

Código: ASM
  1. 5(  63): bsf LATAbits, 0, 0      
  2.    6(  63): bcf LATAbits, 1, 0      
  3.    7(  63): bcf LATAbits, 2, 0
  4.        
  5.    8(  64): bcf LATAbits, 0, 0      
  6.    9(  64): bsf LATAbits, 1, 0      
  7.   10(  64): bcf LATAbits, 2, 0
  8.        
  9.   11(  65): bcf LATAbits, 0, 0      
  10.   12(  65): bcf LATAbits, 1, 0      
  11.   13(  65): bsf LATAbits, 2, 0
  12.        
  13.   14(  66): bcf LATAbits, 0, 0      
  14.   15(  66): bcf LATAbits, 1, 0      
  15.   16(  66): bcf LATAbits, 2, 0
Título: Re:Asignar variable de 3bits a puerto
Publicado por: KILLERJC en 12 de Octubre de 2015, 18:34:47
Citar
Solo para verificar el codigo que produce genere el asm, pero no se cuantos ciclos dura cada instruccion

Duran un ciclo cada una. El problema es la aplicacion. a muchos aplicaciones no les molesta. Solo para que entiendas lo que estas haciendo y los posibles problemas:

Suponete que tenes el puerto en 0x04 (display 3 encendido), es decir 0000 0100 , ejecutando esas instrucciones para encender el segundo display ocurriria esto:

1ra instruccion: 0000 0100
2da instruccion: 0000 0110
3ra instruccion: 0000 0010

Momentaneamente tenes los 2 activos, tal ves 1us o menos segun el clock. En un display en el cual manejas solo los anodos no creo que afecte en nada. no llegarian ni a encender creo.
Tambien tenes que ver que PIC estas trabajando. En tu caso es un PIC18, pero si es un PIC16 hacer eso puede traer otros problemas mas. El PIC18 cuando lee toma el valor del LATx ( este registro no esta conectado con la entrada del pin ) lo modifica en el nucleo y lo guarda.
En un PIC16 ocurre algo similar, nomas que usa el PORTx , ocurre que si haces esto:

bcf PORTAbits, 0, 0       
bsf PORTAbits, 1, 0       
bcf PORTAbits, 2, 0

Y tu diseño tiene una buena capacidad en sus pines vas a tener un error. ejemplo Supongamos que tenes algo conectado con una buena capacidad al pin PORTA,0 , tenes activo ese pin y luego ejecutas el codigo anterior. Ocurriria esto:

Antes de las instruccion:  0000 0001
1ra instruccion: 0000 0001  ( Intenta ponerlo a 0, es decir puso a 0 el tipo D, PERO por la capacidad en el pin la tension no baja rapido, ademas cuando lees,  lees el PIN no el LATCH o valor que le diste de salida )
2da instruccion: El nucleo lee: 0000 0001 (no lee el tipo D, sino el PIN) , modifica 0000 0011 , escribe 0000 0011 (Se perdio el 0 anterior asi que vuelve a 1 en bit de antes)
3ra instruccion: 0000 0011

Por eso mismo tenes que tenerlo en cuenta. Es aplicable si no ocurren estas cosas, por eso mismo los PIC18 ya traen en LATx y usamos el PORTx para leer del pin.
Yo jamas tuve problemas pero por lo que lei en los foros de Microchip en los PIC16 en algunos casos era algo serio. de tal forma que todos los cambios se hacian en una "variable" y luego se pasaba la variable completa al puerto.
Título: Re:Asignar variable de 3bits a puerto
Publicado por: acabello en 12 de Octubre de 2015, 19:04:20
Interesante, entonces esa seria una buena conclusion, tratar de no modificar bit a bit sino todo el puerto.
Título: Re:Asignar variable de 3bits a puerto
Publicado por: KILLERJC en 12 de Octubre de 2015, 19:22:04
Interesante, entonces esa seria una buena conclusion, tratar de no modificar bit a bit sino todo el puerto.

Tu solucion es totalmente valida.

Y la forma de hacerlo va a  depender de tu aplicacion , el PIC, lo que tengas conectado, etc. yo soy partidario de hacerlo directamente como lo hice, es decir Tomo el valor del puerto ( para no modificar los valores de los anteriores bits), le hago una AND y luego de ser necesario una OR, finalmente al puerto todo junto. En ASM prefiero eso. por esos motivos, pero solo queria remarcar lo que podria ocurrir, solo para que lo tengas en cuenta si es que en algun momento te falla y no sabes que es. Especialmente en los PIC16, el PIC18 solo tendrias que se activan los 2 al mismo tiempo por un muy pequeño momento.

Y esto creo que seria mucho peor
Código: [Seleccionar]
#define data(n) (output_bit(pin_c0, bit_test(n, 0)),output_bit(pin_c1, bit_test(n, 1)),output_bit(pin_c2, bit_test(n, 2)))
Ya que los bit_test devolverian un 1 o un 0, usando 3 instrucciones como minimo, El hacer eso significaria casi 6 instrucciones ASM por cada uno de estos:
output_bit(pin_c2, bit_test(n, 2))
Encima se realizarian todos en distintos tiempos, Se toma el valor del primero y se cambia, luego se toma el valor del otro pin y se cambia, tal ves un tema de velocidad. Pero si no usa #fast_io en CCS se le va a complicar manejar el puerto para hacer lo mismo que en XC8 y hacer:

#define output_c((input_c()&0xF8)|(1<<n))

Peero.. nuevamente depende de la aplicacion y tu necesidad de velocidad y esas cosas. Y todas son validas, no vi el codigo resultante de la estructura. deberia haber realizado una y probado.

EDIT:
Trate de realizar el codigo de la estructura y no funciono para nada. Siempre con errores o terminaba poniendo el dato en cualquier lado.
Título: Re:Asignar variable de 3bits a puerto
Publicado por: KILLERJC en 13 de Octubre de 2015, 08:10:25
El codigo con la estructura no me funciono para nada, asi que tome el ejemplo que usa para modificar los puertos el XC8, y lo modifique:

Código: C
  1. typedef union {
  2.     struct {
  3.         unsigned LOW    :3;
  4.         unsigned HIGH   :5;
  5.     };
  6. } MyPORT_t;
  7. extern volatile MyPORT_t MyPORT @ &PORTB;
  8.  
  9.  
  10. int main() {
  11.    
  12.     TRISB = 0x0F;
  13.     ANSEL = 0;
  14.     ANSELH = 0;
  15.     PORTB = 0;
  16.  
  17.     while(1){
  18.     MyPORT.LOW = 0x7;        // Turn ON LOW LEDs on PORTD
  19.     MyPORT.LOW = 0x0;        // Turn OFF LOW LEDs on PORTD
  20.     MyPORT.LOW = 0x1;
  21.     MyPORT.LOW = 0x2;
  22.     MyPORT.LOW = 0x4;
  23.     }
  24. }

El disasm

Código: ASM
  1. !    MyPORT.LOW = 0x7;        // Turn ON LOW LEDs on PORTD
  2. 0x7EB: MOVLW 0x7
  3. 0x7EC: IORWF PORTB, F
  4. !    MyPORT.LOW = 0x0;        // Turn OFF LOW LEDs on PORTD
  5. 0x7ED: MOVLW 0xF8
  6. 0x7EE: ANDWF PORTB, F
  7. !    MyPORT.LOW = 0x1;
  8. 0x7EF: MOVF PORTB, W
  9. 0x7F0: ANDLW 0xF8
  10. 0x7F1: IORLW 0x1
  11. 0x7F2: MOVWF PORTB
  12. !    MyPORT.LOW = 0x2;
  13. 0x7F3: MOVF PORTB, W
  14. 0x7F4: ANDLW 0xF8
  15. 0x7F5: IORLW 0x2
  16. 0x7F6: MOVWF PORTB
  17. !    MyPORT.LOW = 0x4;
  18. 0x7F7: MOVF PORTB, W
  19. 0x7F8: ANDLW 0xF8
  20. 0x7F9: IORLW 0x4
  21. 0x7FA: MOVWF PORTB

Se puede ver que no siempre hace el mismo codigo, Al principio con PORTB = 0, directamente le pone un 0x7 en una OR al puerto, pero luego en los demas no lo hace y vuelve a hacerlo como el define anterior. Raro...

Igual tal ves esto solo funcione en MPLAB
No creo que sea problema el no leer el puerto para ponerlo en 0 y es aventaja al codigo de los define. Es la unica diferencia, por una sola instruccion al momento de apagar todo. No se si hay otra mas y si va a funcionar obviamente, la desventaja es que no puedo usar el 1 para el primer dispaly, 2 para el segundo, etc.