Difference between revisions of "Talk:Сериен порт"
m (moved Talk:Упражнение 3. Сериен порт (1) to Talk:Сериен порт) |
|||
(9 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
− | == | + | ==php== |
+ | Инсталира се ser2net и се конфигурира ser2net.conf | ||
+ | После се достъпва като стандартен сокет | ||
+ | |||
+ | <code><pre> | ||
+ | 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> | ||
+ | </pre></code> | ||
+ | |||
+ | == [http://ilianko.com/files/Serial.zip C#] == | ||
+ | |||
+ | |||
+ | <!-- | ||
+ | ''Начин на работа''' | ||
+ | 1. Намерете десетичния код на ASCII символа. | ||
+ | 2. Тествайте следната програма и проверете резултата си от стъпка едно | ||
+ | <code><pre> | ||
+ | /*********************************************************\ | ||
+ | * Title:Convertion from character to integer | ||
+ | * Edited by ilianko | ||
+ | \*********************************************************/ | ||
+ | |||
+ | #include <stdio.h> | ||
+ | |||
+ | #define ASCII_SYMBOL 'a' | ||
+ | |||
+ | int main() | ||
+ | { | ||
+ | //difine varibles | ||
+ | char ascii = ASCII_SYMBOL; | ||
+ | int code; | ||
+ | |||
+ | //convert types | ||
+ | code = (int) ascii; | ||
+ | |||
+ | //formated output | ||
+ | printf("Desetichniqt kod e %i", code); | ||
+ | return 0; | ||
+ | } | ||
+ | </pre></code> | ||
+ | |||
+ | ''Основната причина за съществуване на различни типове данни е да знае компилатора, колко памет да отдели за всяко число, буква или текст, когато съхранява стойностите им. Информацията се ползва и в последствие, при извеждане или при обработка на данните и взаимодействия с други данни.'' | ||
+ | |||
+ | 3. Създайте програма, която да извежда всички букви букви от ASCII кода в поредица AbCdEfGh.... yZ | ||
+ | |||
+ | '' '''Упътване''' . Всяка буква отговаря на число, всяка следваща буква е число с едно по-голямо. Главните букви започват от 65, малките от 97, а общо са 26. Може да ползвате:'' | ||
<code><pre> | <code><pre> | ||
− | int x = | + | int x = 65; |
char y; | char y; | ||
− | y = ( | + | y = (char) x; |
printf( " %c ", y ); | printf( " %c ", y ); | ||
+ | |||
+ | int i = 0; | ||
+ | for (i = 0; i< 26; i = i + 2) | ||
+ | { ... } | ||
</pre></code> | </pre></code> | ||
− | --[[ | + | |
+ | |||
+ | 4. Създайте програма, която след въвеждане на буква от клавиатурата, извежда дали кодът на буквата е с четен или нечетен номер. | ||
+ | |||
+ | '' '''Упътване.''' Може да използвате примера от [[Упражнение 2. Достъп до периферни устройства.|задача 2 на Упражнение 2]] и кодът по-долу.'' | ||
+ | <code><pre> | ||
+ | if ( ((int) s) % 2) puts(" .... "); | ||
+ | else puts(" ... "); | ||
+ | </pre></code> | ||
+ | |||
+ | 5. Изпълнете програматаза преобразуване на буква в двоичен код, разгледайте кода и пробвайте с различни букви. | ||
+ | |||
+ | <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> | ||
+ | |||
+ | '''Проверка по четност''' | ||
+ | |||
+ | 6. Преработете кодът от предната задача, така че да ви показва, колко единици има в двоичното число и дали броят на единици е четен или нечетен. | ||
+ | |||
+ | '' '''Упътване''' Може да замените '' | ||
+ | <code><pre> | ||
+ | ((a & z) == z) ? '0' : '1'; | ||
+ | </pre></code> | ||
+ | със | ||
+ | <code><pre> | ||
+ | int e=0; | ||
+ | ... | ||
+ | if((a & z) == z) | ||
+ | { | ||
+ | ++e; | ||
+ | b[y] = '1'; | ||
+ | } | ||
+ | </pre></code> | ||
+ | --> | ||
+ | ==Конфигуриране на системна конзола == | ||
+ | |||
+ | http://www.cyberciti.biz/faq/howto-setup-serial-console-on-debian-linux/ | ||
+ | |||
+ | В Ubuntu управлението на процесите при стартиране се управляват от Upstart програмата (която заменя и е обратно съвместима с init). | ||
+ | *init e процес номер 1, PID - 1, т.е. той стартира всички останали процеси. | ||
+ | *тествайте следната команда <code>ps -A | less</code> - извежда всички процеси. | ||
+ | |||
+ | |||
+ | След инициализиране на хардуера се стартира програмата '''getty''' и следват следните стъпки за вход: | ||
+ | *'''getty''' извежда съобщението за вход | ||
+ | *потребителят въвежда името на акаунта | ||
+ | *'''getty''' стартира програмата '''login''' с параметър въведеното име | ||
+ | *'''login''' изисква парола и проверя дали акаунтът е валиден в /etc/shadow | ||
+ | *при валиден акаунт '''login''' извежда текущи съобщения от /etc/motd и стартира шел програма (примерно bash) | ||
+ | *'''bash''' налични стартиращи скриптове (.bashrc) | ||
+ | *'''bash''' извежда промта и чака команди | ||
+ | |||
+ | По подразбиране в Ubuntu getty се стартира на виртуални терминали от tty1 до tty6, на tty7 се стартира графичната система. | ||
+ | За да се стартира getty и на серийния порт, то трябва да се добави файл '''/etc/init/ttyS0.conf''' със следното съдържание: | ||
+ | <code><pre> | ||
+ | # ttyS0 - getty | ||
+ | # | ||
+ | # This service maintains a getty on ttyS0 from the point the system is | ||
+ | # started until it is shut down again. | ||
+ | |||
+ | start on stopped rc or RUNLEVEL=[2345] | ||
+ | stop on runlevel [!2345] | ||
+ | |||
+ | respawn | ||
+ | exec /sbin/getty -L 9600 ttyS0 vt102 | ||
+ | </pre></code> | ||
+ | |||
+ | След което да се рестартира компютъра или да се стартира процеса с командата | ||
+ | sudo start ttyS0 | ||
+ | |||
+ | След така направената конфигурация Linux системата е достъпна през сериен порт | ||
+ | |||
+ | Връзки | ||
+ | *[https://help.ubuntu.com/community/SerialConsoleHowto конфигуриране терминал в Ubuntu] | ||
+ | *[http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/term.html freeBSD] | ||
+ | *[http://superuser.com/questions/122353/how-can-i-login-to-ubuntu-using-a-usb-serial-port USB сериен порт UBUNTU > 10.4] | ||
+ | *[http://versalogic.com/kb/KB.asp?kbid=1551 конфигуриране терминал в Debian с Getty] | ||
+ | |||
+ | |||
+ | '''Задача''' Влезте в Ubuntu през системнатa конзола и тествайте командите: | ||
+ | *reboot, | ||
+ | *halt, | ||
+ | *shutdown. | ||
+ | |||
+ | == [[Управление на сериен порт с POSIX|Комуникация през C, POSIX и сериен порт]] == | ||
+ | '''Задача ''' Тествайте програмата, която изпраща информация по-серийния порт. Свържете два компютъра със сериен кабел, като на единия изпълнявате програмата, а на другия сте включили, някоя от терминалните програми за управление на серийната връзка от предходната задача. Тествайте с различни съобщения. | ||
+ | |||
+ | |||
+ | <code><pre> | ||
+ | #include <stdio.h> | ||
+ | #include <unistd.h> | ||
+ | #include <stdlib.h> | ||
+ | #include <signal.h> | ||
+ | #include <sys/wait.h> | ||
+ | #include <sys/types.h> | ||
+ | #include <fcntl.h> | ||
+ | #include <termios.h> | ||
+ | |||
+ | void handler(int nsig) | ||
+ | { | ||
+ | int status; | ||
+ | |||
+ | //wait for change in child | ||
+ | wait(&status); | ||
+ | |||
+ | if(WIFEXITED(status)) | ||
+ | { //if child is exited | ||
+ | printf("Thank You!\n"); | ||
+ | exit(0); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | int main() | ||
+ | { | ||
+ | int pid, serial; | ||
+ | char ch; | ||
+ | struct termios oIn, nIn, oSerial, nSerial; | ||
+ | |||
+ | //open serial port | ||
+ | serial = open("/dev/ttyS0", O_RDWR | O_NOCTTY); | ||
+ | |||
+ | // Signal handler | ||
+ | (void) signal(SIGCHLD, handler); | ||
+ | |||
+ | // Current configuration | ||
+ | tcgetattr(0,&oIn); | ||
+ | tcgetattr(0,&nIn); | ||
+ | tcgetattr(serial,&oSerial); | ||
+ | tcgetattr(serial,&nSerial); | ||
+ | |||
+ | // Raw mode | ||
+ | nIn.c_lflag = 0; | ||
+ | nSerial.c_lflag = 0; | ||
+ | |||
+ | // Set new configuration | ||
+ | tcsetattr(0, TCSANOW, &nIn); //stdin | ||
+ | tcsetattr(serial, TCSANOW, &nSerial); | ||
+ | |||
+ | write(1,"For exit press \'q\' \n", 20); | ||
+ | |||
+ | fflush(stdout); | ||
+ | fflush(stdin); | ||
+ | |||
+ | // Create new process | ||
+ | pid = fork(); | ||
+ | |||
+ | while(1) | ||
+ | { | ||
+ | if(pid < 1) | ||
+ | { // child process | ||
+ | read(0,&ch,1); // read stdin | ||
+ | write(serial,&ch, 1); //write to serial port | ||
+ | |||
+ | if(ch == 'q') | ||
+ | { | ||
+ | tcsetattr(0, TCSANOW, &oIn); //restore original configuration | ||
+ | tcsetattr(serial, TCSANOW, &oSerial); | ||
+ | exit(0); | ||
+ | } | ||
+ | } | ||
+ | else | ||
+ | { // parent process | ||
+ | read(serial,&ch,1); | ||
+ | write(1,&ch, 1); | ||
+ | } | ||
+ | } | ||
+ | return(0); | ||
+ | } | ||
+ | </pre></code> | ||
+ | |||
+ | |||
+ | <code><pre> | ||
+ | /*********************************************************\ | ||
+ | * Title: Write to serial port | ||
+ | * http://www.easysw.com/~mike/serial/serial.html | ||
+ | * Edited by ilianko | ||
+ | \*********************************************************/ | ||
+ | |||
+ | #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 | ||
+ | |||
+ | //Open for reading and writing + special FIFO 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 | ||
+ | { | ||
+ | //reset of file flags | ||
+ | fcntl(fd, F_SETFL, 0); | ||
+ | } | ||
+ | |||
+ | tcgetattr(fd, &options); //read controller settings | ||
+ | |||
+ | |||
+ | cfsetispeed(&options, B2400); // change input speed | ||
+ | cfsetospeed(&options, B2400); // change output speed | ||
+ | |||
+ | options.c_cflag |= ( CREAD); // enable reciever | ||
+ | options.c_cflag |= ( CLOCAL); // Local line - do not change "owner" of port | ||
+ | options.c_cflag &= ( ~CSTOPB); // set 1 stop bit | ||
+ | |||
+ | tcsetattr(fd,TCSANOW, &options); // load the controller settings | ||
+ | |||
+ | write(fd, "a \n", 3); //write to 3 byte to the serial port | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </pre></code> | ||
+ | |||
+ | За повече информация [[Управление на сериен порт с POSIX]], [http://www.easysw.com/~mike/serial/serial.html POSIX serial port] | ||
+ | |||
+ | == Осцилограма == | ||
+ | |||
+ | '''Задача''' Създайте програма с безкраен цикъл, която да изпраща една буква към серийния порт. Използвайте специално пригодения кабел и разгледайте осцилограмата на сериен сигнал. | ||
+ | |||
+ | == Четене сериен порт == | ||
+ | |||
+ | === Raw === | ||
+ | <code><pre> | ||
+ | /****************************************************************\ | ||
+ | * Edited by Ilianko | ||
+ | * http://www.easysw.com/~mike/serial/serial.html | ||
+ | * 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> | ||
+ | |||
+ | == Самостоятелна подготовка == | ||
+ | #Напишете името си на латиница, преобразувайте буквите с двоичен код и създайте времева диаграма на физическия сигнал. | ||
+ | #Да се напише програма, която изпраща символите от клавиатурата към серийния порт. | ||
+ | #Която да се логва през системната конзола и да рестартира Linux системата. | ||
+ | |||
+ | == Край == | ||
+ | |||
+ | ''' Задача 11 ''' Деинсталирайте GTKterm. | ||
+ | |||
+ | '' '''Упътване:''' Използвайте командата. | ||
+ | <code><pre> | ||
+ | :~$ sudo apt-get purge gtkterm | ||
+ | </pre></code> | ||
+ | |||
+ | |||
+ | == Литература == | ||
+ | http://en.wikipedia.org/wiki/RS-232 | ||
+ | https://learn.sparkfun.com/tutorials/serial-communication/wiring-and-hardware |
Latest revision as of 18:18, 23 February 2015
Contents
php
Инсталира се ser2net и се конфигурира ser2net.conf
После се достъпва като стандартен сокет
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>
C#
Конфигуриране на системна конзола
http://www.cyberciti.biz/faq/howto-setup-serial-console-on-debian-linux/
В Ubuntu управлението на процесите при стартиране се управляват от Upstart програмата (която заменя и е обратно съвместима с init).
- init e процес номер 1, PID - 1, т.е. той стартира всички останали процеси.
- тествайте следната команда
ps -A | less
- извежда всички процеси.
След инициализиране на хардуера се стартира програмата getty и следват следните стъпки за вход:
- getty извежда съобщението за вход
- потребителят въвежда името на акаунта
- getty стартира програмата login с параметър въведеното име
- login изисква парола и проверя дали акаунтът е валиден в /etc/shadow
- при валиден акаунт login извежда текущи съобщения от /etc/motd и стартира шел програма (примерно bash)
- bash налични стартиращи скриптове (.bashrc)
- bash извежда промта и чака команди
По подразбиране в Ubuntu getty се стартира на виртуални терминали от tty1 до tty6, на tty7 се стартира графичната система. За да се стартира getty и на серийния порт, то трябва да се добави файл /etc/init/ttyS0.conf със следното съдържание:
# ttyS0 - getty
#
# This service maintains a getty on ttyS0 from the point the system is
# started until it is shut down again.
start on stopped rc or RUNLEVEL=[2345]
stop on runlevel [!2345]
respawn
exec /sbin/getty -L 9600 ttyS0 vt102
След което да се рестартира компютъра или да се стартира процеса с командата
sudo start ttyS0
След така направената конфигурация Linux системата е достъпна през сериен порт
Връзки
- конфигуриране терминал в Ubuntu
- freeBSD
- USB сериен порт UBUNTU > 10.4
- конфигуриране терминал в Debian с Getty
Задача Влезте в Ubuntu през системнатa конзола и тествайте командите:
- reboot,
- halt,
- shutdown.
Комуникация през C, POSIX и сериен порт
Задача Тествайте програмата, която изпраща информация по-серийния порт. Свържете два компютъра със сериен кабел, като на единия изпълнявате програмата, а на другия сте включили, някоя от терминалните програми за управление на серийната връзка от предходната задача. Тествайте с различни съобщения.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <fcntl.h>
#include <termios.h>
void handler(int nsig)
{
int status;
//wait for change in child
wait(&status);
if(WIFEXITED(status))
{ //if child is exited
printf("Thank You!\n");
exit(0);
}
}
int main()
{
int pid, serial;
char ch;
struct termios oIn, nIn, oSerial, nSerial;
//open serial port
serial = open("/dev/ttyS0", O_RDWR | O_NOCTTY);
// Signal handler
(void) signal(SIGCHLD, handler);
// Current configuration
tcgetattr(0,&oIn);
tcgetattr(0,&nIn);
tcgetattr(serial,&oSerial);
tcgetattr(serial,&nSerial);
// Raw mode
nIn.c_lflag = 0;
nSerial.c_lflag = 0;
// Set new configuration
tcsetattr(0, TCSANOW, &nIn); //stdin
tcsetattr(serial, TCSANOW, &nSerial);
write(1,"For exit press \'q\' \n", 20);
fflush(stdout);
fflush(stdin);
// Create new process
pid = fork();
while(1)
{
if(pid < 1)
{ // child process
read(0,&ch,1); // read stdin
write(serial,&ch, 1); //write to serial port
if(ch == 'q')
{
tcsetattr(0, TCSANOW, &oIn); //restore original configuration
tcsetattr(serial, TCSANOW, &oSerial);
exit(0);
}
}
else
{ // parent process
read(serial,&ch,1);
write(1,&ch, 1);
}
}
return(0);
}
/*********************************************************\
* Title: Write to serial port
* http://www.easysw.com/~mike/serial/serial.html
* Edited by ilianko
\*********************************************************/
#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
//Open for reading and writing + special FIFO 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
{
//reset of file flags
fcntl(fd, F_SETFL, 0);
}
tcgetattr(fd, &options); //read controller settings
cfsetispeed(&options, B2400); // change input speed
cfsetospeed(&options, B2400); // change output speed
options.c_cflag |= ( CREAD); // enable reciever
options.c_cflag |= ( CLOCAL); // Local line - do not change "owner" of port
options.c_cflag &= ( ~CSTOPB); // set 1 stop bit
tcsetattr(fd,TCSANOW, &options); // load the controller settings
write(fd, "a \n", 3); //write to 3 byte to the serial port
return 0;
}
За повече информация Управление на сериен порт с POSIX, POSIX serial port
Осцилограма
Задача Създайте програма с безкраен цикъл, която да изпраща една буква към серийния порт. Използвайте специално пригодения кабел и разгледайте осцилограмата на сериен сигнал.
Четене сериен порт
Raw
/****************************************************************\
* Edited by Ilianko
* http://www.easysw.com/~mike/serial/serial.html
* 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;
}
Canonical
/****************************************************************\
* 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;
}
Самостоятелна подготовка
- Напишете името си на латиница, преобразувайте буквите с двоичен код и създайте времева диаграма на физическия сигнал.
- Да се напише програма, която изпраща символите от клавиатурата към серийния порт.
- Която да се логва през системната конзола и да рестартира Linux системата.
Край
Задача 11 Деинсталирайте GTKterm.
Упътване: Използвайте командата.
:~$ sudo apt-get purge gtkterm
Литература
http://en.wikipedia.org/wiki/RS-232 https://learn.sparkfun.com/tutorials/serial-communication/wiring-and-hardware