1

I'm programming with a PLC and I'm reading values out of it.

It gives me the data in unsigned char. That's fine, but the values in my PLC can be over 255. And since unsigned chars can't give a value over 255 I get the wrong information.

The structure I get from the library:

struct PlcVarValue
{
    unsigned long   ulTimeStamp         ALIGNATTRIB;
    unsigned char   bQuality            ALIGNATTRIB;
    unsigned char   byData[1]           ALIGNATTRIB;
};
  • ulTimeStamp gives the time
  • bQuality gives true/false (be able to read it or not)
  • byData[1] gives the data.

Anyways I'm trying this now: (where ppValues is an object of PlcVarValue)

    unsigned char* variableValue =  ppValues[0]->byData;            
    int iVariableValue = *variableValue;

This works fine... untill ppValues[0]->byData is > 255;

When I try the following when the number is for example 257:

unsigned char testValue = ppValues[0]->byData[0];
unsigned char testValue2 = ppValues[0]->byData[1];

the output is testvalue = 1 and testvalue2 = 1

that doesn't make sense to me.

So my question is, how can I get this solved so it gives me the correct number?

Bart
  • 717
  • 1
  • 9
  • 28
  • 3
    The array is not long enough for a start - the index 1 does not exist in that structure – Ed Heal Oct 02 '15 at 11:47
  • 1
    I think `byData` is most likely a variable length array. – Paul R Oct 02 '15 at 11:48
  • [Why use array size 1 instead of pointer?](http://stackoverflow.com/questions/6390331/why-use-array-size-1-instead-of-pointer), but you probably need to read the documentation for the structure to understand how to get data out of it. – crashmstr Oct 02 '15 at 11:50
  • byData is an unsigned char? it says so in the struct. I can even change it to `unsigned int` but then the values below 255 will give me wrong information. – Bart Oct 02 '15 at 11:50
  • Possible duplicate of [Convert 2 char into 1 int](http://stackoverflow.com/questions/13894209/convert-2-char-into-1-int) – m.s. Oct 02 '15 at 11:50
  • @crashmstr this is the documentation is giving me about this struct: unsigned char byData[1]; Array with the value. The size of this array depends on the data type (byData[1] is only a placeholder with the minimum size). Should only be accessed, if bQuality is TRUE. – Bart Oct 02 '15 at 11:51

1 Answers1

3

That actually looks like a variable-sized structure, where having an array of size 1 at the end being a common way to have it. See e.g. this tutorial about it.

In this case, both bytes being 1 for the value 257 is the correct values. Think of the two bytes as a 16-bit value, and combine the bits. One byte will become the hight byte, where 1 corresponds to 256, and then add the low bytes which is 1 and you have 256 + 1 which of course is equal to 257. Simple binary arithmetic.

Which byte is the high, and which is the low we can't say, but it's easy to check if you can force a message that contains the value 258 instead, as then one byte will still be 1 but the other will be 2.

How to combine it into a single unsigned 16-bit value is also easy if you know the bitwise shift and or operators:

uint8_t high_byte = ...
uint8_t low_byte = ...
uint16_t word = high_byte << 8 | low_byte;
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621