Difference between revisions of "Сериен порт"

From Ilianko
 
(104 intermediate revisions by the same user not shown)
Line 1: Line 1:
 +
== Цел на упражнението ==
 +
Запознаване със сериен порт
 +
 +
== RS-232C ==
 
Интерфейсът RS-232  е с повече от половин век история и в момента когато казваме "сериен порт" най-често става дума за RS-232. В сравнение със съвременните мегабитови интерфейси като USB (също сериен интерфейс), RS-232 връзката изглежда бавна и ненужна, но тя e същественa поради няколко причини:
 
Интерфейсът RS-232  е с повече от половин век история и в момента когато казваме "сериен порт" най-често става дума за RS-232. В сравнение със съвременните мегабитови интерфейси като USB (също сериен интерфейс), RS-232 връзката изглежда бавна и ненужна, но тя e същественa поради няколко причини:
*За разбиране на процеса на комуникация с операционната система. Текстовият интерфейс е в основата на всяка една UNIX система, а той базиран върху концепцията на серийния терминал. Днес хардуерният текстов терминал е заместен със псевдо терминал.
+
*За разбиране на процеса на комуникация с операционната система. Текстовият интерфейс е в основата на всяка една операционна система, а той e базиран върху концепцията на серийния терминал. Днес хардуерният текстов терминал е заместен с псевдо терминал.
[[Image:pty.png|thumb|right|250px|Псевдо терминал Linux]]
 
[[Image:ASR-33.jpg|thumb|left|250px|ASR-33 TeleTYpe]]
 
[[Image:vt05.jpg|thumb|center|250px|VT05 Първият терминал с екран]]
 
 
 
 
 
*Все още се ползва, въпреки че е загубила широката си употреба, все още се ползва в редица приложения - за връзка с индустриални контролери и комуникационна апаратура.
 
 
 
 
 
  
Интерфейсът RS-232  е с повече от половин век история и в момента когато казваме "сериен порт" най-често става дума за RS-232. В сравнение със съвременните мегабитови интерфейси като USB (също сериен интерфейс), RS-232 връзката изглежда бавна и ненужна, но тя e същественa поради няколко причини:
 
*За разбиране на процеса на комуникация с операционната система. Текстовият интерфейс е в основата на всяка една UNIX система, а той базиран върху концепцията на серийния терминал. Днес хардуерният текстов терминал е заместен със псевдо терминал.
 
 
[[Image:pty.png|thumb|right|250px|Псевдо терминал Linux]]
 
[[Image:pty.png|thumb|right|250px|Псевдо терминал Linux]]
 
[[Image:ASR-33.jpg|thumb|left|250px|ASR-33 TeleTYpe]]
 
[[Image:ASR-33.jpg|thumb|left|250px|ASR-33 TeleTYpe]]
Line 18: Line 12:
  
 
*Все още се ползва, въпреки че е загубила широката си употреба. Серийния интрефейс се среща за връзка с индустриални контролери и комуникационна апаратура.
 
*Все още се ползва, въпреки че е загубила широката си употреба. Серийния интрефейс се среща за връзка с индустриални контролери и комуникационна апаратура.
 
+
*USB, Bluetooth, IrDA  предлагат средства за емулиране на RS232 серийна връзка
== RS-232C ==
 
  
 
[[Image:DB25.png|thumb|400px|DB-25]]
 
[[Image:DB25.png|thumb|400px|DB-25]]
 
[[Image:DB9.png|thumb|400px|DB-9]]
 
[[Image:DB9.png|thumb|400px|DB-9]]
 
[[Image:RJ45.png|thumb|400px|RJ-45]]
 
[[Image:RJ45.png|thumb|400px|RJ-45]]
 +
 +
  
 
Повечето серийни интерфейси с ниска скорост са някакъв вариант на RS-232C стандарта. Този стандарт определя електрическите характеристики и значението на сигнала по всеки от проводниците, както и разположението на пиновете в традиционния 25 пинов конектор (DB-25p фиг.4).
 
Повечето серийни интерфейси с ниска скорост са някакъв вариант на RS-232C стандарта. Този стандарт определя електрическите характеристики и значението на сигнала по всеки от проводниците, както и разположението на пиновете в традиционния 25 пинов конектор (DB-25p фиг.4).
  
Пълният стандарт RS-232C (EIA-232-E) реално не се използва, защото определя множество сигнали, които са ненужни при обикновена комуникация. DB-25 конекторите са неудобни и поради големината си. В резултат на това те са заместени от 9 пинов конектор (DB-9, фиг.5), а като удобна алтернатива се ползва и RJ-45.  
+
Пълният стандарт RS-232C (EIA-232-E, ITU-T V.24) реално не се използва, защото определя множество сигнали, които са ненужни при обикновена комуникация. DB-25 конекторите са неудобни и поради големината си. В резултат на това те са заместени от 9 пинов конектор (DB-9, фиг.5), а като удобна алтернатива се ползва и RJ-45.  
  
 
В таблицата са дадени наименованията на сигналите и разположението им на пиновете. Обикновено се ползват 7 проводника за осъществяване на връзка (DSR и DCD; FG и SG; ползват общ проводник).  
 
В таблицата са дадени наименованията на сигналите и разположението им на пиновете. Обикновено се ползват 7 проводника за осъществяване на връзка (DSR и DCD; FG и SG; ползват общ проводник).  
  
'' '''Таблица с значенията на пиновете (мъжки куплунг) за различните конектори.''' ''
+
'' '''Таблица със значенията на пиновете (мъжки куплунг) за различните конектори.''' ''
 
<table border=2 cellpadding=3 cellspacesing=1>
 
<table border=2 cellpadding=3 cellspacesing=1>
 
<tr>
 
<tr>
Line 67: Line 62:
 
На фигури 4,5 и 6 са дедени разположенията на мъжките пинове, в женския конектор те са разположени огледално.
 
На фигури 4,5 и 6 са дедени разположенията на мъжките пинове, в женския конектор те са разположени огледално.
  
=== Кабели ===
+
=== Свързване ===
При свързване на две устройства с RS-232 сигналът за предаване (TD) от едно устройство трябва да се подава на пин за приемане (RD) на второто устройство. Поради това се налага два типа конфигурации на серийните устройствата:
+
При свързване на две устройства с RS-232 сигналът за предаване (Tx,TD) от едно устройство трябва да се подава на пин за приемане (Rx,RD) на второто устройство. Съществуват два типа конфигурации на серийните устройствата:
*DTE (Data Terminal Equipment) - стандартна схема  на свързване
+
*DTE (Data Terminal Equipment) - формално управлява връзката (master) стандартна схема  на свързване
*DCE (Data Communications Equipment) - обърната сигнализация.
+
*DCE (Data Communications Equipment) - (slave) обърната сигнализация.
 
Принципно могат да се свързват устройства DTE към DCT, DTE към DTE, DCT към DCT
 
Принципно могат да се свързват устройства DTE към DCT, DTE към DTE, DCT към DCT
 +
 
Примерно:
 
Примерно:
*компютър (DCT)-rs232-(DCE)modem-FM-modem(DCE)-rs232-(DTE)компютър
+
*компютър (DTE)-rs232-(DCE)modem-FM-modem(DCE)-rs232-(DTE)компютър
*компютър (DCT)-(DTE)компютър.
+
*компютър (DTE)-(DTE)компютър.
  
Всяко едно устройство може да е конфигурирано като DTE или DCE, рядко може да поддържа и двата варианта, но не едновременно.
+
Всяко едно устройство може да е конфигурирано или като DTE или като DCE, рядко може да поддържа и двата варианта, но не в един и същ момент.
  
Когато устройствата са еднотипни трябва да се ползва кръстосан кабел, наречен още '''"null modem"''' кабел. За връзка DТE-DCE се ползва '''прав кабел'''. Съществува и трета разновидност на кабели използвана при cisco апаратура наречени '''"rollover"''' кабели, при които изводите в единия край са огледално пренаредени в другия.
+
Когато устройствата са еднотипни за връзка между тях трябва да се ползва кръстосан кабел, наречен още '''null modem''' кабел. За връзка DТE-DCE се ползва '''прав кабел'''. Съществува и трета разновидност на кабели използвана при cisco апаратура наречени '''"rollover"''' кабели, при които изводите в единия край са огледално пренаредени в другия.
 
   
 
   
 
'' '''Конфигурация на Null Modem кабел''' ''
 
'' '''Конфигурация на Null Modem кабел''' ''
 
<table border="2" cellpadding="3" cellspacing="1">
 
<table border="2" cellpadding="3" cellspacing="1">
     <tr>  
+
     <tr >  
       <th></th>
+
       <td colspan=2  style="text-align:center">DB9-1 пин/проводник</td>
      <th>DB9-1</th>
+
       <td colspan=2  style="text-align:center">DB9-2 пин/проводник</td>   </tr>
       <th>DB-2</th>
 
 
 
      <th></th>
 
    </tr>
 
 
     <tr>  
 
     <tr>  
 
       <td>Receive Data</td>
 
       <td>Receive Data</td>
Line 138: Line 130:
 
     </tr>
 
     </tr>
 
</table>
 
</table>
Серийни
 
 
== Цел на упражнението ==
 
Преговор [[C типове данни int, char, float, array, string, struct|типове данни]], оператори. Достъп до сериен порт.
 
 
 
== Теория ==
 
== Serial port terminal ==
 
 
===Linux ===
 
'''Задача''' Инсталирайте терминалната програма за комуникация през сериен порт GTKterm.
 
 
'' '''Упътване:''' Използвайте командата по-долу. След инсталацията може да намерите програмата в Applications -> Accessories. ''
 
:~$ sudo apt-get install gtkterm
 
 
=== Windows ===
 
'''Задача'''Стартирайте Hyper terminal в MS Windows
 
START -> Programs -> Accessories -> Communications -> Hyper Terminal
 
 
'''Задача''' Осъществете връзка през сериен порт връзка между Windows и Linux на два съседни компютъра.
 
 
Свържете двата компютъра със сериен кабел през RS232 порта. Настройте двете програмите HyperTeminal и GTKterm да предават и приемат с еднакви параметри.
 
 
Тествайте различни скорости на предаване и приемане.
 
 
 
== Променливи ==
 
Разгледайте различните [[C типове данни int, char, float, array, string, struct|типове данни в C]].
 
 
Основната причина за съществуване  на различни типове данни е да знае компилатора, колко памет да отдели за всяко число, буква или текст, когато съхранява стойностите им. Информацията се ползва и в последствие, при извеждане или при обработка на данните и взаимодействия с други данни.
 
 
'''Задача 1.''' Създайте програма, която да преобразува числото 65 в символ и да го извежда.
 
 
'' '''Упътване''' . Използвайте: ''
 
<code><pre>int x = 65;
 
char y;
 
y = (char) x;
 
printf( " %c ", y );
 
</pre></code>
 
 
 
'''Задача 2.''' Създайте програма, която да извежда всички букви букви от ASCII кода в поредица AbCdEfGh.... yZ
 
 
'' '''Упътване''' . Всяка буква отговаря на число, всяка следваща буква е число с едно по-голямо. Главните букви започват от 65, малките от 97, а общо са 26. Може да ползвате:''
 
<code><pre>
 
int i = 0;
 
for (i = 0; i< 26; i = i + 2)
 
{ ... }
 
</pre></code>
 
 
 
'''Задача 3.''' Създайте програма, която след въвеждане на буква от клавиатурата, извежда дали кодът на буквата е с четен или нечетен номер.
 
 
'' '''Упътване.''' Може да използвате примера от [[Упражнение 2. Достъп до периферни устройства.|задача 2 на Упражнение 2]] и кодът по-долу.''
 
<code><pre>
 
if ( ((int) s) % 2) puts(" .... ");
 
else puts(" ... ");
 
</pre></code>
 
 
'''Задача 4. '''Преобразуване на буква в двоичен код. Изпълнете програмата, разгледайте кода и пробвайте с различни букви.
 
 
<code><pre>
 
#include <stdio.h>  /* Standard input/output definitions */
 
 
#define TESTD 'a'
 
 
int main(void)
 
{
 
  int z=128, y = 0;
 
  char a = TESTD;
 
  char b[9] = "00000000";
 
       
 
  for ( y=0;  y < 8;  ++y)
 
  {
 
    b[y] = ((a & z) == z) ? '1' : '0';
 
        /* a = 0 0 1 0 1 0 0 0
 
          AND
 
          z = 0 0 0 0 1 0 0 0
 
          ===================
 
          r = 0 0 0 0 1 0 0 0 = z */
 
    z = z >> 1; // <=> z >>= 1  - преместване с един бит
 
  }
 
   
 
  printf("%s \n", b);
 
  return 0;
 
}
 
</pre></code>
 
 
== Проверка по четност ==
 
'''Задача 5''' Преработете кодът от предната задача, така че да ви показва, колко единици има в двоичното число и дали броят на единици е четен или нечетен.
 
 
'' '''Упътване''' Може да замените
 
<code><pre>
 
((a & z) == z) ? '0' : '1';
 
</pre></code>
 
със
 
<code><pre>
 
int e=0;
 
...
 
if((a & z) == z)
 
{
 
  ++e;
 
  b[y] = '1';
 
}
 
</pre></code>''
 
 
== [[Управление на сериен порт с POSIX|Комуникация през C, POSIX и сериен порт]] ==
 
'''Задача ''' Създайте програма, която да изпраща информация по-серийния порт. Свържете два компютъра със сериен кабел, като на единия изпълнявате програмата, а на другия сте включили, някоя от терминалните програми за управление на серийната връзка от предходната задача.
 
 
<code><pre>
 
 
#include <stdio.h>  /* Standard input/output definitions */
 
#include <string.h>  /* String function definitions */
 
#include <unistd.h>  /* UNIX standard function definitions */
 
#include <fcntl.h>  /* File control definitions */
 
#include <errno.h>  /* Error number definitions */
 
#include <termios.h> /* POSIX terminal control definitions */
 
 
#define PORTNAME  "/dev/ttyS0"
 
 
int main(void)
 
{
 
    int fd; // File descriptor for the port
 
    struct termios options; // Serial port settings
 
 
 
    fd = open( PORTNAME, O_RDWR | O_NOCTTY | O_NONBLOCK);
 
 
    if (fd == -1)//Could not open the port.
 
perror("open_port: Unable to open port");
 
    else
 
      fcntl(fd, F_SETFL, 0);
 
 
    tcgetattr(fd, &options);
 
    cfsetispeed(&options, B2400);
 
    cfsetospeed(&options, B2400);
 
   
 
    options.c_cflag |= ( CREAD);
 
    options.c_cflag |= ( CLOCAL);
 
    options.c_cflag &= ( ~CSTOPB);
 
       
 
    tcsetattr(fd,TCSANOW, &options);
 
 
    write(fd, "a \n", 3); //write to serial port
 
         
 
    return 0;
 
}
 
 
</pre></code>
 
 
За повече информация [[Управление на сериен порт с POSIX]], [[http://www.easysw.com/~mike/serial/serial.html POSIX serial port]]
 
 
== Задача 1 ==
 
 
Създайте програма с безкраен цикъл, която да изпраща една буква към серийния порт. Използвайте специално пригодения кабел и разгледайте осцилограмата на сериен сигнал.
 
 
== Четене сериен порт ==
 
 
=== Raw ===
 
<code><pre>
 
/****************************************************************\
 
* Edited by Ilianko
 
* Description: Raw reading of the serial port
 
\****************************************************************/
 
#include <termios.h>
 
#include <stdlib.h>
 
#include <stdio.h>
 
#include <unistd.h>
 
#include <fcntl.h>
 
     
 
#define BAUDRATE B2400
 
#define MODEMDEVICE "/dev/ttyUSB2"
 
     
 
int  main()
 
{
 
int fd, c, res, stop = 0;
 
    struct termios oldtio,newtio;
 
    char buf[255];
 
       
 
    /* open the device to be non-blocking (read will return immediatly) */
 
    fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
 
    if (fd < 0) {perror(MODEMDEVICE); exit(-1);}
 
       
 
    fcntl(fd, F_SETFL, 0);
 
fcntl(fd, F_SETFL, FNDELAY);       
 
       
 
    tcgetattr(fd,&oldtio); /* save current port settings */
 
       
 
    /* set new port settings for canonical input processing */
 
    newtio.c_cc[VMIN]=1;
 
    newtio.c_cc[VTIME]=0;
 
   
 
    newtio.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
 
    newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
 
    newtio.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
 
           
 
tcsetattr(fd,TCSANOW,&newtio);
 
 
tcflush(fd, TCIFLUSH);
 
 
/* loop while waiting for input. normally we would do something */
 
    while ( stop == 0)
 
{
 
usleep(100);
 
        fflush (stdout);
 
        res = read(fd,buf,10);
 
       
 
        // strcat(buf,buf2);
 
         
 
        for( c=0; c<res; c++)
 
        {
 
          printf("%c", (char) buf[c]);
 
        }
 
}
 
    tcsetattr(fd,TCSANOW,&oldtio);/* restore old port settings */
 
return 0;
 
}
 
</pre></code>
 
  
=== Canonical ===
+
=== Скорост на предаване ===
<code><pre>
+
За успешна комуникация скоростта на предаване на едното устройство трябва да е равна на скоростта на приемане на второто устройство. Повечето серийни контролери не поддържат автоматичен избор на скоростта, затова се налага ръчна конфигурация за съгласуване на двете устройства.
/****************************************************************\
 
* Edited by Ilianko
 
* Description: Raw reading of the serial port
 
\****************************************************************/
 
  
#include <termios.h>
+
Поддържаните скорости зависят от серийния контролер, обикновено са в границите между '''50 bit/s 110, 300, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200 bit/s'''(= 1.8432 MHz / 16)
#include <stdlib.h>
 
#include <stdio.h>
 
#include <unistd.h>
 
#include <fcntl.h>
 
     
 
#define BAUDRATE B2400
 
#define MODEMDEVICE "/dev/ttyUSB2"
 
     
 
int main()
 
{
 
int fd, c, res, stop = 0;
 
    struct termios oldtio,newtio;
 
    char buf[255];
 
       
 
    /* open the device to be non-blocking (read will return immediatly) */
 
    fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
 
    if (fd < 0) {perror(MODEMDEVICE); exit(-1);}
 
       
 
    fcntl(fd, F_SETFL, 0);
 
fcntl(fd, F_SETFL, FNDELAY);       
 
       
 
    tcgetattr(fd,&oldtio); /* save current port settings */
 
       
 
    /* set new port settings for canonical input processing */
 
    newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
 
    newtio.c_iflag = IGNPAR | ICRNL;
 
    newtio.c_oflag = 0;
 
    newtio.c_lflag = ICANON;
 
         
 
    newtio.c_cc[VMIN]=1;
 
    newtio.c_cc[VTIME]=0;
 
       
 
tcsetattr(fd,TCSANOW,&newtio);
 
tcflush(fd, TCIFLUSH);
 
 
 
/* loop while waiting for input. normally we would do something */
 
    while ( stop == 0)
 
{
 
usleep(100);
 
        fflush (stdout);
 
        res = read(fd,buf,10);
 
       
 
        for( c=0; c<res; c++)
 
        {
 
          printf("%c", (char) buf[c]);
 
        }
 
       
 
}
 
    tcsetattr(fd,TCSANOW,&oldtio);/* restore old port settings */
 
return 0;
 
}
 
</pre></code>
 
  
== Самостоятелна подготовка ==
+
Възможна е асиметрична връзка (скоростта в двете посоки (Up/Down link) е различна).
1. Напишете името си на латиница, преобразувайте буквите с двоичен код и създайте времева диаграма на физическия сигнал.
 
1. Да се напише програма, която изпраща символите от клавиатурата към серийния порт.
 
  
== Край ==
+
Понякога името на параметъра дефиниращ скоростта се нарича ''baud'' (J. M. Emile Baudot, - бод - сивола в секунда.)
  
''' Задача 11 ''' Деинсталирайте GTKterm.
+
=== Проверка по четност ===
 +
Към изпращания символ може да се добави един бит за откриване на грешки възникнали при предаване на сигнала. Възможни са три конфигурации:
 +
*проверка по четност
 +
*проверка по нечетност
 +
*без бит за проверка
  
'' '''Упътване:''' Използвайте командата.
+
=== Брой битове ===
<code><pre>
+
Възможни са различни конфигурации на за броя битове в един символ. Най-често се използва 8 бита съответсващи на един байт. Използват и 7 бита от които са достатъчни за един ASCII символ.
:~$ sudo apt-get purge gtkterm
 
</pre></code>
 
  
 +
=== Старт/стоп битове===
 +
След всеки предаден символ линията се поставя в ниско ниво с продължителност от 1, 1.5 или 2 бита.
  
== Литература ==
+
За начало на предаване пред всеки символ линията се поставя в високо ниво с продължите от 1 бит.
  
[[Category: Компютърна периферия]]
+
===FLOW CONTROL===
 +
При препълване на входните буферите може да се поиска спиране на предаването. Може да се реализира софтуерно и хардуерно.
  
== Цел на упражнението ==
+
При софтуерна реализация (Xon/Xoff) по линията (RD/TD) от приемника се изпращат специални символи, които трябва да известят предаващата страна за спиране или възстановяване на предаването.
Преговор [[C типове данни int, char, float, array, string, struct|типове данни]], оператори. Достъп до сериен порт.
 
  
 +
При хардуерна реализация се ползват линиите RTS/CTS или DTR/DSR. За да има предаване двете линии трябва са да във високо ниво.
  
== Теория ==
 
== Serial port terminal ==
 
  
===Linux ===
+
=== Задача: връзка DTE-DTE / Windows-Linux ===
'''Задача''' Инсталирайте терминалната програма за комуникация през сериен порт GTKterm.
 
  
'' '''Упътване:''' Използвайте командата по-долу. След инсталацията може да намерите програмата в Applications -> Accessories. ''
+
'''Задача'''. Свържете два компютъра един с Linux OS и един Windows OS с кръстосан сериен кабел(null modem) през RS232 порта. Настройте съответно двете програми Minicom и PuTTY да предават и приемат с еднакви параметри.  
:~$ sudo apt-get install gtkterm
+
*Тествайте различни настройки за скорости на предаване, проверка по четност и т.н.
  
=== Windows ===
+
'' '''Упътване''' ''
'''Задача'''Стартирайте Hyper terminal в MS Windows
+
*За Ubuntu:
 +
**Инсталирайте терминалната програма за комуникация през сериен порт minicom. Използвайте командата
 +
:~$ apt-get install minicom
 +
**След инсталацията може да намерите програмата в Applications -> Accessories.
 +
**направете съответните настройки
 +
*За Windows
 +
**Свалете от Internet програмата Putty
 +
**Стартирайте Putty и направете съответните настроийки'''
 +
**Или ползвайте Hyper Terminal:
 
  START -> Programs -> Accessories -> Communications -> Hyper Terminal
 
  START -> Programs -> Accessories -> Communications -> Hyper Terminal
  
'''Задача''' Осъществете връзка през сериен порт връзка между Windows и Linux на два съседни компютъра.
+
==сигнализация==
 
 
Свържете двата компютъра със сериен кабел през RS232 порта. Настройте двете програмите HyperTeminal и GTKterm да предават и приемат с еднакви параметри.
 
 
 
Тествайте различни скорости на предаване и приемане.
 
 
 
 
 
== Променливи ==
 
Разгледайте различните [[C типове данни int, char, float, array, string, struct|типове данни в C]].
 
 
 
Основната причина за съществуване  на различни типове данни е да знае компилатора, колко памет да отдели за всяко число, буква или текст, когато съхранява стойностите им. Информацията се ползва и в последствие, при извеждане или при обработка на данните и взаимодействия с други данни.
 
  
'''Задача 1.''' Създайте програма, която да преобразува числото 65 в символ и да го извежда.
+
RS232C определя следните  нива на сигналите за предаване/приемане
 +
*на логическа 1 от -15V до -3V
 +
*на логическа 0 от +3V до +15V
  
'' '''Упътване''' . Използвайте: ''
+
Максималното допустимо напрежение на празен ход е +/- 25V.
<code><pre>int x = 65;
 
char y;
 
y = (char) x;
 
printf( " %c ", y );
 
</pre></code>
 
  
 +
'''Примерен сигнал'''
 +
Подредба на битовете. Първо се изпраща бита с най-малко тегло. (small endian)
  
'''Задача 2.''' Създайте програма, която да извежда всички букви букви от ASCII кода в поредица AbCdEfGh.... yZ
+
Осцилограма на символа "К" от ASCII изпратен с 8 бита, един стопов бит и без контрол по чечност е дадена на фиг. 7. '''К <=> 01001011'''
  
'' '''Упътване''' . Всяка буква отговаря на число, всяка следваща буква е число с едно по-голямо. Главните букви започват от 65, малките от 97, а общо са 26. Може да ползвате:''
+
[[Image:rs232Diagram.png|frame|none|center|фиг7. Осцилограма на главна буква ASCII "K" (0x4b) с 1 старт, 8 данни и 1 стоп битове. LSB/MSB - Least/Most Significant Bit]]
<code><pre>
 
int i = 0;
 
for (i = 0; i< 26; i = i + 2)
 
{ ... }
 
</pre></code>
 
  
 +
'''Задача:''' Направете времева диаграма на първите две букви на името си, ако имате следната конфигурацията на серийната връзка
 +
*8 бита за символ
 +
*проверка по четност/нечетност ако последната цифра на фак. номера ви е четна/нечетна
 +
*2 стоп бита
  
'''Задача 3.''' Създайте програма, която след въвеждане на буква от клавиатурата, извежда дали кодът на буквата е с четен или нечетен номер.
+
'''Задача:''' Да се реализира серийна връзка между две виртуални машини
  
'' '''Упътване.''' Може да използвате примера от [[Упражнение 2. Достъп до периферни устройства.|задача 2 на Упражнение 2]] и кодът по-долу.''
+
'''Задача:''' Да се реализира достъп до серийния порт през Интернет с ser2net
<code><pre>
 
if ( ((int) s) % 2) puts(" .... ");
 
else puts(" ... ");
 
</pre></code>
 
  
'''Задача 4. '''Преобразуване на буква в двоичен код. Изпълнете програмата, разгледайте кода и пробвайте с различни букви.  
+
(Инсталира се ser2net и се конфигурира). Използва се telnet
  
 +
'''Задача:''' Да се реализира достъ до серийния порт през WEB (s ser2net, PHP и Apache)
 +
Достъпва като стандартен сокет. Ползвайте кода по-долу:
 
<code><pre>
 
<code><pre>
#include <stdio.h>  /* Standard input/output definitions */
+
if(isset($_POST['message']))
 
 
#define TESTD 'a'
 
 
 
int main(void)
 
 
{
 
{
   int z=128, y = 0;
+
   $fp =fsockopen("localhost", 2000);
  char a = TESTD;
+
    
   char b[9] = "00000000";
+
   if( !$fp) {
       
+
     echo "Error";die();
   for ( y=0;  y < 8;  ++y)
 
  {
 
     b[y] = ((a & z) == z) ? '1' : '0';
 
        /* a = 0 0 1 0 1 0 0 0
 
          AND
 
          z = 0 0 0 0 1 0 0 0
 
          ===================
 
          r = 0 0 0 0 1 0 0 0 = z */
 
    z = z >> 1; // <=> z >>= 1  - преместване с един бит
 
 
   }
 
   }
   
+
   fread($fp, 128);
   printf("%s \n", b);  
+
   fwrite($fp, "$_POST[message]");
   return 0;
+
  $status = fread($fp, 128);
}
+
   fclose($fp);
</pre></code>
 
 
 
== Проверка по четност ==
 
'''Задача 5''' Преработете кодът от предната задача, така че да ви показва, колко единици има в двоичното число и дали броят на единици е четен или нечетен.
 
 
 
'' '''Упътване''' Може да замените
 
<code><pre>
 
((a & z) == z) ? '0' : '1';
 
</pre></code>
 
със
 
<code><pre>
 
int e=0;
 
...
 
if((a & z) == z)
 
{
 
  ++e;
 
   b[y] = '1';
 
}
 
</pre></code>''
 
 
 
== [[Управление на сериен порт с POSIX|Комуникация през C, POSIX и сериен порт]] ==
 
'''Задача ''' Създайте програма, която да изпраща информация по-серийния порт. Свържете два компютъра със сериен кабел, като на единия изпълнявате програмата, а на другия сте включили, някоя от терминалните програми за управление на серийната връзка от предходната задача.
 
 
 
<code><pre>
 
 
 
#include <stdio.h>  /* Standard input/output definitions */
 
#include <string.h>  /* String function definitions */
 
#include <unistd.h>  /* UNIX standard function definitions */
 
#include <fcntl.h>  /* File control definitions */
 
#include <errno.h>  /* Error number definitions */
 
#include <termios.h> /* POSIX terminal control definitions */
 
 
 
#define PORTNAME  "/dev/ttyS0"
 
  
int main(void)
 
{
 
    int fd; // File descriptor for the port
 
    struct termios options; // Serial port settings
 
 
 
    fd = open( PORTNAME, O_RDWR | O_NOCTTY | O_NONBLOCK);
 
 
    if (fd == -1)//Could not open the port.
 
perror("open_port: Unable to open port");
 
    else
 
      fcntl(fd, F_SETFL, 0);
 
 
    tcgetattr(fd, &options);
 
    cfsetispeed(&options, B2400);
 
    cfsetospeed(&options, B2400);
 
   
 
    options.c_cflag |= ( CREAD);
 
    options.c_cflag |= ( CLOCAL);
 
    options.c_cflag &= ( ~CSTOPB);
 
       
 
    tcsetattr(fd,TCSANOW, &options);
 
  
    write(fd, "a \n", 3); //write to serial port
 
         
 
    return 0;
 
 
}
 
}
  
</pre></code>
+
?>
 
+
<html><head></head>
За повече информация [[Управление на сериен порт с POSIX]], [[http://www.easysw.com/~mike/serial/serial.html POSIX serial port]]
+
<body>
 
+
<form name="serial" action="" method="post">
== Задача 1 ==
+
Message:  <input name="message" type="text"><input type="submit" value="Send">
 
 
Създайте програма с безкраен цикъл, която да изпраща една буква към серийния порт. Използвайте специално пригодения кабел и разгледайте осцилограмата на сериен сигнал.
 
 
 
== Четене сериен порт ==
 
 
 
=== Raw ===
 
<code><pre>
 
/****************************************************************\
 
* Edited by Ilianko
 
* Description: Raw reading of the serial port
 
\****************************************************************/
 
#include <termios.h>
 
#include <stdlib.h>
 
#include <stdio.h>
 
#include <unistd.h>
 
#include <fcntl.h>
 
     
 
#define BAUDRATE B2400
 
#define MODEMDEVICE "/dev/ttyUSB2"
 
     
 
int  main()
 
{
 
int fd, c, res, stop = 0;
 
    struct termios oldtio,newtio;
 
    char buf[255];
 
       
 
    /* open the device to be non-blocking (read will return immediatly) */
 
    fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
 
    if (fd < 0) {perror(MODEMDEVICE); exit(-1);}
 
       
 
    fcntl(fd, F_SETFL, 0);
 
fcntl(fd, F_SETFL, FNDELAY);       
 
       
 
    tcgetattr(fd,&oldtio); /* save current port settings */
 
       
 
    /* set new port settings for canonical input processing */
 
    newtio.c_cc[VMIN]=1;
 
    newtio.c_cc[VTIME]=0;
 
   
 
    newtio.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
 
    newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
 
    newtio.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
 
           
 
tcsetattr(fd,TCSANOW,&newtio);
 
 
tcflush(fd, TCIFLUSH);
 
 
/* loop while waiting for input. normally we would do something */
 
    while ( stop == 0)
 
{
 
usleep(100);
 
        fflush (stdout);
 
        res = read(fd,buf,10);
 
       
 
        // strcat(buf,buf2);
 
         
 
        for( c=0; c<res; c++)
 
        {
 
          printf("%c", (char) buf[c]);
 
        }
 
}
 
    tcsetattr(fd,TCSANOW,&oldtio);/* restore old port settings */
 
return 0;
 
}
 
</pre></code>
 
 
 
=== Canonical ===
 
<code><pre>
 
/****************************************************************\
 
* Edited by Ilianko
 
* Description: Raw reading of the serial port
 
\****************************************************************/
 
 
 
#include <termios.h>
 
#include <stdlib.h>
 
#include <stdio.h>
 
#include <unistd.h>
 
#include <fcntl.h>
 
     
 
#define BAUDRATE B2400
 
#define MODEMDEVICE "/dev/ttyUSB2"
 
     
 
int  main()
 
{
 
int fd, c, res, stop = 0;
 
    struct termios oldtio,newtio;
 
    char buf[255];
 
       
 
    /* open the device to be non-blocking (read will return immediatly) */
 
    fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
 
    if (fd < 0) {perror(MODEMDEVICE); exit(-1);}
 
       
 
    fcntl(fd, F_SETFL, 0);
 
fcntl(fd, F_SETFL, FNDELAY);       
 
       
 
    tcgetattr(fd,&oldtio); /* save current port settings */
 
       
 
    /* set new port settings for canonical input processing */
 
    newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
 
    newtio.c_iflag = IGNPAR | ICRNL;
 
    newtio.c_oflag = 0;
 
    newtio.c_lflag = ICANON;
 
         
 
    newtio.c_cc[VMIN]=1;
 
    newtio.c_cc[VTIME]=0;
 
       
 
tcsetattr(fd,TCSANOW,&newtio);
 
tcflush(fd, TCIFLUSH);
 
 
 
/* loop while waiting for input. normally we would do something */
 
    while ( stop == 0)
 
{
 
usleep(100);
 
        fflush (stdout);
 
        res = read(fd,buf,10);
 
       
 
        for( c=0; c<res; c++)
 
        {
 
          printf("%c", (char) buf[c]);
 
        }
 
       
 
}
 
    tcsetattr(fd,TCSANOW,&oldtio);/* restore old port settings */
 
return 0;
 
}
 
</pre></code>
 
 
 
== Самостоятелна подготовка ==
 
1. Напишете името си на латиница, преобразувайте буквите с двоичен код и създайте времева диаграма на физическия сигнал.
 
1. Да се напише програма, която изпраща символите от клавиатурата към серийния порт.
 
 
 
== Край ==
 
 
 
''' Задача 11 ''' Деинсталирайте GTKterm.
 
  
'' '''Упътване:''' Използвайте командата.
+
<?= (isset($status))? $status:'' ?>
<code><pre>
+
</form>
:~$ sudo apt-get purge gtkterm
+
</body>
 +
</html>
 
</pre></code>
 
</pre></code>
  
 
+
<math>x^1</math>
== Литература ==
+
[[Category:Компютърни интерфейси| ]]
 
 
[[Category: Компютърна периферия]]
 

Latest revision as of 09:29, 4 November 2019

Цел на упражнението

Запознаване със сериен порт

RS-232C

Интерфейсът RS-232 е с повече от половин век история и в момента когато казваме "сериен порт" най-често става дума за RS-232. В сравнение със съвременните мегабитови интерфейси като USB (също сериен интерфейс), RS-232 връзката изглежда бавна и ненужна, но тя e същественa поради няколко причини:

  • За разбиране на процеса на комуникация с операционната система. Текстовият интерфейс е в основата на всяка една операционна система, а той e базиран върху концепцията на серийния терминал. Днес хардуерният текстов терминал е заместен с псевдо терминал.
Псевдо терминал Linux
ASR-33 TeleTYpe
VT05 Първият терминал с екран


  • Все още се ползва, въпреки че е загубила широката си употреба. Серийния интрефейс се среща за връзка с индустриални контролери и комуникационна апаратура.
  • USB, Bluetooth, IrDA предлагат средства за емулиране на RS232 серийна връзка
DB-25
DB-9
RJ-45


Повечето серийни интерфейси с ниска скорост са някакъв вариант на RS-232C стандарта. Този стандарт определя електрическите характеристики и значението на сигнала по всеки от проводниците, както и разположението на пиновете в традиционния 25 пинов конектор (DB-25p фиг.4).

Пълният стандарт RS-232C (EIA-232-E, ITU-T V.24) реално не се използва, защото определя множество сигнали, които са ненужни при обикновена комуникация. DB-25 конекторите са неудобни и поради големината си. В резултат на това те са заместени от 9 пинов конектор (DB-9, фиг.5), а като удобна алтернатива се ползва и RJ-45.

В таблицата са дадени наименованията на сигналите и разположението им на пиновете. Обикновено се ползват 7 проводника за осъществяване на връзка (DSR и DCD; FG и SG; ползват общ проводник).

Таблица със значенията на пиновете (мъжки куплунг) за различните конектори.

DB-25DB-9RJ-45ИмеЗначение
1 - - FDFrame Ground
236TDTransmitted Data
325RDReceived Data
478RTSRequest To Send
587CTSClear To Send
661DSRData Set Ready
754SGSignal Ground
812DCDData Carrier Detect
2043DTRData Terminal Ready

На фигури 4,5 и 6 са дедени разположенията на мъжките пинове, в женския конектор те са разположени огледално.

Свързване

При свързване на две устройства с RS-232 сигналът за предаване (Tx,TD) от едно устройство трябва да се подава на пин за приемане (Rx,RD) на второто устройство. Съществуват два типа конфигурации на серийните устройствата:

  • DTE (Data Terminal Equipment) - формално управлява връзката (master) стандартна схема на свързване
  • DCE (Data Communications Equipment) - (slave) обърната сигнализация.

Принципно могат да се свързват устройства DTE към DCT, DTE към DTE, DCT към DCT

Примерно:

  • компютър (DTE)-rs232-(DCE)modem-FM-modem(DCE)-rs232-(DTE)компютър
  • компютър (DTE)-(DTE)компютър.

Всяко едно устройство може да е конфигурирано или като DTE или като DCE, рядко може да поддържа и двата варианта, но не в един и същ момент.

Когато устройствата са еднотипни за връзка между тях трябва да се ползва кръстосан кабел, наречен още null modem кабел. За връзка DТE-DCE се ползва прав кабел. Съществува и трета разновидност на кабели използвана при cisco апаратура наречени "rollover" кабели, при които изводите в единия край са огледално пренаредени в другия.

Конфигурация на Null Modem кабел

DB9-1 пин/проводник DB9-2 пин/проводник
Receive Data
2
3
Transmit Data
Transmit Data
3
2
Receive Data
Data Terminal Ready
4
6+1
Data Set Ready + Carrier Detect
System Ground
5
5
System Ground
Data Set Ready + Carrier Detect
6+1
4
Data Terminal Ready
Request to Send
7
8
Clear to Send
Clear to Send
8
7
Request to Send

Скорост на предаване

За успешна комуникация скоростта на предаване на едното устройство трябва да е равна на скоростта на приемане на второто устройство. Повечето серийни контролери не поддържат автоматичен избор на скоростта, затова се налага ръчна конфигурация за съгласуване на двете устройства.

Поддържаните скорости зависят от серийния контролер, обикновено са в границите между 50 bit/s 110, 300, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200 bit/s(= 1.8432 MHz / 16)

Възможна е асиметрична връзка (скоростта в двете посоки (Up/Down link) е различна).

Понякога името на параметъра дефиниращ скоростта се нарича baud (J. M. Emile Baudot, - бод - сивола в секунда.)

Проверка по четност

Към изпращания символ може да се добави един бит за откриване на грешки възникнали при предаване на сигнала. Възможни са три конфигурации:

  • проверка по четност
  • проверка по нечетност
  • без бит за проверка

Брой битове

Възможни са различни конфигурации на за броя битове в един символ. Най-често се използва 8 бита съответсващи на един байт. Използват и 7 бита от които са достатъчни за един ASCII символ.

Старт/стоп битове

След всеки предаден символ линията се поставя в ниско ниво с продължителност от 1, 1.5 или 2 бита.

За начало на предаване пред всеки символ линията се поставя в високо ниво с продължите от 1 бит.

FLOW CONTROL

При препълване на входните буферите може да се поиска спиране на предаването. Може да се реализира софтуерно и хардуерно.

При софтуерна реализация (Xon/Xoff) по линията (RD/TD) от приемника се изпращат специални символи, които трябва да известят предаващата страна за спиране или възстановяване на предаването.

При хардуерна реализация се ползват линиите RTS/CTS или DTR/DSR. За да има предаване двете линии трябва са да във високо ниво.


Задача: връзка DTE-DTE / Windows-Linux

Задача. Свържете два компютъра един с Linux OS и един Windows OS с кръстосан сериен кабел(null modem) през RS232 порта. Настройте съответно двете програми Minicom и PuTTY да предават и приемат с еднакви параметри.

  • Тествайте различни настройки за скорости на предаване, проверка по четност и т.н.

Упътване

  • За Ubuntu:
    • Инсталирайте терминалната програма за комуникация през сериен порт minicom. Използвайте командата
:~$ apt-get install minicom
    • След инсталацията може да намерите програмата в Applications -> Accessories.
    • направете съответните настройки
  • За Windows
    • Свалете от Internet програмата Putty
    • Стартирайте Putty и направете съответните настроийки
    • Или ползвайте Hyper Terminal:
START -> Programs -> Accessories -> Communications -> Hyper Terminal

сигнализация

RS232C определя следните нива на сигналите за предаване/приемане

  • на логическа 1 от -15V до -3V
  • на логическа 0 от +3V до +15V

Максималното допустимо напрежение на празен ход е +/- 25V.

Примерен сигнал Подредба на битовете. Първо се изпраща бита с най-малко тегло. (small endian)

Осцилограма на символа "К" от ASCII изпратен с 8 бита, един стопов бит и без контрол по чечност е дадена на фиг. 7. К <=> 01001011

фиг7. Осцилограма на главна буква ASCII "K" (0x4b) с 1 старт, 8 данни и 1 стоп битове. LSB/MSB - Least/Most Significant Bit

Задача: Направете времева диаграма на първите две букви на името си, ако имате следната конфигурацията на серийната връзка

  • 8 бита за символ
  • проверка по четност/нечетност ако последната цифра на фак. номера ви е четна/нечетна
  • 2 стоп бита

Задача: Да се реализира серийна връзка между две виртуални машини

Задача: Да се реализира достъп до серийния порт през Интернет с ser2net

(Инсталира се ser2net и се конфигурира). Използва се telnet

Задача: Да се реализира достъ до серийния порт през WEB (s ser2net, PHP и Apache) Достъпва като стандартен сокет. Ползвайте кода по-долу:

if(isset($_POST['message']))
{
  $fp =fsockopen("localhost", 2000);
  
  if( !$fp) {
    echo "Error";die();
  }
  fread($fp, 128);
  fwrite($fp, "$_POST[message]");
  $status = fread($fp, 128);
  fclose($fp);


}

?>
<html><head></head>
<body>
<form name="serial" action="" method="post">
Message:  <input name="message" type="text"><input type="submit" value="Send">

<?= (isset($status))? $status:'' ?>
</form>
</body>
</html>