|
AVR Modbus RTU, Поможите) |
|
|
|
Aug 2 2010, 05:12
|

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

|
В общем с AVRами дружу недавно, столкнулся с острой необходимостью использования протокола Modbus RTU (т.к. оборудование уже используют на многих объектах и нужно общение приборов с новыми прошивками работающими по тому же принципу). В общем, надеюсь, найдутся добрые люди, которые смогут мне простому смертному помочь в освоении этого протокола на базе ATMega16. Собственно готовых кодов не нужно, мне б полностью принцип понять применительно к моей задаче. Я кое чего нашел от прежнего программиста, вот все что есть:
------------------------------- Протокол передачи данных ModBus RTU. Функция для передачи данных: 04 - «read input registers». Запрашивать 14 регистров начиная с нулевого. Каждый регистр – двухбайтное слово. Обращаю внимание, что в протоколе ModBus все слова передаются старшим байтом вперед. Были случаи что попадалась документация с разными таблицами CRC и разными полиномами. Ниже приведу свои таблицы. Порядок передаваемых данных:
1. Значение A 2. Значение B 3. Значение C 4. Значение D 5. Значение E 6. Значение F 7. Значение G 8. Значение H 9. Значение I 10.Значение J 11.Значение K 12.Значение L 13.Значение M 14.Значение N
Запись параметров - 16 (10 Hex) Preset Multiple Registers Порядок передаваемых данных:
1. Значение I 2. Значение J 3. Значение K 4. Значение L 5. Значение M 6. Значение N
const unsigned char CRCHi[] = { 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40};
const unsigned char CRCLo[] = { 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C, 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80, 0x40};
Надеюсь на помощь!
--------------------
Не так страшна автоматизация, как её малюют.
|
|
|
|
3 страниц
1 2 3 >
|
 |
Ответов
(1 - 36)
|
Aug 2 2010, 05:47
|

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

|
Вопросов много.. За ссылку конечно спасибо, но видимо пока я там ничего понять не смогу. Про модбас знаю только что слово такое есть, узнать бы принцип протокола именно RTU (для моей задачи, глобально протокол осваивать нет необходимости пока). Также как высчитывать CRC16? (как я понял его нужно высчитывать используя две таблицы, которые приведены выше), т.е. полный алгоритм подсчета что с чем складывать куда что сдвигать и при каких условиях. Какие временные интервалы выдерживать при посылках/ожиданиях ответа. Пока только умею атмегой посылать/принимать байты с заданной скоростью без какого либо протокола..) Вобщем, у меня есть формат посылки, которую нужно отправить в прибор, в ответ на которую прибор должен прислать все необходимые данные.. Видимо аццкая жара которая неделю влияет на мозги (белок то сворачивается) и мне б "на пальцах для тупых" основные принципы протокола (по каким правилам что передавать и когда чего принимать) и принцип подсчета црц16 исходя из приведенных таблиц
--------------------
Не так страшна автоматизация, как её малюют.
|
|
|
|
|
Aug 2 2010, 06:02
|

Беспросветный оптимист
     
Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646

|
Если тупо на пальцах именно про RTU, то основная фишка там - это таймаут 3.5 символа по приёму пакета. То есть, если между двумя любыми байтами разрыв больше, то это считается концом пакета. В freemodbus это реализовано с помощью таймера. По приёму каждого символа заводится таймер на 3.5 символа вперёд, а символ кладётся в буфер. Если сработал таймер, значит имеем тайм-аут и соответственно конец пакета. Вызывается обработчик, который анализирует целостность пакета (CRC, заголовок, код команды, длина пакета) и выставляет соответствующие флаги, которые затем обрабатываются функцией eMBpoll(), которая, в свою очередь, вызывает CallBack-функции для обработки команд. Вычисление CRC производится в функции usMBCRC16 (./RTU/mbcrc.c)
--------------------
Программирование делится на системное и бессистемное. ©Моё :) — а для кого-то БГ — это Bill Gilbert =)
|
|
|
|
|
Aug 2 2010, 06:09
|
Местный
  
Группа: Свой
Сообщений: 264
Регистрация: 16-07-05
Из: г. Уфа
Пользователь №: 6 851

|
Почитайте это и вот это. Контрольная сумма считается так: Код static __flash unsigned char aucCRCHi[] = { 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40 };
static __flash unsigned char aucCRCLo[] = { 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C, 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80, 0x40 };
unsigned int usMBCRC16(unsigned char * pucFrame, unsigned int usLen ) { unsigned char ucCRCHi = 0xFF; unsigned char ucCRCLo = 0xFF; int iIndex;
while( usLen-- ) { iIndex = ucCRCLo ^ *( pucFrame++ ); ucCRCLo = ucCRCHi ^ (aucCRCHi[iIndex] ); ucCRCHi = ( aucCRCLo[iIndex] ); } return ucCRCHi << 8 | ucCRCLo; }
--------------------
|
|
|
|
|
Aug 2 2010, 06:43
|

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

|
Цитата(war4one @ Aug 2 2010, 09:09)  Почитайте это и вот это. Контрольная сумма считается так: Благодарю за пример, сегодня уже находил что-то подобное, я пишу на ассемблере пока только, с Си имею дело только когда чего-нить в visual-среде под винду пишу (ну это боловство пока только). В начале я как понимаю мы объявляем переменные а дальше крах мозга...)))) я заранее пршу прощения, так стыдно.....))) ну и собсно исходя из того, что я пишу на машинном уровне мне б понять как соотносится принятый байт со значениями в этих таблицах и как в итоге получается этот несчастный црц.. я не зря "на пальцах для тупых" попросил, но я не безнадежен....)) в последний раз я так мучался когда не знал с чего начать контроллеры осваивать))) ну вот освоил 51, AVR, хочу еще ARM, но тут без Си никак (последнее - енто лирическое отступление, мона пропустить). Вобщем, в идеале, я принимаю все байты посылки, считаю црц, если он правильный то проверяю 1й байт, если он совпадает с адресом прибора, то по функции выдаю ответ с данными, если во время приема возникла тишина в 3,5 байта (исходя из скорости) то полученные данные считаю полностью принятой посылкой (ну и дальше сначала как описал), правильно глаголю? осталос только с этими таблицами разобраться на машинном уровне..
--------------------
Не так страшна автоматизация, как её малюют.
|
|
|
|
|
Aug 2 2010, 08:50
|

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

|
Цитата(MrYuran @ Aug 2 2010, 10:57)  Возвращаем старший и младший байт CRC в виде 16-разрядного слова Вот спасибо хорошо положите на камод.. Епт, все оказывается не так сложно. Спасибо добрый человек за разжовывание..)) на бумажке посчитал по этому методу (через таблички) и все получается, ну пока для посылки всего из одного байта посчитал)) Только после подсчета получается какбы итоговое значение младшего байта CRC ставится старшим байтом, а старшее итоговое ставится младшим, круто блин
--------------------
Не так страшна автоматизация, как её малюют.
|
|
|
|
|
Aug 5 2010, 08:40
|

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

|
на железе сегодня полностью отладил прием 8ми байт (1й - адрес, 2й - функция 3й4й - начальный адрес регистров, 5й6й - кол-во регистров, 7й8й - CRC16), CRC16 считает, при скорости 57600 выжидаю 70мс (3.5/57.6 = 60.8мс, но я решил для верности немножко с запасом) после приема очередного байта, если время прошло считаю как новый фрэйм, также сделал что если приходит больше 8ми байт в одном фрэйме, то каждый 9тый воспринимается как начало нового 8ми байтого фрэйма, короче радости полные штаны))
--------------------
Не так страшна автоматизация, как её малюют.
|
|
|
|
|
Aug 5 2010, 10:14
|

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

|
Цитата(MrYuran @ Aug 5 2010, 11:51)  Это неправильно, в RTU должен быть разрыв 3,5 символа. Если его нет, то это будет ошибка формата фрейма. сделал, теперь молчит если больше 8ми байт. У меня вопрос созрел по самому модбасу. Вобщем как я и говорил у меня ни исходников предыдущей версии прошивки нету ни связи с тем программистом который ее создавал. Так вот, значит посылаю я прибору со старой прошивкой строку: 01 04 00 00 00 01 31 CA а он мне в ответ 01 04 08 00 00 00 00 00 00 FF FF 25 BD Возникает у меня как минимум 2 вопроса 1. Что за 08 и откуда оно берется? Эт явно что-то с модбасом связано 2. Почему так много данных выдает (пускай они даже 00 00), судя по всему он выдает четыре 2хбайтных параметра 00 00 00 00 00 00 FF FF, хотя я в исходящей посылке даю прибору инструкцию на передачу всего одного слова данных начиная с 00 00 адреса. Я предполагал, что ответ будет примерно таким: 01 04 xx xx CRC16 Поможите люди опытныя..)
--------------------
Не так страшна автоматизация, как её малюют.
|
|
|
|
|
Aug 5 2010, 11:09
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(vazz @ Aug 5 2010, 14:40)  при скорости 57600 выжидаю 70мс (3.5/57.6 = 60.8мс, но я решил для верности немножко с запасом) после приема очередного байта, если время прошло считаю как новый фрэйм, также сделал что если приходит больше 8ми байт в одном фрэйме, то каждый 9тый воспринимается как начало нового 8ми байтого фрэйма, короче радости полные штаны)) Вы упорно не желаете читать документацию? По ссылкам которые я привел выше нужно прочитать по крайней мере MODBUS Protocol Specification и Modbus Serial Line Protocol and Implementation Guide V1.02. Если бы вы прочитали вторую, то могли заметить ремарку про паузы. Да и про формат ответа вопросов не возникало.
Эскизы прикрепленных изображений
|
|
|
|
|
Aug 6 2010, 04:01
|

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

|
Цитата(rezident @ Aug 5 2010, 14:09)  Вы упорно не желаете читать документацию? По ссылкам которые я привел выше нужно прочитать по крайней мере MODBUS Protocol Specification и Modbus Serial Line Protocol and Implementation Guide V1.02. Если бы вы прочитали вторую, то могли заметить ремарку про паузы. Да и про формат ответа вопросов не возникало. Справедливо с точки зрения человека который постоянно этим протоколом пользуется. Для меня же задача эта одноразовая и в самом простом ее "формате". Я не ленив, но врядли мне потребуется изучать этот протокол глубже чем "Компьютер - мастер, прибор - slave, 1 запрос - 1 ответ раз в 2-5 секунд". Из рациональных побуждений в плане затрат своего времени, которое дороже денег, я решил спросить у умудренных опытом людей совета в своей простейшей задаче. Мне не трудно изучить всю документацию по этому вопросу, но смысла в досканальном изучении совсем нет и не придвидится. Сегодня почитаю указанные вами документы. Большое спасибо всем за помощь, извините если кого напряг.
--------------------
Не так страшна автоматизация, как её малюют.
|
|
|
|
|
Aug 13 2010, 11:49
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Цитата(vazz @ Aug 5 2010, 14:14)  Так вот, значит посылаю я прибору
01 04 00 00 00 01 31 CA
а он мне в ответ
01 04 08 00 00 00 00 00 00 FF FF 25 BD
Возникает у меня как минимум 2 вопроса
1. Что за 08 и откуда оно берется? Эт явно что-то с модбасом связано request: slave_address[1byte] func[1byte] address[2bytes] reg_qty[2bytes] crc[2bytes] response: slave_address[1byte] func[1byte] bytes_qty[1byte] data[1-250bytes] crc[2bytes] Цитата 2. Почему так много данных выдает (пускай они даже 00 00), судя по всему он выдает четыре 2хбайтных параметра 00 00 00 00 00 00 FF FF, хотя я в исходящей посылке даю прибору инструкцию на передачу всего одного слова данных начиная с 00 00 адреса. Я предполагал, что ответ будет примерно таким: 01 04 xx xx CRC16 Предположения тут неуместны. Что за прибор-то? Вероятно бага в приборе...
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Aug 17 2010, 11:54
|

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

|
Цитата(demiurg_spb @ Aug 13 2010, 14:49)  request: slave_address[1byte] func[1byte] address[2bytes] reg_qty[2bytes] crc[2bytes] response: slave_address[1byte] func[1byte] bytes_qty[1byte] data[1-250bytes] crc[2bytes] bytes_qty - как я понимаю ответ прибора типа "данные приняты без проблем, вот вам ответ", другими словами в случае если ошибок при приеме посылки нет и адрес с функцией совпадают я тупо втыкаю в ответную посылку байт 08 после адреса и функции.. Цитата(demiurg_spb @ Aug 13 2010, 14:49)  Предположения тут неуместны. Что за прибор-то? Вероятно бага в приборе... Вероятно, но дело в том, что прежде чем мне передавать в ответ какие-либо данные мне нужно знать их последовательность, в данном случае какая понимаю ответная посылка имеет фиксированную длину независимо от кол-ва запрошенных данных, но указываемое кол-во данных влияет на заполнение этих фиксированных "вакантных" 4 слов данных... Хотя эт тож догадки.. Связи с программистом этим нет, молчит как рыба, обидно
--------------------
Не так страшна автоматизация, как её малюют.
|
|
|
|
|
Aug 18 2010, 08:51
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Цитата(vazz @ Aug 17 2010, 15:54)  в данном случае какая понимаю ответная посылка имеет фиксированную длину независимо от кол-ва запрошенных данных, но указываемое кол-во данных влияет на заполнение этих фиксированных "вакантных" 4 слов данных... Такого быть не должно. Сколько запросили регистров (N) столько байт (N*2) и получить должны. Цитата Хотя эт тож догадки.. Не нужно гадать. Ещё раз Вам настоятельно рекомендую читать стандарт.
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Apr 1 2011, 14:41
|

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

|
я снова тут! вобщем делюсь своими успехами, изучил особенности модбаса касательно своей задачи основательно и вобщем сделал всем моим приборам поддержку этого протокола, всего одной функции (чтения), но больше и не надо было, зато качественно, выдают ответы как положено, в т.ч. выдают ошибки типа функция не поддерживается, ошибка поля данных и т.д. и т.п. (с модификацией старшего бита функции в случае ошибок, усё как положено). Вобщем сейчас задача встала передо мной, никак не могу сообразить как это решить. Создал я ужо почти некую систему измерения температуры с 16разрядным АЦП, ИОНом крутым, вобщем все оч качественно, с компенсацией цифровых шумов и т.д. и т.п. Так вот система эта состоит из 4 компонентов: 1. комп 2.радиомодуль с usb (к компу) 3. радиомодуль с rs485 (к измерительным блокам) 4.измерительные модули (до 256 на одной шине, подключаются к п.3), все это уже собрано и отлажено многочисленным испытаниями, как точности измерения тк и дальностью взаимодействия, осталось ток дописать под винду программулину, которая всем этим ворочает. Так вот каждый измерительный модуль имеет 72 измерительных входа для датчиков (ну и дополнительные входы для измерения напряжения на проводах компенсации, 3хпроводная схема). Каждый модуль измерительный способен хранить в своей EEPROM 1 полное измерение (с датой и временем). В этом полном измерении (т.е. измерено 72 датчика), для каждого там сохранено 4 байта информации для последующей обработки на компе. Структура записи измерения в EEPROM: [5 байт на дату и время] + [1 байт кол-ва датчиков в отчете] + [5 байт на датчик, 1 на номер датчика, 4 на результаты измерения]x72. В итоге получается массив размером 5+1+5х72 = 366 байт, плюс к этому прибавляется 4 байта служебно информации для передачи по интерфейсу. Итого: 370 байт. Моя процедура подсчета CRC16 корректно считает сумму для пакета длиной не более 256 байт. КАК ПОСЧИТАТЬ CRC16 ДЛЯ ПАКЕТА БОЛЬШЕ 256 БАЙТ? :-) извините если вопрос неуместен и глуп.. ПОМОЖИТЕ, а то кроме этого мне ничо не мешает эту систему довести до конца
--------------------
Не так страшна автоматизация, как её малюют.
|
|
|
|
|
Apr 1 2011, 15:15
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(vazz @ Apr 1 2011, 20:41)  В итоге получается массив размером 5+1+5х72 = 366 байт, плюс к этому прибавляется 4 байта служебно информации для передачи по интерфейсу. Итого: 370 байт. Моя процедура подсчета CRC16 корректно считает сумму для пакета длиной не более 256 байт. КАК ПОСЧИТАТЬ CRC16 ДЛЯ ПАКЕТА БОЛЬШЕ 256 БАЙТ? :-) извините если вопрос неуместен и глуп.. ПОМОЖИТЕ, а то кроме этого мне ничо не мешает эту систему довести до конца Ну если проблема только в подсчете CRC16, то нужно видимо изменить тип переменной которая задает размер пакета. Вместо unsigned char использовать unsigned int. Если вы используете функцию пример которой приведен в приложении к спецификации MODBUS over Serial Line, то там используется типа unsigned short, который нужно заменить на unsigned int. Но я хотел бы задать встречный вопрос: как вы посредством протокола ModBus собираетесь передавать данные больше, чем 252 байта? Стандартными командами ModBus это не получится сделать. Ведь длина пакета не может быть больше, чем 256 байт, а у вас запись 370 байт.
|
|
|
|
|
Apr 1 2011, 15:25
|

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

|
Цитата(Ruslan1 @ Apr 1 2011, 19:08)  Вероятно Вы уперлись в разрядность счетчика, который байты считает Добрый день , Ruslan1! Вобщем считаю я по таблицам, которые приведены в начале темы, а алгоритм следующий (он слегка кривенький в плане написания, но до 256 байт работает): ; +-------------------------------------------------------------------------+ ; | подпрограмма проверки контрольной суммы CRC16 | ; | | ; |temp1,temp10 - кол-во байт для подсчета, temp8,temp6 - начальный адрес 1го байта| ; | выход: temp3 - младший байт CRC16, temp2 - старший байт CRC16 | ; +-------------------------------------------------------------------------+ checkCRC16: ldi temp2,0xFF ;загружаем начальное значение CRCLo ldi temp3,0xFF ;загружаем начальное значение CRCLh ldi temp4,0x00 ;загружаем начальное значение CRCindex add temp6,temp1 adc temp8,temp10 mov temp5,temp6 mov temp9,temp8 loopXORbyte: mov temp6,temp5 mov temp8,temp9 sub temp6,temp1 ;в temp6,temp8 остается адрес текущего байта принятого фрэйма sbc temp8,temp10 mov ZH,temp8 mov ZL,temp6 ld temp6,Z ;в temp6 остается значение байта eor temp2,temp6 mov temp4,temp2 ;получаем новое значение CRCIndex (CRCLo при этом теряется) ldi ZH,0x02 ;выбираем старший массив mov ZL,temp4 ;выбираем элемент массива (по CRCIndex) lpm temp6,Z ;в temp6 получаем значение элемента массива eor temp3,temp6 ;получаем новое значение CRCLo (CRCHi при этом теряется) mov temp2,temp3 ldi ZH,0x01 ;выбираем младший массив mov ZL,temp4 ;выбираем элемент массива (по CRCIndex) lpm temp3,Z ;в temp3 получаем значение элемента массива (что и есть новое CRCHi) subi temp1,1 sbci temp10,0 cpi temp1,0 brne loopXORbyte cpi temp10,0 brne loopXORbyte ret Не клюйте за ассемблер, пока до Си руки не дошли (но скоро дойдут, т.к. скоро приедтся с arm работать и 7дюймовым tft) кстати это алгоритм считает и после 256 байт, я пробовал добавить просто 2ой байт для счетчика, но видимо шо-то не то или с таблицами такой метод не работает. Свыше 256 байт этот алгорит выдает некое значение CRC16, но оно не совпадает к примеру со значеним которое выдает программка для работы с портами при досчете для того же самого пакета Цитата(rezident @ Apr 1 2011, 19:15)  Но я хотел бы задать встречный вопрос: как вы посредством протокола ModBus собираетесь передавать данные больше, чем 252 байта? Стандартными командами ModBus это не получится сделать. Ведь длина пакета не может быть больше, чем 256 байт, а у вас запись 370 байт. Извините что сразу не уточнил, я после своего поста ток понял что этот вопрос последует неминуемо) в этой системе было решено создать свой протокол "засекреченный" типа, он оч похож на модбас, но не совсем, этот протокол позволяет мне значительно сократить время общения главного с подчиненными (вдаваться в подробности думаю нет смысла, хотя если это интересно я могу и рассказать). Сейчас проблема только с подсчетом црц для пакета больше 256 длиной. Система имеет свой собственный радиоканал + локальный физ.интерфейс RS485, к которому больше никакое оборудование никогда не будет цепляться, ну есть еще кое какие маркетинговые причины почему свой протокол.
--------------------
Не так страшна автоматизация, как её малюют.
|
|
|
|
|
Apr 1 2011, 15:48
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(vazz @ Apr 1 2011, 21:25)  Извините что сразу не уточнил, я после своего поста ток понял что этот вопрос последует неминуемо) в этой системе было решено создать свой протокол "засекреченный" типа, он оч похож на модбас, но не совсем, этот протокол позволяет мне значительно сократить время общения главного с подчиненными (вдаваться в подробности думаю нет смысла, хотя если это интересно я могу и рассказать). Ну меня не особенно интересует этот ваш "засекреченный" протокол  У нас тоже есть свой протокол (правда он нисколько не секретный), который был создан на базе протоколов ModBus и PiNet. Общая длина пакета ограничена 65536 (2^16) байт. Но с помощью него можно адресовать 2^32 байт. Делается это очень просто. Есть отдельная команда "чтение со смещением". При исполнении этой команды первые четыре байта поля Data интерпретируются как смещение от адреса, задаваемого полем Starting Address. Если Starting Address будет указывать на начало вашей записи EEPROM, то с помощью смещения вы сможете почитать всю вашу запись (370 байт) за два запроса. Но для этого нужно использовать код "нестандартной" (пользовательской) функции в ModBus. Соответственно поддержать в приборе ответ на запрос с таким кодом функции.
|
|
|
|
|
Apr 1 2011, 16:38
|

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

|
Цитата(rezident @ Apr 1 2011, 19:48)  Ну меня не особенно интересует этот ваш "засекреченный" протокол "засекреченный" эт не всмысле что он супер крутой какой-то и принципиально новый и "тока за отдельные деньги", сам по себе он не представляет никакой ценности)) он только для этой системы, например сейчас если сказать обычному пользователю что для мышки тож дрова нужны он на тя как на дурачка посмотрит, тож самое и тут, у всего есть свои заморочки с сопряжением, но конечному пользователю собсно это даж знать не нужно, тем более система полностью самостоятельна и не предполагает быть интегрированна в некую другую систему сбора данных. Я эту процедуру подсчета crc как тогда еще написал так больше и не трогал, а тут понадобилось больше 256 байт передавать.. и чо делать хз. Я даж не понимаю как наращивание счетчика еще одним байтом помогает, если значений в массивах таблиц всего по 256 в каждой. Т.е. при переполнении счетчика что с чем должно ксориться если массив таблицы закончился. Вот этот бы момент уточнить. Мож другие таблицы нужны и принцип несколько иной.. Вот например я прям ща запрашиваю полное измерение из модуля, получаю от него: 3E 01 01 01 0B 00 00 48 01 00 53 FF FF 02 00 63 FF FF 03 00 68 FF FF 04 00 78 FF FF 05 00 55 FF FF 06 00 73 FF FF 07 00 81 FF FF 08 00 88 FF FF 09 00 68 FF FF 0A 00 7C FF FF 0B 00 7A FF FF 0C 00 84 FF FF 0D 00 64 FF FF 0E 00 77 FF FF 0F 00 75 FF FF 10 00 87 FF FF 11 00 55 FF FF 12 00 67 FF FF 13 00 61 FF FF 14 00 6A FF FF 15 00 63 FF FF 16 00 66 FF FF 17 00 6D FF FF 18 00 7C FF FF 19 00 47 FF FF 1A 00 57 FF FF 1B 00 55 FF FF 1C 00 67 FF FF 1D 00 47 FF FF 1E 00 5E FF FF 1F 00 52 FF FF 20 00 68 FF FF 21 00 44 FF FF 22 00 4B FF FF 23 00 4B FF FF 24 00 57 FF FF 25 00 5B FF FF 26 00 58 FF FF 27 00 50 FF FF 28 00 4B FF FF 29 00 43 FF FF 2A 00 3F FF FF 2B 00 28 FF FF 2C 00 38 FF FF 2D 00 3A FF FF 2E 00 41 FF FF 2F 00 3A FF FF 30 00 42 FF FF 31 00 28 FF FF 32 00 36 FF FF 33 00 2D FF FF 34 00 3D FF FF 35 00 2B FF FF 36 00 38 FF FF 37 00 1A FF FF 38 00 1E FF FF 39 00 1D FF FF 3A 00 1D FF FF 3B 00 1D FF FF 3C 00 1F FF FF 3D 00 37 FF FF 3E 00 2C FF FF 3F 00 2C FF FF 40 00 25 FF FF 41 00 2D FF FF 42 00 23 FF FF 43 00 44 FF FF 44 00 41 FF FF 45 00 46 FF FF 46 00 39 FF FF 47 00 30 FF FF 48 00 29 FF FF DC FB DC FB - эт по его мнению CRC16 Для этой же последовательности (кроме DC FB) программка для работы с портами выдает crc16 = 4A C3. Модуль не прав, т.к. даж если всю последовательность прогнать через программку (вместе с crc), то нулей не получается(( блин, я решил попробовать прогнать через программку эту последовательность с ее же мыданной crc16 с полной уверенносью, что она мне ща в конце нули напишет и о ужас: 3E 01 01 01 0B 00 00 48 01 00 53 FF FF 02 00 63 FF FF 03 00 68 FF FF 04 00 78 FF FF 05 00 55 FF FF 06 00 73 FF FF 07 00 81 FF FF 08 00 88 FF FF 09 00 68 FF FF 0A 00 7C FF FF 0B 00 7A FF FF 0C 00 84 FF FF 0D 00 64 FF FF 0E 00 77 FF FF 0F 00 75 FF FF 10 00 87 FF FF 11 00 55 FF FF 12 00 67 FF FF 13 00 61 FF FF 14 00 6A FF FF 15 00 63 FF FF 16 00 66 FF FF 17 00 6D FF FF 18 00 7C FF FF 19 00 47 FF FF 1A 00 57 FF FF 1B 00 55 FF FF 1C 00 67 FF FF 1D 00 47 FF FF 1E 00 5E FF FF 1F 00 52 FF FF 20 00 68 FF FF 21 00 44 FF FF 22 00 4B FF FF 23 00 4B FF FF 24 00 57 FF FF 25 00 5B FF FF 26 00 58 FF FF 27 00 50 FF FF 28 00 4B FF FF 29 00 43 FF FF 2A 00 3F FF FF 2B 00 28 FF FF 2C 00 38 FF FF 2D 00 3A FF FF 2E 00 41 FF FF 2F 00 3A FF FF 30 00 42 FF FF 31 00 28 FF FF 32 00 36 FF FF 33 00 2D FF FF 34 00 3D FF FF 35 00 2B FF FF 36 00 38 FF FF 37 00 1A FF FF 38 00 1E FF FF 39 00 1D FF FF 3A 00 1D FF FF 3B 00 1D FF FF 3C 00 1F FF FF 3D 00 37 FF FF 3E 00 2C FF FF 3F 00 2C FF FF 40 00 25 FF FF 41 00 2D FF FF 42 00 23 FF FF 43 00 44 FF FF 44 00 41 FF FF 45 00 46 FF FF 46 00 39 FF FF 47 00 30 FF FF 48 00 29 FF FF 4A C3 B7 0F в конце B7 0F!(( эт получается что моя процедура мож и арбайтен?) блин посчитайте кто нить для этой последовательности crc16, а то чо-то я уже ничо не понимаю.. вот для этого же пакета что последнирислал тока без 4 последних байт (это суммы crc две подряд) посчитал тут http://webnet77.com/cgi-bin/helpers/crc.pl вообще 3 результат) во хрень в экспериментах пошел дальше взял эту же последовательность с црц который посчитан самим модулем и прогнал через прогрммку, в и тоге тоже получил не 00 00, а B7 0F, как и в случае с предыдущим примером. шо то в этом есть.. или совпадение? 3E 01 01 01 0B 00 00 48 01 00 53 FF FF 02 00 63 FF FF 03 00 68 FF FF 04 00 78 FF FF 05 00 55 FF FF 06 00 73 FF FF 07 00 81 FF FF 08 00 88 FF FF 09 00 68 FF FF 0A 00 7C FF FF 0B 00 7A FF FF 0C 00 84 FF FF 0D 00 64 FF FF 0E 00 77 FF FF 0F 00 75 FF FF 10 00 87 FF FF 11 00 55 FF FF 12 00 67 FF FF 13 00 61 FF FF 14 00 6A FF FF 15 00 63 FF FF 16 00 66 FF FF 17 00 6D FF FF 18 00 7C FF FF 19 00 47 FF FF 1A 00 57 FF FF 1B 00 55 FF FF 1C 00 67 FF FF 1D 00 47 FF FF 1E 00 5E FF FF 1F 00 52 FF FF 20 00 68 FF FF 21 00 44 FF FF 22 00 4B FF FF 23 00 4B FF FF 24 00 57 FF FF 25 00 5B FF FF 26 00 58 FF FF 27 00 50 FF FF 28 00 4B FF FF 29 00 43 FF FF 2A 00 3F FF FF 2B 00 28 FF FF 2C 00 38 FF FF 2D 00 3A FF FF 2E 00 41 FF FF 2F 00 3A FF FF 30 00 42 FF FF 31 00 28 FF FF 32 00 36 FF FF 33 00 2D FF FF 34 00 3D FF FF 35 00 2B FF FF 36 00 38 FF FF 37 00 1A FF FF 38 00 1E FF FF 39 00 1D FF FF 3A 00 1D FF FF 3B 00 1D FF FF 3C 00 1F FF FF 3D 00 37 FF FF 3E 00 2C FF FF 3F 00 2C FF FF 40 00 25 FF FF 41 00 2D FF FF 42 00 23 FF FF 43 00 44 FF FF 44 00 41 FF FF 45 00 46 FF FF 46 00 39 FF FF 47 00 30 FF FF 48 00 29 FF FF DC FB B7 0F
Сообщение отредактировал vazz - Apr 1 2011, 17:22
--------------------
Не так страшна автоматизация, как её малюют.
|
|
|
|
|
Apr 2 2011, 09:11
|

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

|
к сожалению ничего не могу найти в сети по моему вопросу... может опыта не хватает.. поэтому могу ток с бубном прыгать пока, и это кое что дает, но я не понял пока о чем это говорит, попробую объяснить, к примеру есть массив данных: Код 3E 01 01 01 0B 00 00 48 01 00 50 FF FF 02 00 65 FF FF 03 00 61 FF FF 04 00 77 FF FF 05 00 57 FF FF 06 00 6E FF FF 07 00 84 FF FF 08 00 87 FF FF 09 00 66 FF FF 0A 00 7A FF FF 0B 00 73 FF FF 0C 00 84 FF FF 0D 00 65 FF FF 0E 00 71 FF FF 0F 00 76 FF FF 10 00 84 FF FF 11 00 56 FF FF 12 00 68 FF FF 13 00 61 FF FF 14 00 6B FF FF 15 00 5D FF FF 16 00 6C FF FF 17 00 65 FF FF 18 00 78 FF FF 19 00 49 FF FF 1A 00 57 FF FF 1B 00 53 FF FF 1C 00 64 FF FF 1D 00 4F FF FF 1E 00 5C FF FF 1F 00 55 FF FF 20 00 65 FF FF 21 00 46 FF FF 22 00 45 FF FF 23 00 49 FF FF 24 00 56 FF FF 25 00 5A FF FF 26 00 50 FF FF 27 00 4D FF FF 28 00 47 FF FF 29 00 40 FF FF 2A 00 3C FF FF 2B 00 2B FF FF 2C 00 32 FF FF 2D 00 39 FF FF 2E 00 40 FF FF 2F 00 36 FF FF 30 00 40 FF FF 31 00 27 FF FF 32 00 34 FF FF 33 00 2A FF FF 34 00 3A FF FF 35 00 2A FF FF 36 00 32 FF FF 37 00 1D FF FF 38 00 1D FF FF 39 00 15 FF FF 3A 00 20 FF FF 3B 00 1B FF FF 3C 00 20 FF FF 3D 00 37 FF FF 3E 00 2D FF FF 3F 00 2D FF FF 40 00 20 FF FF 41 00 28 FF FF 42 00 1E FF FF 43 00 3C FF FF 44 00 41 FF FF 45 00 41 FF FF 46 00 34 FF FF 47 00 39 FF FF 48 00 2A FF FF мой модуль по приведенному выше алгоритму (на асме) считает для него crc16 = F4 17. Программка для работы с портами (IODump называется) считает для этого же массива crc16 = 84 8D. Это разные результаты, НО... Если взять этот массив и в конце добавить к нему F4 17 и прогнать через программку IODump в надежде получить 00 00, то я получу результат crc16 = 63 5B. Также если взять этот массив и в конце добавить к нему 84 8D и прогнать через программку IODump в надежде получить 00 00, то я опять же получаю результат crc16 = 63 5B. И это не совпадение, можно и еще несколько разных пакетов аналогично проверить и значения будут одинаковыми. Я немного в замешательстве, мож все таки у кого нить есть правильный алгоритм вычисления, для эталона, чтоб понять как дальше жить то..)
Сообщение отредактировал vazz - Apr 3 2011, 09:05
--------------------
Не так страшна автоматизация, как её малюют.
|
|
|
|
|
Apr 2 2011, 11:26
|

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

|
Цитата(rezident @ Apr 2 2011, 15:11)  Правильный алгоритм в спецификации ModBus привден. И даже функция на языке Си имеется. эт оттуда и таблицы и функция (просто на асм переделанная)
--------------------
Не так страшна автоматизация, как её малюют.
|
|
|
|
|
Apr 3 2011, 05:54
|

Частый гость
 
Группа: Участник
Сообщений: 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
--------------------
Не так страшна автоматизация, как её малюют.
|
|
|
|
|
Apr 3 2011, 08:19
|
Профессионал
    
Группа: Участник
Сообщений: 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
|
|
|
|
|
Apr 3 2011, 09:00
|

Частый гость
 
Группа: Участник
Сообщений: 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
--------------------
Не так страшна автоматизация, как её малюют.
|
|
|
|
|
Aug 17 2014, 12:07
|
Частый гость
 
Группа: Свой
Сообщений: 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.
|
|
|
|
|
Aug 17 2014, 18:10
|
Частый гость
 
Группа: Свой
Сообщений: 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.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|