Настройки последовательного порта
В этом разделе кратко описан набор настраиваемых параметров последовательного порта (основной объём сведений о буферах RX и TX сюда не входит, он описан здесь).
Открытие и закрытие последовательного порта
Свойство ser.enabled определяет, открыт порт или закрыт. По умолчанию порт закрыт, поэтому его нужно открыть явно. Закрытый последовательный порт не принимает и не передаёт данные, но доступ к его буферам RX и TX остаётся и в этот момент.
Переназначение линий последовательного порта
В зависимости от платформы переназначать выходную линию RTS/W0out/cout и входную линию CTS/W0&1in/cin (то есть выбирать, на каких выводах ввода-вывода устройства они находятся) может быть разрешено или нет. Подробнее см. документацию по платформе вашего устройства (например, для EM1000 она находится здесь). Если устройство поддерживает переназначение, нужное соответствие выбирается свойствами ser.ctsmap и ser.rtsmap. Если устройство не поддерживает переназначение, этих свойств на его платформе нет. Переназначать линии можно только при закрытом последовательном порте.
Выбор режима UART, Wiegand или Clock/Data
Свойство ser.mode выбирает для последовательного порта режим UART, Wiegand или clock/data. Сменить режим можно только при закрытом последовательном порте.
Как фиксируются входящие данные
Важно понять концепцию «фиксации данных RX». Вы уже знаете, что последовательный порт записывает все входящие данные в буфер приёма (RX). Новое здесь то, что записанные в буфер данные не сразу «сообщаются» вашему приложению. Пока не выполнены определённые условия, они остаются «незафиксированными». Незафиксированные данные для приложения фактически невидимы, как будто их нет вовсе.
В режиме UART данные фиксируются, когда общий объём незафиксированных и зафиксированных данных в буфере приёма (RX) превышает половину ёмкости буфера или когда превышена межсимвольная пауза, заданная свойством ser.interchardelay. В режимах Wiegand и clock/data первое условие не отслеживается, поэтому данные может зафиксировать только межсимвольная пауза.
Межсимвольная пауза - это время, прошедшее с начала приёма последнего символа UART в режиме UART или с последнего заднего фронта на линии W0&1in/cin в режимах Wiegand и clock/data. Идея в том, что когда данные перестают поступать, последовательный порт начинает отсчитывать задержку. Как только задержка превышает время, заданное свойством ser.interchardelay, данные фиксируются и становятся видимыми для приложения.
Другое свойство, ser.autoclose, определяет, будет ли порт закрыт (ser.enabled = NO), когда межсимвольная пауза достигнет значения ser.interchardelay.
В режиме UART межсимвольная задержка позволяет приложению обрабатывать данные эффективнее. Пока данные остаются невидимыми, последовательный порт может накопить большой блок данных, который приложение обработает за один раз. Представьте, что данные поступают в порт символ за символом, и приложению тоже приходится обрабатывать этот поток символ за символом. Накладные расходы могут оказаться значительными, а общая производительность приложения - сильно упасть! Если же входящие данные объединяются в порции приличного размера, приложению не придётся обрабатывать их мелкими кусками, и производительность вырастет. Конечно, здесь нужен баланс: попытка объединять данные в слишком большие блоки может снизить отзывчивость приложения, и программа будет казаться вялой.
Учтите, что межсимвольная пауза не отсчитывается, когда новые данные не поступают, потому что последовательный порт установил на линии RTS уровень LOW (не готов). Так может быть при включённом управлении потоком (подробнее об управлении потоком ниже).
В режимах Wiegand и clock/data межсимвольная задержка - это способ обнаружить конец входящего потока данных. Рекомендуется задавать паузу примерно в 10 раз больше интервала между данными. Например, если данные Wiegand приходят со скоростью 1 бит за 20ms, задайте задержку 200ms, и она будет надёжным признаком конца передачи. Здесь пригодится ser.autoclose: как только пауза обнаружена, порт будет закрыт, и это не позволит следующей передаче Wiegand попасть в буфер приёма (RX), пока приложение не обработало предыдущую.
Как фиксируются исходящие данные
Для исходящих данных используется похожая концепция «фиксации данных», как и для входящих. Цель - иметь возможность зафиксировать данные для отправки один раз, даже если они подготавливались бит за битом. Так приложение может избежать отправки данных мелкими кусками. Подробнее об этом - в разделе Состояние памяти буфера.
Настройки режима UART
Ряд настроек относится только к режиму UART. У последовательного порта есть все обычные параметры связи UART: скорость (бод), чётность, 7/8 бит. Свойства для выбора числа стоп-бит нет. Второй стоп-бит можно эмулировать, задав ser.parity = 3 - PL_SER_PR_MARK.
Свойство ser.baudrate на самом деле хранит значение делителя. Можно задать любую скорость, указав правильный делитель. Есть даже свойство ser.div9600 (только чтение), позволяющее вычислить значение делителя независимо от платформы: оно возвращает делитель, необходимый (для текущей платформы) для достижения 9,600bps.
Фактическая скорость вычисляется так: baudrate = (9600 * ser.div9600) / ser.baudrate. Например, если нужно получить 38,400bps, а ser.div9600 возвращает 12, то нужно задать ser.baudrate = 3, потому что (9,600 * 12) / 38,400 = 3. Это платформонезависимый расчёт скорости, так как ser.div9600 возвращает разные значения для разных платформ.
Например:
function set_baud(baud as integer) as integer
'baud: 0- 1200, 1-2400, 2-4800, 3- 9600, 4-19200, other-38400
select case baud
case 0: ser.baudrate=ser.div9600*8 '9600/1200=8
case 1: ser.baudrate=ser.div9600*4 '9600/2400=4
case 2: ser.baudrate=ser.div9600*2 '9600/4800=2
case 3: ser.baudrate=ser.div9600 '9600/9600=1
case 4: ser.baudrate=ser.div9600/2 '19200/9600=2
case else: ser.baudrate=ser.div9600/4 '38400/9600=4
end function
На LTPP3 свойства ser.baudrate и ser.div9600 заменены свойством ser.baud.
Последовательный порт может работать в полнодуплексном или полудуплексном режиме, что определяется свойством ser.interface (подробнее см. Режим UART). В полнодуплексном режиме порт может при необходимости использовать управление потоком. В полудуплексном режиме можно выбрать полярность сигнала управления направлением.
Escape-последовательности
В режиме UART последовательный порт может распознавать так называемые «escape-последовательности», которые задаются свойствами ser.esctype и ser.escchar. Когда такая последовательность распознана, генерируется специальное событие (on_ser_esc), а порт отключается. Разумеется, того же можно добиться программно, но тогда пришлось бы разбирать все входящие данные, что сильно замедлило бы работу. Escape-последовательности реализованы с расчётом на эффективность и скорость.
Escape-последовательности довольно произвольны. Они соответствуют стилю escape-последовательностей, который Tibbo применяла раньше. Тем не менее они полезны для некоторых задач. Например, если у приложения есть обычный режим и последовательный режим «настройки», с помощью такой последовательности можно переключиться в режим настройки.
Escape-последовательности работают, даже если используется замыкание буферов, и это делает их особенно мощными. Если вы создаёте устройство, которое просто передаёт данные между последовательным интерфейсом и интерфейсом Ethernet, для производительности вы будете использовать замыкание буферов, но всё равно сможете обнаруживать escape-последовательности, чтобы переключиться в режим последовательного программирования или выполнить другую подобную задачу.