blow
blow

Reputation: 13209

[ansi c]Pass bitifield as reference

In microchip C30 compiler i can set pin i/o value using LAT register in this way:

LATBbits.LATB10=1;

LATBbits is defined as:

typedef struct tagLATBBITS {
  unsigned LATB0:1;
  unsigned LATB1:1;
  unsigned LATB2:1;
  unsigned LATB3:1;
  unsigned LATB4:1;
  unsigned LATB5:1;
  unsigned LATB6:1;
  unsigned LATB7:1;
  unsigned LATB8:1;
  unsigned LATB9:1;
  unsigned LATB10:1;
  unsigned LATB11:1;
  unsigned LATB12:1;
  unsigned LATB13:1;
  unsigned LATB14:1;
  unsigned LATB15:1;
} LATBBITS;
extern volatile LATBBITS LATBbits __attribute__((__sfr__));

My target is to write a function that can set i/o value using LAT register as an argument, in pseudocode:

void setPin(unsigned int* latReg, unsigned int value){
  (*latReg)=value;
}

setPin(&LATBbits.LATB10, 1);

Unfortunately this code won't compile because "cannot take address of bit-field 'LATB10'".

I need it because i want to realize a simil-class library that can handle a port expander. Each port expander can have different pins, so i need to configure it and i think to do something like this:

typedef struct sPortExpander{
  unsigned int* CS;
  unsigned int* SPBUFF;
  ecc...
} PortExpander

void PortExpander_setOutput(PortExpander p, unsigned char value){
  (*p.CS)=0;
  // Send SPI data
  (*p.CS=1);
}

In this way i can manage multiple port expander.

So, there is a way to do what i try to do?

Thanks.

Upvotes: 2

Views: 244

Answers (1)

user529758
user529758

Reputation:

Declare the struct as __attribute__((packed)), then use:

void function setPin(struct LATBBITS *reg, unsigned int fieldno, unsigned int value){
    if (value)
        *(uint16_t *)reg |= (1 << fieldno);
    else
        *(uint16_t *)reg &= ~(1 << fieldno);
}

Upvotes: 1

Related Questions