LINUX.ORG.RU

Управлять прибором через LPT/COM порт


0

0

Хочется посылать комманды типа "выставить +1 на таком-то пине" драйверу порта из программы. Нужно, собственно, четыре пина, которыми можно управлять.

Библиотека parpin это делает, но требует root привелегий, поскольку использует inb/outb.

Можно ли делать подобное не-suid-программой с помощью соответствующих ioctl? В идеале хотелось бы через последовательный порт....

Заранее спасибо,

Ростислав

anonymous

вообще это называется написать драйвер....

anonymous
()

Инфа по последовательному порту.
WARNING: linux only.

Имеются следующие ioctls:
- ioctl(fd, TIOCMGET, &stat): получить биты состояния в stat
- ioctl(fd, TIOCMBIS, &ctl): установить биты управления, указанные в ctl
- ioctl(fd, TIOCMBIC, &ctl): сбросить биты управления, указанные в ctl
- ioctl(fd, TIOCMSET, &ctl): заменить регистр управления содержимым ctl

Биты управления:
- TIOCM_RTS
- TIOCM_DTR
- TIOCM_OUT1
- TIOCM_OUT2
- TIOCM_LOOP

Биты состояния:
- TIOCM_CTS
- TIOCM_DSR
- TIOCM_CAR
- TIOCM_RNG

Исходник для посмотреть:
- /usr/src/linux/drivers/char/serial.c

Заголовки для включения в программу:
- sys/ioctl.h
- linux/termios.h

ЗЫ: не ручаюсь, что для изменения регистра управления нужно передавать &ctl, а не ctl. Погляди в исходнике для уверенности.

ЗЗЫ: TIOCM_LOOP появился только в linux-2.3.x (в 2.2.x эта константа не определена).

nobody ★★
()

2nobody:

Спасибо.

Спаял тестер на светодиодах, поигрался, спеки почитал...

Видимо, ловить можно только три сигнала -- TD, DTR и RTS (больше оно не умеет...) Два последних легко перещёлкиваются. Можно ли TD в такой же режим загнать?

А что делают TIOCM_OUT1,TIOCM_OUT2, TIOCM_LOOP?

Это просто ради любопытства. Уже ясно, что сигналов не хватает. Придётся на LPT делать. А где про его ёктлы почтиать?

Ростислав

anonymous
()

в исходниках ядра конечно

grustnoe ★★
()

Так у тебя только в одну сторону данные? Тогда все проще.

char data = 0x55; //тут твои данные для записи
int fd = open("/dev/lp0", O_WRONLY);
write(fd, &data, 1);

Это самый простой и гарантированно рабочий способ для любой UNIX-like платформы. Но есть нюанс: на своем девайсе тебе нужно корректно повесить сигналы состояния принтера -- некоторые на землю, некоторые на +5В. Иначе ядро станет говорить, что "принтер" твой is busy, is out of paper и прочую чушь ("печатать" оно при этом не будет).

Можно вместо /dev/lp0 использовать /dev/parport0. В этом случае ядро не проверяет состояние принтера, просто выводит твои байты на пины данных. Но тут тоже вроде были какие-то (чисто программные) нюансы. Почитай доку на модуль ядра (в каталоге /usr/src/linux/Documentation).

ЗЫ: про сигналы OUT1, OUT2 и LOOP почитай в каком-нибудь описалове асинхронного последовательного порта. Лично мне сейчас лень лезть за книгой на антресоли (потому как спать уже хочется ужасно). Если сам не найдешь, я завтра слазю и тебе опишу. Насчет "загнать TD в такой же режим" -- не получится. Порт-то асинхронный, протокол у него NRZ.

ЗЗЫ: имей в виду, параллельный порт таким способом попалить -- как нефиг делать. Лучше всего, если у прибора автономное питание (батареи). А если он от сети, то померь сначала разность потенциалов между землями компа и девайса (она приложится к сигнальным линиям когда ты комп соединишь с девайсом). Эта разность может быть порядка 300В -- порт в этом случае выгорает мгновенно (проверено на собственном горьком опыте).

nobody ★★
()

Спасибо.

Мы тут посовещались и решили использовать СОМ порт. Инфу о режимах работы прибора гнать по линии данных последовательным кодом (одна микруха лишняя в приборе), а стробы, коих только два и надо, по RTS и DTR. Осталось только научиться слать данные так, чтоб эти стробы не трогать. Думаю, это не так сложно сделать..

Ростислав

anonymous
()

На кой ляд тебе стробировать данные? Асинхронный последовательный протокол -- самосинхронизирующийся. На приборе привязывайся к RTS, по этому сигналу настраивай свою UART и выставляй CTS (DSR просто соедини с DTR). Когда тебе прийдет байт, UART прерывание даст. (если я правильно понял, один лишний корпус, про который ты написал -- это i16550A или что-то совместимое? или просто преобразователь уровней из RS232C в TTL?)

ЗЫ: насчет сигналов LOOP и OUT. Их назначение -- самотестирование UART (когда LOOP устанавливается в 1, выход UART внутри нее замыкается на ее же вход).

nobody ★★
()

Стробировать надо другие данные. У меня сигнал с прибора цифруется звуковой картой. Мне надо прибору сказать что-то типа "приготовились-поехали-закончили" (стробы). А иногда, не критично по времени, поменять режимы, то есть сказать, какой датчик будем опрашивать на следующем цикле (по последовательной линии). туда же можно засылать всякие ещё штуки типа "включились-выключились". Или, например, сигналы управления встроеной кофеваркой, или ещё каким-нибудь прибамбасом. :))

А корпус -- не знаю названия (паять не я буду), преобразователь уровней плюс сдвиговый регистр. То есть то, что развернёт байт с сигнальной линии на восемь ног и (optional) продержит его там до прихода следующего байта.

Ростислав

anonymous
()

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

Если же ты все-таки хочешь давать команду именно сигналом, то можно отменить использование RTS/CTS:

ptr_to_termios->c_cflag &= ~(CCTS_OFLOW | CRTS_IFLOW | MDMBUF);

А DTR тебе по-любому придется соединять с DSR. Так что свободный выходной сигнал у тебя только один.

ЗЫ: насчет оцифровки звуковой картой. Удалось-таки победить шумы звуковухи? Или сигнал на нее уже усиленный приходит? Или у тебя с самого датчика лошадиный сигнал идет? (просто любопытство, поскольку область профессиональных интересов пересекается с твоей.)

nobody ★★
()

Замечание: про DTR прогнал (думал про свое, вот и написалось автоматом).

nobody ★★
()

Насчёт миллисекунд и многозадачности. Мне кажется, что с приоритетом -20 должно сработать. Задержки мне до 5 миллисекунд -- не критично, но со стробами спокойнее. Возможно, это всё ненужное усложнение...

Шумов в звуковухе -- два-три бита из 16-ти. Меня интересуют только шумы нулевого уровня, поскольку именно они сужают динамический диапазон. Я научился одновременно цифровать и воспроизводить по триггеру. То есть загрузили выхоной буфер, инициализировали входной и по свистку поехали. Замкнул выход на вход и посмотрел. Забавно получается. там около 2мс задержки. Это, похоже, аппаратное ограничение АС97. А может, я что не так напрограммил. Но мне это не критично.

Сигнал у меня изначально -- доли микровольта. Перед оцифровкой раскачивается до нужной амплитуды. (Эта часть уже есть).

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

Про DTR я так и понял, пока первый пост читал.

Ростислав

anonymous
()

> Как, кстати, сдвиговый регистр с нужным прибамбасом
> (см. выше) называется? И как его в магазине назвать?
Вообще-то я не знаю, существует ли в природе то, о чем ты писал. В смысле -- есть ли оно в одном корпусе. Сдвиговый регистр сам по себе -- есть. Преобразователь уровней TTL <-> RS232C -- тоже есть. Точное название микросхем можно поглядеть по справочнику (у меня дома нет его). В магазине (или на рынке) можно так и сказать, что тебе надо -- продавец поймет.

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

Как работает сдвиговый регистр. У него есть 10 ног (на самом деле больше, но не суть). На одну ногу ему приходит частота, на другую -- последовательные данные, а с оставшихся восьми ты можешь забирать данные, преобразованные из последовательного вида в параллельный. По фронту (или по спаду) частоты микросхема сдвигает содержимое выходных ног, а на освободившееся место считывает состояние входной ноги. По следующему фронту (или спаду) все повторяется. То есть синхронный обмен, потому что присутствует сигнал, управляющий чтением каждого бита.

Асинхронный протокол не имеет управляющих сигналов. Передатчик поддерживает линию в определенном состоянии, говорящем приемнику, что ничего не передается. Перед началом передачи байта передатчик делает стартовый бит. Он изменяет состояние линии на противоположное. Длится это состояние заранее известное время. Затем передаются биты данного байта (для RS232C -- младший бит первым). Каждый бит длится заранее известное время. После передачи последнего бита передатчик делает стоповый бит. Для следующего байта все повторяется сначала.

Так что, как видишь, задача эта не для сдвигового регистра. Надо либо реализовывать порт программно, либо использовать UART. Можешь поглядеть по справочнику в разделе "Асинхронные приемники-передатчики". Или в магазине спроси аналог Intel'овской 16550A. Но справочник тебе все равно понадобится, потому что надо ноги знать.

nobody ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.