d7d1cd 0 21 августа, 2012 Опубликовано 21 августа, 2012 · Жалоба Привет всем. Помогите с реализацией приема по UART. По прерыванию я заполняю буфер приема байтами. В конце приема будет 2 байта контрольной суммы. Вопрос в том, как определить, что по UART полностью передана вся команда. Все команды будут разной длины. Подскажите как решается подобная проблема. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Артём__ 0 21 августа, 2012 Опубликовано 21 августа, 2012 · Жалоба По прерыванию я заполняю буфер приема байтами. В конце приема будет 2 байта контрольной суммы. Вопрос в том, как определить, что по UART полностью передана вся команда. Все команды будут разной длины. Нужно определить длину команды (по заголовку например) и затем принять нужное число байт. Потом сверить сумму. Подскажите как решается подобная проблема. Хорошо бы знать формат команды. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
d7d1cd 0 21 августа, 2012 Опубликовано 21 августа, 2012 · Жалоба Я анализирую протокол обмена прибора, чтобы сделать что-то свое. Там первый байт всегда сетевой адрес, следующий - номер команды, далее - параметры команды (которые могут иметь различную длину или могут вообще отсутствовать), последние 2 байта - контрольная сумма, вычисленная по всем байтам команды. Сетевой адрес не может нести информацию о длине команды. Кроме того, вдруг во время передачи какой-то байт передастся неправильно, тогда ожидаемое число байт может быть определено неправильно. Для этого и существует контрольная сумма: чтобы понять, правильно принята вся команда или нет. Еще: в протоколе обмена написано "Критерием окончания передачи команды является гарантированный таймаут. Для скорости 9600 бит/сек он равен примерно 5 мс. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Артём__ 0 21 августа, 2012 Опубликовано 21 августа, 2012 · Жалоба Для этого и существует контрольная сумма: чтобы понять, правильно принята вся команда или нет. Еще: в протоколе обмена написано "Критерием окончания передачи команды является гарантированный таймаут. Для скорости 9600 бит/сек он равен примерно 5 мс. void StartTimeouTimer() { //..... } void RxCompleteIsr() { RxBuffer[RxIndex++]=ReadNewByte(); StartTimeouTimer(); } volatile unsigned char PacketTimeot; void PacketTimeoutIsr() { PacketTimeot=1; DisableTimeoutTimer(); } То есть в прерывании RxCompleteIsr запускается таймер на 5 мс. Если произошло прерывание PacketTimeoutIsr - значит пакет принят и осталось проверить его сумму. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 21 августа, 2012 Опубликовано 21 августа, 2012 · Жалоба Своё изобретать ИМХО последнее дело. Есть сотни уже придуманных до Вас протоколов, а некоторые из них являются чуть-ли не стандартами де-факто в некоторых отраслях, как например MODBUS в некоторых промышленных системах. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
d7d1cd 0 21 августа, 2012 Опубликовано 21 августа, 2012 · Жалоба Своё изобретать ИМХО последнее дело. Есть сотни уже придуманных до Вас протоколов, а некоторые из них являются чуть-ли не стандартами де-факто в некоторых отраслях, как например MODBUS в некоторых промышленных системах. Имеено MODBUS и подразумевает таймаут в конце передачи пакета. Мне интересно как эту задержку на 5 мс реализовать программно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Артём__ 0 21 августа, 2012 Опубликовано 21 августа, 2012 · Жалоба как эту задержку на 5 мс реализовать программно. Не нужно её пытаться программно организовывать - у вас МК будет 5 мс NOP-ы исполнять? А если 500 мс потребуется? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
d7d1cd 0 21 августа, 2012 Опубликовано 21 августа, 2012 · Жалоба Не нужно её пытаться программно организовывать - у вас МК будет 5 мс NOP-ы исполнять? А если 500 мс потребуется? Тогда как "подождать" 5 мс? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 21 августа, 2012 Опубликовано 21 августа, 2012 · Жалоба таймером:-) Ну или можно передать 4 байта в уарт с отключенным передатчиком драйвера RS485, если такой имеется. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Артём__ 0 21 августа, 2012 Опубликовано 21 августа, 2012 · Жалоба Тогда как "подождать" 5 мс? Ну я ж привёл пример 2-3 поcтами выше... void StartTimeouTimer() { //..... } #define BUF_LENGTH 100 unsigned char RxBuffer[BUF_LENGTH]; volatile unsigned char RxIndex; void RxCompleteIsr() { RxBuffer[RxIndex++]=ReadNewByte(); // чтение принятого байта в буфер StartTimeouTimer();// запуск таймаута 5 мс } volatile unsigned char PacketTimeot; void PacketTimeoutIsr() { PacketTimeot=1; // пакет принят DisableTimeoutTimer();// запрет прерываний от таймаута } void main () { // настройка uart-а для приёма на нужной скорости и с разрешением прерываний по приёму InitUart(); while (1) { if (PacketTimeot) { PacketTimeot=0; // пакет принят // проверка и тд } // другие нужные действия } } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
d7d1cd 0 21 августа, 2012 Опубликовано 21 августа, 2012 · Жалоба таймером:-) Ну или можно передать 4 байта в уарт с отключенным передатчиком драйвера RS485, если такой имеется. Как это можно сделать таймером? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 21 августа, 2012 Опубликовано 21 августа, 2012 · Жалоба Артём Вам рассказал уже об этом. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
d7d1cd 0 21 августа, 2012 Опубликовано 21 августа, 2012 (изменено) · Жалоба Понятно, что надо запустить функцию StartTimeouTimer(). А ее реализацию можно привести? void StartTimeouTimer() { //???????????????????????????????????????????????? } Изменено 21 августа, 2012 пользователем d7d1cd Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Артём__ 0 21 августа, 2012 Опубликовано 21 августа, 2012 · Жалоба Понятно, что надо запустить функцию StartTimeouTimer(). А ее реализацию можно привести? Нет, пока нельзя: вы же не привели тип МК и источник и частоту тактирования. Приведёте, может кто и подскажет. Хотя что там сложного: запустить тактирование и разрешить прерывание по совпадению или переполнению. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
d7d1cd 0 22 августа, 2012 Опубликовано 22 августа, 2012 · Жалоба Нет, пока нельзя: вы же не привели тип МК и источник и частоту тактирования. Приведёте, может кто и подскажет. Хотя что там сложного: запустить тактирование и разрешить прерывание по совпадению или переполнению. МК MSP430F149, тактирование от внешнего кварца частотой 8 МГц. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться