|
|
  |
Принцип построения консоли управления устройством, Поделитесь опытом кто как делает :) |
|
|
|
Aug 12 2009, 08:43
|

Профессионал
    
Группа: Свой
Сообщений: 1 001
Регистрация: 27-06-06
Пользователь №: 18 409

|
Стоит задача разаработать устройство которое должно иметь возможность управляться через UART. Думаю встроить отладочную консоль чтобы можно было посылать в устройство комманды и получать ответы. Комманды в виде одиночных символов реализовал. Теперь хочу расширить функциональность консоли и реализовать длинные команды (наподобие АТ-комманд). Причём хочется сделать аппаратно-независимую консоль чтобы можно было переносить из проекта в проект меняя только низкоуровневые функции приёма/отправки символовов через UART. Подскажите кто как делает подобные консоли. Интересует прежде всего как осуществляется поиск комманд в потоке принимаемых символов (выделение слов длиной 2 и более символа)? Какие стандартные библиотеки можно использовать? Сейчас реализована входная FIFO-UART которая заполняется в прерываниях и функция считывания символа из FIFO которая возвращает -1 если нет данных или принятый символ. Одиночные символы отлавливать легко (считал - обработал), два - уже сложнее но пока реализую устанавливая флаги. Как отловить три и более символа - вот тут нужны идеи
|
|
|
|
|
Aug 12 2009, 10:26
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Собираете словарь команд (ASCIIZ), например Код const char cmd0[] ="READ"; const char cmd1[] ="ERASE"; const char cmd2[] ="WRITE"; const char *command_set[3] = {&cmd0,&cmd1,&cmd2}; Затем, поочередно сравниваете принятый токен со строками словаря, до тех пор, пока следующий символ из словаря не будет равен \0. Дальше - все зависит от синтаксиса - допускаете ли Вы у себя разделители токенов или нет... Если разделители необязательны - возвращаете индекс, соответствующий command_set[j] указателю на распознанную команду, и текущую позицию в буфере, подразумевающую дальнейший разбор аргументов. Далее - switch() и тд произвольной сложности. Игнорирование регистра символа делаете?
|
|
|
|
|
Aug 12 2009, 11:24
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(_Pasha @ Aug 12 2009, 13:26)  Собираете словарь команд (ASCIIZ), например С размахом  Код int command( struct Cmd *cmd ) { //--------------------------------------------------------------------------- case 'sst ': ... break;
case 'psst': .... break;
//--- Dummy arguments print ----------- case 'aa ': printf( "\nargc=%i ls='%s'\r", cmd->argc, cmd->command_line ); for( int i=0; i<= cmd->argc; i++ ) printf( "argn[%i]=%08lX\r", i, cmd->argn[i] ); break; Команды - по первым четырем (для 32битника) символам. Стандартная разборка на аргументы делается заранее.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Aug 12 2009, 15:44
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

|
Цитата(Goodefine @ Aug 12 2009, 17:31)  Зато обеспечивают детерминированное поведение системы, при значительном потоке символов... Сказано мощно. Это что, длинные команды как средство нейтрализации ошибок реализации протокола?  Автору. Передерите какой-нить стандартный протокол, слишком много аспектов существуют в протоколах.
--------------------
Уходя, оставьте свет...
|
|
|
|
|
Aug 12 2009, 17:21
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

|
Цитата(Goodefine @ Aug 12 2009, 18:50)  В качестве контрпримера можно рассмотреть поведение управляемого объекта, с односимвольным набором команд, на вход которого постоянно что-то приходит. Без ошибок. При прочих равных, разумеется... И что, как контрпример себя ведет? Использую односимвольные наборы команд в обе стороны. Никаких проблем. Очень удобно - в одну сторону идут коды нажатых клавиш, а в другую - коды символов, подлежащих отображению. Полный дуплекс, физический и логический. Если русский язык не нужен, коды управления дисплеем помещаются в правую сторону ASCII без проблем. Тут главное - не пытаться придумывать что-то посредине между "простым" протоколом и "нормальным" протоколом, в результате получится зависающая хрень.
--------------------
Уходя, оставьте свет...
|
|
|
|
|
Aug 12 2009, 17:49
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(Dog Pawlowa @ Aug 12 2009, 23:21)  Очень удобно - в одну сторону идут коды нажатых клавиш, а в другую - коды символов, подлежащих отображению. Полный дуплекс, физический и логический. Но это вроде немного не то, что хотел топикстартер? Я лично применяю более-менее полноценную консоль, типа такого: CODE // обработчик команды. typedef int (* CmdHandler)(char * args);
// структура с информацией о команде typedef struct { char * command_name; // имя CmdHandler handler; // обработчик } Command;
const Command CommandTable[] = { {"GET", GetCommandHandler}, {"SET", SetCommandHandler}, {"TERM", TermHandler}, ... };
int parse_command_line(char * buf) { char *lt; char *token; int i;
token = GetToken(buf, <); if (!token) return FALSE;
for (i=0; i<sizeof(CommandTable) / sizeof(CommandTable[0]); i++) if (!strcmp(CommandTable[i].command_name, token)) { if (!CommandTable[i].handler) return FALSE; return CommandTable[i].handler(lt); }
return FALSE; }
void interpreter(void) { char buf[81]; for (;;) { rs_puts("\r\n=>"); rs_gets(buf, 80); if (!parse_command_line(buf)) rs_puts("ERR"); } } Гораздо приятнее писать "SET PARAM1=23.4", чем "sA34", имея заодно возможность отредактировать строку при неверном вводе. Да и не накладно это особо.
Причина редактирования: Уменьшение видимого размера цитаты исходника.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Aug 12 2009, 19:06
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(Dog Pawlowa @ Aug 13 2009, 00:27)  Если уж пошла речь о том, что приятнее, то я пришел к выводу, что лучше ПиСишное приложение, одно на все устройства, а из устройства может быть прочитано, какой физический смысл имеет PARAM1. Типа SNMP. Согласен, так тоже неплохо. Но есть, как мне кажется, пара аргументов против. Первый - универсальность. Линукс/виндовз/что-то там ещё, разные версии... Ну и можно банально забыть писишную программу  Терминалка же есть везде. И второй аргумент - в терминале можно не только конфигурировать устройство (SET/GET), но и выполнять что-то специфическое. Например, непрерывный вывод значения АЦП до нажатия любой кнопки, дрыгание заданной ножкой с заданной частотой. Интерактив, короче. Для таких применений сложно придумать универсальную программу для ПиСи, имхо.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|