Bitwise operating on CAN message contents

Hi! Sorry in advance if this is a dumb question. I have looked for it in the forum but just gotten myself more confused.

I am recieving CAN data as an array of 8 bytes

uint8_t buf[8];

from this function from seeed can library:

CAN.readMsgBuf(&len, buf);

The 1st 2 bytes of this array represent a DC current that the Transmitting device is sensing.
I hooked up a USB can monitor to watch this data to make sure it's being transmitted as expected from looking at the device's DB file using Kvaser database editor.
Obviously both of these bytes can range from 0x00 up to 0xFF. This SHOULD mean a range of decimal values from 0 to 65535.

I want to bitshift one and then OR them together, so that I can display that value as a decimal on a 4 x 7-segment display from adafruit.

Here is my question - if I do this:

int current1;
int current2;
int current;

current1 = int(buf[0]); 
current2 = int(buf[1]);
         
current = (((uint16_t)current1 << 8) | current2);

and the data going into buf[0] is, for example, 0x11
and the data going into buf[1] is, for example, 0xD1,

will THIS happen:

0x11 0xD1

binary: 00010001 11010001

-> bitshifted, ANDed together: 00010000111010001

-> in decimal, 8657

(then I divide it by 10 because the transmitting device sends w factor 0.1) -> 865.7A

OR, will THIS happen:

0x11 0xD1

-> bitshifted, ANDed together: 0x11D1

binary: 0001000111010001

-> in decimal, 4561

4561 / 10 = 456.1A (what I want)

I want the 2nd possibility to be my result.
I have the rest of the code working, showing other data that are sent in only 1 byte, so they're easy. But I am a noob and easily confused by data types and whatnot, so I'm not sure how to approach the 2-byte data.
How do I AND the bytes together into 1, 4-character hex value, BEFORE I do any math on it?
TIA!

if you are working on a UNO, Mega etc remember that an int is 16 bits
try calculating using unsigned int, e.g.

void setup() {
  byte buf[]={0x11, 0xD1};
  unsigned int current=(unsigned int) buf[0] << 8 | buf[1];
  Serial.begin(115200);
  Serial.println(current);
}

void loop() {}

which displays

4561

note the use of the bitwise OR operator (not AND)

(unsigned int) buf[0] << 8 | buf[1];

Use the standard Arduino function:

as you know the result is a 16 bit unsigned integer, I would use uint16_t as the type, this way you get always the same behaviour wether you are on a 8 bits or 32 bits MCU.

"official" types from the C++ specification: Fundamental types - cppreference.com and Fixed width integer types (since C++11) - cppreference.com

I would not use word as it's defined by Arduino as unsigned int regardless of the platform

and so it will be 16 bits on a UNO but 32 bits on an ESP32.

Thank you so much, that's really helpful! Once I can get back to my shop I'll try and post a video of the result :slight_smile:

Great reminder, thanks J-M-L. I do plan on expanding my microcontroller collection so it's important that I pay attention to stuff like that :slight_smile:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.