Autor Tema: Asignar variable de 3bits a puerto  (Leído 3965 veces)

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

Desconectado dogflu66

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3510
Asignar variable de 3bits a puerto
« 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.
Saludos desde Granada, España.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Asignar variable de 3bits a puerto
« Respuesta #1 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


« Última modificación: 05 de Octubre de 2015, 18:44:48 por KILLERJC »

Desconectado RALF2

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 2060
Re: Asignar variable de 3bits a puerto
« Respuesta #2 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

Desconectado acabello

  • PIC10
  • *
  • Mensajes: 18
Re: Asignar variable de 3bits a puerto
« Respuesta #3 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. }


Desconectado PalitroqueZ

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5474
    • Electrónica Didacta
Re: Asignar variable de 3bits a puerto
« Respuesta #4 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

La propiedad privada es la mayor garantía de libertad.
Friedrich August von Hayek

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Asignar variable de 3bits a puerto
« Respuesta #5 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.

Desconectado dogflu66

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3510
Re: Asignar variable de 3bits a puerto
« Respuesta #6 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:
Saludos desde Granada, España.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Asignar variable de 3bits a puerto
« Respuesta #7 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.
« Última modificación: 06 de Octubre de 2015, 06:08:30 por KILLERJC »

Desconectado acabello

  • PIC10
  • *
  • Mensajes: 18
Re: Asignar variable de 3bits a puerto
« Respuesta #8 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.

Desconectado dogflu66

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3510
Re: Asignar variable de 3bits a puerto
« Respuesta #9 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.
Saludos desde Granada, España.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Asignar variable de 3bits a puerto
« Respuesta #10 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 ))
« Última modificación: 06 de Octubre de 2015, 09:28:32 por KILLERJC »

Desconectado acabello

  • PIC10
  • *
  • Mensajes: 18
Re: Asignar variable de 3bits a puerto
« Respuesta #11 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);
}

Desconectado acabello

  • PIC10
  • *
  • Mensajes: 18
Re: Asignar variable de 3bits a puerto
« Respuesta #12 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.

Desconectado dogflu66

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3510
Re: Asignar variable de 3bits a puerto
« Respuesta #13 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
}
Saludos desde Granada, España.

Desconectado dogflu66

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3510
Re: Asignar variable de 3bits a puerto
« Respuesta #14 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
}

« Última modificación: 10 de Octubre de 2015, 09:33:56 por dogflu66 »
Saludos desde Granada, España.