прочитать последнюю строку последовательного порта - PullRequest
0 голосов
/ 01 марта 2019

Я никогда не писал ни одного кода на tcl и довольно новичок в области последовательной связи, поэтому заранее извините, если мой вопрос не имеет смысла.

Я пытаюсь решить эту проблему , где я хочу слушать последовательный порт и построчно печатать обновления в SciLab, как обычный последовательный терминал (например, последовательный монитор Arduino).В Serial Communication Toolbox для Scilab есть макрос readserial (источник на GitHub ):

function buf=readserial(h,n)
   if ~exists("n","local") then
     N=serialstatus(h); n=N(1)
   end
   TCL_EvalStr("binary scan [read "+h+" "+string(n)+"] cu* ttybuf")
   buf=ascii(evstr(TCL_GetVar("ttybuf")));
endfunction

, где TCL_EvalStr интерпретирует строку в tcl.Итак, мой вопрос заключается в том, как мне изменить строку:

binary scan [read "+h+" "+string(n)+"] cu* ttybuf

, чтобы она возвращала только последнюю непустую строку на последовательном порту?Я также был бы признателен, если бы вы могли eli5, что эта линия делает?

PS1. Так далеко от здесь Я пытался:

 TCL_EvalStr("binary scan [lindex [split [read -nonewline "+h+" "+string(n)+"] "\n"] end] cu* ttybuf")

ноЯ получаю сообщение об ошибке:

Ошибка: синтаксическая ошибка, неожиданная строка, ожидание "," или)

В SciLab.

PS2. Определение новой функции:

function buf=readlnserial(h)
   TCL_EvalStr("binary scan [lindex [split [read -nonewline "+h+"] \"\n\"] end] cu* ttybuf")
   buf=ascii(evstr(TCL_GetVar("ttybuf")));
endfunction

приводит к сообщению об ошибке:

Неопределенная операция для заданных операндов.

проверка или определение функции% c_l_s для перегрузки.

В терминале SciLab.

PS3. Команды:

TCL_EvalStr('[split [read -nonewline '+h+'] "\n"]')

или

TCL_EvalStr("[split [read -nonewline "+h+"] '\n']")

оба приводят к ошибке:

Ошибка: обнаружена неоднородная строка, начинающаяся с 'и заканчивающаяся ".

В SciLab.

PS4. Я думаю, что если я буду использовать команду SciLab TCL_EvalFile вместо TCL_EvalStr, я смогу решить вышеуказанную проблему. Мне просто нужно выяснить, как передать h в сценарий tcl и прочитать обратно ttybuf.

PS5. Я смог разрешить безумный конфликт между строкой SciLab и "\n", используя фигурные скобки вместо двойных кавычек:

 TCL_EvalStr("binary scan [lindex [split [read -nonewline "+h+"] {\n}] end] cu* ttybuf")

однако он все еще не дает того, что я ищу.

PS6. Для тех, кто попал сюда из-за разнородных строк с двойными или двойными кавычками, правильный синтаксис будет 'this '"string'" is inside quotation'.Обычно одинарные кавычки перед другими одинарными или двойными кавычками превращают их в буквальные символы.

1 Ответ

0 голосов
/ 01 марта 2019

Во-первых, давайте закончим разбирать строку:

binary scan [read "+h+" "+string(n)+"] cu* ttybuf

Это действительно так:

binary scan [read CHANNEL NUM_BYTES] cu* ttybuf

где CHANNEL - это действительно название канала Tcl, которым вы являетесьчтение из (которое, вероятно, должно быть в двоичном режиме, но это выходит за рамки кода, который вы показываете), а NUM_BYTES - это количество байтов, которые нужно прочитать.Затем это обрабатывается в список чисел (записанных в переменную Tcl ttybuf), которые являются беззнаковыми байтами, которые были прочитаны.


Теперь вы хотите использовать линейно-ориентированное чтение.Ну, команда Tcl read этого не делает (это либо с фиксированным буфером, либо с ориентацией на весь файл);вам нужно gets для линейно-ориентированного чтения.(При чтении из последовательной строки вы никогда не захотите обработки, ориентированной на весь файл; она никогда не достигнет EOF. Вы можете выполнить хитрость с неблокирующим чтением ... но это довольно сложно.)

Команда gets вернетследующая строка, считанная из канала, с удаленным маркером конца строки.Мы все еще можем использовать его с бинарными каналами (это немного странно, но не невозможно), так что это означает, что мы можем затем сделать:

binary scan [gets CHANNEL] cu* ttybuf

Преобразование этого обратно через всю эту оболочку 'Вы получили:

function buf=readserialline(h)
   TCL_EvalStr("binary scan [gets "+h+"] cu* ttybuf")
   buf=ascii(evstr(TCL_GetVar("ttybuf")));
endfunction

Я переименовал его, и я удалил все манипуляции с n;линии являются строками и не имеют фиксированной длины.(Интересно, сможем ли мы получить строку напрямую, без преобразования через список байтов; это было бы немного более эффективно. Но это вторично по отношению к тому, чтобы это работало вообще.)

...