View previous topic :: View next topic |
Author |
Message |
germans
Joined: 04 Feb 2016 Posts: 11
|
Accessing a specific bit of a variable |
Posted: Wed Feb 10, 2016 11:10 pm |
|
|
Hi guys, I'm trying to access to a specific bit of an unsigned short, but i can't do it right. Here is an example of my function:
Code: | unsigned short function(unsigned short address)
{
address.b7 = 0; // I NEED HERE A VALID EXPRESSION
address.b6 = 0; // I NEED HERE A VALID EXPRESSION
return address;
} |
As argument i have a byte variable (address: "b7,b6,...b1,b0") and i want to make the first 2 bits (bit7 and bit6) zeros, but i want to keep the rest of the bits as original.
Example:
address = 10110010
dir = function(address);
dir = 00110010
Which command should i use to get access to an specific bit in a byte? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Thu Feb 11, 2016 2:17 am |
|
|
Step back.
What you post can't work in any way, unless you are in ANSI mode?.
A standard 'short', in CCS, is a single bit.
So you are handing the function a single bit, and expecting a single bit back. As such the variable does not 'have' a bit 6, or a bit 7....
Use 'unsigned int8', which then has eight bits, and importantly will have eight bits in just about every compiler/configuration.
This is why you will see the 'old hands', pushing the use of the numbered sizes, rather than using names like 'short', 'long' etc., since these have different meanings in different environments...
Then, there are a huge number of different ways of doing this.
The first, is to simply use the CCS bit_set/bit_clear operation.
So:
Code: |
unsigned short function(unsigned short address)
{
bit_clear(address,7); //Clear bit 7
bit_clear(address,6); //Clear bit 6
return address;
}
|
Used on a fixed bit like this, the compiler codes each of these as the processor bit set and clear instructions. Super efficient. These exist because the processor has these instructions, so CCS offered these instructions as an alternative to the standard methods of using masks etc..
Then use a structure/union with bitfields:
Code: |
#include <18F4620.h>
#device ADC=10
#use delay(crystal=20000000)
struct bits
{
int8 b0:1;
int8 b1:1;
int8 b2:1;
int8 b3:1;
int8 b4:1;
int8 b5:1;
int8 b6:1;
int8 b7:1;
}; //This declares a structure type, called 'bits'.
typedef union {
struct bits b;
int8 byt;
} bitaccess; //declares a new 'type' called 'bitaccess', that is
//both a bitaccess structure, and a int8
unsigned int8 function(bitaccess address)
{
address.b.b7=0; //Clear bit 7
address.b.b6=0; //Clear bit 6
return address.byt;
}
void main()
{
int8 val;
val=0xFF;
val=function(val);
while(TRUE)
{
}
}
|
Here we declare two different ways of accessing the same memory. A structure of single bits, and a single byte.
This can then be expanded as:
Code: |
struct bits2
{
int8 dummy:6; //six dummy bits
int8 twobits:2; //The upper two bits
};
typedef union {
struct bits2 part;
int8 byt;
} bitaccess;
unsigned int8 function(bitaccess address)
{
address.part.twobits=0; //Clear bit 6, and 7
return address.byt;
}
|
Here the structure is declared to have 6 dummy bits, and a 2 bit variable called 'twobits'. Writing to this, then operates both bits in one instruction line. This is a very 'neat' way to work with things where you need to access two or three bits 'together' in a variable. So you could say:
address.part.twobits=2;
and bit 7 will be set, and bit 6 cleared!.
Then there is the simple old 'use a bit mask' method.
So you wouldn't even use a function:
dir=address & 0x3F;
would give you the low six bits of 'address'. |
|
|
germans
Joined: 04 Feb 2016 Posts: 11
|
|
Posted: Thu Feb 11, 2016 7:39 am |
|
|
Hey, Thanks a lot for your complete answer! |
|
|
avatarengineer
Joined: 13 May 2013 Posts: 51 Location: Arizona
|
|
Posted: Tue Mar 01, 2016 4:04 pm |
|
|
I use a Global union variable for many many operations.
Code: |
union {
int32 asDLong;
int16 asWord[2];
int8 asByte[4];
int1 asBit[32];
} XferDL;
|
Often manipulating bits or bytes in countless routines,
this single global variable makes life easier. |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Tue Mar 01, 2016 6:33 pm |
|
|
two ways to restructure your function:
Code: |
unsigned short function(unsigned int8 address)
{
#bit b7 =address.7
#bit b6 =address.6
b6=0;b7=0;
return (address);
}
// or
unsigned short function(unsigned int8 address)
{ return (address&0b00111111;); }
|
in reality the argument 'address' could be a byte too-
and CCS will merrily treat it as an unsigned int8 for you
Last edited by asmboy on Wed Mar 09, 2016 6:26 pm; edited 1 time in total |
|
|
soonc
Joined: 03 Dec 2013 Posts: 215
|
Lots of good replies... but |
Posted: Tue Mar 08, 2016 9:34 am |
|
|
No one mentioned the built in functions:
bit_test(Variable,bit); which can handle 8,16,and 32bit variables.
If you need to manipulate bit then look at:
bit_clear() and bit_set() |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Tue Mar 08, 2016 9:48 am |
|
|
Er. Actually (quote from first answer):
"The first, is to simply use the CCS bit_set/bit_clear operation. "
Followed by an example showing these being used. |
|
|
soonc
Joined: 03 Dec 2013 Posts: 215
|
|
Posted: Tue Mar 08, 2016 11:00 am |
|
|
Ttelmah wrote: | Er. Actually (quote from first answer):
"The first, is to simply use the CCS bit_set/bit_clear operation. "
Followed by an example showing these being used. |
But not bit_test() |
|
|
|