Побитовые операторы и преобразование int в 2 байта и обратно - PullRequest
6 голосов
/ 13 июня 2010

первый раз, привет, ребята!

Так что, надеюсь, кто-то может помочь .. Мой фон - php, поэтому ввод слова типа lowend, например, char - это байты, которые являются битами ... которые являются двоичными значениями ... и т. Д., Требуется некоторое время, чтобы освоить;)

То, что я пытаюсь сделать, это отправить некоторые значения с платы Ardunio в openFrameWorks (оба с ++).

То, что в настоящее время делает этот скрипт (и работает хорошо для одного датчика, я мог бы добавить), когда запрашивается данные для отправки, является ...

int value_01 = analogRead(0);  // which outputs between 0-1024

 unsigned char val1;
 unsigned char val2;

//some Complicated bitshift operation           
    val1 = value_01 &0xFF;
    val2 = (value_01 >> 8) &0xFF;  

    //send both bytes
    Serial.print(val1, BYTE);
    Serial.print(val2, BYTE);

Видимо, это самый надежный способ передачи данных. Так что теперь, когда он отправляется через последовательный порт, байты добавляются в строку символов и преобразуются обратно с помощью ..

int num = ( (unsigned char)bytesReadString[1] << 8 | (unsigned char)bytesReadString[0] );

Итак, напомню, что я пытаюсь получить данные с 4 датчиков (что, как я предполагаю, будет 8 из этих серийных отпечатков?) И иметь int num_01 - num_04 ... в конце всего этого.

Я предполагаю, что это (как и в большинстве случаев) может быть довольно легко для тех, кто имеет опыт в этих понятиях ..

Любая помощь будет принята с благодарностью. Спасибо

Ответы [ 4 ]

7 голосов
/ 13 июня 2010

Напишите функцию для абстрактной отправки данных (я избавился от ваших временных переменных, потому что они не добавляют много значения):

void send16(int value)
{
    //send both bytes
    Serial.print(value & 0xFF, BYTE);
    Serial.print((value >> 8) & 0xFF, BYTE);
}

Теперь вы можете легко отправлять любые данные, которые вы хотите:

send16(analogRead(0));
send16(analogRead(1));
...
1 голос
/ 13 июня 2010

Просто отправьте их один за другим.

Обратите внимание, что последовательный драйвер позволяет отправлять один байт (8 бит) за раз. Значение от 0 до 1023 включительно (что похоже на то, что вы получаете) умещается в 10 бит. Так что 1 байт недостаточно. 2 байта, то есть 16 битов, достаточно (есть дополнительное пространство, но если скорость передачи не является проблемой, вам не нужно беспокоиться об этом потраченном впустую месте).

Итак, первые два байта могут содержать данные для вашего первого датчика. Следующие два байта содержат данные для второго датчика, следующие два байта для третьего датчика и последние два байта для последнего датчика.

Я предлагаю вам использовать функцию, предложенную Р. Самуэлем Клатчко для отправляющей стороны, и, надеюсь, вы сможете решить, что вам нужно делать на принимающей стороне.

0 голосов
/ 13 июня 2010

Чтобы немного обобщить код "Отправить" -

void SendBuff(const void *pBuff, size_t nBytes)
{
    const char *p = reinterpret_cast<const char *>(pBuff);
    for (size_t i=0; i<nBytes; i++)
        Serial.print(p[i], BYTE);
}

template <typename T>
void Send(const T &t)
{
    SendBuff(&t, sizeof(T));
}
0 голосов
/ 13 июня 2010
   int num = ( (unsigned char)bytesReadString[1] << 8 | 
               (unsigned char)bytesReadString[0] );

Этот код не будет делать то, что вы ожидаете.

Когда вы сдвигаете 8-битный символ без знака, вы теряете лишние биты.

11111111 << 3 == 11111000

11111111 << 8 == 00000000

т.е. любой беззнаковый символ при сдвиге на 8 бит должен быть равен нулю.

Вам нужно что-то похожее на это:

typedef unsigned uint;
typedef unsigned char uchar;

uint num = (static_cast<uint>(static_cast<uchar>(bytesReadString[1])) << 8 ) |
           static_cast<uint>(static_cast<uchar>(bytesReadString[0]));

Вы можете получить тот же результат от:

typedef unsigned short ushort;
uint num = *reinterpret_cast<ushort *>(bytesReadString);

Если порядок байтов в порядке. Должен работать на Little Endian (x86 или x64), но не на Big Endian (PPC, Sparc, Alpha и т.

...