LINUX 使用tcgetattr与tcsetattr函数控制终端

为了便于通过程序来获得和修改终端参数,Linux还提供了tcgetattr函数和tcsetattr函数。tcgetattr用于获取终端的相关参数,而tcsetattr函数用于设置终端参数。这两个函数的具体信息如表6.2所示。

表6.2 tcgetattr函数和tcsetattr函数

头文件

 

函数形式

int tcgetattr(int fd, struct termios *termios_p);

int tcsetattr(int fd, int optional_actions, const struct termios *termios_p);

返回值

成功

失败

是否设置errno

0

−1

说明:tcgetattr函数用于获取与终端相关的参数。参数fd为终端的文件描述符,返回的结果保存在termios结构体中,该结构体一般包括如下的成员:

 

 
  1. tcflag_t c_iflag;

  2. tcflag_t c_oflag;

  3. tcflag_t c_cflag;

  4. tcflag_t c_lflag;

  5. cc_t c_cc[NCCS];

  6.  


 

其具体意义如下。

 
c_iflag:输入模式标志,控制终端输入方式,具体参数如表6.3所示。

表6.3 c_iflag参数表

键    值

说    明

IGNBRK

忽略BREAK键输入

BRKINT

如果设置了IGNBRK,BREAK键的输入将被忽略,如果设置了BRKINT ,将产生SIGINT中断

IGNPAR

忽略奇偶校验错误

PARMRK

标识奇偶校验错误

INPCK

允许输入奇偶校验

ISTRIP

去除字符的第8个比特

INLCR

将输入的NL(换行)转换成CR(回车)

IGNCR

忽略输入的回车

ICRNL

将输入的回车转化成换行(如果IGNCR未设置的情况下)

IUCLC

将输入的大写字符转换成小写字符(非POSIX)

IXON

允许输入时对XON/XOFF流进行控制

IXANY

输入任何字符将重启停止的输出

IXOFF

允许输入时对XON/XOFF流进行控制

IMAXBEL

当输入队列满的时候开始响铃,Linux在使用该参数而是认为该参数总是已经设置

c_oflag:输出模式标志,控制终端输出方式,具体参数如表6.4所示。

表6.4 c_oflag参数

键    值

说    明

OPOST

处理后输出

OLCUC

将输入的小写字符转换成大写字符(非POSIX)

ONLCR

将输入的NL(换行)转换成CR(回车)及NL(换行)

OCRNL

将输入的CR(回车)转换成NL(换行)

ONOCR

第一行不输出回车符

ONLRET

不输出回车符

OFILL

发送填充字符以延迟终端输出

OFDEL

以ASCII码的DEL作为填充字符,如果未设置该参数,填充字符将是NUL(‘\0’)(非POSIX)

NLDLY

换行输出延时,可以取NL0(不延迟)或NL1(延迟0.1s)

CRDLY

回车延迟,取值范围为:CR0、CR1、CR2和 CR3

TABDLY

水平制表符输出延迟,取值范围为:TAB0、TAB1、TAB2和TAB3

BSDLY

空格输出延迟,可以取BS0或BS1

VTDLY

垂直制表符输出延迟,可以取VT0或VT1

FFDLY

换页延迟,可以取FF0或FF1

c_cflag:控制模式标志,指定终端硬件控制信息,具体参数如表6.5所示。

 

LINUX 使用tcgetattr函数与tcsetattr函数控制终端二

2009-11-24 15:30

表6.5 c_oflag参数

键    值

说    明

CBAUD

波特率(4+1位)(非POSIX)

CBAUDEX

附加波特率(1位)(非POSIX)

CSIZE

字符长度,取值范围为CS5、CS6、CS7或CS8

CSTOPB

设置两个停止位

CREAD

使用接收器

PARENB

使用奇偶校验

PARODD

对输入使用奇偶校验,对输出使用偶校验

HUPCL

关闭设备时挂起

CLOCAL

忽略调制解调器线路状态

CRTSCTS

使用RTS/CTS流控制

c_lflag:本地模式标志,控制终端编辑功能,具体参数如表6.6所示。

 

表6.6 c_lflag参数

键    值

说    明

ISIG

当输入INTR、QUIT、SUSP或DSUSP时,产生相应的信号

ICANON

使用标准输入模式

XCASE

在ICANON和XCASE同时设置的情况下,终端只使用大写。如果只设置了XCASE,则输入字符将被转换为小写字符,除非字符使用了转义字符(非POSIX,且Linux不支持该参数)

ECHO

显示输入字符

ECHOE

如果ICANON同时设置,ERASE将删除输入的字符,WERASE将删除输入的单词

ECHOK

如果ICANON同时设置,KILL将删除当前行

ECHONL

如果ICANON同时设置,即使ECHO没有设置依然显示换行符

ECHOPRT

如果ECHO和ICANON同时设置,将删除打印出的字符(非POSIX)

TOSTOP

向后台输出发送SIGTTOU信号

c_cc[NCCS]:控制字符,用于保存终端驱动程序中的特殊字符,如输入结束符等。c_cc中定义了如表6.7所示的控制字符。

表6.7 c_cc支持的控制字符

说    明

说    明

VINTR

Interrupt字符

VEOL

附加的End-of-file字符

VQUIT

Quit字符

VTIME

非规范模式读取时的超时时间

VERASE

Erase字符

VSTOP

Stop字符

VKILL

Kill字符

VSTART

Start字符

VEOF

End-of-file字符

VSUSP

Suspend字符

VMIN

非规范模式读取时的最小字符数

  

tcsetattr函数用于设置终端的相关参数。参数fd为打开的终端文件描述符,参数optional_actions用于控制修改起作用的时间,而结构体termios_p中保存了要修改的参数。
optional_actions可以取如下的值。
 
TCSANOW:不等数据传输完毕就立即改变属性。
TCSADRAIN:等待所有数据传输结束才改变属性。
TCSAFLUSH:清空输入输出缓冲区才改变属性。

错误信息:
EBADF:非法的文件描述符。
EINTR:tcsetattr函数调用被信号中断。
EINVAL:参数optional_actions使用了非法值,或参数termios中使用了非法值。
ENCTTY:非终端的文件描述符。

实例演练:
程序p6.2.c通过修改终端控制字符,将终端输入结束符由“Ctrl+D”,修改成了“Ctrl+G”。首先,程序调用tcgetattr函数获得标准 输入的termios信息,将termios结构体中的c_cc[VEOF]控制字符的修改成0x07(即Ctrl+G);然后,使用tcsetattr 函数将修改后的termios参数设置到终端中。具体代码如下所示:

 
  1. //p6.2.c 修改终端控制字符示例

  2. #include

  3. #include

  4. #include

  5. #include

  6.  
  7. int main(void){

  8. //term用于存储获得的终端参数信息

  9. struct termios term;

  10. int err;

  11.  
  12. //获得标准输入的终端参数,将获得的信息保存在term变量中

  13. if(tcgetattr(STDIN_FILENO,&term)==-1){

  14. perror("Cannot get standard input description");

  15. return 1;

  16. }

  17.  
  18. //修改获得的终端信息的结束控制字符

  19. term.c_cc[VEOF]=(cc_t)0x07;

  20.  
  21. //使用tcsetattr函数将修改后的终端参数设置到标准输入中

  22. //err用于保存函数调用后的结果

  23. err=tcsetattr(STDIN_FILENO,TCSAFLUSH,&term);

  24.  
  25. //如果err为-1或是出现EINTR错误(函数执行被信号中断),

  26. //给出相关出错信息

  27. if(err==-1 && err==EINTR){

  28. perror("Failed to change EOF character");

  29. return 1;

  30. }

  31.  
  32. return 0;

  33. }

 

使用gcc编译p6.2.c程序,得到名为p6.2的可执行程序。在执行p6.2程序前,按“Ctrl+D”可以使终端结束。执行p6.2程序后,按“Ctrl+D”失去了作用,而输入“Ctrl+G”实现了原来“Ctrl+D”的功能

转自:http://blog.chinaunix.net/uid-10747583-id-97303.html

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

 

串口操作需要的头文件

 
  1. #include /*标准输入输出定义*/

  2.  
  3. #include /*标准函数库定义*/

  4.  
  5. #include /*Unix 标准函数定义*/

  6.  
  7. #include

  8.  
  9. #include

  10.  
  11. #include /*文件控制定义*/

  12.  
  13. #include /*PPSIX 终端控制定义*/

  14.  
  15. #include /*错误号定义*/


 

 

1.打开串口

在前面已经提到linux下的串口访问是以设备文件形式进行的,所以打开串口也即是打开文件的操作。函数原型可以如下所示:

 

int open(“DE_name”,int open_Status)

 

参数说明:

(1)DE_name:要打开的设备文件名

比如要打开串口1,即为/dev/ttyS0。

(2)open_Status:文件打开方式,可采用下面的文件打开模式:

  O_RDONLY:以只读方式打开文件

  O_WRONLY:以只写方式打开文件

O_RDWR:以读写方式打开文件

O_APPEND:写入数据时添加到文件末尾

O_CREATE:如果文件不存在则产生该文件,使用该标志需要设置访问权限位mode_t

O_EXCL:指定该标志,并且指定了O_CREATE标志,如果打开的文件存在则会产生一个错误

O_TRUNC:如果文件存在并且成功以写或者只写方式打开,则清除文件所有内容,使得文件长度变为0

O_NOCTTY:如果打开的是一个终端设备,这个程序不会成为对应这个端口的控制终端,如果没有该标志,任何一个输入,例如键盘中止信号等,都将影响进程。

O_NONBLOCK:该标志与早期使用的O_NDELAY标志作用差不多。程序不关心DCD信号线的状态,如果指定该标志,进程将一直在休眠状态,直到DCD信号线为0。

函数返回值:

成功返回文件描述符,如果失败返回-1

例如:

在 Linux 下串口文件是位于 /dev 下的。串口一 为 /dev/ttyS0,串口二 为 /dev/ttyS1。打开串口是通过使用标准的文件打开函数操作:

 
  1. int fd;

  2.  
  3. /*以读写方式打开串口*/

  4.  
  5. fd = open( "/dev/ttyS0", O_RDWR);

  6.  
  7. if (fd==-1)

  8.  
  9. {

  10.  
  11. /* 不能打开串口一*/

  12.  
  13. perror(" 提示错误!");

  14.  
  15. }


 

2.设置串口

最基本的设置串口包括波特率设置,效验位和停止位设置。串口的设置主要是设置

 struct termios 结构体的各成员值。

 
  1. struct termio

  2.  
  3. { unsigned short c_iflag; /* 输入模式标志 */

  4.  
  5. unsigned short c_oflag; /* 输出模式标志 */

  6.  
  7. unsigned short c_cflag; /* 控制模式标志*/

  8.  
  9. unsigned short c_lflag; /* local mode flags */

  10.  
  11. unsigned char c_line; /* line discipline */

  12.  
  13. unsigned char c_cc[NCC]; /* control characters */

  14.  
  15. };


 

设置这个结构体很复杂,我这里就只说说常见的一些设置:

2.1 波特率设置

波特率的设置定义在,其包含在头文件里。

常用的波特率常数如下:

B0-------à0                     B1800-------à1800

B50-----à50                    B2400------à2400

B75-----à75                    B4800------à4800

B110----à110                 B9600------à9600

B134----à134.5              B19200-----à19200

B200----à200                 B38400------à38400

B300----à300                 B57600------à57600

B600----à600                 B76800------à76800

B1200---à1200              B115200-----à115200

假定程序中想要设置通讯的波特率,使用cfsetispeed( )和cfsetospeed( )函数来操作,获取波特率信息是通过cfgetispeed()和cfgetospeed()函数来完成的。

比如可以这样来指定串口通讯的波特率:

 
  1. #include //头文件定义

  2.  
  3. ........

  4.  
  5. .......

  6.  
  7. struct termios opt; /*定义指向termios 结构类型的指针opt*/

  8.  
  9.  
  10.  
  11. /***************以下设置通讯波特率****************/

  12.  
  13. cfsetispeed(&opt,B9600 ); /*指定输入波特率,9600bps*/

  14.  
  15. cfsetospeed(&opt,B9600);/*指定输出波特率,9600bps*/

  16.  
  17. /************************************************/

  18.  
  19. .........

  20.  
  21. ..........


 

一般来说,输入、输出的波特率应该是一致的。

下面是另一个修改波特率的代码:

 
  1. struct termios Opt;

  2.  
  3. tcgetattr(fd, &Opt);

  4.  
  5. cfsetispeed(&Opt,B19200); /*设置为19200Bps*/

  6.  
  7. cfsetospeed(&Opt,B19200);

  8.  
  9. tcsetattr(fd,TCANOW,&Opt);


 

设置波特率的例子函数:

 
  1. /**

  2.  
  3. *@brief 设置串口通信速率

  4.  
  5. *@param fd 类型 int 打开串口的文件句柄

  6.  
  7. *@param speed 类型 int 串口速度

  8.  
  9. *@return void

  10.  
  11. */

  12.  
  13. int speed_arr[] = { B38400, B19200, B9600, B4800, B2400, B1200, B300,

  14.  
  15. B38400, B19200, B9600, B4800, B2400, B1200, B300, };

  16.  
  17. int name_arr[] = {38400, 19200, 9600, 4800, 2400, 1200, 300, 38400,

  18.  
  19. 19200, 9600, 4800, 2400, 1200, 300, };

  20.  
  21. void set_speed(int fd, int speed){

  22.  
  23. int i;

  24.  
  25. int status;

  26.  
  27. struct termios Opt;

  28.  
  29. tcgetattr(fd, &Opt);

  30.  
  31. for ( i= 0; i < sizeof(speed_arr) / sizeof(int); i++) {

  32.  
  33. if (speed == name_arr[i]) {

  34.  
  35. tcflush(fd, TCIOFLUSH);

  36.  
  37. cfsetispeed(&Opt, speed_arr[i]);

  38.  
  39. cfsetospeed(&Opt, speed_arr[i]);

  40.  
  41. status = tcsetattr(fd1, TCSANOW, &Opt);

  42.  
  43. if (status != 0) {

  44.  
  45. perror("tcsetattr fd1");

  46.  
  47. return;

  48.  
  49. }

  50.  
  51. tcflush(fd,TCIOFLUSH);

  52.  
  53. }

  54.  
  55. }

  56.  
  57. }


 

2.2 设置效验的函数:

 
  1. /**

  2.  
  3. *@brief 设置串口数据位,停止位和效验位

  4.  
  5. *@param fd 类型 int 打开的串口文件句柄

  6.  
  7. *@param databits 类型 int 数据位 取值 为 7 或者8

  8.  
  9. *@param stopbits 类型 int 停止位 取值为 1 或者2

  10.  
  11. *@param parity 类型 int 效验类型 取值为N,E,O,,S

  12.  
  13. */

  14.  
  15. int set_Parity(int fd,int databits,int stopbits,int parity)

  16.  
  17. {

  18.  
  19. struct termios options;

  20.  
  21. if ( tcgetattr( fd,&options) != 0) {

  22.  
  23. perror("SetupSerial 1");

  24.  
  25. return(FALSE);

  26.  
  27. }

  28.  
  29. options.c_cflag &= ~CSIZE;

  30.  
  31. switch (databits) /*设置数据位数*/

  32.  
  33. {

  34.  
  35. case 7:

  36.  
  37. options.c_cflag |= CS7;

  38.  
  39. break;

  40.  
  41. case 8:

  42.  
  43. options.c_cflag |= CS8;

  44.  
  45. break;

  46.  
  47. default:

  48.  
  49. fprintf(stderr,"Unsupported data sizen"); return (FALSE);

  50.  
  51. }

  52.  
  53. switch (parity)

  54.  
  55. {

  56.  
  57. case 'n':

  58.  
  59. case 'N':

  60.  
  61. options.c_cflag &= ~PARENB; /* Clear parity enable */

  62.  
  63. options.c_iflag &= ~INPCK; /* Enable parity checking */

  64.  
  65. break;

  66.  
  67. case 'o':

  68.  
  69. case 'O':

  70.  
  71. options.c_cflag |= (PARODD | PARENB); /* 设置为奇效验*/

  72.  
  73. options.c_iflag |= INPCK; /* Disnable parity checking */

  74.  
  75. break;

  76.  
  77. case 'e':

  78.  
  79. case 'E':

  80.  
  81. options.c_cflag |= PARENB; /* Enable parity */

  82.  
  83. options.c_cflag &= ~PARODD; /* 转换为偶效验*/

  84.  
  85. options.c_iflag |= INPCK; /* Disnable parity checking */

  86.  
  87. break;

  88.  
  89. case 'S':

  90.  
  91. case 's': /*as no parity*/

  92.  
  93. options.c_cflag &= ~PARENB;

  94.  
  95. options.c_cflag &= ~CSTOPB;break;

  96.  
  97. default:

  98.  
  99. fprintf(stderr,"Unsupported parityn");

  100.  
  101. return (FALSE);

  102.  
  103. }


 

2.3 设置停止位

 
  1. switch (stopbits)

  2.  
  3. {

  4.  
  5. case 1:

  6.  
  7. options.c_cflag &= ~CSTOPB;

  8.  
  9. break;

  10.  
  11. case 2:

  12.  
  13. options.c_cflag |= CSTOPB;

  14.  
  15. break;

  16.  
  17. default:

  18.  
  19. fprintf(stderr,"Unsupported stop bitsn");

  20.  
  21. return (FALSE);

  22.  
  23. }

  24.  
  25. /* Set input parity option */

  26.  
  27. if (parity != 'n')

  28.  
  29. options.c_iflag |= INPCK;

  30.  
  31. tcflush(fd,TCIFLUSH);

  32.  
  33. options.c_cc[VTIME] = 150; /* 设置超时15 seconds*/

  34.  
  35. options.c_cc[VMIN] = 0; /* Update the options and do it NOW */

  36.  
  37. if (tcsetattr(fd,TCSANOW,&options) != 0)

  38.  
  39. {

  40.  
  41. perror("SetupSerial 3");

  42.  
  43. return (FALSE);

  44.  
  45. }

  46.  
  47. return (TRUE);

  48.  
  49. }


 

 

    在上述代码中,有两句话特别重要:

options.c_cc[VTIME] = 0; /* 设置超时0 seconds*/  

options.c_cc[VMIN] = 13; /* define the minimum bytes data to be readed*/

这两句话决定了对串口读取的函数read()的一些功能。我将着重介绍一下他们对read()函数的影响。

对串口操作的结构体是

 
  1. Struct{

  2.  
  3. tcflag_t c_iflag; /*输入模式标记*/

  4.  
  5. tcflag_t c_oflag; /*输出模式标记*/

  6.  
  7. tcflag_t c_cflag; /*控制模式标记*/

  8.  
  9. tcflag_t c_lflag; /*本地模式标记*/

  10.  
  11. cc_t c_line; /*线路规程*/

  12.  
  13. cc_t c_cc[NCCS]; /*控制符号*/

  14.  
  15. };


 

其中cc_t, c_line只有在一些特殊的系统程序(比如,设置通过tty设备来通信的网络协议)中才会用。在数组c_cc中有两个下标(VTIME和VMIN)对应的元素不是控制符,并且只是在原始模式下有效。只有在原始模式下,他们决定了read()函数在什么时候返回。在标准模式下,除非设置了O_NONBLOCK选项,否则只有当遇到文件结束符或各行的字符都已经编辑完毕后才返回。

控制符VTIME和VMIN之间有着复杂的关系。VTIME定义要求等待的零到几百毫秒的时间量(通常是一个8位的unsigned char变量,取值不能大于cc_t)。           VMIN定义了要求等待的最小字节数(不是要求读的字节数——read()的第三个参数才是指定要求读的最大字节数),这个字节数可能是0。

l) 如果VTIME取0,VMIN定义了要求等待读取的最小字节数。函数read()只有在读取了VMIN个字节的数据或者收到一个信号的时候才返回。

2) 如果VMIN取0,VTIME定义了即使没有数据可以读取,read()函数返回前也要等待几百毫秒的时间量。这时,read()函数不需要像其通常情况那样要遇到一个文件结束标志才返回0。

3) 如果VTIME和VMIN都不取0,VTIME定义的是当接收到第一个字节的数据后开始计算等待的时间量。如果当调用read函数时可以得到数据,计时器马上开始计时。如果当调用read函数时还没有任何数据可读,则等接收到第一个字节的数据后,计时器开始计时。函数read可能会在读取到VMIN个字节的数据后返回,也可能在计时完毕后返回,这主要取决于哪个条件首先实现。不过函数至少会读取到一个字节的数据,因为计时器是在读取到第一个数据时开始计时的。

4) 如果VTIME和VMIN都取0,即使读取不到任何数据,函数read也会立即返回。同时,返回值0表示read函数不需要等待文件结束标志就返回了。

这就是这两个变量对read函数的影响。

 

2.4 串口属性配置

在程序中,很容易配置串口的属性,这些属性定义在结构体struct termios中。为在程序中使用该结构体,需要包含文件,该头文件定义了结构体struct termios。该结构体定义如下:

#define NCCS 19

struct termios {

             tcflag_t c_iflag;               /* 输入参数 */

             tcflag_t c_oflag;               /* 输出参数 */

             tcflag_t c_cflag;               /* 控制参数*/

             tcflag_t c_ispeed;              /* 输入波特率 */

tcflag_t c_ospeed;              /* 输出波特率 */

             cc_t c_line;                   /* 线控制 */

             cc_t c_cc[NCCS];              /* 控制字符*/

};

其中成员c_line在POSIX(Portable Operating System Interface for UNIX)系统中不使用。对于支持POSIX终端接口的系统中,对于端口属性的设置和获取要用到两个重要的函数是:

(1).int tcsetattr(int fd,int opt_DE,*ptr)

该函数用来设置终端控制属性,其参数说明如下:

fd:待操作的文件描述符

opt_DE:选项值,有三个选项以供选择:

TCSANOW:  不等数据传输完毕就立即改变属性

TCSADRAIN:等待所有数据传输结束才改变属性

TCSAFLUSH:清空输入输出缓冲区才改变属性

*ptr:指向termios结构的指针

函数返回值:成功返回0,失败返回-1。

(2).int tcgetattr(int fd,*ptr)

该函数用来获取终端控制属性,它把串口的默认设置赋给了termios数据数据结构,其参数说明如下:

fd:待操作的文件描述符

*ptr:指向termios结构的指针

函数返回值:成功返回0,失败返回-1。

2.5 注意的问题:

如果不是开发终端之类的,只是串口传输数据,而不需要串口来处理,那么使用原始模式(Raw Mode)方式来通讯,设置方式如下:

options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /*Input*/

options.c_oflag &= ~OPOST; /*Output*/

3.读写串口

3.1 串口读操作(接收端)

用open函数打开设备文件,函数返回一个文件描述符(file descriptors,fd),通过文件描述符来访问文件。读串口操作是通过read函数来完成的。函数原型如下:

int read(int fd, *buffer,length);

参数说明:

(1).int fd:文件描述符

(2).*buffer:数据缓冲区

(3).length:要读取的字节数

函数返回值:

读操作成功读取返回读取的字节数,失败则返回-1。

3.2 串口写操作(发送端)

写串口操作是通过write函数来完成的。函数原型如下:

write(int fd, *buffer,length);

参数说明:

(1).fd:文件描述符

(2).*buffer:存储写入数据的数据缓冲区

(3).length:写入缓冲去的数据字节数

函数返回值:

成功返回写入数据的字节数,该值通常等于length,如果写入失败返回-1。

例如:向终端设备发送初始化命令

设置好串口之后,读写串口就很容易了,把串口当作文件读写就是。

·发送数据

char buffer[1024];

int Length;int nByte;

nByte = write(fd, buffer ,Length)

 

4.关闭串口

关闭串口就是关闭文件。

close(fd);

5.例子

下面是一个简单的读取串口数据的例子,使用了上面定义的一些函数和头文件

 
  1. /**********************************************************************

  2.  
  3. 代码说明:使用串口二测试的,发送的数据是字符,

  4.  
  5. 但是没有发送字符串结束符号,所以接收到后,后面加上了结束符号。

  6.  
  7. 我测试使用的是单片机发送数据到第二个串口,测试通过。

  8.  
  9. **********************************************************************/

  10.  
  11. #define FALSE -1

  12.  
  13. #define TRUE 0

  14.  
  15. /*********************************************************************/

  16.  
  17. int OpenDev(char *Dev)

  18.  
  19. {

  20.  
  21. int fd = open( Dev, O_RDWR );

  22.  
  23. //| O_NOCTTY | O_NDELAY

  24.  
  25. if (-1 == fd)

  26.  
  27. {

  28.  
  29. perror("Can't Open Serial Port");

  30.  
  31. return -1;

  32.  
  33. }

  34.  
  35. else

  36.  
  37. return fd;

  38.  
  39. }

  40.  
  41. int main(int argc, char **argv){

  42.  
  43. int fd;

  44.  
  45. int nread;

  46.  
  47. char buff[512];

  48.  
  49. char *dev = "/dev/ttyS1"; //串口二

  50.  
  51. fd = OpenDev(dev);

  52.  
  53. set_speed(fd,19200);

  54.  
  55. if (set_Parity(fd,8,1,'N') == FALSE) {

  56.  
  57. printf("Set Parity Errorn");

  58.  
  59. exit (0);

  60.  
  61. }

  62.  
  63. while (1) //循环读取数据

  64.  
  65. {

  66.  
  67. while((nread = read(fd, buff, 512))>0)

  68.  
  69. {

  70.  
  71. printf("nLen %dn",nread);

  72.  
  73. buff[nread+1] = '';

  74.  
  75. printf( "n%s", buff);

  76.  
  77. }

  78.  
  79. }

  80.  
  81. //close(fd);

  82.  
  83. // exit (0);

  84.  
  85. }

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值