Reputation: 487
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
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
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
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
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