volatile unsigned int BANDERAS; /* Variable tipo estructura para */
typedef struct tagBANDERASBits /* marcar eventos de interrupciones en*/
{ /* las interrupciones. */
unsigned int :15;
unsigned int tecla:1; /* Bandera para indicar el uso de la
* interrupción por notificación de
* cambio en un pin. */
} BANDERASBits;
Es que en realidad ahi estas creando 3 cosas distintas.
El primero es un entero sin signo llamado BANDERAS.
El segundo es un struct llamado tagBANDERASBits (es el nombre de la DEFINICION de estructura) y que dice como esta conformado. Formado por esta parte del codigo:Código: C
struct tagBANDERASBits /* marcar eventos de interrupciones en*/ { /* las interrupciones. */ unsigned int :15; unsigned int tecla:1; /* Bandera para indicar el uso de la * interrupción por notificación de * cambio en un pin. */ }
Luego tenes el typedef que "convierte" el struct tagBANDERASBits en BANDERASBits
Es decir TU codigo y este que voy a poner son equivalentes:Código: C
volatile unsigned int BANDERAS; struct tagBANDERASBits { unsigned int :15; unsigned int tecla:1;} typedef struct tagBANDERASBits BANDERASBits;
Uno usa el typedef para luego resumir la definición de la variable:Código: C
// Con typedef BANDERASBits my_struct; // Sin typedef struct tagBANDERASBits my_struct;
extern volatile uint16_t PORTD __attribute__((__sfr__));
typedef struct tagPORTDBITS {
uint16_t RD0:1;
uint16_t RD1:1;
uint16_t RD2:1;
uint16_t RD3:1;
uint16_t RD4:1;
uint16_t RD5:1;
uint16_t RD6:1;
uint16_t RD7:1;
uint16_t RD8:1;
uint16_t RD9:1;
uint16_t RD10:1;
uint16_t RD11:1;
} PORTDBITS;
extern volatile PORTDBITS PORTDbits __attribute__((__sfr__));
volatile unsigned int *BANDERAS; /* Variable tipo estructura para */
typedef struct tagBANDERASBits /* marcar eventos de interrupciones en*/
{ /* las interrupciones. */
unsigned int :15;
unsigned int tecla:1; /* Bandera para indicar el uso de la
* interrupción por notificación de
* cambio en un pin. */
} &BANDERASBits;
Gracias de antemano nuevamente por la ayuda brindada.
Comprendo ahora que estas intentando hacer.. Pero para lo que vos buscas hacer es mejor usar una union.
Cada compilador tiene su forma que no es estandar ni pertenece a C de definir algunas cosas, como es el caso de los registros en XC8 y luego tenemos XC16 que es mas parecido a gcc. Voy a copiar de forma completa la definicion de un puerto en XC8, el de XC16 ya lo pasaste, asi que lo voy a explicar nomas.
XC8:Código: C
// Register: PORTC #define PORTC PORTC extern volatile unsigned char PORTC @ 0x007; #ifndef _LIB_BUILD asm("PORTC equ 07h"); #endif // bitfield definitions typedef union { struct { unsigned RC0 :1; unsigned RC1 :1; unsigned RC2 :1; unsigned RC3 :1; unsigned RC4 :1; unsigned RC5 :1; unsigned RC6 :1; unsigned RC7 :1; }; } PORTCbits_t; extern volatile PORTCbits_t PORTCbits @ 0x007;
De aca tenes que observar 2 cosas.... el @ 0x007, que es la direccion de memoria que ocupa el registro PORTC.
Y la otra es que se definen 2 cosas en la misma direccion , uno que es el PORTC, y otro que es la estructura que es PORTCbits, por eso acceden a lo mismo.
En cambio XC16 pertenece o es un GCC modificado por Microchip.. El cual podes hacer uso de los atributos:
https://gcc.gnu.org/onlinedocs/gcc-3.2/gcc/Function-Attributes.html
Observaras en la lista que no existe ningun atributo __sfr__ , y que es especial de Microchip.
Esto hace muy parecido a lo visto con XC8 y lo maneja de forma interna el compilador (realizado unicamente para sus registros). Por eso lo que planteas no funcionaria....
-----------------------------------
Si podes hacerlo con una union, ejemplo:Código: C
typedef union BANDERA_t { uint16_t completo; struct bits_s { uint16_t bandera:15; uint16_t tecla:1;} bits; } BANDERA_t;
En tu main:Código: C
BANDERA_t BANDERAS; while(1){ BANDERAS.completo = 0x0AA0; // Con esto accedo a los 16 bits BANDERAS.bits.tecla = 1; // Con esto accedo a la parte de 1 bit BANDERAS.bits.bandera = 12; // Con esto accedo a los demas 15 bits }
Tanto el completo como los bits, ocupan una sola posicion de memoria. El unico problema de los bitfields, es que es de implementacion especifica de cada compilador el orden de los mismos. Por ejemplo, en la simulacion puedo observar que el bit de tecla es el de mayor peso. Pero que en otro compilador (por si deseas usar el mismo codigo en otro lado) podria no ser asi. Asi que necesitas tener eso en cuenta.
Si te preguntas , uint16_t significa entero sin signo de 16 bits y esta definido en stdint.h el cual necesitas agregar si queres usar esas definiciones, sino reemplazalo por tu unsigned int.
Comprendo ahora que estas intentando hacer.. Pero para lo que vos buscas hacer es mejor usar una union.
Cada compilador tiene su forma que no es estandar ni pertenece a C de definir algunas cosas, como es el caso de los registros en XC8 y luego tenemos XC16 que es mas parecido a gcc. Voy a copiar de forma completa la definicion de un puerto en XC8, el de XC16 ya lo pasaste, asi que lo voy a explicar nomas.
XC8:Código: C
// Register: PORTC #define PORTC PORTC extern volatile unsigned char PORTC @ 0x007; #ifndef _LIB_BUILD asm("PORTC equ 07h"); #endif // bitfield definitions typedef union { struct { unsigned RC0 :1; unsigned RC1 :1; unsigned RC2 :1; unsigned RC3 :1; unsigned RC4 :1; unsigned RC5 :1; unsigned RC6 :1; unsigned RC7 :1; }; } PORTCbits_t; extern volatile PORTCbits_t PORTCbits @ 0x007;
De aca tenes que observar 2 cosas.... el @ 0x007, que es la direccion de memoria que ocupa el registro PORTC.
Y la otra es que se definen 2 cosas en la misma direccion , uno que es el PORTC, y otro que es la estructura que es PORTCbits, por eso acceden a lo mismo.
En cambio XC16 pertenece o es un GCC modificado por Microchip.. El cual podes hacer uso de los atributos:
https://gcc.gnu.org/onlinedocs/gcc-3.2/gcc/Function-Attributes.html
Observaras en la lista que no existe ningun atributo __sfr__ , y que es especial de Microchip.
Esto hace muy parecido a lo visto con XC8 y lo maneja de forma interna el compilador (realizado unicamente para sus registros). Por eso lo que planteas no funcionaria....
-----------------------------------
Si podes hacerlo con una union, ejemplo:Código: C
typedef union BANDERA_t { uint16_t completo; struct bits_s { uint16_t bandera:15; uint16_t tecla:1;} bits; } BANDERA_t;
En tu main:Código: C
BANDERA_t BANDERAS; while(1){ BANDERAS.completo = 0x0AA0; // Con esto accedo a los 16 bits BANDERAS.bits.tecla = 1; // Con esto accedo a la parte de 1 bit BANDERAS.bits.bandera = 12; // Con esto accedo a los demas 15 bits }
Tanto el completo como los bits, ocupan una sola posicion de memoria. El unico problema de los bitfields, es que es de implementacion especifica de cada compilador el orden de los mismos. Por ejemplo, en la simulacion puedo observar que el bit de tecla es el de mayor peso. Pero que en otro compilador (por si deseas usar el mismo codigo en otro lado) podria no ser asi. Asi que necesitas tener eso en cuenta.
Si te preguntas , uint16_t significa entero sin signo de 16 bits y esta definido en stdint.h el cual necesitas agregar si queres usar esas definiciones, sino reemplazalo por tu unsigned int.
Muchas gracias @KILLERJC, ahora tengo todo mucho más claro.
tanto en la definición de xc8 como en la de xc16 definen el puerto antes y después de la definición de la unión, ¿Por qué hacen esto?, ¿Es lo que me explicas de interno a cada compilador?.
Citartanto en la definición de xc8 como en la de xc16 definen el puerto antes y después de la definición de la unión, ¿Por qué hacen esto?, ¿Es lo que me explicas de interno a cada compilador?.
No importa el orden de la definicion.
Siempre que apunte hacia el mismo lado, que en XC8 gracias al @ y e XC16 al atributo __sfr__ lo hacen, uno de forma mas explicita que el otro , en XC8 indica la direccion, mientras que XC16 lo hace interno al compilador, es decir no ves la direccion de memoria a la que se apunta.
Pero de todas formas esto no es necesario para lo que estabas buscando hacer, y como te digo es especifico de estos compiladores. Los de otras marcas se manejan de forma distinta.
La forma que deberias hacerlo es con la union como te lo plantee. Intenta liberarte de lo que hacen los compiladores.
typedef union /* Variable tipo estructura para */
{ /* marcar eventos de interrupciones en*/
unsigned int Banderas; /* marcar eventos de interrupciones en*/
struct /* las interrupciones. */
{
unsigned int restantes:15;
unsigned int tecla:1; /* Bandera para indicar el uso de la
* interrupción por notificación de
* cambio en un pin. */
} BANDERASBits;
} SENALES;
#include "globales.h"
/* Definición de constantes a usar en las interrupciones. */
SENALES senales; /* Depende de las variables definidas */
senales.banderas = 0; /* en globales.h. */
dentro del archivo "interrupt.h".
cuando compilo esto me está dando el error
[code]
interrup.h:17:16: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'senales'
Dos cosas:
Estas poniendo esto en algun lugar fuera de una funcion, por lo tanto te da error. acabo de probarlo y es el mismo error que te da.Código: C
senales.banderas = 0;
Y segundo es Banderas con B mayuscula, C es case sensitive, el MPLAB te permite completarlo, al presionar el punto si no se abre enseguida (que se puede cambiar para que lo haga) podes presionar Ctrl + Barra espaciadora, y te abre las sugerencias.