Acquiring information about binary from decimal - c

Suppose that an instruction aw is code 010 defined by a 32 bit structure as follows:
bits 31-25 unused (all 0s)
bits 24-22: code
bits 21-19: argument 1
bits 18-16: argument 2
bits 15-0: offset (a 16-bit, 2's complement number with a range of -32768 to 32767)
Given the number 8454151, how can I determine if the code is aw?
I tried to shift the number 22 bits, like 8454151 >> 22, but I keep getting 0. Any ideas on how I can obtain the bit information for the code (to check whether it's aw or something else)?

If you just have to verify if an instruction is of a certain operation, the code needing the least cycles would be as follows:
const uint32_t mask = 7 << 22; // Shift 3 set bits by 22 in order to build
// a mask where bits 22-24 are set.
const uint32_t inst_aw = 2 << 22; // Shift the opcode by 22 to build a comparable value
uint32_t instruction = ...; // Your instruction word
if ((instruction & mask) == inst_aw) {
// Do your thing
}
Anyway if you have to build something like an "instruction decoder" or "interpreter", I'd recommend using a lookup table with instruction names (or function pointers) indexed by the instruction code:
/*! \brief Instruction names lookup table. Make sure it has always 8 entries
in order to avoid access beyond the array limits */
const char *instruction_names[] = {
/* 000 */ "Unknown instruction 000",
/* 001 */ "Unknown instruction 001",
/* 010 */ "AW",
...
/* 111 */ "Unknown instruction 111"
};
uint32_t instruction = ...;
unsigned int opcode = (instruction >> 22) & 0x07; // Retrieving the opcode by shifting right 22
// times and mask out all bit except the last 3
printf("Instruction is: %s", instruction_names[opcode]);

A bit shift should work. Be sure to check the data types. You can also "and" the number with 0x01C000 and then compare.

Related

Why bit shift left on system call bits?

In kernel/ipc.h Tanenbaum defines the system call bits as:
/* System call numbers that are passed when trapping to the kernel. The
* numbers are carefully defined so that it can easily be seen (based on
* the bits that are on) which checks should be done in sys_call().
*/
#define SEND 1 /* 0 0 0 1 : blocking send */
#define RECEIVE 2 /* 0 0 1 0 : blocking receive */
#define SENDREC 3 /* 0 0 1 1 : SEND + RECEIVE */
#define NOTIFY 4 /* 0 1 0 0 : nonblocking notify */
#define ECHO 8 /* 1 0 0 0 : echo a message */
but then in kernel/table.c the system call bits are defined as:
/* Define system call traps for the various process types. These call masks
* determine what system call traps a process is allowed to make.
*/
#define TSK_T (1 << RECEIVE) /* clock and system */
#define SRV_T (~0) /* system services */
#define USR_T ((1 << SENDREC) | (1 << ECHO)) /* user processes */
Why is everything bit shifted over to the left? 1 << RECEIVE would be 0100 instead of 0010. Doesn't that mean that the clock and system tasks can NOTIFY but not RECEIVE?
The values formed in the code you show from kernel/table.c are not the values of the code numbers for system calls. They are bit masks for the system calls.
Bit masks are commonly used to implement sets. Suppose we have three objects, such as an apple, a banana, and a cherry, and we wish to record whether some set X does or does not contain an apple, does or does not contain a banana, and does or does not contain a cherry.
We can do this by assigning the bit at position 0 (value 1) to represent an apple, the bit at position 1 (value 2) to represent a banana, and the bit at position 2 (value 4) to represent a cherry. Then whether any set X does or does not contain these items can be represented by a number which does or does not have the corresponding bits set. For example, the number 5 has bits at positions 0 and 2 set, so it represents a set that contains an apple and a cherry but not a banana.
The code in kernel/table.c assigns bits in a bit mask so that the system call with code i is represented by the bit at position i. Thus, the value of the bit in the bit mask for the system call with code i has value 1 << i.
Here is a table showing the values of the call codes and the values of their bit masks:
Call Name Code Number Bit Mask
SEND 1 2
RECEIVE 2 4
SENDREC 3 8
NOTIFY 4 16
ECHO 8 256
The way these are used is that, to represent a set containing several calls, the bit mask values for those calls are added together (or, equivalent, combined with a bitwise OR operation). So the set containing SEND, RECEIVE, and SENDREC is represented by 2+4+8 = 14.
So 1 << SENDREC is the value of the bit that represents SENDREC in the mask, and 1 << ECHO is the value of the bit that represents ECHO in the mask. The OR of these values, 1 << SENDREC | 1 << ECHO, is a bit mask that includes SENDREC and ECHO but does not include SEND or the other codes.
Some operations on bit masks are:
If i is the number of an item, 1<<i is the value of the bit that represents it in the set.
To add one item i to a set X, OR the bit into the set, with X |= 1<<i.
To take the union of two sets X and Y, OR them, with X | Y.
To take the intersection of two sets X and Y, AND them, with X & Y.

How to create bitfield out of existing variables in C

I am working on a Motorola HCS08 µCU in CodeWarrior V10.6, I am trying to create an extern bitfield which has bits from existing registers. The way the bitfields are created in the µCU header is like
typedef unsigned char byte;
typedef union {
byte Byte;
struct {
byte PTAD0 :1;
byte PTAD1 :1;
byte PTAD2 :1;
byte PTAD3 :1;
byte PTAD4 :1;
byte PTAD5 :1;
byte PTAD6 :1;
byte PTAD7 :1;
} Bits;
} PTADSTR;
extern volatile PTADSTR _PTAD #0x00000000;
#define PTAD _PTAD.Byte
#define PTAD_PTAD0 _PTAD.Bits.PTAD0
#define PTAD_PTAD1 _PTAD.Bits.PTAD1
#define PTAD_PTAD2 _PTAD.Bits.PTAD2
#define PTAD_PTAD3 _PTAD.Bits.PTAD3
#define PTAD_PTAD4 _PTAD.Bits.PTAD4
#define PTAD_PTAD5 _PTAD.Bits.PTAD5
#define PTAD_PTAD6 _PTAD.Bits.PTAD6
#define PTAD_PTAD7 _PTAD.Bits.PTAD7
Which will let the register value be changed either by PTAD = 0x01, or PTAD_PTAD0 = 1, for example. This definition is basically the same for PTAD, PTBD, PTCD, ... PTGD, the only thing changing is the address.
My attemp to create a custom bitfield out of the previous existing variables is
typedef union {
byte Byte;
struct {
byte *DB0;
byte *DB1;
byte *DB2;
byte *DB3;
byte *DB4;
byte *DB5;
byte *DB6;
byte *DB7;
} Bits;
} LCDDSTR;
I would create and initialize the bitfield as LCDDSTR lcd = {{&PTGD_PTGD6, &PTBD_PTBD5, ...}}, because by some reason, the initialization like LCDSTR lcd = {*.Bits.DB0 = &PTGD_PTGD6, *.Bits.DB1 = &PTBD_PTBD5, ...} (treating it as a struct, please correct me again) advice in How to initialize a struct in accordance with C programming language standards does not work with this compiler (it does work on an online compiler).
However, as you may see I am sort of grouping the bits, and (if it would work) I would be able to change the values of the actual register by doing *lcd.Bits.DB0 = 1, or something like that, but if I do lcd.Byte = 0x00, I would be changing the last (I think) byte of the memory address contained in lcd.Bits.DB0, you know, because the struct doesn't actually contains the data, but the pointers instead.
How would I go on achieving a struct that is able to contain and modify bits from several registers? (I guess the problem here is that in memory the bits are not one next to the other, which I guess would make it easier). Is it even possible? I hope it is.
How would I go on achieving a struct that is able to contain and modify bits from several registers? (I guess the problem here is that in memory the bits are not one next to the other..
I don't think you can do it with a struct. That is because bitfields by definition have to occupy the same or contiguous addresses.
However macros may be useful here
#define DB0 PTGD_PTGD6
#define DB1 PTBD_PTBD5
....
And to clear the bits to all 0's or set to all 1's you can use a multiline macro
#define SET_DB(x) do { \
PTGD_PTGD6 = x; \
PTBD_PTBD5 = x; \
...... \
} while(0)
How would I go on achieving a struct that is able to contain and modify bits from several registers?
You can't.
A structure must represent a single, continuous block of memory -- otherwise, operations like taking the sizeof the structure, or performing operations on a pointer to one would make no sense.
If you want to permute the bits of a value, you will need to find some way of doing so explicitly. If the order of your bits is relatively simple, this may be possible with a few bitwise operations; if it's weirder, you may need to use a lookup table.
Beyond that: bitfields in C are pretty limited. The language does not make a lot of guarantees about how a structure containing bitfields will end up laid out in memory; they are generally best avoided for portable code. (Which doesn't apply here, as you're writing code for a specific compiler/microcontroller combination, but it's worth keeping in mind in general.)
Your union does unfortunately not make any sense, because it forms a union of one byte and 8 byte*. Since a pointer is 16 bit on HCS08, this ends up as 8*2 = 16 bytes of data, which can't be used in any meaningful way.
Please note that the C structure called bit-fields is very poorly specified by the standard and therefore should be avoided in any program. See this.
Please note that the Codewarrior register maps aren't remotely close to following the C standard (nor MISRA-C).
Please note that structs in general are problematic for hardware register mapping, since structs can contain padding. You don't have that problem on HCS08 specifically, since it doesn't require alignment of data. But most MCUs do require that.
It is therefore better to roll out your own register map in standard C if you have that option. The port A data register could simply be defined like this:
#define PTAD (*(volatile uint8_t*)0x0000U)
#define PTAD7 (1U << 7)
#define PTAD6 (1U << 6)
#define PTAD5 (1U << 5)
#define PTAD4 (1U << 4)
#define PTAD3 (1U << 3)
#define PTAD2 (1U << 2)
#define PTAD1 (1U << 1)
#define PTAD0 (1U << 0)
As we can tell, defining the bit masks is mostly superfluous anyway, as PTAD |= 1 << 7; is equally readable to PTAD |= PTAD7;. This is because this was a pure I/O port. Defining textual bit masks for status and control registers on the other hand, increases the readability of the code significantly.
If you want to modify bits from several registers, you'd do something like the following:
Assume we have a RGB (red-green-blue) LED, common cathode, with 3 colors connected to 3 different pins on 3 different ports. Instead of beating up the PCB designer, you could do this:
#define RGB_RED_PTD PTAD
#define RGB_RED_PTDD PTADD
...
#define RGB_BLUE_PTD PTBD
#define RGB_BLUE_PTDD PTBDD
...
#define RGB_GREEN_PTD PTDD
#define RGB_GREEN PTDD PTDDD
#define RGB_RED_PIN 1
#define RGB_BLUE_PIN 5
#define RGB_GREEN_PIN 3
You can now set these independently of where they happen to be located on the hardware:
void rgb_init (void)
{
RGB_RED_PTDD |= (1 << RGB_RED_PIN);
RGB_BLUE_PTDD |= (1 << RGB_BLUE_PIN);
RGB_GREEN_PTDD |= (1 << RGB_GREEN_PIN);
}
void rgb_yellow (void)
{
RGB_RED_PTD |= (1 << RGB_RED_PIN);
RGB_BLUE_PTD &= ~(1 << RGB_BLUE_PIN);
RGB_GREEN_PTD |= (1 << RGB_GREEN_PIN);
}
And so on. Examples were for HCS08 but the same can of course be used universally on any MCU with direct port I/O.
It sounds like an approach such as the following is along the lines of where you would like to go with a solution.
I have not tested this as I do not have the hardware however this should provide an alternative to look at.
This assumes that you want to turn on particular pins or turn off particular pins but there will not be a case where you will want to turn on some pins and turn off other pins for a particular device in a single operation. If that should be the case I would consider making the type of RegPinNo be an unsigned short to include an op code for each register/pin number combination.
This also assumes that timing of operations is not a critical constraint and that the hardware has sufficient horsepower such that small loops are not much of a burden on throughput and hogging CPU time needed for other things. So this code may need changes to improve optimization if that is a consideration.
I assume that you want some kind of a easily readable way of expressing a command that will turn on and off a series of bits scattered across several areas of memory.
The first thing is to come up with a representation of what such a command would look like and it seems to me that borrowing from a char array to represent a string would suffice.
typedef byte RegPinNo; // upper nibble indicates register number 0 - 7, lower nibble indicates pin number 0 - 7
const byte REGPINNOEOS = 0xff; // the end of string for a RegPinNo array.
And these would be used to define an array of register/pin numbers as in the following.
RegPinNo myLed[] = { 0x01, 0x12, REGPINNOEOS }; // LED is addressed through Register 0, Pin 0 and Register 1, Pin 1 (zero based)
So at this point we have a way to describe that a particular device, an LED in this case, is addressed through a series of register/pin number items.
Next lets create a small library of functions that will use this representation to actually modify the specific pins in specific registers by traversing this array of register/pin numbers and performing an operation on it such as setting the bit in the register or clearing the bit in the register.
typedef unsigned char byte;
typedef union {
byte Byte;
struct {
byte PTAD0 : 1;
byte PTAD1 : 1;
byte PTAD2 : 1;
byte PTAD3 : 1;
byte PTAD4 : 1;
byte PTAD5 : 1;
byte PTAD6 : 1;
byte PTAD7 : 1;
} Bits;
} PTADSTR;
// Define a pointer to the beginning of the register area. This area is composed of
// 8 different registers each of which is one byte in size.
// We will address these registers as Register 0, Register 1, ... Register 7 which just happens
// to be how C does its zero based indexing.
// The bits representing pins on the PCB we will address as Pin 0, Pin 1, ... Pin 7.
extern volatile PTADSTR (* const _PTAD) = 0x00000000;
void SetRegPins(RegPinNo *x)
{
byte pins[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
int i;
for (i = 0; x[i] != REGPINNOEOS; i++) {
byte bRegNo = (x[i] >> 4) & 0x07; // get the register number, 0 - 7
byte bPinNo = x[i] & 0x07; // get the pin number, 0 - 7
_PTAD[bRegNo].Byte |= pins[bPinNo];
}
}
void ClearRegPins(RegPinNo *x)
{
byte pins[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
int i;
for (i = 0; x[i] != REGPINNOEOS; i++) {
byte bRegNo = (x[i] >> 4) & 0x07; // get the register number, 0 - 7
byte bPinNo = x[i] & 0x07; // get the pin number, 0 - 7
_PTAD[bRegNo].Byte &= ~pins[bPinNo];
}
}
void ToggleRegPins(RegPinNo *x)
{
byte pins[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
int i;
for (i = 0; x[i] != REGPINNOEOS; i++) {
byte bRegNo = (x[i] >> 4) & 0x07; // get the register number, 0 - 7
byte bPinNo = x[i] & 0x07; // get the pin number, 0 - 7
_PTAD[bRegNo].Byte ^= pins[bPinNo];
}
}
You would use the above something like the following. Not sure what a time delay function would look like in your environment so I am using a function Sleep() which takes an argument as to the number of milliseconds to delay or sleep.
void LightLed (int nMilliSeconds)
{
RegPinNo myLed[] = { 0x01, 0x12, REGPINNOEOS }; // LED is addressed through Register 0, Pin 0 and Register 1, Pin 1 (zero based)
SetRegPins(myLed); // turn on the LED
Sleep(nMilliSeconds); // delay for a time with the LED lit
ClearRegPins(myLed); // turn the LED back off
}
Edit - A Refinement
A more efficient implementation that would allow multiple pins to be set in a particular register at the same time would be to define the use of RegPinNo as being an unsigned short` with the upper byte being the register number and the lower byte being the pins to manipulate as a bit mask for the byte.
With this approach you would have a SetRegPins() function that would look like the following. A similar change would be needed for the other functions.
void SetRegPins(RegPinNo *x)
{
int i;
for (i = 0; x[i] != REGPINNOEOS; i++) {
byte bRegNo = (x[i] >> 8) & 0x07; // get the register number, 0 - 7
byte bPinNo = x[i] & 0xFF; // get the pin mask
_PTAD[bRegNo].Byte |= bPinNo;
}
}
And the typedefs would look like:
typedef unsigned short RegPinNo; // upper byte indicates register number 0 - 7, lower byte provides pin mask
const byte REGPINNOEOS = 0xffff; // the end of string for a RegPinNo array.
And these elements would be used like:
void LightLed (int nMilliSeconds)
{
RegPinNo myLed[] = { 0x0002, 0x0103, REGPINNOEOS }; // LED is addressed through Register 0, Pin 1 and Register 1, Pin 0 and Pin 1 (zero based)
SetRegPins(myLed); // turn on the LED
Sleep(nMilliSeconds); // delay for a time with the LED lit
ClearRegPins(myLed); // turn the LED back off
}

How to read/write into specific bits of a unsigned char

I want to read and write from/to an unsigned char according to the table below:
for example I have following variables:
unsigned char hsi_div = 0x01; /* HSI/2 */
unsigned char cpu_div = 0x05; /* Fmaster/32 */
I want to write hsi_div to bits 4,3 and cpu_div to bits 2,1,0 (imagine the whole char is named CLK_DIVR):
CLK_DIVR |= hsi_div << 4; //not correct!
CLK_DIVR |= cpu_div << 2; //not correct!
And lets say I want to read the register back to make sure I did it correct:
if( ((CLK_DIVR << 4) - 1) & hsi_div) ) { /* SET OK */ }
if( ((CLK_DIVR << 2) - 1) & cpu_div) ) { /* SET OK */ }
Is there something wrong with my bitwise operations!? I do not get correct behaviour.
I assume CLK_DIVR is a hardware peripheral register which should be qualified volatile. Such registers should be set up with as few writes as possible. You change all write-able bits, so just
CLK_DIVR = (uint8_t)((hsi_div << 3) | (cpu_div << 0));
Note using fixed width type. That makes mentioniong it is an 8 bit register unnecessary. According to the excerpt, the upper bits are read-only, so they are not changed when writing. The cast keeps the compiler from issuing a truncation warning which is one of the recommended warnings to always enable (included in -Wconversion for gcc).
The shift count is actually the bit the field starts (the LSbit). A shift count of 0 means "no shifting", so the shift-operator is not required. I still use it to clarify I meant the field starts at bit 0. Just let the compiler optimize, concentrate on writing maintainable code.
Note: Your code bit-or's whatever already is in the register. Bit-or can only set bits, but not clear them. Addiionally the shift counts were wrong.
Not sure, but if the excerpt is for an ARM Cortex-M CPU (STM32Fxxxx?), reducing external bus-cycles becomes more relevant, as the ARM can take quite some cycles for an access.
For the HSIDIV bit fields you want:
hw_register = (hw_register & 0x18) | (hsi_value & 0x03) << 0x03;
This will mask the value to 2 bits wide then shift to bit position 3 and 4.
The CPUDIV fields are:
hw_register = (hw_register & 0x7) | (cpu_value & 7);
Reading the register:
hsi_value = (hw_register & 0x18) >> 3;
cpu_value = hw_register & 0x07;
Just
CLK_DIVR |= hsi_div << 3;
CLK_DIVR |= cpu_div << 0;
Since hsi_div is a 2-digit binary, you have to move it three positions to skip the CPUDIV field. And the cpu_div is already at the end of the field.

Reading 22 bits via SPI [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I am trying to read ADC(ADS8320) values using SPI communication. I am using IAR embedded workbench for ARM and SM470R1B1 controller. In the data sheet it says first 6 bits are dummy read and next 16 bits is the actval data. I am trying to read 24 bits and ignore first 6 bits and last 2 bits. I am getting wrong values when i try with the below code.
unsigned int readADC8320(void)
{
value = AD8320_16(0xFFFFFF); // read registe
return value;
}
unsigned int AD8320_16(unsigned int value)
{
unsigned int data;
AD8320_CS_Status(0);
SW_Delay(DELAY_10US);
while(GIODOUTA&X2);
data = spi2(value >> 16); //read high 8 bits
data = (data << 6)| spi2(value >> 8); //read next 8 bits but 6+8 =14
data = (data << 8)| spi2(value >> 2); //add last two bits only
SW_Delay(DELAY_10US);
AD8320_CS_Status(1);
return data;
}
unsigned char spi2(unsigned char data)
{
// Write byte to SPI2DAT1 register
SPI2DAT1 = data;
while(!(SPI2CTRL3 & 0x01)){} // Wait for RxFlag to get set
return (SPI2BUF & 0x000000FF); // Read SPIBUF
}
Can anyone suggest me where i am doing wrong. I am quite poor with shift operations.
Your code looks wonky. For example, what purpose does value have?
The datasheet you linked to indicates that the 22 clock cycles suffice (and that 24 clock cycles are okay), no extra delays are needed, assuming the SPI clock is within limits (at most 2.4 MHz, I believe). So, I'd expect your code to look more like
void AD8320_setup(void)
{
/* TODO:
* - Set SPI2 clock frequency, if programmable (max. 2.4 MHz)
* - Set SPI2 transfer size, if programmable (8 bits per byte)
* - Set SPI2 to latch data on the falling edge of clock pulse
* - Set SPI2 to pull clock high when inactive
* - Set AD8320 chip select pin as an output
* - Set AD8320 chip select pin high (it is active low)
* - Ensure AD8320 is powered
*/
}
uint16_t AD8320_16(void)
{
uint16_t result;
/* TODO: Set AD8320 chip select pin 0/LOW (to select it)
*/
/* TODO: Clear SPI2 FIFO if it has one,
* so that we get actual wire data,
* not old cached data.
*/
result = ((uint16_t)(spi2_read() & 3U)) << 14;
result |= ((uint16_t)spi2_read()) << 6;
result |= ((uint16_t)spi2_read()) >> 2;
/* TODO: Set AD8320 chip select pin 1/HIGH (to deselect it)
*/
return result;
}
The prototype for spi2_read is typically unsigned char spi2_read(void);, but it might be of any integer type that can represent all eight bit values correctly (0 to 255, inclusive). Above, I cast the result -- after masking out any irrelevant bits, if any, with a binary AND operation -- to uint16_t before shifting it into the correct position in the result, so that regardless of the spi2_read() return type, we can use it to construct our 16-bit value.
The first spi2_read() reads the first 8 bits. I am assuming your device SPI bus sends and receives the most significant bit first; this means that the 6 dummy bits are most significant bits, and the 2 least significant bits are the most significant bits of the result. That's why we only keep the two least significant bits of the first byte, and transfer it 14 places left -- that way we get them in the most significant position.
The second spi2_read() reads the next eight bits. These are bits 13..6 of the data; that's why we shift this byte left by 6 places, and OR with the existing data.
The last spi2_read() reads the next eight bits. The last two bits are to be discarded, because only the first (most significant) 6 bits contain the rest of the data we're interested in. So, we shift this down by 2 places, and OR with the existing data.
Preparing spi2 involves stuff like word size (8 bits), data rate (if programmable), and so on.
The chip select for the AD8320 is just a generic output pin, it's just active low. That's why it's described as ^CS/SHDN in the datasheet: chip selected when low, shutdown when high.
The chip is a micropower one, so it requires less than 2mA, so you could conceivably power it from an output pin on many microcontrollers. If you were to do so, you'd also have to remember to make that pin an output and 1/high in _setup() function.

Why Bitshift operators?

I dont understand when and why you would use bitshift operators for microchip programming: for example...
SWITCH_DDR &= ~SWITCH_BIT;
SWITCH_PORT |= SWITCH_BIT;
Why use these operators?
Or...
void SerialInit(void)
{
UBRRH = ((XTAL / (8 * 250000)) - 1)>>8; // 250kbps at 16Mhz
UBRRL = (XTAL / (8 * 250000)) - 1;
UCSRA = (1<<U2X);
UCSRB = (1<<TXEN);
UCSRC = (1<<URSEL) + (1<<UCSZ1) + (1<<UCSZ0);
}
Whats going on here??? someone please explain graphically with 0's and 1's please. Or here's another example:
ulong MesureLC(void)
{
int i;
TCCR1B = 0;
CountHigh = 0;
TCNT1 = 0;
for (i=0;i<25000;i++)
{
TCCR1B = (1<<CS12) + (1<<CS11) + (1<<CS10); // WTF ???
UDR = 0x55;
while(!(UCSRA & (1<<UDRE)));
}
while(!(UCSRA & (1<<TXC)));
TCCR1B = 0;
CountLow = TCNT1;
Count = CountLow + (CountHigh << 16);
return Count;
}
I need to understand this stuff. Any help is appreciated.
A number of reasons spring to mind as to why you would use them.
The first is that sometimes memory is tight on micro-controller type devices and you may want to store as much as possible in as little space as possible.
This requirement may also be driven by the fact that other devices or software you interface with have that same minimal-space desire. They may use sub-byte data types for doing work, one example being TCP/IP headers where fields range from a single bit (such as the DF field) up to much more (such as the IP addresses).
In fact, that second bit of code you gave, SerialInit, is setting up properties for a serial comms chip (UART = Universal Asynchronous Receiver and Transmitter). UCSRx usually stands for UART Control/Status Register #x so you're writing information to a fairly low-level device to control its behaviour.
Another reason is that you may have memory mapped I/O. That means that, though you think you're writing to memory, you may well be sending those bits directly to an I/O device of some sort.
A classic example may be the use of a memory mapped byte where a seven-segment LEDs is controlled.
The LED may be structured as:
+---+---+---+---+---+---+---+---+
| d | e | g | f | a | b | c | p |
+---+---+---+---+---+---+---+---+
# # # # # # # #
# # # # # # # #===========#
# # # # # # # #
# # # # # # #===========# #
# # # # # # # #
# # # # # #===========# # #
# # # # # # # #
# # # # #=====# # # #
# # # # # # # #
# # # # +-------+ # # #
# # # # |aaaaaaa| # # #
# # # # +-+-------+-+ # # #
# # # # |f| |b| # # #
# # # #===|f| |b|===# # #
# # # |f| |b| # #
# # # +-+-------+-+ # #
# # #=========|ggggggg| # #
# # +-+-------+-+ # #
# # |e| |c| # #
# #===========|e| |c|=======# #
# |e| |c| #
# +-+-------+-+ +---+ #
#=================|ddddddd| |ppp|=====#
+-------+ +---+
where each of the seven segments and the dot are controlled by a different bit. If you wanted to turn on a single segment while leaving the others as they are, you would use bit operations like your question contains.
By way of example, turning on the g segment involves an operation like:
mmap_byte |= 0x20; // binary 00100000
Turning it off involves:
mmap_byte &= 0xdf; // binary 11011111
You may also find yourself in a situation where single bits or groups of bit in a byte control totally distinct devices and you don't want the operation of one to affect the other.
As to what bitwise operators do, they are operators that work on a multi-bit value but conceptually one bit at a time:
AND is 1 only if both of its inputs are 1.
OR is 1 if one or more of its inputs are 1.
XOR is 1 only if exactly one of its inputs are 1.
NOT is 1 only if its input are 0.
left shift shifts bits left a certain amount.
right shift shifts bits right a certain amount.
Discounting the shifts for now, these can be best described as truth tables. Inputs possibilities are on the top and left, the resultant bit is one of the four (two in the case of NOT since it only has one input) values shown at the intersection of the two inputs.
AND | 0 1 OR | 0 1 XOR | 0 1 NOT | 0 1
----+----- ---+---- ----+---- ----+----
0 | 0 0 0 | 0 1 0 | 0 1 | 1 0
1 | 0 1 1 | 1 1 1 | 1 0
One example is if you only want the lower 4 bits of an integer, you AND it with 15 (binary 1111) so:
201: 1100 1001
AND 15: 0000 1111
------------------
IS 9 0000 1001
Another example is if you have two 4-bit values that you want to pack into an 8-bit one, you can use all three of your operators (left-shift, and and or):
packed_val = ((val1 & 15) << 4) | (val2 & 15)
The & 15 operation will make sure that both values only have the lower 4 bits.
The << 4 is a 4-bit shift left to move val1 into the top 4 bits of an 8-bit value.
The | simply combines these two together.
If val1 is 7 and val2 is 4:
val1 val2
==== ====
& 15 (and) xxxx-0111 xxxx-0100 & 15
<< 4 (left) 0111-0000 |
| |
+-------+-------+
|
| (or) 0111-0100
If you have feature which can be enabled or disabled, you can use single bit to set state: 1 or 0. This way in 1 byte you are able to set 8 features.
If you need to store value (lets say somewhere from 0 to 7) you only need 3 bits for that (000 in binary = 0 in dec, 001 = 1, 010 = 2, ..., 111 = 7). And you still have 5 out of 8 bits free.
Whats going on here??? someone please explain graphically with 0's and 1's
1 << 2 = 00000001 << 2 = 00000100 = 4
4 >> 2 = 00000100 >> 2 = 00000001 = 1
I think the real question is not "what the hell does this mean", but rather "why the hell do developers writing programs for micro-controllers seem to love this way?"
Well I don't know if they love that way. I'm not a developer at all and I'm just a little bit interested in micro-controllers, but here is what I think.
Have You ever seen a documentation for a chip? Here is an example from some Atmel pdf.
USART Control and Status Register –
UCSRnB
• Bit 7 – RXCIEn: RX Complete
Interrupt Enable n Writing this bit to
one enables interrupt on the RXCn
Flag. A USART Receive Complete
interrupt will be generated only if
the RXCIEn bit is written to one, the
Global Interrupt Flag in SREG is
written to one and the RXCn bit in
UCSRnA is set.
• Bit 6 – TXCIEn: TX Complete
Interrupt Enable n Writing this bit to
one enables interrupt on the TXCn
Flag. A USART Transmit Complete
interrupt will be generated only if
the TXCIEn bit is written to one, the
Global Interrupt Flag in SREG is
written to one and the TXCn bit in
UCSRnA is set.
... • Bit 5 – UDRIEn: ... • Bit 4 –
RXENn: ... • Bit 3 – TXENn: ... • Bit
2 – UCSZn2: ... • Bit 1 – RXB8n: ... •
Bit 0 – TXB8n: ...
The problem is, that the chip is controlled by setting or clearing individual bits in some control registers. Those registers have ugly names in the documentation and the bits have ugly names too. The development environment comes already with all the macros with the names resembling those form the documentation defined.
Now suppose one wants to enable an interupt on the RXCn Flag and leave all other settings unchanged. This requires setting one bit in one particular register leaving other bits unchanged. The operator |= is the easiest way to do this
Assumming the address of the register is 0x3F (I made up the number, it doesn't matter) one could write this:
*((unsigned char*)0x3F) |= 0x80;// I want to set bit number 7 (RXCIEn)
Now, how readable is this?
In the development environment, there are already defined macros like UCSRnB and RXCIEn and using them is an obvious thing. It just so happens that RXCIEn is a bit number, not a value of that bit, so to code the same as above one has to write
UCSRnB |= (1 << RXCIEn);
Thanks to the documentation something like
UCSRnB = (1<<RXENn)|(1<<TXENn);
is considered more readable than
*((unsigned char*)0x3F) = 0x18; // I want to set bits number 4 and 3 (RXENn and TXENn)
The documentation itself is full of examples of code using those defined macros and I guess developers get used to it too quickly, to try to find a better way.
In the first example you gave:
SWITCH_DDR &= ~SWITCH_BIT;
SWITCH_PORT |= SWITCH_BIT;
That's not a bitshift, instead it's a bitmask.
Specifically the first statement turns off a given bit in a value, and the second turns the same bit on, leaving all other bits untouched.
Let's say SWITCH_DDR and SWITCH_PORT are special memory values that control the behaviour of some device. Each of its bits turns on/off a feature. If you want to control a given feature separately, you have to be able to change a bit without interfering with the others.
Let's also say the feature controlled by SWITCH_BIT is the leftmost bit in a byte. So SWITCH_BIT would have the value 0x80 (10000000 in binary).
When you do the first statement you are inverting SWITCH_BIT with the ~ operator (obtaining 01111111 in binary) and applying a binary AND to SWITCH_DDR. That efectively clears the leftmost bit and leaves the others unchanged.
The second statement does a binary OR, therefore the opposite result.
Now, about the shift operations, there are many applications to them, (much of was already mentioned in another answers), I will simply explain the specific use in the code you posted. So you have:
void SerialInit(void)
{
UBRRH = ((XTAL / (8 * 250000)) - 1)>>8; // 250kbps at 16Mhz
UBRRL = (XTAL / (8 * 250000)) - 1;
UCSRA = (1<<U2X);
UCSRB = (1<<TXEN);
UCSRC = (1<<URSEL) + (1<<UCSZ1) + (1<<UCSZ0);
}
The thing here is similar to the previous example (setting specific bits in a value) but there are a few differences due to the situation:
a) While in the first example you had the bitmask already made (SWITCH_BIT), here the constants are simply the POSITION of the bit. For instance, U2X contains the position of the bit that needs to be turned on/off (from right to left), not its bitmask. Doing (1<<U2X) effectively produces the corresponding bitmask. If the bit that needs to be turned on is the leftmost (as I made in SWITCH_BIT example), U2X would be 7 and the result of the shift would be the same 10000000 in binary.
b) In the last line:
UCSRC = (1<<URSEL) + (1<<UCSZ1) + (1<<UCSZ0);
This is combining the bitmasks produced by each constant (whose values, again, are the bit positions from the right). The thing is that the programmer decided to use the + operator instead of binary OR because he/she knew that when you don't have "colliding" bits, their result is the same. Personally, I would always use the binary OR, to make clear that what I'm doing is not an arithmetic addition.
c) Finally, about the first line
UBRRH = ((XTAL / (8 * 250000)) - 1)>>8;
Seems more complicated, apparently is a clock division factor, I'd have to look at the documentation to understand better. I'd not worry about it for now, it probably will become clear in time.
So looking at your SerialInit function.
You have left a lot of details out here but there is still enough to go by. So clearly you are initializing a serial port and the first couple of lines are the clock divisor. Since chips can run at different clocks and the chip usually doesnt try to guess at what clock you want say 9600 buad you have to do the math to divide down say a 12mhz reference clock. So XTAL / (8 *250000) is trying to get from the 16mhz down to 250000 with an 8x oversampling. I guess that number is 0x200 but for sake of an example lets say that number is 0x234. The UBBRH register looks to be the high half of the register so it wants the upper bits, apparently upper 8 bits (or less) the UBBRL is the lower half of that divisor so it wants the lower 8 bits.
The upper 8 bits of 0x0234 are 0x02, to get 0x02 from 0x0234 you need to shift
0x0234 = 0b0000001000110100 (0b indicating binary where 0x indicates hex)
This is not a rotate this is a logical shift, the C language does not have a rotate (nor an arithmetic shift). So that means the number of bits we shift to the right end up in a bit bucket.
so 0b0000001000110100 shifted right 8 times becomes 0bxxxxxxxx00000010. The xxes are the new bits shifted in and in C those are actually zero. But it doesnt matter here because the register being written to is 8 bits so only the lower 8 bits count.
So the second write of our 0x234 to UBRRL, is the lower 8 bits. The C compiler is going to chop off the lower 8 bits 0x34 and write that to the register.
So between those two lines of code we computed the divisor for the serial clock of 0x234 and write 0x02 to the upper divisor register and 0x34 to the lower.
The next line UCSRA = (1 << U2X);
Apparently there is register that wants a single bit set. I dont know what U2X is but lets say it is a 5 1<<5 means take the 0x01 or 0b00000001. shifted left five means shift move the bits that are there to the left and in C bring 5 zeros in on the right. Bits on the top of the variable, the leftmost 5 bits fall off into a bit bucket.
So
0b00000001
add five zeros to visualize
0b0000000100000
then chop five off the left
0b00100000
and we end up with 0x20.
The UCSRB line works the same way.
The UCSRC line is the same as well but three bits are being set
UCSRC = (1 << URSEL) + (1 << UCSZ1) + (1 << UCSZ0);
For sake of an example let me make up some numbers to fill in the ones not defined in your example.
UCSRC = (1 << 5) + (1 << 2) + (1 << 4);
As we did with UCSRA and UCSRB visualize those numbers
one with five zeros shifted in
0b100000
Pad that on the left to make it a full 8 bits
0b00100000
one with 2 zeros and one with 4 zeros
0b100 padded is 0b00000100
0b10000 padded is 0b00010000
So the three components so far are:
0b00100000
0b00000100
0b00010000
and when added together become
0b00110100 = 0x34
And that value is what is is written to the register.
Now you have to be careful using add instead of or. If you are not careful with your defines or dont bother to look you may find that the same bit is defined with two names and you may feel you wanted both features not knowing it is the same bit, the add will mess that up, the or wont. For example if URSEL and UCSZ1 happened to be the same bit
UCSRC = (1 << URSEL) + (1 << UCSZ1) + (1 << UCSZ0);
UCSRC = (1 << 5) + (1 << 5) + (1 << 4);
you would get
0b00100000
0b00100000
0b00010000
which adds to
0b01010000
when you probably wanted to or them and get
0b00110000
There are other times when an or is bad and you want to add, so you have to know your numbers not just names for defines when you do this math.
Normally WHY you would do this form of bit shifting, in particular with micros and drivers is that a register in a device may be defining more than one thing. A serial port is a perfect example, say you had a control register that looked like this
0b0SPPLLLL
where SS is stop bits 1=2 stop bits 0 = 1 stop bit
PP is parity 0b00 = no parity 0b01 = even 0b10 = odd
LLLL is length 0b1000 = 8, 0b0111 = 7 bits, etc
You will very often find code for such a register that does something like:
SCONTROL = (0 << 7)|(2 << 4)|(8 << 0);
Except that hardcoded numbers are replaced with defines:
SCONTROL = (ONESTOPBIT << STOPBITS)|(NOPARITY << PARITYBITS)|(DATABITS8 << DATABITS);
The shifts allow for the programmer to think of each field independent of the others without using bitfields which are messy and broken and very bad (never use).
The and with not is an easy way to not have to deal with the variable length
SWITCH_DDR &= ~SWITCH_BIT;
SWITCH_PORT |= SWITCH_BIT;
So if you want to read-modify-write something and say the lower 3 bits are what you want to modify and dont want to mess with the other bits in the register you might do something like this:
ra = SOMEREGISTER;
ra&=~7;
ra|=newnumber&7;
SOMEREGISTER = ra;
The ra&=~7 means
start with
0x0000....0000111
take the ones complement, which is make the zeros ones and ones zeros
0x1111....1111000
and that with what ra had in it before anding with a 1 means you keep your value anding with zero makes it a zero so the lower three bits have been forced to 0 the other dont-care-how-many bits are unchanged. then you or in the new number to set the lower three bits to whatever you wanted to change to and then write back to the register the changed value.
Then and with inverted mask thing can be easier than doing the math yourself, ~7 instead of 0xFFFF...FF8. How it helps is you may only need one define:
#define SOMEMASK 0x7
and then use
ra&=~SOMEMASK;
ra|=newvalue&SOMEMASK.
You might get even more clever and say
#define SOMEMASKBITS 3
#define SOMEMASK ((1
And you dont even have to think about 0x7 being three ones. you just put a 3 in there.
A bit-shift operator comes in two main varieties (and I'm not talking about the direction): shift, and rotate.
Additionally, both come in two directions, so typically you have four:
shift-left
shift-right
rotate left
rotate right
The first two shift the bits a number of bits to one direction. Any bits that "fall off" the end disappear. Any bits that "appear" on the other end, are zero.
Typically you also specify how many bits to shift the value.
So:
1000 shl 1 = 0000 (the 1 fell off the end, and a 0 appeared on the other end)
1000 shr 1 = 0100 (a zero fell off the right end)
Rotation doesn't lose bits that fall off, instead they are rotated back in on the other side.
1000 rol 1 = 0001 (the 1 was rotated back in on the other side)
You can think of the two operations as:
For shifting, the number contains an infinite number of zeroes on both ends, that follows the value as you shift it
For rotation, the number is repeated an infinite number in both directions, that follows the value as you shift it
There's also a variant of the rotation one, rotate through carry, that uses the carry flag in the process as an extra bit.
If the carry flag starts as 0, here's what happens:
1000 rcl 1 = 0000 (rcl = rotate through carry to left)
0000 rcl 1 = 0001 (now the 1 came back, it was temporarily stored in carry flag)
The last one can, in machine code, be used to move single bits from one register to another:
rcl ax, 1 ; rotate AX-register, 16-bit, left 1 bit, through carry
rcr bx, 1 ; rotate BX-register, 16-bit, right 1 bit, through carry
Here we take the leftmost bit from AX, temporarily rotate it out into the carry flag, and then rotate it back into the leftmost bit of BX.
Now, you can usually combine shifting with the other bitwise operators. For instance, to set bit N of value (where N is 0-based, and bit 0 is the rightmost one), you can do this:
value = value OR (1 shl N)
Here we first shift the value 1 N times to the left. If N is 0, this does not shift the bit at all.
Then we OR the result of that shifting with the existing value, and store it. OR has the effect of combining the 1's so that if either value has a 1-bit in a specific position, the result is also a 1-bit in that position.
So for the shifting:
1 shl 0 = 00000001 shl 0 = 00000001
1 shl 1 = 00000001 shl 0 = 00000010
1 shl 2 = 00000001 shl 0 = 00000100
1 shl 3 = 00000001 shl 0 = 00001000
1 shl 4 = 00000001 shl 0 = 00010000
1 shl 5 = 00000001 shl 0 = 00100000
1 shl 6 = 00000001 shl 0 = 01000000
1 shl 7 = 00000001 shl 0 = 10000000
Then the OR:
???????? OR 00100000 = ??1?????, where ? means whatever it was before
Let me take a couple of the lines of code you've posted:
UBRRH = ((XTAL / (8 * 250000)) - 1)>>8; // 250kbps at 16Mhz
UBRRL = (XTAL / (8 * 250000)) - 1;
The first does a calculation, (XTAL / (8 * 250000)) - 1, which I don't know the purpose behind. This is normal math, however, so it calculates something. Let's call it a frequency (judging by the comment.)
This value is calculated twice, so let's rewrite the above statements:
UBRRH = value >>8; // 250kbps at 16Mhz
UBRRL = value;
Here I have to guess, but I'm guessing that UBRRH and UBRRL are both declared to be of type "BYTE", which means they can store at most 8 bits of value each. This means that the code actually reads like this:
UBRRH takes the upper 8 bits of "value", shifts them into the lower 8 bits, and stores those. Since it only stores a byte, it chops off the rest, which means it grabs bits 8-15
UBRRL takes the lower 8 bits, and chops off the rest, which means it grabs bits 0-7
Since the names of the two end in L and H, they fit with the assumption.
The bitwise operators operate (as their name suggests on bits). In the first chunk of code you have given these operators are used for setting and reseting a specific bit. For simplicity assume that SWITCH_DDR is a 8bit integer and that SWITCH_BIT is also a 8bit integer that has a constant value of 2:
SWITCH_DDR = 00000000; // initial value of SWITCH_DDR is 0
SWITCH_BIT = 00000010;
Then you can use the bitwise OR to set the specific bit of SWITCH_DDR to 1:
SWITCH_DDR |= SWITCH_BIT; // SWITCH_DDR is 00000010 now
To verify if the SWITCH_BIT bit is set you use the AND operator:
TEMP = 10101010 & SWITCH_BIT; // TEMP is 00000010 now (1 in TEMP is set only if there's 1 in both operands)
if (TEMP == SWITCH_BIT) // The condition is true
{ /* Do something */ }
TEMP = SWITCH_DDR & SWITCH_BIT; // TEMP is again 00000010 because we set it to 00000010 before and the AND operator doesn't therefore change anything
if (TEMP == SWITCH_BIT) // The condition is also true
{ /* Do something */ }
To unset a specific bit you can use this:
TEMP = ~SWITCH_BIT; // TEMP is now 11111101
SWITCH_DDR &= TEMP; // This preserves everything (because 1 & 1 = 1 and 1 & 0 = 0) but the SWITCH_BIT bit which will be always set to 0 (anything & 0 = 0)
The shift operators just shift the bits left or right:
RESULT = 10010010 << 1; // RESULT is 00100100
RESULT <<= 1; // RESULT is 01001000
RESULT <<= 2; // RESULT is 00100000
RESULT >>= 1; // RESULT is 00010000
There is one special thing about the shift operators - you can use them for a fast division/multiplication with powers of 2:
RESULT = 3 << 1; // Result is 6 (3 * 2)
RESULT = 5 << 2; // Result is 20 (5 * 4)
RESULT = 1 << 7; // Result is 128 (1 * 128)
RESULT = 36 >> 1; // Result is 18 (36 / 2)
RESULT = 35 >> 1; // Result is 17 (35 / 2)
It's worth noting, btw, that on many small processors there are specialized instructions for setting and clearing individual bits of an I/O port. I would suggest that you find out something about any processor you'll be using, because optimal coding styles vary from one to another. For example, consider the groups of statements:
some_port |= 8; /* Statement #1a -- Note value is a power of 2 */
some_port |= 2; /* Statement #1b -- Note value is a power of 2 */
some_port |= 9; /* Statement #2 -- Note value is not a power of 2 */
On some processors (e.g. ARM or Z80), if some_port is declared volatile (which it should be), each statement will be three instructions, so the first sequence will take twice the time and space of the first. On some others (e.g. PIC) the first two statements will be one instruction each, while the second will be two instructions, so both sequences will take the same time and space. Still others will offer a space advantage to one and a time advantage to the other.
Time/space for 1st and 2nd methods of setting bits
(time in cycles unless noted)
1st 2nd
2/4 2/3 8051 (standard)
4/4 3/3 8051 (accelerated clone)
2/2 2/2 PIC
10/4 8/6 6805

Resources