Стартовая страница › Форумы › Взаимодействие с устройствами › Modbus › Modbus RTU — BCD Format
Помечено: Modbus
- В этой теме 29 ответов, 3 участника, последнее обновление 9 лет, 3 месяца назад сделано
manjey73.
-
АвторЗаписи
-
13.04.2017 в 12:58 #5273
baurУчастникПопробуйте просто int считать для начала с формулой
в смысле не uint а просто int?
я так сделал картина не меняется-
Ответ изменён 9 лет, 4 месяца назад пользователем
baur.
13.04.2017 в 13:11 #5275
manjey73УчастникСтранно, 206592 должно быть правильным числом, судя по калькулятору.
А что не так не въеду пока…13.04.2017 в 13:16 #5276
manjey73Участникя тормоз, оно то уже преобразовалось в десятичное….. соответственно и дополнительное BCD в десятичное не надо….
У меня пока кроме огорода ничего не получается, сейчас через копирование массива попробую…-
Ответ изменён 9 лет, 4 месяца назад пользователем
manjey73.
13.04.2017 в 14:23 #5278
manjey73УчастникНе ту функцию нашел для преобразования… Попробуйте вот эту
public int bcd2dec(double val)
{
int index = 0;
int range = 4;
int intval = Convert.ToInt32(val);
byte[] buf_bcd = BitConverter.GetBytes(intval);
Array.Reverse(buf_bcd);
List<byte> temp = new List<byte>(buf_bcd);
byte[] buf_dec = temp.GetRange(index, range).ToArray();
int result = 0;
foreach (byte bcd in buf_dec)
{
result *= 100;
result += (10 * (bcd >> 4));
result += bcd & 0xf;
}
return result;
}название bcd2dec, Описание — Преобразование int из BCD в DEC
Сделал только для int, вызов в формуле так же bcd2dec(Cnl)
Тестировал на вашем значении 20659213.04.2017 в 14:55 #5282
MikhailМодераторНа всякий случай дополню:
Т.к. в документации указано, что число 32-битное, то считывать по Модбас нужно как uint (4 байта). Затем преобразовывать с помощью формул в базе конфигурации.
Внутри Вашей формулы сначала преобразуйте (uint)Cnl, т.к. как правильно написали, все входные каналы имеют тип double. Ну а затем уже можете выделять байты, биты, чтобы перевести из BCD в обычное число.13.04.2017 в 14:56 #5283
baurУчастникmanjey73, спасибо!!! заработал
завтра протестирую еще раз …-
Ответ изменён 9 лет, 4 месяца назад пользователем
baur.
13.04.2017 в 14:58 #5284
baurУчастникВнутри Вашей формулы сначала преобразуйте (uint)Cnl
получается bcd2dec((uint)Cnl)?
13.04.2017 в 15:11 #5288
manjey73УчастникНет, просто bcd2dec(Cnl), так как канал в сервер уже передается в формате double самой системой. На вход формулы значение идет в double, как оно прилетает из Коммуникатора в Сервер.
То, что вы опрос делаете uint 4 байта это взаимодействие Коммуникатора с прибором, этого входная формула не касается.
-
Ответ изменён 9 лет, 4 месяца назад пользователем
manjey73.
13.04.2017 в 20:53 #5297
manjey73Участникpublic int BcdToDec(double val)
{
byte[] bcdNumber = BitConverter.GetBytes((UInt32)val);
Array.Reverse(bcdNumber);
int result = 0;
foreach (byte b in bcdNumber)
{
int digit1 = b >> 4;
int digit2 = b & 0x0f;
result = (result * 100) + digit1 * 10 + digit2;
}
return result;
}Вызов так же, BcdToDec(Cnl) — забыл что эта версия кода работает только с 4-х байтными переменными
14.04.2017 в 07:07 #5298
baurУчастникПо документации там 10-ти значный счетчик, как они вмешается в 32bit?
14.04.2017 в 07:42 #5299
baurУчастникв смысле, как вместится символ 9 999 999 999?
14.04.2017 в 08:59 #5303
manjey73УчастникПотому что это BCD формат, считается не байт а октет (или как оно там правильно) 4 бита, в которых можно разместить цифры от 0 до 9.
4 байта это 8 символов.
Но у вас же вроде всего 4 байта от прибора идет или вы что-то не договорили ?Тогда документация или трындит или читать надо 8 байт а не 4, при чтении 8 байт надо вариант формулы bcd2dec возвращать к оригинальному виду с обработкой long типа
14.04.2017 в 09:04 #5306
manjey73Участнику вас 2 регистра подряд. 8 знаков и еще какие-то Non Ressetable 10 digit — скорее всего в этом регистре всего 2 знака, либо там уже не BCD формат, как говорит документация.
25.05.2017 в 05:20 #5909
baurУчастникМожно ли применить эту формулу для BDC 16 bit (ushort 2 байта)?
25.05.2017 в 11:20 #5919
manjey73УчастникВроде можно, единственное, может придется добавить еще два нулевых байта вперед или в конец уже внутри формулы, ну или потестировать как есть и посмотреть что получится.
Вы же всегда можете сделать так ВызовФормулы((UInt32)ваш ushort) — никто же не мешает…
Если в формулу надо подать double, то надо сделать (double)ваш ushort.
Ну или подкорректировать просто формулу под вашу задачу, чтобы лишнего не писать…
Собственно каналы все равно в Сервер прилетают в double. -
Ответ изменён 9 лет, 4 месяца назад пользователем
-
АвторЗаписи
- Для ответа в этой теме необходимо авторизоваться.