Linux串口设置参数 您所在的位置:网站首页 linux设置串口输入 Linux串口设置参数

Linux串口设置参数

2024-07-11 16:02| 来源: 网络整理| 查看: 265

在Linux环境下,串口名从ttyS0开始依次是ttyS1、ttyS2等。在本程序中,使用ttyS0作为通信串口。在打开ttyS0的时候,选项 O_NOCTTY 表示不能把本串口当成控制终端,否则用户的键盘输入信息将影响程序的执行; O_NDELAY表示打开串口的时候,程序并不关心另一端 的串口是否在使用中。在Linux中,打开串口设备和打开普通文件一样,使用的是open()系统调用。比如我么打开串口设备1也就是COM1,只需要:

fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY );

打开的串口设备有很多设置选项。本文中使用int setup_com(int fd)设置。在系统头文件中 定义了终端控制结构struct termios,tcgetattr()和tcsetattr()两个系统函数获得和设置这些属性。结构 struct termios中的域描述的主要属性包括:

c_cflag : 控制选项 c_lflag : 线选项 c_iflag : 输入选项 c_oflag :输出选项 c_cc :控制字符 c_ispeed :输入数据波特率 c_ospeed :输出数据波特率

如果要设置某个选项,那么就使用"|="运算,如果关闭某个选项就使用"&="和"~"运算。本文使用的各个选项的意义定义如下:

c_cflag: 

CLOCAL 本地模式,不改变端口的所有者 CREAD 表示使能数据接收器 PARENB 表示偶校验 PARODD 表示奇校验 CSTOPB 使用两个停止位 CSIZE 对数据的bit使用掩码 CS8 数据宽度是8bit c_lflag:

ICANON 使能规范输入,否则使用原始数据(本文使用) ECHO 回送(echo)输入数据 ECHOE 回送擦除字符 ISIG 使能SIGINTR,SIGSUSP, SIGDSUSP和 SIGQUIT 信号 c_iflag: 

IXON 使能输出软件控制 IXOFF 使能输入软件控制 IXANY 允许任何字符再次开启数据流 INLCR 把字符NL(0A)映射到CR(0D) IGNCR 忽略字符CR(0D) ICRNL 把CR(0D)映射成字符NR(0A) c_oflag: OPOST 输出后处理,如果不设置表示原始数据(本文使用原始数据) c_cc[VMIN]: 最少可读数据 c_cc[VTIME]: 等待数据时间(10秒的倍数)

根据以上设置的定义,串口端口设置函数setup_com()定义如下:

int setup_com(int fd){ struct termios options; tcgetattr(fd, &options); /* Set the baud rates to 38400...*/ cfsetispeed(&options, B38400); cfsetospeed(&options, B38400); /* Enable the receiver and set local mode...*/ options.c_cflag |= (CLOCAL | CREAD); /* Set c_cflag options.*/ options.c_cflag |= PARENB; options.c_cflag &= ~PARODD; options.c_cflag &= ~CSTOPB; options.c_cflag &= ~CSIZE; options.c_cflag |= CS8; /* Set c_iflag input options */ options.c_iflag &=~(IXON | IXOFF | IXANY); options.c_iflag &=~(INLCR | IGNCR | ICRNL); options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /* Set c_oflag output options */ options.c_oflag &= ~OPOST; /* Set the timeout options */ options.c_cc[VMIN] = 0; options.c_cc[VTIME] = 10; tcsetattr(fd, TCSANOW, &options); return 1; } 6.7.2 设置串口通信参数

串口通信参数指的是波特率、数据位、奇偶校验位和停止位。对串口实现控制的时候同样要用到termio结构体。下面将结合具体的代码说明如何设置这些参数。

1.波特率设置 获得端口波特率信息是通过cfgetispeed函数和cfgetospeed函数来实现的。cfgetispeed函数用于获得结构体 termios_p中的输入波特率信息,而cfgetospeed函数用于获得结构体termios_p 中的输出波特率信息。这两个函数的具体信息如表 6.9所示。

表6.9 cfgetispeed函数和cfgetospeed函数

头文件

函数形式

speed_t cfgetispeed(const struct termios *termios_p);

speed_t cfgetospeed(const struct termios *termios_p);

返回值

是否设置errno

返回termios_p结构中的输入/输出端口的波特率

cfsetispeed函数和cfsetospeed函数用于设置端口的输入/输出波特率。一般情况下,输入和输出波特率是相等的。cfsetispeed函数和cfsetospeed函数的函数声明信息如表6.10所示。

表6.10 cfsetispeed函数和cfsetospeed函数

头文件

函数形式

int cfsetispeed(struct termios *termios_p, speed_t speed);

int cfsetospeed(struct termios *termios_p, speed_t speed);

返回值

是否设置errno

返回termios_p结构中的输入/输出端口的波特率

cfsetispeed函数和cfsetospeed函数会修改结构体termios_p中的波特率信息,其中参数speed可以使用表6.11中所列出的宏。

表6.11 speed参数常用波特率信息

宏 定 义       波特率(单位:bit/s)         宏 定 义          波特率(单位:bit/s)

B1800            1800                                 B50

B2400            2400                                 B75

B4800            4800                                 B110                 110

B9600            9600                                 B134                  134

B19200           19200                              B150                 150

B38400           38400                              B200                  200

B57600            57600                             B300                  300

B115200          115200                           B600                  600

B230400           230400                         B1200                 1200

使用cfsetispeed函数和cfsetospeed函数进行串口波特率设置具体代码如下所示:

#include //头文件定义 #include  #include < termios.h > …… struct termios opt; /*定义指向termios 结构类型的指针opt*/ …… //获得串口指向termios结构的指针 tcgetattr(fd, &Opt); cfsetispeed(&opt,B9600 ); /*指定输入波特率,9600bps*/ cfsetospeed(&opt,B9600);/*指定输出波特率,9600bps*/ //将修改后的termios数据设置到串口中 tcsetattr(fd,TCANOW,&Opt); ……

2.数据位 数据位指的是每字节中实际数据所占的比特数。要修改数据位可以通过修改termios结构体中c_cflag成员来实现。CS5、CS6、CS7和CS8分别表示数据位为5、6、7和8。值得注意的是,在设置数据位时,必须先使用CSIZE做位屏蔽。具体设置代码如下:

#include //头文件定义 #include  #include < termios.h > …… struct termios opt; /*定义指向termios 结构类型的指针opt*/ ....... //获得串口指向termios结构的指针 tcgetattr(fd, &Opt); … //屏蔽其他标志 Opt.c_cflag&=~CSIZE; //将数据位修改为8bit Opt.c_cflag |=CS8; …

//将修改后的termios数据设置到串口中 tcsetattr(fd,TCANOW,&Opt); ……

3.奇偶校验位 奇偶校验可以选择偶校验、奇校验、空格等方式,也可以不使用校验。如果要设置为偶校验的话,首先要将termios结构体中c_cflag设置 PARENB标志,并清除PARODD标志。如果要设置奇校验,要同时设置termios结构体中c_cflag设置PARENB标志和PARODD标 志。如果不想使用任何校验的话,清除termios结构体中c_cflag的PARENB位。表6.12所示为设置奇偶校验的具体方法。

表6.12 设置奇偶校验位

设 置

具 体 代 码

无校验

opt.c_cflag &= ~PARENB;

奇校验

opt.c_cflag |= (PARODD | PARENB);

偶校验

opt.c_cflag &= ~ PARENB;

opt.c_cflag &= ~PARODD;

opt.c_cflag &= ~PARENB;

opt.c_cflag &= ~CSTOPB;

下面给出将串口通信的奇偶校验设置为偶校验的例子,具体代码如下:

#include //头文件定义 #include  #include < termios.h > …… struct termios opt; /*定义指向termios 结构类型的指针opt*/ …… //获得串口指向termios结构的指针 tcgetattr(fd, &Opt); … opt.c_cflag &= ~ PARENB; opt.c_cflag &= ~PARODD; …

//将修改后的termios数据设置到串口中 tcsetattr(fd,TCANOW,&Opt); ……

4.数据流控制 数据流控制指是使用何种方法来标志数据传输的开始和结束。可以选择不使用数据流控制、使用硬件进行流控制和使用软件进行流控制。数据流控制设置如表6.13所示。

表6.13 数据流控制设置

设 置

具 体 代 码

不使用数据流控制

opt.c_cflag &= ~CRTSCTS

opt.c_cflag |= CRTSCTS

opt.c_cflag | = IXON|IXOFF|IXANY

由于使用硬件流控制需要相应连接的电缆,常用的流控制方法还是使用软件进行流控制。下面给出了设置不使用数据流控制的相关代码:

#include //头文件定义 #include  #include < termios.h > …… struct termios opt; /*定义指向termios 结构类型的指针opt*/ …… //获得串口指向termios结构的指针 tcgetattr(fd, &opt); … opt.c_cflag &= ~CRTSCTS…

//将修改后的termios数据设置到串口中 tcsetattr(fd,TCANOW,&Opt); …… 串口操作采用UNIX类似的方式,打开/关闭/发送/接收等基本操作采用类

似文件系统的方式进行,而一些属性的设置和控制则使用termios来进行。

串口对应的设备文件名为”/dev/ttyS0”。

1. 打开串口

fd = open(“/dev/ttyS0”, O_RDWR);

如果只发送数据,可以使用O_WRONLY, 如果只接收数据,可以

设置成O_RDONLY。

2. 关闭串口

close(fd);

3. 接收数据

ret = read(fd, buf, 100);

串口默认的打开方式是非阻塞的,因此本函数只是接收缓冲中的数

据,而并非直接操作IO。如果要加入一些IO的属性,请参见”使用

超时”和”设置串口属性”。

如果缓冲中有接收到的数据,那么本函数将返回实际接收到的数据

长度,当然不会超过指定的100字节。

如果缓冲中没有数据,那么将返回0。

如果接收失败,那么将返回-1,错误代码放在errno中。

4. 发送数据

ret = write(fd, buf, 100);

返回值表示实际发送的数据长度。

5. 设置串口属性

tcgetattr(int fd, struct termios *termios_p);

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

串口打开后,使用的串口属性实际上是上一次关闭串口前的设置。

这个设置也就是一个结构struct termios,其中主要有以下的属性:

tcflag_t c_iflag // 输入属性

tcflag_t c_oflag // 输出属性

tcflag_t c_cflag // 控制属性

tcflag_t c_lflag // 本地属性

cc_t c_cc[NCCS] // 控制字

c_iflag

IGNBRK 忽略接收到的break信号

BRKINT 如果IGNBRK被设置,break信号将被忽

略,否则如果BRKINT被设置,接收到

break信号将导致输入/输出队列被清空,并

且当前控制串口的前台进程将收到一个

SIGINT信号。如果IGNBRK和BRKINT都

没有被设置 ,收到的break信号将被接收为

NULL,即{post.content}。但是如果PARMARK被设

置,接收到的break信号将被接收为7{post.content}

IGNPAR 忽略帧错误或奇偶校验错。

PARMARK 如果没有设置IGNPAR,设置本属性表示在

接收到的带有错误的帧格式或奇偶校验的字符将被前缀

377{post.content}。如果两者都没有设置,带有错误的帧格式或奇偶

校验的字符将被接收为{post.content}。

INPCK 打开输入数据的奇偶校验。

ISTRIP 滤掉第8位。

INLCR 将接收到的NL(换行)转换成CR(回车)。

IGNCR 忽略接收到的CR。

ICRNL 将收到的CR转换成NL(除非设置了

IGNCR)。

IUCLC 将接收到的大写字符转换成小写。

IXON 打开输出的XON/XOFF控制。

IXOFF 打开输入的XON/XOFF控制。

c_oflag

OLCUC 将小写字符转换成大写后输出。

ONLCR 将NL转换成CR-NL后输出。

OCRNL 将CR转换成NL后输出。

ONLRET 不发送CR。

c_cflag

CBAUD 波特率掩码,可以设置为

B2400

B4800

B9600

B19200

B38400

B57600

B115200

CSIZE 字符长度掩码,可以设置为

CS5

CS6

CS7

CS8

CSTOPB 设置为两个停止位。(默认为1个)

CREAD 打开接收功能。

PARENB 打开发送的奇偶校验生成功能和接收的奇偶

校验检查功能,默认的是偶校验。

PARODD 使用奇校验。

CLOCAL 忽略modem信号线。

CRTSCTS 打开RTS/CTS硬件流控。

c_lflag

由于使用该类属性不多,因此在此不作介绍。

c_cc

常用的是c_cc[VMIN],表示调用read函数时等待接收

的最少字符个数。例如设置为1时,read函数至少要读

到1个字符才会返回。

optional_actions

可以设置为

TCSANOW 立即更新当前的设置。

TCSADRAIN 在当前发送缓冲的所由数据发送 完毕后再更新当前设置。

TCSAFLUSH 同TCSADRAIN,只是在更新前

所有为被读取的收到的数据将被丢弃。

6. 使用超时

int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,

struct timeval *timeout);

此函数用于控制接收、发送或异常出现之前的超时。

fd_set是句柄的集合,其中的句柄都是被监测的对象。

readfds表示需要监测其中句柄代表的设备是

否可以从中读取数据。

writefds表示需要监测其中句柄代表的设备

是否可以向其写入数据。

exceptfds表示需要监测其中句柄代表的设备

是否出现异常。

timeout是这样一个结构

struct timeval{

long tv_sec; // 秒

long tv_usec; // 微秒

n则是所有监测的句柄中的最大值加一。

系统提供一些定义号的操作来操作fd_set:

FD_CLR(int fd, fd_set *fds);

将fd从fds集合中去掉。

FD_ISSET(int fd, fd_set *fds);

检查fd是否在fds集合中。

FD_SET(int fd, fd_set *fds);

将fd加入fds集合中。

FD_ZERO(fd_set *fds);

将fds集合清空。

7. 其它串口操作

int tcdrain(int fd);

等待所有发送缓冲的数据全部发送出去后返回。

int tcflush(int fd, int queue_selector);

queue_selector:

TCIFLUSH

丢弃所有未读取的接收到的数据。

TCOFLUSH

丢弃所有为发送的发送缓冲的数据。

TCIOFLUSH

丢弃上面两种数据。

#include

#include

#include

#include

int main()

int fd;

struct termios attr;

fd_set fds;

struct timeval tv;

unsigned char buf[1024];

// 打开串口

fd = open(“/dev/ttyS0”, O_RDWR);

if (fd == -1)

return -1;

// 读取串口当前属性

tcgetattr(fd, &attr);

// 设置最少接收字符个数为0

attr.c_cc[VMIN] = 0;

// 不处理iflag、oflag和lflag

attr.c_iflag = 0;

attr.c_oflag = 0;

attr.c_lflag = 0;

// 设置波特率为9600,字符长度为8位,偶校验,允许接收

attr.c_cflag = B9600 | CS8 | PARENB | CLOCAL | CREAD;

// 设置串口属性

tcsetattr(fd, TCSANOW, &attr);

// 发送字符串

write(fd, “12345\n”, 6);

// 清除监测集合

FD_ZERO(&fds);

// 将串口句柄加入到监测集合中

FD_SET(fd, &fds);

// 设置超时为5秒

tv.tv_sec = 5;

tv.tv_usec = 0;

// 监测串口是否有数据接收到,超时为5秒

if (select(fd+1, &fds, NULL, NULL, &tv)



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有