Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

C18 structure for 'bits'

Status
Not open for further replies.

Mike - K8LH

Well-Known Member
Been searching awhile now for example on how to use a C18 structure to emulate the basic "bit" access that BoostC includes automatically, that is;
Code:
  myvar.0 = 1;        // set bit 0 in variable "myvar" to '1'
Any help would be appreciated.

TIA, Mike, K8LH
 
Look here:
**broken link removed**

like btbass from there said:

"look at the Pic18F header files. They make extensive use of bitfields. You can learn a trick or two by studying the header files."

heh i must say C18 is the least documented compiler i ever saw lol
 
Last edited:
Been searching awhile now for example on how to use a C18 structure to emulate the basic "bit" access that BoostC includes automatically, that is;
Code:
  myvar.0 = 1;        // set bit 0 in variable "myvar" to '1'
Any help would be appreciated.

TIA, Mike, K8LH


In my opinion the simplest way is to define two macros:
Code:
[COLOR=black]#define bitset(var,bitno) (var|=1<<bitno)[/COLOR]
[COLOR=black]#define bitclr(var,bitno) (var&=~(1<<bitno))[/COLOR]

These macros will be translated into 1-cycle assembly intrusctions by the compiler.
I use them with 8-bit variables.
 
Last edited:
Nice!!! Do you mind if i though that in my C18 PDF? Whats your name?

Its would be like:
Code:
#define SpecialBit 2
unsigned char MyVar;

MyVar = 0;
bitset(MyVar,SpecialBit);
Then :
"MyVar would be 0 to start then after the bitset command, MyVar equals 00000100."
 
Last edited:
In my opinion the simplest way is to define two macros:
Code:
[COLOR=black]#define bitset(var,bitno) (var|=1<<bitno)[/COLOR]
[COLOR=black]#define bitclr(var,bitno) (var&=~(1<<bitno))[/COLOR]
These macros will be translated into 1-cycle assembly intrusctions by the compiler.
I use them with 8-bit variables.

I'm aware of the macros, thank you. Wouldn't help much if I wanted to do something like this though;
Code:
  mode.0 ^= 1;      ; toggle sideband mode
Probably just go back to BoostC. Thanks guys.
 
This works for x.b0 ^= 1;
Code:
typedef union {
  struct {
    unsigned b0:1; 
    unsigned b1:1; 
    unsigned b2:1; 
    unsigned b3:1;
    unsigned b4:1; 
    unsigned b5:1; 
    unsigned b6:1; 
    unsigned b7:1;
  };
  struct {
    unsigned asByte:8;
  };
}  bitByte;  
....
  bitByte x;

  x.b3=1;
  x.asByte = 0x55;
The downside is that you must say x.asByte=123 and that you have to say x.b0 instead of x.0. Neither is a big deal if you are used to structures.
The upside is that you can use variables on the RHS;

Generated asm
Code:
131:                 bitByte ii;
132:                 
133:                 ii.b3=1;
  0152    0E01     MOVLW 0x1
  0154    86DB     BSF 0xfdb, 0x3, ACCESS
134:                 
135:                 ii.asByte = 0x55;
  0156    52DE     MOVF 0xfde, F, ACCESS
  0158    0E55     MOVLW 0x55
  015A    6EDD     MOVWF 0xfdd, ACCESS
3v0
 
I'm just trying to find a way to test and clear individual switch flag bits like I do in BoostC. Suggestions? Thanks.

Code:
#define swSet swflags.0
#define swUp swflags.1
#define swDn swflags.2


while(1)
{ while(swSet)            // while "set" mode
  if(swUp)                // if "up" switch press
  { swUp = 0;             // clear switch flag bit
    incvalue();           // bump value
  }
  if(swDn)                // if "dn" switch press
  { swDn = 0;             // clear switch flag bit
    decvalue();           // bump value
  }
}
 
Last edited:
How about simple ANDing? Note: i didnt test this out lol but seems fine in my head lol

Code:
while(1){ 
    while(swflags & (1<<swSet))         // while "set" mode
    if(swflags & (1<<swUp))             // if "up" switch press
    { 
        swflags = ~(1<<swUp);           // clear switch flag bit
        incvalue();                     // bump value
    }
    if(swflags & (1<<swDn))             // if "dn" switch press
    { 
        swflags = ~(1<<swDn);           // clear switch flag bit
        decvalue();                     // bump value
    }
}

Ill change it into something simpler 1 minute
 
Last edited:
Jason,

That will work perfectly with minor correction but it's not as clean or as intuitive as the BoostC example...
 
Last edited:
heh and i made this too:
Code:
#define bitset(var,bitno) (var|=1<<bitno);
#define bitclr(var,bitno) (var&=~(1<<bitno));

unsigned char bitchk(unsigned char var,char bitno){
    unsigned char tmp;
    tmp = var & (1<<bitno);
    return tmp;
}

while(1){ 
    while(bitchk(swflags,swSet))         // while "set" mode
    if(bitchk(swflags,swUp))             // if "up" switch press
    { 
        bitclr(swflags,swUp);           // clear switch flag bit
        incvalue();                     // bump value
    }
    if(bitchk(swflags,swDn))             // if "dn" switch press
    { 
        bitclr(swflags,swDn);           // clear switch flag bit
        decvalue();                     // bump value
    }
}
 
Last edited:
Hi 3v0,

Thank you very much for for showing me how to build the structure. Unfortunately, if I understand you correctly, accessing the variable as a byte becomes extremely clumsy (ie; x.asbyte = 0x55).

Right now the portion of my program that manipulates the switch flags variable as a byte works just fine in both BoostC and in C18 (the C18 code below looks almost identical to the BoostC version) so I don't want to muck up that part.

I really do appreciate the input guys... Thank you!!!

Mike

Code:
unsigned char swold = 0;        // switch state latch
unsigned char flags = 0;        // short switch flag bits
unsigned char flong = 0;        // long switch flag bits
unsigned char tmr1k = 0;        // 1 second timer
unsigned char tmr25 = 25;       //
unsigned char beep = 0;         //
unsigned char bctr = 32;        //

#pragma interrupt isr_hi

/****************************************************************/
/*  time from 'newhi' (press) to 'newlo' (release) determines   */
/*  which flag bit, short or long, is toggled                   */
/*                                                              */
/*  swnew.0  ___---___---___----------___----------___          */
/*  swold.0  ____---___---___----------___----------__          */
/*  delta.0  ___-__-__-__-__-_________-__-_________-__          */
/*  newhi.0  ___-_____-_____-____________-____________          */
/*  newlo.0  ______-_____-____________-____________-__          */
/*  flags.0  _______------____________________________ short    */
/*  slong.0  __________________________-------------__ long     */
/*                                                              */

void isr_hi()                   // 1 msec interrupts
{ unsigned char swnew;          //
  unsigned char delta;          //
  unsigned char newhi;          //
  unsigned char newlo;          //

  PIR1bits.TMR2IF = 0;          // clr timer2 interrupt flag

  if(beep)                      // if beep task running
  { if(!(beep&1))               // if beep is even (b0 = 0)
      PORTB ^= 1<<spkr;         // toggle speaker pin
    if(!--bctr)                 // if end of 32 msec count
    { bctr = 32;                // reset 32 msec timer and
      beep--;                   // decrement beep counter
    }                           //
  }                             //

  if(!--tmr25)                  // if 25 msec interval
  { tmr25 = 25;                 // reset for 25 msecs and...
    swnew = ~PORTC;             // sample active lo switches
    swnew &= 0b00000111;        // on RC2, RC1, and RC0 pins
    delta = swnew ^ swold;      // state changes (hi or lo)
    newhi = delta & swnew;      // new hi level changes
    newlo = delta & swold;      // new lo level changes
    swold = swnew;              // update switch state latch

    if(tmr1k)                   // if 1 second timer running
      if(!--tmr1k)              // dec it and if timed out
        beep = 4;               // task double beep feedback
    if(newhi)                   // if new press
    { tmr1k = 1000/25;          // start 1 second timer and
      beep = 2;                 // task single beep feedback
    }                           //
    if(newlo)                   // if new release
    { if(!tmr1k)                // if 1 second timeout
        flong ^= newlo;         // toggle 'long' switch flag
      else                      // otherwise
        flags ^= newlo;         // toggle 'short' switch flag
      tmr1k = 0;                // clear 1 second timer
    }                           //
  }                             //
}
 
Last edited:
Hi 3v0,

Thanks to your example (and patience) I think I figured it out and I'm able to keep my original BoostC variable names and macro names. Thank you.

Thank you all for the fine examples. I learned a lot from all of them.

Kind regards, Mike

Code:
[COLOR=Red]typedef union
{ struct
  { unsigned b0:1;
    unsigned b1:1;
    unsigned b2:1;
    unsigned b3:1;
    unsigned b4:1;
    unsigned b5:1;
    unsigned b6:1;
    unsigned b7:1;
  };
  struct
  { unsigned asbyte:8;
  };
} bitbyte;

bitbyte x;

#define flags x.asbyte      // switch flag bits
#define RunSw x.b0          // Motor on/off switch on RC0 (flags.b0)
#define DirSw x.b2          // Motor fwd/rev switch on RC2 (flags.b2)[/COLOR]

while(1)
{ if(RunSw)                 // if "Run" switch press
  { RunSw = 0;              // clear switch flag bit
    MotorOn ^= 1;           // toggle motor on/off pin
  }
}
 
Last edited:
Yeah, I'm lookin' into that right now. Trying the following to access bits as sw.Run, sw.Jog, sw.Dir, and byte-wide access as sw.flags for parallel switch logic in ISR. I suppose I could get used to doing it this way, if I have to (grin).

Regards, Mike

Code:
typedef union
{ struct
  { unsigned Run:1;               // Run switch flag (sw on RC0)
    unsigned Jog:1;               // Jog switch flag (sw on RC1)
    unsigned Dir:1;               // Dir switch flag (sw on RC2)
    unsigned unused:5;            // spare/unused bits
  };
  struct
  { unsigned flags:8;             // byte wide flag access
  };
} bitbyte;

bitbyte sw;
 
Last edited:
Status
Not open for further replies.

New Articles From Microcontroller Tips

Back
Top