2013-10-08 2 views
2

это моя проблема:«побитовое или» работает иногда

Я пишу программу в QtCreator, который считывает некоторые данные батареи (напряжение, ток, ...). Каждое значение передается в два байта, и я должен объединить их в UINT16. Иногда моя программа делает это правильно и показывает правильное значение (около 12 В). Но в другой раз это не работает и показывает около 65V. Проблема возникает только в том случае, если я подключил нагрузку к батарее. Затем он иногда говорит 65V, а иногда и 12V. Я использовал более старую программу, чтобы оберегать данные, которые я получаю от батареи, и эти данные говорят все время около 12 В, поэтому это не данные, что не так.

Это то, что я написал в моей программе acutal:

voltage = data[6] << 8; 
voltage = voltage | data[7]; 

То, что я узнал до сих пор:

Проблема не возникает, если напряжение достигает значения specefic (например, падает с 12.XV до 11.XV), похоже, в ней нет системы.

Я уже преобразовал значения, которые я получаю в двоичные числа, чтобы увидеть, есть ли что-то, что-то поменялось. Это не тот случай.

старая программа делает это, что то же самое, как и в моей реальной программе:

voltage = data[6]<<8; 
voltage|= data[7]; 

EDIT: - Это то, что я знаю о доставленной данных:

Формат: Unsigned Int

Единицы измерения: мВ

Диапазон: от 0 до 65535 мВ ==> 1000 = 1V

  • Для переменной «напряжение» я выбрал UINT16 в своей новой программе.
  • В моем старом кодексе я использую unsigned short для «напряжения». Когда я изменяю это в своей новой программе, это не влияет на мою проблему.

Некоторые больше информации о том, как работает программа, может быть полезным, может быть:

  • зачитывает буфера (14 байт)
  • проверки, если первые байты «$» (знак для соответствующих данных)
  • проверка, если второй байт 7 (значок для данных батареи)
  • затем сделать переключение передач и побитовое или то, что я написал выше
  • результат печати

Самое страшное в том, что он работает иногда, когда нагрузка применяется, и если я жду какое-то время, это не сработает, а затем внезапно это снова и снова, независимо от того, какое напряжение.

EDIT2:

программы разные, есть все разные для моего прохода, за исключением. Я только работаю над этим чтением данных о батарее/я построил эту область. Старая программа была написана с использованием MSVisual Studio 2009 C++ Express. Для новой программы я использую QtCreator с Mingw4.8 в качестве компилятора. данные [] имеет тип QByteArray:

В .h: UINT16 напряжение;

В .c:

QByteArray data = com_port.readLine(1000); 

if (data[0] == '$') 
      { 
       switch (data[1]) 
       { 
        case 7: 
         voltage = data[6]<<8; 
         voltage = voltage|data[7]; 
         qDebug() << voltage; 
       } 
      } 

Целью обеих программ является то же самое, и я использую ту же батарею.

+2

были бы полезны точные типы информации об утере/данных и инициализации. Как и масштабный коэффициент (какова величина 1Volt). Также имеет ли «старый» код эту проблему в условиях нагрузки? –

+0

Теперь было бы полезно, как вы инициализировали «напряжение». Если бы это был 'int', а не' uint', например, вы могли бы столкнуться с подобными проблемами. – Yellow

+0

65 - магическое число, 2^16 = 65536. Измените тип * данных * на неподписанный тип, чтобы избежать проблем с расширением знака. Другими словами, замените * char * на * unsigned char *. –

ответ

6

Вот моя догадка: Если ваши данные [7] обозначены символом char (либо явно, либо вашим компилятором, обрабатывающим char как подписанное значение), и ЕСЛИ коэффициент масштабирования составляет 0,1 вольт, тогда переход от 12,7 вольт до 12,8 вольт сделать данные [7] отрицательным. Затем вы подписываете его до 16 бит (подразумеваемым литом), поэтому ваше значение результата составляет около 65000, что равно примерно 6500V - похожее на 65V, которое вы, кажется, видите (у любого шанса есть пара дополнительных нулей ?). В тот момент, когда вы опускаетесь до 12,7 В или ниже, вы возвращаетесь к реальному напряжению.

Например:

12,7 вольт = 0b01111111 -> (знак распространяется на 16 бит) -> 0b00000000 01111111 -> 127 -> 12,7 Вольт

12,8 вольт = 0b10000000 -> (знак распространяется на 16 бит) -> 0b11111111 10000000 -> 65408 -> 6540,8 Volt

Это просто догадка - поскольку фактические типы/коэффициент масштабирования не предусмотрены.

EDIT:

То, что вы, вероятно, хотите сделать это

unsigned int voltage = ((((unsigned int)(data[6])) << 8) | (((unsigned int)data[7])&0xff)) & 0xffff; 

Вы можете изменить неподписанных Int к вашему UInt16. Вы можете потерять некоторые из скобок (на основе приоритета оператора) и отбросить последний « 0xffff», но это так же ясно, как и получается.

+0

«Напряжение» беззнаковое int, поэтому я думаю, что это не имеет никакого отношения к этому. На самом деле это была проблема, когда я хотел прочитать текущую информацию в своей старой программе, потому что текущая подпись была подписана. Поэтому я потратил много времени на преобразование подписанных/неподписанных значений, и, наконец, я думаю, что понял эту конвертирующую вещь. – Malte

+1

@Malte - это напряжение без знака int или что-то вроде uint16_t? каков тип данных - это char? Можете ли вы предоставить точные декларации? –

+0

В .h-файле переменная 'напряжение' объявляется как UINT16. В техническом описании батареи указано, что тип данных не имеет значения int (0-65535). – Malte

Смежные вопросы