9 years, 1 month ago.

Bitwise assignment operators

Does the mbed complier permit the use of bitwise assignment operators such as, " &= ", " |= ", or " <<= "? (the quotes are not part of the operators) Here's an example of how to use this operator, and what it's supposed to do:

EXAMPLE--

uint32_t bit_byte = 0x000FF000;

printf("This is bit_byte before a twelve-bit shift: %#X\n\r", bit_byte);

bit_byte <<= 12;

printf("\n\rThis is bit_byte after a twelve-bit shift: %#X\n\r", bit_byte);

OUTPUT SHOULD BE--

This is bit_byte before a twelve-bit shift: 0x000FF000

This is bit_byte after a twelve-bit shift: 0xFF000000

BUT I GET--

This is bit_byte before a twelve-bit shift: 0x000FF000

This is bit_byte after a twelve-bit shift:

In other words, no output of the results of the shift and assignment.

I also don't get any warnings at compile time either.

Is there a library that I need to include and if so, why no warning?

There are other ways of doing this:

bit_byte = bit_byte << 12;

but using the bitwise assignment operators make for more compact, easily readable code.

I've already worked around this issue with something like the above code, but I miss that set of operators.

Thanks for reading.

Tom

1 Answer

9 years, 1 month ago.

The operators should work just fine. Have used them myself. Check the code following the printf. Perhaps there is a crash that causes the printf to stop also. You may also want to explicitly use:

// Host PC Communication channels
Serial pc(USBTX, USBRX);

pc.printf("\n\rThis is bit_byte after a twelve-bit shift: %#X\n\r", bit_byte);

while(1);

Yes, they should, but they don't.

The printf() statements were never a problem. They were not added until a problem became apparent. I used those to set up an output for the reader to understand what was happening.

In mbed, the assignment operators neither assigned nor operated. Adding another line helped.

The larger focus of the program is to take raw data, (low-to high pulses from a sensor,) save that data, then convert that data into something the display driver can pass on to the 4-digit 7-segment display.

The code below takes an uint32_t value, splits it up into three 8-bit bytes, (the scale of the data is larger than two bytes, but smaller than three bytes,) then it puts this data in specific locations in the EEPROM. The EEPROM has 8-bit memory locations, so 32-bit data needs to be sliced and diced in an orderly way for storage and retrieval. The point of putting data in an EEPROM is that if the power is cut, there will be a record of how much fuel has been used from the cell. When power is resumed, the data can be shoved back into the display conversion routines and passed along to the display without missing a beat. So far it works fine without the bitwise assignment operators functioning the way I would expect.

Other areas of the program have more opportunities for bitwise assignment operators to work their magic. This is a sample that really only has one line where it would be handy.

void save_pulse_count(uint32_t signal_pulse){
     
    uint32_t gas_can;
    char filler[2];
     
    gas_can = signal_pulse >> 16;						// Shift off lower 16 bits for high byte
    printf("this is gas_can high byte:\t\t%#X\n\r",gas_can);	// Verify
    filler[0] = hi_addr;                						// Load array with address and data
    filler[1] = (uint8_t)gas_can;     
    memory.write(EEPROM_write,filler,2,0);				// Write to EEPROM
    wait(0.01);                              					// EEPROM is slow reader needs a delay
    
    gas_can = signal_pulse & 0xFF00;					// Mask off upper eight bits for middle byte
    gas_can = gas_can >> 8;							// Shift off lower byte of data
    printf("this is gas_can middle byte:\t\t%#X\n\r",gas_can);	// Verify
    filler[0] = md_addr;							// Load result into a char array
    filler[1] = (uint8_t)gas_can;
    memory.write(EEPROM_write,filler,2,0);				// Write to EEPROM
    wait(0.01);									// Read War and Peace

    gas_can = signal_pulse & 0x0000FF;			        // Mask off upper 16 bytes for low byte
    printf("this is gas_can low byte:\t\t%#X\n\r",gas_can);	// Verify
    filler[0] = lo_addr;								// Load
    filler[1] = (uint8_t)gas_can;
    memory.write(EEPROM_write,filler,2,0);				// Write to EEPROM
    wait(0.01); 									// Take a nap
    
return;} 

             //	gas_can = gas_can >> 8;  	// This worked consistently without fail
	     //	gas_can >>= 8;			// This did not and the compiler did not complain	
posted by TOM SPARKS 14 Mar 2015

Hmm, I dont see why the bitshift should go wrong. Maybe it is the \t\t in your printf? Anyhow, the code can probably be simplified even more:

void save_pulse_count(uint32_t signal_pulse){
     
    char filler[2];
     

    filler[0] = hi_addr;                                        // Load array with address and data
    filler[1] = (signal_pulse >> 16) & 0xFF;     
    printf("this is the high byte: %#X\n\r", filler[1] );    // Verify
    memory.write(EEPROM_write,filler,2,0);              // Write to EEPROM
    wait(0.01);                                                 // EEPROM is slow reader needs a delay   

    filler[0] = md_addr;                            // Load result into a char array
    filler[1] = (signal_pulse >> 8) & 0xFF;     
    printf("this is the middle byte: %#X\n\r", filler[1] );    // Verify
    memory.write(EEPROM_write,filler,2,0);              // Write to EEPROM
    wait(0.01);                                 // Read War and Peace
 
    filler[0] = lo_addr;                                // Load
    filler[1] = (signal_pulse) & 0xFF;     
    printf("this is the low byte: %#X\n\r", filler[1] );    // Verify
    memory.write(EEPROM_write,filler,2,0);              // Write to EEPROM
    wait(0.01);                                     // Take a nap
    
return;} 

You may even be able to write all bytes to the EEPROM in one go by defining an array of 6 bytes,

posted by Wim Huiskamp 16 Mar 2015