linux 下串口通信

以前跟着做过VxWorks的开发,主要通信方式是串口,因为底层BSP包已经做好了,串口通信非常简单。后来接触Linux,在一块OK6410上跑Linux串口通信,才发现原来天真的以为甚是简单的串口变得如此的不简单。

#include <termios.h>

1、串口的操作

1.1打开:fd = open("/dev/ttySAC1", O_RDWR | O_NOCTTY | O_NDELAY);
              O_RDWR 读写方式打开;
              O_NOCTTY 不允许进程管理串口(不太理解,一般都选上);
              O_NDELAY 非阻塞(默认为阻塞,打开后也可以使用fcntl()重新设置)

1.2写入:n = write(fd, "linux", 5);
                n实际写入字节数;

1.3读取:res = read(fd,buf,len);
                 res 读取的字节数;

1.4设置:fcntl(fd, F_SETFL, FNDELAY); //非阻塞
                 fcntl(fd, F_SETFL, 0); // 阻塞

1.5关闭:close(fd);

2、串口配置

struct termios options;  // 串口配置结构体
tcgetattr(fd,&options); //获取当前设置
bzero(&options,sizeof(options));
options.c_cflag  |= B115200 | CLOCAL | CREAD; // 设置波特率,本地连接,接收使能
options.c_cflag &= ~CSIZE; //屏蔽数据位
options.c_cflag  |= CS8; // 数据位为 8 ,CS7 for 7
options.c_cflag &= ~CSTOPB; // 一位停止位, 两位停止为 |= CSTOPB
options.c_cflag &= ~PARENB; // 无校验
 //options.c_cflag |= PARENB; //有校验
//options.c_cflag &= ~PARODD // 偶校验
//options.c_cflag |=  PARODD    // 奇校验
options.c_cc[VTIME] = 0; // 等待时间,单位百毫秒 (读)。后有详细说明
options.c_cc[VMIN] = 0; // 最小字节数 (读)。后有详细说明
tcflush(fd, TCIOFLUSH); // TCIFLUSH刷清输入队列。
                                       TCOFLUSH刷清输出队列。 
                                       TCIOFLUSH刷清输入、输出队列。
tcsetattr(fd, TCSANOW, &options); // TCSANOW立即生效;
                                                        TCSADRAIN:Wait until everything has been transmitted;
                                                        TCSAFLUSH:Flush input and output buffers and make the change

3、VTIME 和  VMIN

VTIME  定义要求等待的零到几百毫秒的值(通常是一个8位的unsigned char变量)。
VMIN 定义了要求等待的最小字节数, 这个字节数可能是0。
只有设置为阻塞时这两个参数才有效,仅针对于读操作。
说起来比较复杂,举个例子吧,设置为阻塞状态,写操作未进行实验,这里仅讨论读操作,
read(fd,&buf,8); // 读串口

3.1
options.c_cc[VTIME] = 0;
options.c_cc[VMIN] = 0;
VMIN = 0,当缓冲区字节数 >= 0 时进行读操作,实际上这时读串口操作并未被阻塞,因为条件始终被满足。

3.2
options.c_cc[VTIME] = 0;
options.c_cc[VMIN] = 1;
VMIN = 1,当缓冲区字节数 >= 1 时进行读操作,当没有数据时读串口操作被阻塞。

3.3
options.c_cc[VTIME] = 0;
options.c_cc[VMIN] = 4;
VMIN = 4,当缓冲区字节数 >= 4 时进行读操作,否则读串口操作被阻塞。每次读出的最大字节数由read函数中第三个参数决定。直到缓冲区剩下的数据< read 第三个参数 并且< 4 (如果这时read第三参数为 1 则进行4次读操作直至读完缓冲区,如read第三参数为2,连续进行读操作,直至缓冲区空或还剩一个字符)。没有设置VTIME,剩下的字符没有确定的期限,直到下次满足读条件的时候才被读出。

----------------------------------考虑VTIME-----------------------------

3.4
options.c_cc[VTIME] = 10; //单位百毫秒
options.c_cc[VMIN] = 4;
同3.3的区别就是,没满足条件或读缓冲区中剩下的数据会在1秒(10百毫秒)后读出。另外特别注意的是当设置VTIME后,如果read第三个参数小于VMIN ,将会将VMIN 修改为read的第三个参数,即使用read(fd,&buf,2);,以上设置变为:
options.c_cc[VTIME] = 10;
options.c_cc[VMIN] = 2;

 

 

==================================================================================================================================

1.打开串口函数open_port()中要实现的函数:
(1)open("/dev/ttys0",O_RDWR | O_NOCTTY | O_NDELAY);/*打开串口0*/
(2)fcntl(fd,F_SETFL,0)/*恢复串口为阻塞状态*/
(3)isatty(STDIN_FILENO) /*测试是否为中断设备 非0即是中断设备*/

2.配置串口参数函数set_opt()中要实现的函数:
(1)保存原先有串口配置
tcgetattr(fd,&oldtio);

(2)先将新串口配置清0
bzore(&newtio,sizeof(newito));

(3)激活选项CLOCAL和CREAD 并设置数据位大小
newtio.c_cflag |=CLOCAL | CREAD;
newtio.c_cflag &= ~CSIZE;
newtio.c_cflag |=CS8;

(4)设置奇偶校验
奇校验:
newtio.c_cflag |= PARENB;
newtio.c_cflag |= PARODD;
newtio.c_iflag |= (INPCK | ISTRIP);
偶校验:
newtio.c_iflag |= (INPCK | ISTRIP);
newtio.c_cflag |= PAREND;
newtio.c_cflag &= ~PARODD;
无奇偶校验:
newtio.c_cflag &= ~PARENB;

(5) 设置停止位
newtio.c_cflag &= ~CSTOPB; /*停止位为1*/
newtio.c_cflag |= CSTOPB;/*停止位为0*/

(6)设置波特率:
cfsetispeed(&newtio,B115200);
cfsetospeed(&newtio,B115200);

(7)设置等待时间和最小接受字符:
newtio.c_cc[VTIME] = 0;
newtio.c_cc[VMIN] = 0;

(8)处理为接收字符:
tcflush(fd,TCIFLUSH);

(9)激活新配置:
tcsetattr(fd,TCSANOW,&newtio);
3.读写串口
write(fd,buff,8);
read(fd,buff,8);


例程:

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <stdlib.h>
int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop)
{
/* 五个参量 fd打开文件 speed设置波特率 bit数据位设置   neent奇偶校验位 stop停止位 */
    struct termios newtio,oldtio;
    if ( tcgetattr( fd,&oldtio) != 0) {
        perror("SetupSerial 1");
        return -1;
    }
    bzero( &newtio, sizeof( newtio ) );
    newtio.c_cflag |= CLOCAL | CREAD;
    newtio.c_cflag &= ~CSIZE;
    switch( nBits )
    {
    case 7:
        newtio.c_cflag |= CS7;
    break;
    case 8:
        newtio.c_cflag |= CS8;
    break;
    }
    switch( nEvent )
    {
    case 'O':
        newtio.c_cflag |= PARENB;
        newtio.c_cflag |= PARODD;
        newtio.c_iflag |= (INPCK | ISTRIP);
        break;
    case 'E':
        newtio.c_iflag |= (INPCK | ISTRIP);
        newtio.c_cflag |= PARENB;
        newtio.c_cflag &= ~PARODD;
        break;
    case 'N':
        newtio.c_cflag &= ~PARENB;
        break;
    }
switch( nSpeed )
    {
    case 2400:
        cfsetispeed(&newtio, B2400);
        cfsetospeed(&newtio, B2400);
        break;
    case 4800:
        cfsetispeed(&newtio, B4800);
         cfsetospeed(&newtio, B4800);
        break;
    case 9600:
        cfsetispeed(&newtio, B9600);
        cfsetospeed(&newtio, B9600);
        break;
    case 115200:
        cfsetispeed(&newtio, B115200);
        cfsetospeed(&newtio, B115200);
        break;
    default:
        cfsetispeed(&newtio, B9600);
        cfsetospeed(&newtio, B9600);
        break;
    }
    if( nStop == 1 )
        newtio.c_cflag &= ~CSTOPB;
    else if ( nStop == 2 )
    newtio.c_cflag |= CSTOPB;
    newtio.c_cc[VTIME] = 0;
    newtio.c_cc[VMIN] = 0;
    tcflush(fd,TCIFLUSH);
    if((tcsetattr(fd,TCSANOW,&newtio))!=0)
    {
        perror("com set error");
        return -1;
    }
    printf("set done!\n");
    return 0;
}
int open_port(int fd,int comport)
{
/* fd 打开串口 comport表示第几个串口 */
    char *dev[]={"/dev/ttyS0","/dev/ttyS1","/dev/ttyS2"};
    long vdisable;
    if (comport==1)
    {    fd = open( "/dev/ttyS0", O_RDWR|O_NOCTTY|O_NDELAY);
        if (-1 == fd){
            perror("Can't Open Serial Port");
            return(-1);
        }
        else
            printf("open ttyS0 .....\n");
    }
    else if(comport==2)
    {    fd = open( "/dev/ttyS1", O_RDWR|O_NOCTTY|O_NDELAY);

    if (-1 == fd){
        perror("Can't Open Serial Port");
            return(-1);
        }
        else
            printf("open ttyS1 .....\n");
    }
    else if (comport==3)
    {
        fd = open( "/dev/ttyS2", O_RDWR|O_NOCTTY|O_NDELAY);
        if (-1 == fd){
            perror("Can't Open Serial Port");
            return(-1);
        }
        else
            printf("open ttyS2 .....\n");
    }
    if(fcntl(fd, F_SETFL, 0)<0)
        printf("fcntl failed!\n");
    else
        printf("fcntl=%d\n",fcntl(fd, F_SETFL,0));
    if(isatty(STDIN_FILENO)==0)
        printf("standard input is not a terminal device\n");
    else
        printf("isatty success!\n");
    printf("fd-open=%d\n",fd);
    return fd;
}
int main(void)
{
    int fd;
    int nread,i;
    char buff[]="Hello\n";
    if((fd=open_port(fd,1))<0){
        perror("open_port error");
        return;
    }
    if((i=set_opt(fd,115200,8,'N',1))<0){
    perror("set_opt error");
        return;
    }
    printf("fd=%d\n",fd);
//    fd=3;
    nread=read(fd,buff,8);
    printf("nread=%d,%s\n",nread,buff);
    close(fd);
    return;

}


我自己的程序:

/

#ifndef _COM_H
#define _COM_H

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <stdlib.h>

int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop);
int open_port(int fd,int comport);
unsigned char uart_cmd(unsigned char *buffer,int tx, int rx);

#endif


/

#include "com.h"

//使用开发板的con2(con0,con1,con2)

 

int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop)
{
/* 五个参量 fd打开文件 speed设置波特率 bit数据位设置   neent奇偶校验位 stop停止位 */
    struct termios newtio,oldtio;
    if ( tcgetattr( fd,&oldtio) != 0) {
        perror("SetupSerial 1");
        return -1;
    }
    bzero( &newtio, sizeof( newtio ) );
    newtio.c_cflag |= CLOCAL | CREAD;
    newtio.c_cflag &= ~CSIZE;
newtio.c_oflag &= ~(ONLCR | OCRNL); //
newtio.c_iflag &= ~(IXON | IXOFF | IXANY);    //
    switch( nBits )
    {
    case 7:
        newtio.c_cflag |= CS7;
    break;
    case 8:
        newtio.c_cflag |= CS8;
    break;
    }
    switch( nEvent )
    {
    case 'O':
        newtio.c_cflag |= PARENB;
        newtio.c_cflag |= PARODD;
        newtio.c_iflag |= (INPCK | ISTRIP);
        break;
    case 'E':
        newtio.c_iflag |= (INPCK | ISTRIP);
        newtio.c_cflag |= PARENB;
        newtio.c_cflag &= ~PARODD;
        break;
    case 'N':
        newtio.c_cflag &= ~PARENB;
        break;
    }
switch( nSpeed )
    {
    case 2400:
        cfsetispeed(&newtio, B2400);
        cfsetospeed(&newtio, B2400);
        break;
    case 4800:
        cfsetispeed(&newtio, B4800);
         cfsetospeed(&newtio, B4800);
        break;
    case 9600:
        cfsetispeed(&newtio, B9600);
        cfsetospeed(&newtio, B9600);
        break;
    case 115200:
        cfsetispeed(&newtio, B115200);
        cfsetospeed(&newtio, B115200);
        break;
    default:
        cfsetispeed(&newtio, B9600);
        cfsetospeed(&newtio, B9600);
        break;
    }
    if( nStop == 1 )
        newtio.c_cflag &= ~CSTOPB;
    else if ( nStop == 2 )
    newtio.c_cflag |= CSTOPB;
    newtio.c_cc[VTIME] =5; //测试时该大一点
    newtio.c_cc[VMIN] = 0;//set min read byte!
    tcflush(fd,TCIFLUSH);
    if((tcsetattr(fd,TCSANOW,&newtio))!=0)
    {
        perror("com set error");
        return -1;
    }
    printf("set done!\n");
    return 0;
}
int open_port(int fd,int comport)
{
/* fd 打开串口 comport表示第几个串口 */
    char *dev[]={"/dev/ttySAC0","/dev/ttySAC1","/dev/ttySAC2"};
    long vdisable;
    if (comport==1)
    {    fd = open( "/dev/ttySAC0", O_RDWR|O_NOCTTY|O_NDELAY);
        if (-1 == fd){
            perror("Can't Open Serial Port");
            return(-1);
        }
        else
            printf("open ttySAC0 .....\n");
    }
    else if(comport==2)
    {    fd = open( "/dev/ttySAC1", O_RDWR|O_NOCTTY|O_NDELAY);

    if (-1 == fd){
        perror("Can't Open Serial Port");
            return(-1);
        }
        else
            printf("open ttySAC1 .....\n");
    }
    else if (comport==3)
    {
        fd = open( "/dev/ttySAC2", O_RDWR|O_NOCTTY|O_NDELAY);
        if (-1 == fd){
            perror("Can't Open Serial Port");
            return(-1);
        }
        else
            printf("open ttySAC2 .....\n");
    }
    if(fcntl(fd, F_SETFL, 0)<0)
        printf("fcntl failed!\n");
    else
        printf("fcntl=%d\n",fcntl(fd, F_SETFL,0));
    if(isatty(STDIN_FILENO)==0)
        printf("standard input is not a terminal device\n");
    else
        printf("isatty success!\n");
    printf("fd-open=%d\n",fd);
    return fd;
}

//我的应用函数
unsigned char uart_cmd(unsigned char *buffer,int tx, int rx)
{
int fd;
int i;
int nread=0;
int nwrite=0;
unsigned char mybuffer[520],buffer1[520];
if(( fd=open_port(fd,3)) < 0)//使用开发板的con2
{
   perror("open_port error");
   return -1;
}

if(( i=set_opt(fd,115200,8,'N',1) ) < 0)
{
   perror("set_opt error");
   return -1;
}

if(( nwrite=write(fd,buffer,tx)) != tx)
{
   perror("write error");
   return -1;
}
printf("nwrite=%d\n",nwrite);

for(i=0;i<rx;i++)//read only one byte once,loop for rx times!
{
   if((nread=read(fd,mybuffer+i,1)) != 1)
   {
    perror("read error");
    return -1;
   }
}
mybuffer[rx]='\0';


strncpy(buffer,mybuffer,rx+1);

close(fd);
return 0;
}

 ===========================================================================================================================

1、获取文件的flags,即open函数的第二个参数:

       flags = fcntl(fd,F_GETFL,0);

2、设置文件的flags:

      fcntl(fd,F_SETFL,flags);

3、增加文件的某个flags,比如文件是阻塞的,想设置成非阻塞:

       flags = fcntl(fd,F_GETFL,0);

       flags |= O_NONBLOCK;

      fcntl(fd,F_SETFL,flags);

4、取消文件的某个flags,比如文件是非阻塞的,想设置成为阻塞:

      flags = fcntl(fd,F_GETFL,0);

      flags &= ~O_NONBLOCK;

      fcntl(fd,F_SETFL,flags);

 

 

获取和设置文件flags举例::

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <error.h>

char buf[500000];

int main(int argc,char *argv[])
{
        int ntowrite,nwrite;
        const char *ptr ;
        int flags;
   
        ntowrite = read(STDIN_FILENO,buf,sizeof(buf));
        if(ntowrite <0)
        {  
                perror("read STDIN_FILENO fail:");
                exit(1);
        }  
        fprintf(stderr,"read %d bytes\n",ntowrite);
   
        if((flags = fcntl(STDOUT_FILENO,F_GETFL,0))==-1)
        {  
                perror("fcntl F_GETFL fail:");
                exit(1);
        }  
        flags |= O_NONBLOCK;
        if(fcntl(STDOUT_FILENO,F_SETFL,flags)==-1)
        {  
                perror("fcntl F_SETFL fail:");
                exit(1);
        }  
   
        ptr = buf;
        while(ntowrite > 0)
        {  
                nwrite = write(STDOUT_FILENO,ptr,ntowrite);
                if(nwrite == -1)
                {  

                        perror("write file fail:");
                }  
                if(nwrite > 0)
                {  
                        ptr += nwrite;
                        ntowrite -= nwrite;
                }  
        }  
   
        flags &= ~O_NONBLOCK;
        if(fcntl(STDOUT_FILENO,F_SETFL,flags)==-1)
        {  
                perror("fcntl F_SETFL fail2:");
        }  
        return 0;
}

===============================================================================================================================

This chapter discusses how to configure a serial port from C using the POSIX termios interface.

The POSIX Terminal Interface

Most systems support the POSIX terminal (serial) interface for changing parameters such as baud rate, character size, and so on. The first thing you need to do is include the file<termios.h>; this defines the terminal control structure as well as the POSIX control functions.

The two most important POSIX functions are tcgetattr(3) and tcsetattr(3). These get and set terminal attributes, respectively; you provide a pointer to atermios structure that contains all of the serial options available:

Table 3 - Termios Structure Members
MemberDescription
c_cflagControl options
c_lflagLine options
c_iflagInput options
c_oflagOutput options
c_ccControl characters
c_ispeedInput baud (new interface)
c_ospeedOutput baud (new interface)

Control Options

The c_cflag member controls the baud rate, number of data bits, parity, stop bits, and hardware flow control. There are constants for all of the supported configurations.
Table 4 - Constants for the c_cflag Member
ConstantDescription
CBAUDBit mask for baud rate
B00 baud (drop DTR)
B5050 baud
B7575 baud
B110110 baud
B134134.5 baud
B150150 baud
B200200 baud
B300300 baud
B600600 baud
B12001200 baud
B18001800 baud
B24002400 baud
B48004800 baud
B96009600 baud
B1920019200 baud
B3840038400 baud
B5760057,600 baud
B7680076,800 baud
B115200115,200 baud
EXTAExternal rate clock
EXTBExternal rate clock
CSIZEBit mask for data bits
CS55 data bits
CS66 data bits
CS77 data bits
CS88 data bits
CSTOPB2 stop bits (1 otherwise)
CREADEnable receiver
PARENBEnable parity bit
PARODDUse odd parity instead of even
HUPCLHangup (drop DTR) on last close
CLOCALLocal line - do not change "owner" of port
LOBLKBlock job control output
CNEW_RTSCTS
CRTSCTS
Enable hardware flow control (not supported on all platforms)

The c_cflag member contains two options that should always be enabled,CLOCAL and CREAD. These will ensure that your program does not become the 'owner' of the port subject to sporatic job control and hangup signals, and also that the serial interface driver will read incoming data bytes.

The baud rate constants (CBAUD, B9600, etc.) are used for older interfaces that lack thec_ispeed and c_ospeed members. See the next section for information on the POSIX functions used to set the baud rate.

Never initialize the c_cflag (or any other flag) member directly; you should always use the bitwise AND, OR, and NOT operators to set or clear bits in the members. Different operating system versions (and even patches) can and do use the bits differently, so using the bitwise operators will prevent you from clobbering a bit flag that is needed in a newer serial driver.

Setting the Baud Rate

The baud rate is stored in different places depending on the operating system. Older interfaces store the baud rate in thec_cflag member using one of the baud rate constants in table 4, while newer implementations provide thec_ispeed and c_ospeed members that contain the actual baud rate value.

The cfsetospeed(3) and cfsetispeed(3) functions are provided to set the baud rate in thetermios structure regardless of the underlying operating system interface. Typically you'd use the following code to set the baud rate:

  • Listing 2 - Setting the baud rate.

    struct termios options;
    
    /*
     * Get the current options for the port...
     */
    
    tcgetattr(fd, &options);
    
    /*
     * Set the baud rates to 19200...
     */
    
    cfsetispeed(&options, B19200);
    cfsetospeed(&options, B19200);
    
    /*
     * Enable the receiver and set local mode...
     */
    
    options.c_cflag |= (CLOCAL | CREAD);
    
    /*
     * Set the new options for the port...
     */
    
    tcsetattr(fd, TCSANOW, &options);
    

The tcgetattr(3) function fills the termios structure you provide with the current serial port configuration. After we set the baud rates and enable local mode and serial data receipt, we select the new configuration usingtcsetattr(3). The TCSANOW constant specifies that all changes should occur immediately without waiting for output data to finish sending or input data to finish receiving. There are other constants to wait for input and output to finish or to flush the input and output buffers.

Most systems do not support different input and output speeds, so be sure to set both to the same value for maximum portability.

Table 5 - Constants for tcsetattr
ConstantDescription
TCSANOWMake changes now without waiting for data to complete
TCSADRAINWait until everything has been transmitted
TCSAFLUSHFlush input and output buffers and make the change

Setting the Character Size

Unlike the baud rate, there is no convienience function to set the character size. Instead you must do a little bitmasking to set things up. The character size is specified in bits:

  • options.c_cflag &= ~CSIZE; /* Mask the character size bits */
    options.c_cflag |= CS8;    /* Select 8 data bits */
    
Setting Parity Checking

Like the character size you must manually set the parity enable and parity type bits. UNIX serial drivers support even, odd, and no parity bit generation. Space parity can be simulated with clever coding.

  • No parity (8N1):
    options.c_cflag &= ~PARENB
    options.c_cflag &= ~CSTOPB
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS8;
    
  • Even parity (7E1):
    options.c_cflag |= PARENB
    options.c_cflag &= ~PARODD
    options.c_cflag &= ~CSTOPB
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS7;
    
  • Odd parity (7O1):
    options.c_cflag |= PARENB
    options.c_cflag |= PARODD
    options.c_cflag &= ~CSTOPB
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS7;
    
  • Space parity is setup the same as no parity (7S1):
    options.c_cflag &= ~PARENB
    options.c_cflag &= ~CSTOPB
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS8;
    
Setting Hardware Flow Control

Some versions of UNIX support hardware flow control using the CTS (Clear To Send) and RTS (Request To Send) signal lines. If theCNEW_RTSCTS or CRTSCTS constants are defined on your system then hardware flow control is probably supported. Do the following to enable hardware flow control:

  • options.c_cflag |= CNEW_RTSCTS;    /* Also called CRTSCTS */
    

Similarly, to disable hardware flow control:

  • options.c_cflag &= ~CNEW_RTSCTS;
    

Local Options

The local modes member c_lflag controls how input characters are managed by the serial driver. In general you will configure thec_lflag member for canonical or raw input.

Table 6 - Constants for the c_lflag Member
ConstantDescription
ISIGEnable SIGINTR, SIGSUSP, SIGDSUSP, and SIGQUIT signals
ICANONEnable canonical input (else raw)
XCASEMap uppercase \lowercase (obsolete)
ECHOEnable echoing of input characters
ECHOEEcho erase character as BS-SP-BS
ECHOKEcho NL after kill character
ECHONLEcho NL
NOFLSHDisable flushing of input buffers after interrupt or quit characters
IEXTENEnable extended functions
ECHOCTLEcho control characters as ^char and delete as ~?
ECHOPRTEcho erased character as character erased
ECHOKEBS-SP-BS entire line on line kill
FLUSHOOutput being flushed
PENDINRetype pending input at next read or input char
TOSTOPSend SIGTTOU for background output

Choosing Canonical Input

Canonical input is line-oriented. Input characters are put into a buffer which can be edited interactively by the user until a CR (carriage return) or LF (line feed) character is received.

When selecting this mode you normally select the ICANON, ECHO, andECHOE options:

  • options.c_lflag |= (ICANON | ECHO | ECHOE);
    
Choosing Raw Input

Raw input is unprocessed. Input characters are passed through exactly as they are received, when they are received. Generally you'll deselect theICANON, ECHO, ECHOE, and ISIG options when using raw input:

  • options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
    
     
    ==================================================================================================================

    #include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <termios.h>

    int main(void) {         int fd;         struct termios opts;

            fd = open("/dev/ttyS0", O_RDWR);         if (fd < 0)         {                 perror("open ttys0");                 return 1;         }

            tcgetattr(fd, &opts);

            opts.c_cflag |= CLOCAL;         opts.c_cflag &= ~CRTSCTS;

            opts.c_cflag &= ~CSIZE;         opts.c_cflag |= CS8;         opts.c_cflag &= ~CSTOPB;

            opts.c_cflag &= ~PARENB;

            cfsetispeed(&opts, B9600);         cfsetospeed(&opts, B9600);

            tcsetattr(fd, TCSANOW, &opts);

            while (1)         {                 write(fd, "hello", 5);                 sleep(2);

            char buf[512];

            fd = open("/dev/ttyS0", O_RDWR);         if (fd < 0)         {                 perror("open ttys0");                 return 1;         }

            tcgetattr(fd, &opts);

            opts.c_cflag |= CLOCAL;         opts.c_cflag |= CREAD;         opts.c_cflag &= ~CRTSCTS;

            opts.c_cflag &= ~CSIZE;         opts.c_cflag |= CS8;         opts.c_cflag &= ~CSTOPB;

            opts.c_cflag &= ~PARENB;

            cfsetispeed(&opts, B9600);         cfsetospeed(&opts, B9600);

            tcsetattr(fd, TCSANOW, &opts);

            while (1)         {                 ret = read(fd, buf, 512);                 buf[ret] = '\0';                 printf("from : %s\n", buf);         }

     

  • 3
    点赞
  • 51
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值