Difference between revisions of "Управление на сериен порт с POSIX"
Line 64: | Line 64: | ||
c_ospeed Скорост на прадаване | c_ospeed Скорост на прадаване | ||
</pre> | </pre> | ||
− | |||
+ | '''Общи настройки.''' Битовете в полето на c_cflag управляват скоростта, броя на битовете в изпращаната дума, контрол по четност, стоп битовете и хардуерното управление на данните. В таблицата са описани константите за някои от подържаните опции: | ||
− | Константи | + | <code> |
− | Описание | + | Константи Описание |
− | CBAUD | + | CBAUD Bit mask for baud rate |
− | Bit mask for baud rate | + | B0 0 baud (drop DTR) |
− | B0 | + | B2400 2400 baud |
− | 0 baud (drop DTR) | + | B19200 19200 baud |
− | B2400 | + | B115200 115,200 baud |
− | 2400 baud | + | EXTA External rate clock |
− | B19200 | + | EXTB External rate clock |
− | 19200 baud | + | CSIZE Bit mask for data bits |
− | B115200 | + | CS7 7 data bits |
− | 115,200 baud | + | CS8 8 data bits |
− | EXTA | + | CSTOPB 2 stop bits (1 otherwise) |
− | External rate clock | + | CREAD Enable receiver |
− | EXTB | + | PARENB Enable parity bit |
− | External rate clock | + | PARODD Use odd parity instead of even |
− | CSIZE | + | HUPCL Hangup (drop DTR) on last close |
− | Bit mask for data bits | + | CLOCAL Local line - do not change "owner" of port |
− | CS7 | + | LOBLK Block job control output |
− | 7 data bits | + | CNEW_RTSCTS Enable hardware flow control (not supported on all platforms) |
− | CS8 | ||
− | 8 data bits | ||
− | CSTOPB | ||
− | 2 stop bits (1 otherwise) | ||
− | CREAD | ||
− | Enable receiver | ||
− | PARENB | ||
− | Enable parity bit | ||
− | PARODD | ||
− | Use odd parity instead of even | ||
− | HUPCL | ||
− | Hangup (drop DTR) on last close | ||
− | CLOCAL | ||
− | Local line - do not change "owner" of port | ||
− | LOBLK | ||
− | Block job control output | ||
− | CNEW_RTSCTS | ||
− | Enable hardware flow control (not supported on all platforms) | ||
CRTSCTS | CRTSCTS | ||
+ | </code> | ||
Две от опциите на c_cflag трябва да бъдат винаги активирани CLOCAL и CREAD. Първата няма да позволи на вашата програмата да поеме контрола върху серийния порт, което би причинило случайни затваряния на линията и сигнали за управление. Втората ще осигури драйвера на серийния интерфейс да чете пристигащите данни. Константите за скоростта (CBAUD, B9600 и т.н) се използват при по-стари интерфейси, където липсват полетата c_ispeed и c_ospeed. | Две от опциите на c_cflag трябва да бъдат винаги активирани CLOCAL и CREAD. Първата няма да позволи на вашата програмата да поеме контрола върху серийния порт, което би причинило случайни затваряния на линията и сигнали за управление. Втората ще осигури драйвера на серийния интерфейс да чете пристигащите данни. Константите за скоростта (CBAUD, B9600 и т.н) се използват при по-стари интерфейси, където липсват полетата c_ispeed и c_ospeed. |
Revision as of 13:34, 26 October 2011
Достъп до сериен порт
Всеки сериен порт в UNIX система има един или повече съответни файла, намиращи се в директория /dev. В Linux най-често съответните файлове за серийните портове са:
- Port 1 - /dev/ttyS0,
- Port 2 - /dev/ttyS1 и т.н..
Отваряне на серийния порт: Както вече знаем, серийният порт се представя като файл и лесно може да се досетим, че за достъп до този файл може да използваме функцията open(2). Единствено трябва да съобразим и настроим правата за достъп, които по подразбиране са дадени единствено на root потребителя.
Примерен код на C за отваряне на сериен порт:
#include <stdio.h> /* Входно изходна библиотека */
#include <string.h>/* Стринг библиотека */
#include <unistd.h>/* UNIX стандартна библиотека */
#include <fcntl.h> /* Библиотека за управление на файловете */
#include <errno.h> /* Библиотека за обработка на грешки */
#include <termios.h> /* POSIX библиотека за управление на терминала */
// 'open_port()' - Отваря сериен порт 1.
// Връща файлов дескриптор при успешно отваряне и -1 при грешка.
int open_port(void) {
int fd; // Файлов дескриптор на порта
fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1) //портът не може да бъде отворен
perror("open_port: Unable to open /dev/ttyS0 - ");
else
fcntl(fd, F_SETFL, 0); // ресетване на флаговете за настройкa
Опции при отваряне: Освен стандартната опция при отваряне на файл за четене и запис ( O_RDWR - флаг) има още две опции, които се задават.
- O_NOCTTY – програмата няма да поема управлението на терминала
- O_NDELAY – не се чака сигнал DCD (Data Carier Detect – пин 1), за да се активира четенето от порта.
Изпращане на данни. Изпращането на данни е лесно, просто пишем във файла на порта с функцията write(2) и проверяваме дали има грешки. Примерно:
n = write(fd, "ATZ\r", 4); if (n < 0) fputs("write() of 4 bytes failed!\n", stderr);
Функцията write(2) връща броя на изпратените битове или -1 при грешка.
Четене на данни от серийния порт. Четенето от серийния порт е малко особено. Когато портът е в режим „raw data“, всяко повикване на функцията read(2) ще върне символите, които реално се намират в буфера. Примерно:
while ( stop == 0) { usleep(100); fflush (stdout); res = read(fd,buf,10); for( c=0;c<res; c=c+1) printf("%c", (char) buf[c]); }
Ако няма символи, функцията ще чака, докато пристигне някакъв символ, докато не изтече времето на таймера или не настъпи някаква грешка. За да се избегне чакането може да се използва следното:
fcntl(fd, F_SETFL, FNDELAY);
FNDELAY – дава настройка read(2) да връща 0, когато няма данни.
Затварянето на серийния порт става с close(fd). Затварянето на серийния порт ще постави DTR в ниско ниво.
Настройка на серийния порт
POSIX терминален интерфейс. Повечето системи поддържат POSIX терминален интерфейс за промяна на параметри като скорост на предаване, дължина на символа, контрол по четност и т.н. Първото нещо, което трябва да се направи, е <termios.h> да бъде включен към програмата. В този файл се дефинират както структурата, която ще управлява терминала, така и POSIX управляващи функции.
Двете най-важни функции са tcgetattr(3) и tcsetattr(3). Тези две функции съответно връщат текущите настройки и задават нови настройки на терминала. Един от аргументите на функциите е показалец към структурата termios, съдържаща следните полета: Таблица 1.
Променлива Описание c_cflag Общи настройки c_lflag Настройки на линията c_iflag Входни настройки c_oflag Изходни настройки c_cc Управление на символите c_ispeed Скорост на приемане c_ospeed Скорост на прадаване
Общи настройки. Битовете в полето на c_cflag управляват скоростта, броя на битовете в изпращаната дума, контрол по четност, стоп битовете и хардуерното управление на данните. В таблицата са описани константите за някои от подържаните опции:
Константи Описание
CBAUD Bit mask for baud rate
B0 0 baud (drop DTR)
B2400 2400 baud
B19200 19200 baud
B115200 115,200 baud
EXTA External rate clock
EXTB External rate clock
CSIZE Bit mask for data bits
CS7 7 data bits
CS8 8 data bits
CSTOPB 2 stop bits (1 otherwise)
CREAD Enable receiver
PARENB Enable parity bit
PARODD Use odd parity instead of even
HUPCL Hangup (drop DTR) on last close
CLOCAL Local line - do not change "owner" of port
LOBLK Block job control output
CNEW_RTSCTS Enable hardware flow control (not supported on all platforms)
CRTSCTS
Две от опциите на c_cflag трябва да бъдат винаги активирани CLOCAL и CREAD. Първата няма да позволи на вашата програмата да поеме контрола върху серийния порт, което би причинило случайни затваряния на линията и сигнали за управление. Втората ще осигури драйвера на серийния интерфейс да чете пристигащите данни. Константите за скоростта (CBAUD, B9600 и т.н) се използват при по-стари интерфейси, където липсват полетата c_ispeed и c_ospeed. Важно: Никога да не се инициализират флаговете на полетата директно, винаги трябва да се използват побитовите оператори AND, OR и NOT за задаване стойността на битовете в променливата. Различните операционни системи (дори пачовете) биха могли да използват по различен начин битовете, така че използването на побитовите оператори ще предотврати нежелано объркване. Настройка на скоростта. Функциите cfsetospeed(3) и cfsetispeed(3) се използват за настройка на termios структурата, независимо от операционната система. Функцията tcgetattr(3) записва текущите настройки на серийния контролер в termios структурата. След като зададем нова стойност за скоростта и активираме CLOCAL и CREAD, функцията tcsetattr() записва новите настройките в контролера. Опцията TCSANOW задава настройките да бъдат активирани веднага, без да се чака край на приемане или изпращане на текуща сесия от данни. Друга опция, която позволява задаване изчакване до приключване на сесията за приемане или предаване е TCSADRAIN, също и за директно изтриване на данните в изходните и входните буфери се ползва TCSAFLUSH. Листинг 2.Примерен код за задаване на скоростта:
Повечето системи не поддържат различни скорости на приемане и предаване, затова за по-голяма съвместимост е добре двете скорости да са еднакви. Други важни настройки са представени в Листинг 3. Листинг 3. Задаване на дължина на символа; проверка по четност (Parity check) и хардуерно управление на връзката ( Hardware Flow Control)
2.3. Локални настройки Локалните настройки задавани с полето c_lflag управляват как входящите символи се обработват от серийния драйвер. По същество два са режимите на приемане, които могат да се настроят – каноничен и директен. Режим каноничен вход. Режим каноничен вход е линийно ориентиран. Входните символи се записват в буфера, те могат да бъдат редактирани интерактивно от потребителя, докато не се получи символ CR ( carriage return) или LF (line feed). За задаване на този режим обикновено се избират следните опции: ICANON, ECHO и ECHOE.
options.c_lflag |= (ICANON | ECHO | ECHOE); Режим на директен достъп. При директен достъп входните данни не се обработват. Пристигналите символи се предават директно без промени в момента на пристигането им. За работа в директен режим следните опции се деактивират: ICANON, ECHO, ECHOE и ISIG.
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); Важно: Никога не активирайте echo (ECHO, ECHOE), когато изпращате команди към модем или друг компютър, който връща ехо, в противен случай ще се генерира неуправляема обратна връзка.
2.4. Входящи настройки Настройките, задавани с полето c_iflag управляват обработката на всеки пристигнал символ Задаване на проверка по четност: Ако в c_cflag е активирана проверка по четност, то трябва да се зададат и съответните настройки в c_iflag. За тази цел се използват следните константи: INPCK, IGNPAR, PARMRK и ISTRIP. За проверка и изрязване на бита за проверка се използват INPCK и ISTRIP. options.c_iflag |= (INPCK | ISTRIP); INGPAR трябва да се ползва внимателно, защото казва на драйвера на серийния порт да игнорира грешките и да предаде входните данни, независимо дали има грешки или не. PARMRK задава маркиране на входните грешки във входящия поток, като се използват специални символи. Ако INGPAR е активирано, NUL символ (х000) се добавя пред всеки символ с грешка. Ако INGPAR не е активирано, DEL (x177) и NUL символи се изпращат заедно с всеки сгрешен символ. Настройка на софтуерно управление на връзката: Софтуерното управление на връзката се активира с константите IXON, IXOFF и IXANY.
options.c_iflag |= (IXON | IXOFF | IXANY);
За деактивиране на софтуерното управление просто се нулират битовете options.c_iflag &= ~(IXON | IXOFF | IXANY); Масивите съдържащи описание на XON (символи за начало) и XOFF ( символи за край) са дефинирани в c_cc масива.
2.5. Изходни настройки Полето c_oflag съдържа опции за филтриране на изходните данни. Както при режимите за приемане може да се избере обработен или директен изход. options.c_oflag |= OPOST; // Избор на обработен изход options.c_oflag &= ~OPOST; //Директен изход