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

 
 
4 страниц V   1 2 3 > »   
Reply to this topicStart new topic
> Принцип построения консоли управления устройством, Поделитесь опытом кто как делает :)
mempfis_
сообщение Aug 12 2009, 08:43
Сообщение #1


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

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



Стоит задача разаработать устройство которое должно иметь возможность управляться через UART.
Думаю встроить отладочную консоль чтобы можно было посылать в устройство комманды и получать ответы.
Комманды в виде одиночных символов реализовал. Теперь хочу расширить функциональность консоли и реализовать длинные команды
(наподобие АТ-комманд). Причём хочется сделать аппаратно-независимую консоль чтобы можно было переносить из проекта в проект меняя только низкоуровневые функции приёма/отправки символовов через UART.

Подскажите кто как делает подобные консоли. Интересует прежде всего как осуществляется поиск комманд в потоке принимаемых символов (выделение слов длиной 2 и более символа)? Какие стандартные библиотеки можно использовать?

Сейчас реализована входная FIFO-UART которая заполняется в прерываниях и функция считывания символа из FIFO которая возвращает -1 если нет данных или принятый символ. Одиночные символы отлавливать легко (считал - обработал), два - уже сложнее но пока реализую устанавливая флаги.
Как отловить три и более символа - вот тут нужны идеи smile.gif
Go to the top of the page
 
+Quote Post
ukpyr
сообщение Aug 12 2009, 10:17
Сообщение #2


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

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



нужен приемный буфер на макс.количество символов в команде и обнулением счетчика по тайм-ауту.
признак завершения команды - символ CR.
для парсера команд как минимум нужна функция парсера DEC/HEX чисел.
парсер HEX легко реализуется путем преобразования Char HEX->BIN и сдвига на 4 бита влево.
DEC - нужно дополнительное преобразование BCD->BIN (поразрядным умножением на степени 10 или сдвигом+BCD коррекцией).
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Aug 12 2009, 10:26
Сообщение #3


;
******

Группа: Участник
Сообщений: 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() и тд произвольной сложности.

Игнорирование регистра символа делаете?
Go to the top of the page
 
+Quote Post
zltigo
сообщение Aug 12 2009, 11:24
Сообщение #4


Гуру
******

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



Цитата(_Pasha @ Aug 12 2009, 13:26) *
Собираете словарь команд (ASCIIZ), например

С размахом smile.gif
Код
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
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Aug 12 2009, 11:40
Сообщение #5


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(zltigo @ Aug 12 2009, 14:24) *
Стандартная разборка на аргументы делается заранее.

Дык это разбиение на токены заранее можно сделать... а разбор аргументов команды - личное дело самой команды smile.gif Или Вы оговорились?
Go to the top of the page
 
+Quote Post
DpInRock
сообщение Aug 12 2009, 12:06
Сообщение #6


Гуру
******

Группа: Участник
Сообщений: 2 254
Регистрация: 4-05-07
Из: Moscow
Пользователь №: 27 515



Длинные команды - бессмысленное пижонство.


--------------------
On the road again (Canned Heat)
Go to the top of the page
 
+Quote Post
Goodefine
сообщение Aug 12 2009, 14:31
Сообщение #7


Местный
***

Группа: Свой
Сообщений: 211
Регистрация: 6-08-07
Из: Приднестровье, Тирасполь
Пользователь №: 29 581



Зато обеспечивают детерминированное поведение системы, при значительном потоке символов...


--------------------
Любой, заслуживающий внимания, опыт приобретается себе в убыток...
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Aug 12 2009, 15:44
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Цитата(Goodefine @ Aug 12 2009, 17:31) *
Зато обеспечивают детерминированное поведение системы, при значительном потоке символов...

Сказано мощно.
Это что, длинные команды как средство нейтрализации ошибок реализации протокола? smile.gif

Автору.
Передерите какой-нить стандартный протокол, слишком много аспектов существуют в протоколах.


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
Goodefine
сообщение Aug 12 2009, 15:50
Сообщение #9


Местный
***

Группа: Свой
Сообщений: 211
Регистрация: 6-08-07
Из: Приднестровье, Тирасполь
Пользователь №: 29 581



Цитата(Dog Pawlowa @ Aug 12 2009, 18:44) *
Это что, длинные команды как средство нейтрализации ошибок реализации протокола? smile.gif

Не совсем smile.gif
В качестве контрпримера можно рассмотреть поведение управляемого объекта, с односимвольным набором команд, на вход которого постоянно что-то приходит. Без ошибок. При прочих равных, разумеется...


--------------------
Любой, заслуживающий внимания, опыт приобретается себе в убыток...
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Aug 12 2009, 17:21
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Цитата(Goodefine @ Aug 12 2009, 18:50) *
В качестве контрпримера можно рассмотреть поведение управляемого объекта, с односимвольным набором команд, на вход которого постоянно что-то приходит. Без ошибок. При прочих равных, разумеется...

И что, как контрпример себя ведет?
Использую односимвольные наборы команд в обе стороны. Никаких проблем.
Очень удобно - в одну сторону идут коды нажатых клавиш, а в другую - коды символов, подлежащих отображению. Полный дуплекс, физический и логический. Если русский язык не нужен, коды управления дисплеем помещаются в правую сторону ASCII без проблем.
Тут главное - не пытаться придумывать что-то посредине между "простым" протоколом и "нормальным" протоколом, в результате получится зависающая хрень.


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Aug 12 2009, 17:49
Сообщение #11


фанат дивана
******

Группа: Свой
Сообщений: 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, &lt);
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", имея заодно возможность отредактировать строку при неверном вводе.
Да и не накладно это особо.
Причина редактирования: Уменьшение видимого размера цитаты исходника.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Aug 12 2009, 18:27
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Цитата(AHTOXA @ Aug 12 2009, 20:49) *
Гораздо приятнее писать "SET PARAM1=23.4"...


Если уж пошла речь о том, что приятнее, то я пришел к выводу, что лучше ПиСишное приложение, одно на все устройства, а из устройства может быть прочитано, какой физический смысл имеет PARAM1. Типа SNMP.

Хотя протокол именно текстовый - чтобы было "приятнее писать".


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Aug 12 2009, 19:06
Сообщение #13


фанат дивана
******

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



Цитата(Dog Pawlowa @ Aug 13 2009, 00:27) *
Если уж пошла речь о том, что приятнее, то я пришел к выводу, что лучше ПиСишное приложение, одно на все устройства, а из устройства может быть прочитано, какой физический смысл имеет PARAM1. Типа SNMP.


Согласен, так тоже неплохо. Но есть, как мне кажется, пара аргументов против. Первый - универсальность. Линукс/виндовз/что-то там ещё, разные версии... Ну и можно банально забыть писишную программуsmile.gif Терминалка же есть везде.
И второй аргумент - в терминале можно не только конфигурировать устройство (SET/GET), но и выполнять что-то специфическое. Например, непрерывный вывод значения АЦП до нажатия любой кнопки, дрыгание заданной ножкой с заданной частотой. Интерактив, короче. Для таких применений сложно придумать универсальную программу для ПиСи, имхо.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Aug 12 2009, 19:08
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Читал протокол Пирамида. Правда это надпротокольный уровень. Основная идея состоит в том, что терминальное (писишное) приложение прочитает инфу с любого прибора и правильно её отобразит. То есть прибор(изделие) выдаёт по спец запросу - свою структуру, список полей и их тип, а приложение универсальное. Я предпочитаю INI файлы текстовые.
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Aug 12 2009, 19:10
Сообщение #15


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(Dog Pawlowa @ Aug 12 2009, 21:27) *
из устройства может быть прочитано, какой физический смысл имеет PARAM1.

+1 Все хинты и информация о параметре (разме/знаковость/диапазон) хранятся в приборе. Пустая консоль только спрашивает номер параметра в списке.
Go to the top of the page
 
+Quote Post
Goodefine
сообщение Aug 12 2009, 19:32
Сообщение #16


Местный
***

Группа: Свой
Сообщений: 211
Регистрация: 6-08-07
Из: Приднестровье, Тирасполь
Пользователь №: 29 581



Цитата(Dog Pawlowa @ Aug 12 2009, 20:21) *
И что, как контрпример себя ведет?
Использую односимвольные наборы команд в обе стороны. Никаких проблем.
Очень удобно - в одну сторону идут коды нажатых клавиш, а в другую - коды символов, подлежащих отображению...

У Вас все просто: все что отдал - сканкод, все что принял - подлежит отображению...
Я другое имел ввиду. К примеру возьмем дисплей с управляемой внешне подсветкой. Скажем, увеличить на одну градацию - символ "h", уменьшить - "l" . Остальное - отображаем. Как тогда контроллер отреагирует на на сообщение "hello world", если не использовать детерминацию ни по длине строки, ни по времени между поступлениями символов? Если же команды будут длинными, типа "light_background_down" / "light_background_up", то лишними проверками можно себя не утруждать - шанс, что потребуется отобразить именно такую строку, минимален. В этом суть моего первого замечания...


--------------------
Любой, заслуживающий внимания, опыт приобретается себе в убыток...
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Aug 13 2009, 02:18
Сообщение #17


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Цитата(Goodefine @ Aug 12 2009, 22:32) *
В этом суть моего первого замечания...

Понятно.
Пожалуй, мы ушли далеко от обычного определения консоли.
Если устройство выдает "промпт", а человек как-то реагирует в пределах предоставленных ему возможностей, то подобные коллизии исключаются.


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Aug 13 2009, 05:02
Сообщение #18


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(zltigo @ Aug 12 2009, 14:24) *
Код
....
case 'sst ':
...
case 'psst':
....
case 'aa  ':
....

Команды - по первым четырем (для 32битника) символам.

А все-таки, если у человека тупо буфер, нету манагера кучи для построения деревьев в ОЗУ - АВР средненький, короче, - так построить интерпретатор команд не получится! smile.gif

Цитата(AHTOXA @ Aug 12 2009, 22:06) *
Ну и можно банально забыть писишную программуsmile.gif
Интерактив, короче. Для таких применений сложно придумать универсальную программу для ПиСи, имхо.

Ага, ОРС-серверы всякие не забывают, а тут-досада smile.gif
Ничего сложного в универсальной программе - все действия реализуются через регистровую модель. В одном регистре - временной интервал выборки, в другом - адрес источника, в третьем - размер данных. К терминалке это уже не будет иметь отношение - это личное дело девайса - поддержит он данную функцию или нет.


Цитата(Goodefine @ Aug 12 2009, 22:32) *
Как тогда контроллер отреагирует на на сообщение "hello world"

Это все бессмысленно без
а) строгого разделения команд без аргументов, хотя бы пробелами.
б) минимального синтаксического разбора команд с аргументами.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Aug 13 2009, 05:45
Сообщение #19


фанат дивана
******

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



Цитата(_Pasha @ Aug 13 2009, 11:02) *
Ничего сложного в универсальной программе - все действия реализуются через регистровую модель. В одном регистре - временной интервал выборки, в другом - адрес источника, в третьем - размер данных. К терминалке это уже не будет иметь отношение - это личное дело девайса - поддержит он данную функцию или нет.


ОРС-серверы - это для устройств, постоянно находящихся на связи. Тут действительно, забыть проблематичноsmile.gif Если же терминал применяется изредка, то шансы возрастают.

Цитата(_Pasha @ Aug 13 2009, 11:02) *
Ничего сложного в универсальной программе - все действия реализуются через регистровую модель. В одном регистре - временной интервал выборки, в другом - адрес источника, в третьем - размер данных. К терминалке это уже не будет иметь отношение - это личное дело девайса - поддержит он данную функцию или нет.


Как реализовать через регистровую модель мини-DOS для флеш-карточки, например?


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Aug 13 2009, 05:52
Сообщение #20


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(AHTOXA @ Aug 13 2009, 08:45) *
Как реализовать через регистровую модель мини-DOS для флеш-карточки, например?

Легко. Регистр адреса + регистр данных + регистр управления/статуса.
Остальное - епархия девайса.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Aug 13 2009, 06:00
Сообщение #21


фанат дивана
******

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



Что-то не могу себе представить... Расскажите чуть подробнее, как, например, будет реализована команда "DIR"?


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Aug 13 2009, 06:09
Сообщение #22


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(AHTOXA @ Aug 13 2009, 09:00) *
как, например, будет реализована команда "DIR"?

Тогда лучше определиться, что мы хотим - получить блочное устройство накопитель данных или девайс, общающийся посредством терминала. А команда DIR - средствами оси.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Aug 13 2009, 06:17
Сообщение #23


фанат дивана
******

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



Насколько я понял, автор темы хочет консоль управления/отладки.
Если мы реализуем блочное устройство и будем читать карточку средствами оси, то это мало поможет нам отлаживать код работы с файловой системой внутри устройства.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
mempfis_
сообщение Aug 13 2009, 06:41
Сообщение #24


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

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



Цитата(AHTOXA @ Aug 13 2009, 09:17) *
Насколько я понял, автор темы хочет консоль управления/отладки...


Именно. Мне нужна консоль в устройстве чтобы посылая определённые команды из терминала можно было изменить настройки, перепрошить устройство, считать текущие параметры и т.д. Ничего сверхумного и сверхсложного не нужно.
Может быть я даже неправильно назвал тему - скорее нужно было назвать "как отловить из потока симмволов команды длиной более 2х символов".
Но пару идей в дискуссии по тому как это сделать (ну и как собственно организовать консоль и систему команд) я уже приметел smile.gif

Все спасибо за дисскуссию. Надеюсь она не остановится и ещё прозвучит ещё много идей smile.gif

По поводу длинных команд - буквы F, E, L не так информативны как WFLASH, EFLASH, WLOCK и т.п.
Сразу видно что я хочу записать флэш, стереть её, записать лок-биты. Вобщем небольшое увеличение длины команды позволяет сразу переходить на необходимую подпрограмму обработки. Будет и самому интуитивно понятнее и система команд значительно расширяется.

Сообщение отредактировал mempfis_ - Aug 13 2009, 06:46
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Aug 13 2009, 07:02
Сообщение #25


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(AHTOXA @ Aug 13 2009, 09:17) *
Насколько я понял, автор темы хочет консоль управления/отладки.

Тогда здесь регистровая модель(у нас с Вами болтовня именно с нее началась) - никаким макаком. Но, вернемся к периодическому опросу АЦП или чего другого. Очевидно, что хотя бы период опроса может быть регулируемым.

Цитата(mempfis_ @ Aug 13 2009, 09:41) *
Именно. Мне нужна консоль ... Будет и самому интуитивно понятнее и система команд значительно расширяется.

И обязательная команда help (лучше "?")для всех приборов.
А еще страшнее - контекстная помощь, например help WFLASH или ?WFLASH - как по мне, то лучше в постфиксной форме
Код
WFLASH ?
. Объясню: "?" может рассматриваться как стандартный аргумент команды, минимум писанины. Дополнительные хинты уже зависят от принятой команды.

И еще раз скажу: просто команды - это уже обговорили. А как же быть с аргументами? wink.gif Они ж тоже переменной длины!
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Aug 13 2009, 07:23
Сообщение #26


фанат дивана
******

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



Цитата(_Pasha @ Aug 13 2009, 13:02) *
Но, вернемся к периодическому опросу АЦП или чего другого. Очевидно, что хотя бы период опроса может быть регулируемым.


Дык, какие проблемы? Аргументы (всё что после команды) передаются обработчику. Там может быть и период:
>POOLADC 0 0 20 - опросить АЦП, число опросов 0 (до нажатия кнопы), канал 0, интервал 20 мс.

Цитата(_Pasha)
И обязательная команда help (лучше "?")для всех приборов.
А еще страшнее - контекстная помощь, например help WFLASH или ?WFLASH - как по мне, то лучше в постфиксной форме
Код
WFLASH ?
.


+1, кроме постфиксной формы. Зачем делать это в каждой команде, проще централизованноsmile.gif
Типа :
Код
typedef struct
{
    char *const    command_name;    // command name
    CmdHandler    handler;            // command handler
    char *const    help_text;        // command description
}Command;

const Command CommandTable[] =
{
     {"GET",                    GetCommandHandler,    "get variable (VARS for list)"},
     {"SET",                    SetCommandHandler,    "set variable (VARS for list)"},
     {"HELP",                HelpHandler,        "display this help"},
...
};


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Aug 13 2009, 07:33
Сообщение #27


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(AHTOXA @ Aug 13 2009, 10:23) *
проще централизованноsmile.gif

Ага. Не увидел сразу.
? без параметров вываливает список команд из CommandTable[]
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Aug 13 2009, 09:30
Сообщение #28


фанат дивана
******

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



Цитата(_Pasha @ Aug 13 2009, 13:33) *
Ага. Не увидел сразу.


Ну, сразу и не было, я убрал, чтоб не загромождать идеюsmile.gif

Цитата(_Pasha @ Aug 13 2009, 13:33) *
? без параметров вываливает список команд из CommandTable[]


Ага. Плюс к этому есть такой же массив описаний переменных, с именем перемнной, ф-ями Get/Set, типом переменной границами и описанием (для хелпа). Я таскаю это хозяйство по всем проектам, очень помогает.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Aug 13 2009, 16:01
Сообщение #29


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Цитата(mempfis_ @ Aug 13 2009, 09:41) *
"как отловить из потока симмволов команды длиной более 2х символов".


Так в принципе, ничего нового не выдумано, насколько я понимаю. Всё тоже как и 30 лет назад.

1) если идёт сплошной поток, то префикс команды (Байтстафинг). Как вы уже отметили в модемах используется. Префикс AT (за малым исключением). То есть "hgjghjhati3" будет квалифицировано как команда "i3" - идентификация устройства. Префикс может быть любым, в том числе и односимвольным. Я обычно использую "Ъ". smile.gif Естественно префикс из простого потока данных изымается (заменяется на комбинацию), либо удваивается. Один из вариантов WAKE.

2) Применяется пауза (в том числе определённой длительности) перед началом команды.

3) Применяется комбинация 1 и 2.

Есть ещё битстафинг (я применял), но он неподходит для UARTа.
Go to the top of the page
 
+Quote Post
rezident
сообщение Aug 13 2009, 19:03
Сообщение #30


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



В дополнение ко всему хотел бы заметить, что конфигурирование устройства и его отладка это немного разные вещи. Конфигуратор на основе текстового меню легко делается. И совершенно без разницы куда выводится это меню: на экран устройства или в UART и соответственно откуда управляется: с клавы устройства или опять же из UART.
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Aug 14 2009, 06:54
Сообщение #31


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Цитата(rezident @ Aug 13 2009, 22:03) *
В дополнение ко всему хотел бы заметить, что конфигурирование устройства и его отладка это немного разные вещи. Конфигуратор на основе текстового меню легко делается. И совершенно без разницы куда выводится это меню: на экран устройства или в UART и соответственно откуда управляется: с клавы устройства или опять же из UART.

+1

Кроме того, я бы не вставлял в рабочую прогу отладочные режимы. Отладка предполагает свободный доступ к железу. Для рабочего режима это, на мой взгляд, недопустимо. Фактически - это даст возможность пользователю убить работоспособность изделия.

Делали один проект, и программист, который писал головную прогу (на IBM) требовал, чтобы я предоставил прямой доступ к памяти устройства (под MODBUS). Я наотрез отказался. Их мотивация - что будет всё отлажено и PC прога не будет вредить устр-ву. За то это даст более широкие возможности, в том числе и по отладке. Моя мотивация - кто будет нести ответственность за работоспособность моего железа?
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Aug 14 2009, 07:13
Сообщение #32


Беспросветный оптимист
******

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



Цитата(SasaVitebsk @ Aug 14 2009, 10:54) *
Кроме того, я бы не вставлял в рабочую прогу отладочные режимы. Отладка предполагает свободный доступ к железу. Для рабочего режима это, на мой взгляд, недопустимо. Фактически - это даст возможность пользователю убить работоспособность изделия.

Ну почему, можно запаролить критические команды. А пароль никому не давать.


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
amaora
сообщение Aug 14 2009, 17:02
Сообщение #33


Местный
***

Группа: Участник
Сообщений: 421
Регистрация: 2-01-08
Пользователь №: 33 778



Обычно использую бинарный протокол для отладки, но если надо текстовую консоль, скопировал бы схему работы с юниксовых шелл+терминал, что то лучше придумать сложно.

Код
u8 uart_read();
void uart_write(u8 val);

//...

do {
    c = uart_read();
    buff[i++];
    if (c == CR) {
        uart_write('\n');
        parse_line(buff);
        i = 0;
        continue;
    }
    if (c == BACKSPACE) {
        uart_write('\b');
        --i;
        continue;
    }
    uart_write(c);
}
while(1);


Конечно тут мало проверок, и можно удалять только последний символ, это упрощенный пример.
Go to the top of the page
 
+Quote Post
defunct
сообщение Aug 15 2009, 15:52
Сообщение #34


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата
Принцип построения консоли управления устройством

1. Байт парсер, выделяющий строки команд и управляющие символы из потока. Вызывается или непосредственно из RX INT или из обработчика "OnRead" TCP сокета.
2. Задача поиска обработчика для выделенной из потока строки. (по табличке, в точности так как привел AHTOXA).
3. Обработчик каждой команды.
4. Общий парсер параметров, который пытается интерпретировать строку параметров всеми известными ему форматами: как целое число, как float-point число, как IP addres, mac-address, дата, время, строка и т.д и т.п..
5. Ну и контекстный Help. (вызываемый в обработчике каждой команды, если команда вызвана с параметром "?" или "--help").
Go to the top of the page
 
+Quote Post
AlexMad
сообщение Aug 20 2009, 18:52
Сообщение #35


Местный
***

Группа: Свой
Сообщений: 262
Регистрация: 18-02-05
Из: SPb
Пользователь №: 2 743



Цитата(zltigo @ Aug 12 2009, 15:24) *
С размахом smile.gif
Код
int command( struct Cmd *cmd )
{
//---------------------------------------------------------------------------
case 'sst ':
...
        break;

Команды - по первым четырем (для 32битника) символам. Стандартная разборка на аргументы делается заранее.

А не трудно показать начало ветвления (switch). Что за тип Вы ему даете? У меня как-то не срабатывает подобное, хотя пытался такое изобразить не раз. Компилятор варнингует, что нельзя сравнивать мультичарестерный чар (multi-character character constant).

И везде встречал побайтный анализ, что приводит к огромным ветвлениям switch/case.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Aug 20 2009, 19:23
Сообщение #36


Гуру
******

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



Цитата(AlexMad @ Aug 20 2009, 20:52) *
А не трудно показать начало ветвления (switch). Что за тип Вы ему даете?

Код
struct Cmd{                 // Command
unsigned long cmdcode;
.......
};

    switch( cmd->cmdcode )
    {

.....

Цитата
У меня как-то не срабатывает подобное, хотя пытался такое изобразить не раз. Компилятор варнингует, что нельзя сравнивать мультичарестерный чар (multi-character character constant).

Естественно, что это исходник, как уже писал, для 32bit. Для 16bit, соответственно только пара символов, ну а с 8bit sad.gif smile.gif
Если какой-то компилятор warning, выдает, что бывает - надо отключить для этого куска через #pragma
Предупреждать он, конечно, может, но работать, как приказано, обязан.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
C.S.
сообщение Aug 25 2009, 11:56
Сообщение #37


Участник
*

Группа: Участник
Сообщений: 52
Регистрация: 6-05-09
Из: Москва
Пользователь №: 48 733



Цитата(mempfis_ @ Aug 12 2009, 12:43) *
Сейчас реализована входная FIFO-UART которая заполняется в прерываниях и функция считывания символа из FIFO которая возвращает -1 если нет данных или принятый символ. Одиночные символы отлавливать легко (считал - обработал), два - уже сложнее но пока реализую устанавливая флаги.
Как отловить три и более символа - вот тут нужны идеи smile.gif


А расскажите пожалуйста теорию про FIFO (я на асме пишу под Мегу8). Не понимаю самого принципа.
Форма команд моему девайсу: <префикс начала><команда> [<параметры>]<CRLF>
Выделил какой-то буфер, думаю тупо заполнять его поступающими данными из UART, инкрементируя указатель... и не могу сообразить, с какого момента начать его обрабатывать?
Вижу варианты:
1. Буфер переполнен - выдаём ошибку
2. Нашли CRLF - парсим буфер, обрабатываем команду
3. Какой-то тайм-аут передачи - буфер отбасывается, ошибка
4. Неверная команда - выдаём ошибку.
Обрабатывать думаю - искать старт команды в буфере (три байта), и написать что-то типа strcmp.

Мыслю верно? Смущает, как определить то, что передача данных закончилась...

Если кому интересно, нашёл "для тупых" тут статейку. Идеи разжёваны идаже примеры есть http://www.atmel.ru/Articles/Atmel12.htm
Причина редактирования: Излишнее цитирование.
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Aug 25 2009, 12:08
Сообщение #38


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(C.S. @ Aug 25 2009, 14:56) *
Смущает, как определить то, что передача данных закончилась...

<префикс начала><команда> [<параметры>]<CRLF>
<CRLF> - как раз передача данных закончилась. Про таймаут Вы уже говорили...

<префикс начала> - если будете обрабатывать в прерывании, FIFO Вам не нужен будет совсем.
Go to the top of the page
 
+Quote Post
C.S.
сообщение Aug 25 2009, 12:25
Сообщение #39


Участник
*

Группа: Участник
Сообщений: 52
Регистрация: 6-05-09
Из: Москва
Пользователь №: 48 733



2_Pasha Кхм, я путаюсь уровнем ниже. Как принимаемое пихать в буфер и что делать, если будут слать следующую команду,пока обрабатывается текущая. Думаю отключать UART на приём(?).
То-есть есть отдельно принималка строки и есть отдельно парсер. Вот с принималкой строки затыки следующие:
0. Есть область памяти и счётчик адреса = буфер. Так?
1.1. По прерыванию пихаем байт, инкрементируем счётчик, проверяем переполнение счётчика, выдаём ошибки, если надо (переполнен буфер).
1.2. После принятия очередного байта проверяем два последних на CRLF. Если равны = отключаем приём, передаём буфер парсеру.
2. Парсер уже сам разбирается - команда/ошибка, выдаёт ответ или выполняет её, в конце разрешая приём.

Есть ли тут какие-то подводные камни? Первый вижу сам - пока обрабатываем что-то, теряем посылаемое в этот момент. Это я закладываю в протокол: если не пришёл ответ от команды, повторить посылку.

И ещё непонятно с таймаутом - как его посчитать? Выходит что-то типа ватчдога? Или вообще не делать, а просто ждать CRLF?

Видел модуль, там типа терминала через RS-232 написано, так, вроде там таймаута нет никакого. Просто строка кончается CRLF.
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Aug 25 2009, 12:58
Сообщение #40


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(C.S. @ Aug 25 2009, 15:25) *
Первый вижу сам - пока обрабатываем что-то, теряем посылаемое в этот момент. Это я закладываю в протокол: если не пришёл ответ от команды, повторить посылку.

Тогда FIFO (пардон за Си):
Код
volatile char buffer[BUFSIZE];
volatile unsigned char pos_rd, pos_wr;

// прерывание UART
{
char tmp=UDR;
buffer[pos_wr++] = tmp;
if(pos_wr >= BUFSIZE ) pos_wr = 0;
}

// опр числа принятых символов
// условие кгда нет символов одно  - это pos_wr == pos_rd
unsigned char sym_pending(void)
{
return (pos_wr >= pos_rd) ? (pos_wr - pos_rd) : ( pos_wr + BUFSIZE - pos_rd);
}
// чтение из буфера
char sym_read(void)
{
char tmp = buffer[pos_rd++];
if(pos_rd >= BUFSIZE) pos_rd = 0;
return tmp;
}


Цитата
И ещё непонятно с таймаутом - как его посчитать? Выходит что-то типа ватчдога?

Для начала определитесь, для чего именно Вам таймаут. Он может быть как на время между принятыми командами, так и на время между символами.
ЗЫ для определения переполнения буфера можно параллельно ввести счетчик принятых байт. При чтении - декрементировать его.
Go to the top of the page
 
+Quote Post
C.S.
сообщение Aug 25 2009, 13:02
Сообщение #41


Участник
*

Группа: Участник
Сообщений: 52
Регистрация: 6-05-09
Из: Москва
Пользователь №: 48 733



На время между символами. Наверное, может и не нужен. Заложу - если команда не выполнилась - послать CRLF (очистка буфера) и повторить команду.
А sym_pending у Вас как вызывается? Где-то в цикле или по таймеру?
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Aug 25 2009, 13:03
Сообщение #42


фанат дивана
******

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



Цитата(C.S. @ Aug 25 2009, 18:25) *
Как принимаемое пихать в буфер и что делать, если будут слать следующую команду,пока обрабатывается текущая. Думаю отключать UART на приём(?).


Во-первых, кто это будет так плохо себя вести? smile.gif Во-вторых, если такое всё же возможно, можно сделать два буфера на приём (и соответственно два счётчика), один принимается (в прерывании), другой обрабатывается (парсером). И флажок, номер_готового_буфера (0/1).
Цитата
И ещё непонятно с таймаутом - как его посчитать? Выходит что-то типа ватчдога?

На да. При каждом принятом символе некий счётчик устанавливается в заданное значение, а в прерывании таймера - декрементируется. Как стал нулём, так тогось, тайм-аут. Только вот что делать по тайм-ауту?
Цитата
Или вообще не делать, а просто ждать CRLF?

Да, так гораздо проще. Единственно, когда тайм-аут нужен, это в том случае, если при входе в консоль устройство перестаёт работать в штатном режиме. Тогда его минут через пять после ухода забывчивого наладчика таки желательно вернуть в рабочее состояниеsmile.gif
Цитата
Видел модуль, там типа терминала через RS-232 написано, так, вроде там таймаута нет никакого. Просто строка кончается CRLF.
И это правильно. Вдруг человек просто задумался? smile.gif


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Aug 25 2009, 13:17
Сообщение #43


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(C.S. @ Aug 25 2009, 16:02) *
А sym_pending у Вас как вызывается? Где-то в цикле или по таймеру?

Конечно, где-то в основном процессе. Вначале узнаем, сколько символов принято, а потом можем еще и покапризничать smile.gif - надо обрабатывать или нет. Может, есть другие более важные задачи.
Затем - читаем посимвольно. Разворачиваем это все в другой буфер (к сожалению). и парсим от замеченного начала и до замеченного ВКПС.
ЗЫ FIFO_flush делается как присвоение pos_wr = pos_rd. позаботившись об атомарности . Если надо, конечно.
Go to the top of the page
 
+Quote Post
C.S.
сообщение Aug 25 2009, 13:26
Сообщение #44


Участник
*

Группа: Участник
Сообщений: 52
Регистрация: 6-05-09
Из: Москва
Пользователь №: 48 733



Цитата
Разворачиваем это все в другой буфер (к сожалению). и парсим от замеченного начала и до замеченного ВКПС

Аааа! А я-то хотел обрабатывать в том же, куда принял. Тогда можно рыбу накатать и проверить.

По таймауту - чистить буфер. Не успели передать строку целиком - значит пришёл мусор. Оставлю как опцию.

Насчёт плохо себя ведущих - вообще, потом думаю о каком-то протоколе, где несколько мастеров и несколько подчинённых. Хотел, чтобы они слали друг другу инфу в формате АдресПолучателя АдресОтправителя Инфа. Выходит, что сама магистраль может быть забита чем угодно, и в этом случае просто будет несколько попыток достучаться до девайса (передаёт и принимает всегда одна пара).
Но это пока задумки и вопросы для другой темы. Мне б пока с компютера научиться управлять и команды парсить...
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Aug 25 2009, 13:36
Сообщение #45


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(C.S. @ Aug 25 2009, 16:26) *
Аааа! А я-то хотел обрабатывать в том же, куда принял.

FIFO ведь не самоцель, а средство разгрузки основного процесса от тяжелых прерываний. Оно может быть каких-нить компромиссных размеров, скажем, 8 байт. Учитывая двойную буферизацию UDR, может хватить.
Да и приемный буфер может быть динамическим.
А если "рыбу накатать" - у Вас будет эдакий бегемот в ОЗУ сидеть статически, чтоб не прозевать команду, да еще и там же ее парсить... не думаю, что сие полезно.
ЗЫ: это ж ответ от девайса пойдет только после приема команды? Тогда у Вас большой буфер для работы на RX/TX и ФИФО на прием.
Go to the top of the page
 
+Quote Post
C.S.
сообщение Aug 25 2009, 13:54
Сообщение #46


Участник
*

Группа: Участник
Сообщений: 52
Регистрация: 6-05-09
Из: Москва
Пользователь №: 48 733



Цитата
это ж ответ от девайса пойдет только после приема команды? Тогда у Вас большой буфер для работы на RX/TX и ФИФО на прием

Эммм... А как иначе (про ответ)? Если я девайсу шлю например команду SETBR 1,100 - вот он её должен распарсить, выполнить и ответить OK? Так ведь и выходит - причём, обработка, ответ? Я по 32 байта выделил на буферы...
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Aug 25 2009, 14:03
Сообщение #47


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(C.S. @ Aug 25 2009, 16:54) *
Так ведь и выходит - причём, обработка, ответ? Я по 32 байта выделил на буферы...

Тогда нафига Вам второй буфер ? Если, конечно, во время ответа хост не пошлет еще чего-нить.
Go to the top of the page
 
+Quote Post
C.S.
сообщение Aug 25 2009, 14:17
Сообщение #48


Участник
*

Группа: Участник
Сообщений: 52
Регистрация: 6-05-09
Из: Москва
Пользователь №: 48 733



Так а если надо будет вернуть чего-то более разумное в ответ, нежели ОК? Тогдабудет ОК <данные>
Вот и думал(ю) сделать буфер на отправку: забиваем его всем, чем надо, вызываем подпрограмму, которая по прерываниям его автономно отсылает.
Можно, конечно и так: отослать ОК, отослать пробел, отослать данные - но логическая целостность как-то теряется.
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Aug 25 2009, 14:36
Сообщение #49


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(C.S. @ Aug 25 2009, 17:17) *
Так а если надо будет вернуть чего-то более разумное в ответ, нежели ОК? Тогдабудет ОК <данные>

1. Принимаем команду в буфер
2. Парсим ее в буфере
3. Все аргументы - преобразуются и хранятся в локальных переменных.
4. Выполняются действия с полученным набором аргументов.
5. Ответ отправляется в тот же буфер. Ставится счетчик TxCNT = длине отправляемой строки
6. Разрешаем UDRE. (в нем отправляем и как только TxCNT ==0 запрещаем прерывание)
7. Ждем пока UDRE не станет ==0
За это время FIFO - если может заполниться - то оставьте его 32 байта, если низзя принимать команду - оставляйте меньше. Если новая команда не может поступить ранее, чем отдан ответ, этот факт фиксируется с помощью переполнения ФИФО, и далее - ответ, типа "?"
Go to the top of the page
 
+Quote Post
C.S.
сообщение Aug 25 2009, 15:18
Сообщение #50


Участник
*

Группа: Участник
Сообщений: 52
Регистрация: 6-05-09
Из: Москва
Пользователь №: 48 733



Понял. Идиот. Спасибо большое!
Go to the top of the page
 
+Quote Post
C.S.
сообщение Aug 27 2009, 09:33
Сообщение #51


Участник
*

Группа: Участник
Сообщений: 52
Регистрация: 6-05-09
Из: Москва
Пользователь №: 48 733



Парсинг команд сделал. Использовал побайтовое сравненпие буфера в цикле, одновременно считая побайтово команду из памяти программ. Команды закодировал так:
Код
UARTCmdListTable:
.DB    8,    /*ОБЩЕЕ ЧИСЛО КОМАНД в ШТУКАХ!*/    \
    2,    "UP",        /*01: Кнопка "Вверх"*/        \
    3,    "DWN",        /*02: Кнопка "Вниз"*/    \
    4,    "LAMP",        /*03: Кнопка "Вкл-Выкл" (ON|OFF)*/    \

Соответственно - считаем числа, грузим в счётчики - и циклом крутимся. Нашли - из таблицы
Код
UARTCmdProcTable:
.DW    UARTCommand_UP;01
.DW    UARTCommand_DWN;02
.DW    UARTCommand_LAMP;03

выбираем нужный адрес и ICALL. Работает. Получилось, видимо,также как на СИ с массивом. Команда получает позицию её аргументов в буфере и делает с ними что хочет.

Сообщение отредактировал C.S. - Aug 27 2009, 09:34
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Aug 27 2009, 14:19
Сообщение #52


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(C.S. @ Aug 27 2009, 12:33) *
Команды закодировал так:


По идее, ОБЩЕЕ ЧИСЛО КОМАНД в ШТУКАХ! можно определить директивой equ.
Во-вторых, в своем первом посте (на который zltigo сказал "с размахом") я не договорил, что если имеется ситуация, когда для нескольких команд есть одинаковый набор аргументов (одинаковое кол-во и тип и даже диапазон иногда) - то зачем плодить сущности, можно сам парсинг утрясти/утоптать. Т.е аргументы уже будут считаны, преобразованы и уложены куда надо, а потом по индексу - вызываем нужную функцию. Разумеется, это не принципиально, так, не более, чем свое имхо.
Go to the top of the page
 
+Quote Post
C.S.
сообщение Aug 27 2009, 14:45
Сообщение #53


Участник
*

Группа: Участник
Сообщений: 52
Регистрация: 6-05-09
Из: Москва
Пользователь №: 48 733



Хм, попробую и так. Просто делить их по запятой. А насчёт EQU - стиля кода придерживаюсь, тут специально исключение сделано: вся запись - одна строка вида <Всего><Длина1><Текст1><Длина2><Текст2>...
Гоняю сейчас прогу (на ВБ быстро написал), или по терминалу - распознаёт, даже HELP выводит %)
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 22nd July 2025 - 01:18
Рейтинг@Mail.ru


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