реклама на сайте
подробности

 
 
3 страниц V  < 1 2 3  
Reply to this topicStart new topic
> AVR Modbus RTU, Поможите)
vazz
сообщение Apr 2 2011, 11:26
Сообщение #31


Частый гость
**

Группа: Участник
Сообщений: 189
Регистрация: 21-01-10
Пользователь №: 54 971



Цитата(rezident @ Apr 2 2011, 15:11) *
Правильный алгоритм в спецификации ModBus привден. И даже функция на языке Си имеется.


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


--------------------
Не так страшна автоматизация, как её малюют.
Go to the top of the page
 
+Quote Post
vazz
сообщение Apr 3 2011, 05:54
Сообщение #32


Частый гость
**

Группа: Участник
Сообщений: 189
Регистрация: 21-01-10
Пользователь №: 54 971



Короче переделал я алгоритм расчета 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 - Apr 3 2011, 09:03


--------------------
Не так страшна автоматизация, как её малюют.
Go to the top of the page
 
+Quote Post
ukpyr
сообщение Apr 3 2011, 08:19
Сообщение #33


Профессионал
*****

Группа: Участник
Сообщений: 1 264
Регистрация: 17-06-08
Из: бандустан
Пользователь №: 38 347



Цитата
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 - Apr 3 2011, 08:23
Go to the top of the page
 
+Quote Post
vazz
сообщение Apr 3 2011, 09:00
Сообщение #34


Частый гость
**

Группа: Участник
Сообщений: 189
Регистрация: 21-01-10
Пользователь №: 54 971



Цитата(ukpyr @ Apr 3 2011, 12:19) *
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


--------------------
Не так страшна автоматизация, как её малюют.
Go to the top of the page
 
+Quote Post
truppik
сообщение Aug 17 2014, 12:07
Сообщение #35


Частый гость
**

Группа: Свой
Сообщений: 81
Регистрация: 24-07-14
Из: NA
Пользователь №: 82 352



Добрый день!
Думаю правильно будет спросить в этой теме, а не создавать новую по схожему вопросу что обсуждалось выше. Ситуация:
Для проверки работоспособности, есть простая плата на 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 ибо наименее безглюченная при запуске и работе. Но связи так и не добился.

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


--------------------
never know best.
Go to the top of the page
 
+Quote Post
truppik
сообщение Aug 17 2014, 18:10
Сообщение #36


Частый гость
**

Группа: Свой
Сообщений: 81
Регистрация: 24-07-14
Из: NA
Пользователь №: 82 352



Немного разобрался с тем, почему при чтении выдавало ошибку #2.
Подсказку нашел в соседней ветке http://electronix.ru/forum/index.php?showt...86005&st=15
так вот,там как я понял было дело в прошивке - надо было увеличивать на 1 (к примеру 1001) адрес к примеру Input регистра, и тогда он читался по адресу 1000 извне.
у меня схожая ситуация, но противоположно надо делать получается...


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


--------------------
never know best.
Go to the top of the page
 
+Quote Post
Lagman
сообщение Aug 19 2014, 17:10
Сообщение #37


Знающий
****

Группа: Свой
Сообщений: 875
Регистрация: 28-10-05
Пользователь №: 10 245



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

3 страниц V  < 1 2 3
Reply to this topicStart new topic
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 9th August 2025 - 15:14
Рейтинг@Mail.ru


Страница сгенерированна за 0.01747 секунд с 7
ELECTRONIX ©2004-2016