Tim M
Tim M

Reputation: 487

Reading Single Bit from a Char

This is my first post here so please forgive anything I do wrong :) This is my situation. I am writing a simple data transfer operation for a PIC16F876 using MPLAB and the HI-Tech C compiler.

I have a char called data, I wanted to access the bits in data and send them to portB0, starting with the MSB.

In assembly I would simply do:

PORTB,0 = data,7 // to get the MSB and put it on port B0, I would then do this for all bits.

However in C this seems to be more complicated. I have done some research and have found a function which works:

getBit(char data, int bitNumber)
{
     return (data & (1 << bitNumber-1)) != 0;
}

Then I just use:

PORTBbits.RB0 = getBit(data,7);

This is OK, but messy and seems to take longer, I dont know why I need an extra function... So my question is: Is there not a simple method to access a bit in a register? like:

PORTBbits.RB0 = data,7

I cant understand why there would not be as the complier converts it in to assembly anyway??!!!!

Thanks in advance. Regards, Tim.

Upvotes: 2

Views: 8684

Answers (4)

John U
John U

Reputation: 2993

Some (most?) micros have several registers for the pins - if you know what you are going to do then (f'rexample) writing to the SET or CLEAR pin registers saves the whole read-modify-write/masking kerfuffle.

You probably know, but for the sake of clarence - SET/CLEAR registers work by only setting or clearing the pin if the bit written is 1, if 0 is written the pin state is not changed, which means the hardware is doing the work for you. To set pin 3 of a port you just write 0x04 to the port_SET register. To clear it, you write 0x04 to the port_CLEAR register.

It's not always possible to use these, but it shaves a lot of CPU cycles off if you can.

Upvotes: 0

K Scott Piel
K Scott Piel

Reputation: 4380

Bear in mind that when you use a function, such as this, that means that you're going to push two values on the stack, perform a jump, execute operations, pop the stack and return a value.

You could get around it via a MACRO which would inline the code

#define GETBIT(x,n) ((x >> (n-1)) & 1)

Option #2 is the use of inline ASM if you're given to masochism and screaming to save cycles. ~smile~

Upvotes: 3

Remy Lebeau
Remy Lebeau

Reputation: 597215

Another way to accomplish what you looking for is something like this:

PORTBbits.RB0 = (data >> 7) & 1;

Or more generically:

#define BIT(x,n) (((x) >> (n)) & 1)
PORTBbits.RB0 = BIT(data, 7);

Upvotes: 12

unxnut
unxnut

Reputation: 8839

If you just need the bit, you can get it by ( data & (1 << (bitNumber-1)) ) != 0. Or you could define a macro to make it more readable as

#define getBit(x,y) ((x) & (1 << ((y)-1))) != 0

and call it by getBit(data,bitNumber)

The macro will remove the function overhead. But there is no operator to give you the bit value the way you wanted.

Upvotes: 2

Related Questions