Интерфейсы ASCII некрасивы по определению. В идеале у вас есть какая-то структура фрейма, которая, возможно, у вас есть, $ указывает на разделение между фреймами, и вы говорите, что они имеют длину 11 символов. Если всегда 11, то это хорошо, если только иногда это сложнее, мы надеемся, что $ в начале и 0x0A и или 0x0D / 0x0A в конце (CR / LF). Обычно у меня есть один модуль кода, который просто извлекает байты из последовательного порта и помещает их в (циклический) буфер. Буферизация датируется тем временем, когда последовательные порты практически не имели буфера на борту, но даже сегодня, особенно с микроконтроллерами, это все еще так. Затем еще один модуль кода, который следит за буфером поиска кадров. В идеале этот буфер должен быть достаточно большим, чтобы оставить там кадр и иметь место для следующего кадра, и не требовать другого буфера для хранения копий полученных кадров. используя циклический буфер, этот второй модуль может перемещать (при необходимости, отбрасывая) указатель заголовка на маркер начала кадра и ожидает полного объема данных. Как только появляется полный кадр, он вызывает другую функцию, которая обрабатывает этот кадр. Эта функция может быть той, о которой вы спрашиваете. И «просто закодируй это» может быть ответом, ты в микроконтроллере, поэтому ты не можешь использовать ленивое высокоуровневое настольное приложение в решениях операционной системы. Вам понадобится какая-то функция strcmp, если она была создана вами или доступна вам через библиотеку, или не зависит от вашего решения. Грубая сила if (strncmp (& frame [1], "bob", 3) == 0) тогда, иначе if (strncmp (& frame [1], "ted", 3) тогда, иначе if ... Конечно работает, но вы можете жевать свой диск такими вещами, или нет. И буферизация, необходимая для такого подхода, может сжечь много оперативной памяти. Этот подход очень читабелен и удобен в обслуживании, хотя и переносим. Может не быть быстрым (поддерживаемым) обычно конфликтует с надежностью и / или производительностью), но это может не беспокоить, если только вы можете обработать его до того, как появится следующий, или до того, как необработанные данные выпадут из циклического буфера. В зависимости от задачи подпрограмма проверки кадра может просто проверить, что кадр хорош, я обычно ставлю начальные и конечные маркеры, длину и некоторую арифметическую контрольную сумму, и если это плохой кадр, он отбрасывается, это экономит много кода, проверяя на плохой / поврежденный данные. Когда подпрограмма обработки кадра возвращается к поиску подпрограммы кадра, она перемещает указатель заголовка, чтобы очистить кадр, поскольку он больше не n хороший, хороший кадр или плохой. Средство проверки кадров может только проверить кадр и передать его еще одной функции, которая выполняет синтаксический анализ. Каждый блок lego в этом расположении имеет очень простую задачу и работает в предположении, что блок lego под ним выполнил свою задачу должным образом. Модульный, объектно-ориентированный, любой термин, который вы хотите использовать, значительно упрощает проектирование, кодирование, обслуживание, отладку. (за счет производительности и ресурсов). Этот подход хорошо работает для любого потока последовательного типа, будь то последовательный порт в микроконтроллере (с достаточным количеством ресурсов), а также для приложений на настольном компьютере, которые просматривают последовательные данные из последовательного порта или данные TCP, которые также являются последовательными и НЕ ориентированы на фреймы.
если у вашего микроресурса нет ресурсов для всего этого, то подход конечного автомата также работает довольно хорошо.Каждый поступающий байт помечает конечный автомат одним состоянием.Начните с ожидания в ожидании первого байта, является ли первый байт $?не выбрасывай его и возвращайся в режим ожидания.если первый байт равен $, тогда переходите к следующему состоянию.Если вы ищете, скажем, команды «and», «add», «or» и «xor», то второе состояние будет сравниваться с «a», «o» и «x», если ни одна из них тогдаидти на холостыеесли a, то перейдите в состояние, которое сравнивается для n и d, если a o, то перейдите в состояние, которое ищет r.Если поиск r in или состояния не видит r, то перейдите в режим ожидания, если это произойдет, обработайте команду и затем перейдите в режим ожидания.Код читабелен в том смысле, что вы можете посмотреть на конечный автомат и увидеть слова a, n, d, a, d, d, o, r, x, o, r, и куда они в конечном итоге ведут, но обычноне считается читаемым кодом.Этот подход использует очень мало оперативной памяти, немного больше опирается на ROM, но в целом может использовать наименьшее количество ROM по сравнению с другими подходами синтаксического анализа.И здесь снова очень переносимо, за пределами микроконтроллеров, но за пределами микроконтроллеров люди могут подумать, что вы безумны с этим видом кода (ну, конечно, если это не verilog или vhdl).Этот подход сложнее поддерживать, труднее читать, но он очень быстрый и надежный и использует наименьшее количество ресурсов.
Чтобы понять, какой подход после интерпретации команды, вы должны убедиться, что вы можете выполнить команду безпотеря любых байтов на последовательном порту, либо из-за детерминированной производительности кода, либо из-за прерываний, либо из-за чего-либо.работа легче, получающиеся инструкции выполняются, уродливы.И один размер не подходит никому по определению.Просто запустите кодирование, попробуйте конечный автомат и попробуйте if-then-else-strncmp и оптимизацию между ними.Вы должны быстро увидеть, какой из них лучше всего подходит как для вашего стиля кодирования, так и для инструментов / процессора и решаемой проблемы.