Перейти к содержанию
    

Правильный алгоритм в спецификации ModBus привден. И даже функция на языке Си имеется.

 

эт оттуда и таблицы и функция (просто на асм переделанная)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Короче переделал я алгоритм расчета crc из табличного в стандартный с тем же полиномом A001

 

;  +-------------------------------------------------------------------------+
;  |              подпрограмма проверки контрольной суммы CRC16              |
;  |                                                                         |
;  |temp1,temp10 - кол-во байт для подсчета, temp8,temp6 - начальный адрес 1го байта|
;  |      выход: temp3 - младший байт CRC16, temp2 - старший байт CRC16      |
;  +-------------------------------------------------------------------------+
checkCRC16:
    ldi        temp2,0xFF        ;загружаем начальное значение CRC (МБ)
    ldi        temp3,0xFF        ;загружаем начальное значение CRC (СБ)
    ldi        temp4,0x01        ;загружаем значение полинома
    ldi        temp5,0xA0
    add        temp6,temp1        ;прибавляем к нач.адресу кол-во байт
    adc        temp8,temp10
    mov        temp7,temp6        ;копируем результат в temp7,temp9
    mov        temp9,temp8
loopCalcCRC16:
    mov        temp6,temp7        ;копируем результат в temp6,temp8
    mov        temp8,temp9
    sub        temp6,temp1        ;в temp6,temp8 остается адрес текущего байта принятого фрэйма
    sbc        temp8,temp10
    mov        ZH,temp8
    mov        ZL,temp6
    ld        temp6,Z            ;в temp6 остается значение байта
    eor        temp2,temp6        ;ксорим значение байта со значением CRC (МБ)
    ldi        temp6,8
loopXORbyte:
    sbrc    temp2,0            ;проверяем младший бит CRC (МБ)
    jmp        MB_CRCL_1
    jmp        MB_CRCL_0
MB_CRCL_1:
    clc                        ;сдвигаем вправо весь CRC
    ror        temp3
    ror        temp2
    eor        temp2,temp4        ;ксорим значение CRC с полиномом
    eor        temp3,temp5
    jmp        skip_MB_CRCL_0
MB_CRCL_0:
    clc                        ;сдвигаем вправо весь CRC
    ror        temp3
    ror        temp2
skip_MB_CRCL_0:
    dec        temp6
    brne    loopXORbyte
    subi    temp1,1            ;уменьшаем счетчик байт
    sbci    temp10,0
    cpi        temp1,0
    brne    loopCalcCRC16
    cpi        temp10,0
    brne    loopCalcCRC16    ;и проверяем достиг ли он 0
    ret

 

Этот код полностью повторяет С# код пользователя Linore с форума http://programmersforum.ru/showthread.php?t=82812&page=2

 

Правильность посчитанной суммы проверял программкой СRC Find (Подбор полинома) неизвестного автора, там можно ввести hex-пакет длиной больше 256 и получившуюся контрольную сумму, затем эта программка просчитывает все полиномы от 0x0000 до 0xFFFF, так вот для пакета:

 

3E0101010B00004801005AFFFF02005FFFFF030062FFFF04004DFFFF050062FFFF06007CFFFF0700
6BFFFF08008AFFFF090062FFFF0A0079FFFF0B007BFFFF0C007FFFFF0D0056FFFF0E006AFFFF0F00
7DFFFF10007EFFFF110045FFFF120065FFFF130073FFFF14005FFFFF15005AFFFF160068FFFF1700
76
FFFF180076FFFF190057FFFF1A006BFFFF1B0061FFFF1C0069FFFF1D0039FFFF1E0072FFFF1F0058
FFFF200044FFFF210039FFFF220033FFFF230060FFFF240032FFFF25005FFFFF260048FFFF27005C
FF
FF280057FFFF290047FFFF2A0040FFFF2B003BFFFF2C0049FFFF2D0034FFFF2E0052FFFF2F0035FF
FF300035FFFF310033FFFF320041FFFF33004EFFFF340033FFFF350025FFFF36002DFFFF370007FF
FF
38002FFFFF390026FFFF3A0024FFFF3B0006FFFF3C0032FFFF3D0034FFFF3E0029FFFF3F0032FFFF
40003DFFFF41004CFFFF42000BFFFF43005CFFFF440036FFFF450055FFFF46002CFFFF470058FFFF
480019FFFF

 

мой модуль выдал crc16 = 0x403F, программка CRC Find при вычислении полинома выдала что совпал полином 0xA001

 

Программка для работы с портами IODump, которой я пользуюсь похоже считает crc16 корректно только для пакетов длиной не больше 256 и считает она тоже с полиномом 0xA001, например для этого же пакета она считает crc16 = 0x1604 и при проверке через прогу CRC Find ни с одним полиномом не совпадает. Вот такие дела собственно.

 

Кстати предыдущий способ (табличный) тоже корректно работал, все правильно считает, все дело было в кривой программке для работы с портами(((

Изменено пользователем vazz

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

freemodbus.berlios.de - готовый модуль.
имхо сделано весьма неоптимально, тем более для АВР. Зачем-то включили настройку посл.порта в инициализацию, в результате пришлось лепить порты под все архитектуры. CRC считают для всего фрейма, тогда как можно обновлять прямо в прерывании приема/передачи для каждого байта.

 

vazz попробуйте такую функцию:

#define CRC16_MODBUS_INIT 0xffff
#define CRC16_MODBUS_POLY 0xa001
U16 crc16_modbus_upd(U8 data, U16 crc_prev) {
    U8 flag_xor;
    crc_prev ^= data;
    for (U8 cnt_bits = 8; cnt_bits; cnt_bits--) {
        flag_xor = crc_prev & 1;
        crc_prev >>= 1;
        if (flag_xor) crc_prev ^= CRC16_MODBUS_POLY;
    }
}

Изменено пользователем ukpyr

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

vazz попробуйте такую функцию:

#define CRC16_MODBUS_INIT 0xffff
#define CRC16_MODBUS_POLY 0xa001
U16 crc16_modbus_upd(U8 data, U16 crc_prev) {
    U8 flag_xor;
    crc_prev ^= data;
    for (U8 cnt_bits = 8; cnt_bits; cnt_bits--) {
        flag_xor = crc_prev & 1;
        crc_prev >>= 1;
        if (flag_xor) crc_prev ^= CRC16_MODBUS_POLY;
    }
}

 

благодарю, но обе функции которые я испытал работают замечательно, изначально моя ошибка была в том что ориентировался на свою программку для работы с портами как на эталон подсчета crc, оказалось все работало у меня изначально, зря паниковал, зато разобрался во всех этих заморочках досконально, эт плюс. ТУТ ОКАЗЫВАЕТСЯ ЕСТЬ ТЭГИ "CODE", а я блин понапихал тут кодов без соответствующего оформления..)) sorry

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Добрый день!

Думаю правильно будет спросить в этой теме, а не создавать новую по схожему вопросу что обсуждалось выше. Ситуация:

Для проверки работоспособности, есть простая плата на atmega32 , кварц внешний 16МГц. Кабель UART TTL-232R-3V3 (собран на FT232), взял исходники freeModbus , чуть подредактировал (пишу на Atmel Studio 6.1), скомпилировалось все прекрасно. Залил в МК, запустил утилиту modpoll.exe с параметрами:

modpoll.exe -m rtu -a 10 -r 1000 -c 5 -t 3 -b 38400 -d 8 -p even COM3

pause>nul

 

МК находит, читает с него регистры и все вроде бы хорошо. но, беру любую другую программу для работы с ModBus RTU и ничего не коннектиться. типа ошибка связи. Вот остановился сейчас на этом http://modbustool.codeplex.com ибо наименее безглюченная при запуске и работе. Но связи так и не добился.

 

Что это может быть ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Немного разобрался с тем, почему при чтении выдавало ошибку #2.

Подсказку нашел в соседней ветке http://electronix.ru/forum/index.php?showt...86005&st=15

так вот,там как я понял было дело в прошивке - надо было увеличивать на 1 (к примеру 1001) адрес к примеру Input регистра, и тогда он читался по адресу 1000 извне.

у меня схожая ситуация, но противоположно надо делать получается...

9c8a55b25fa1b672904c35a19ddd1e75.jpeg

 

кто нибудь сталкивался с таким ? получается мастер на ПК по версии Modbus'a новее, чем в МК ? Пример реализации для AVR брал отсюда http://robot-develop.org/archives/125

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Скорей всего это особенность вашего мастера, в программе запрос идет по 999 ячейке как и указано пользователем. Есть программа modbus poll в ней можно задавать "protocol style addresses. BASE 0" или "PLC style addresses. Base 1" http://www.modbustools.com/base.asp

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...