目前遇到的串口编程都是用于通信,很少作为终端显示。以前没有对串口编程做深入研究,本次以libmodbus源码中对串口的设置为例,详解总结串口编程时配置的属性(struct termios)

以libmodbus中_modbus_rtu_connect函数为例

【1】打开串口设备

static int _modbus_rtu_connect(modbus_t *ctx)
{struct termios tios;speed_t speed;modbus_rtu_t *ctx_rtu = ctx->backend_data;/*O_RDWR:读写O_NOCTTY:该端口不作为终端使用,如果没有设置该标志位,一些输入信号会影响到程序O_NDELAY:非阻塞模式O_EXCL:未知,待测????*/ctx->s = open(ctx_rtu->device, O_RDWR | O_NOCTTY | O_NDELAY | O_EXCL);if (ctx->s == -1) {fprintf(stderr, "ERROR Can't open the device %s (%s)\n",ctx_rtu->device, strerror(errno));return -1;}

【2】保存旧属性

    tcgetattr(ctx->s, &(ctx_rtu->old_tios));

【3】设置输出、输入波特率

    memset(&tios, 0, sizeof(struct termios));switch (ctx_rtu->baud) {case 110:speed = B110;break;case 300:speed = B300;break;case 600:speed = B600;break;case 1200:speed = B1200;break;case 2400:speed = B2400;break;case 4800:speed = B4800;break;case 9600:speed = B9600;break;case 19200:speed = B19200;break;case 38400:speed = B38400;break;case 57600:speed = B57600;break;case 115200:speed = B115200;break;default:speed = B9600;}if ((cfsetispeed(&tios, speed) < 0) ||(cfsetospeed(&tios, speed) < 0)) {close(ctx->s);ctx->s = -1;return -1;}

【4】设置控制属性

CREAD、CLOCAL这两个选项可以保证你的程序不会变成端口的所有者,而端口所有者必须去处理发散性作业控制和挂断信号,同时还保证了串行接口驱动会读取过来的数据字节
如果串口不是用来做终端显示,这两个选项就够了

    tios.c_cflag |= (CREAD | CLOCAL);

####【5】设置数据位,先清空后设置

    tios.c_cflag &= ~CSIZE;switch (ctx_rtu->data_bit) {case 5:tios.c_cflag |= CS5;break;case 6:tios.c_cflag |= CS6;break;case 7:tios.c_cflag |= CS7;break;case 8:default:tios.c_cflag |= CS8;break;}

####【6】设置停止位

    if (ctx_rtu->stop_bit == 1)tios.c_cflag &=~ CSTOPB;else /* 2 */tios.c_cflag |= CSTOPB;

####【7】设置奇偶校验位
PARENB Enable parity bit:使能校验
PARODD Use odd parity instead of even:使用奇校验
#####【7.1】不使用校验位

    if (ctx_rtu->parity == 'N') {/* None */tios.c_cflag &=~ PARENB;}

#####【7.2】使用偶校验

 else if (ctx_rtu->parity == 'E') {/* Even */tios.c_cflag |= PARENB;tios.c_cflag &=~ PARODD;}

#####【7.3】使用奇校验

 else {/* Odd */tios.c_cflag |= PARENB;tios.c_cflag |= PARODD;}

####【8】终端输入(行输入)的特性
ISIG Enable SIGINTR, SIGSUSP, SIGDSUSP, and SIGQUIT signals:使能信号中断
ICANON Enable canonical input (else raw);使用规范的输入流,否则是原始输入流
XCASE Map uppercase \lowercase (obsolete):大小写映射(不再推荐使用)
ECHO Enable echoing of input characters:使能回显
ECHOE Echo erase character as BS-SP-BS
ECHOK Echo NL after kill character
ECHONL Echo NL
NOFLSH Disable flushing of input buffers after interrupt or quit characters
IEXTEN Enable extended functions
ECHOCTL Echo control characters as ^char and delete as ~?
ECHOPRT Echo erased character as character erased
ECHOKE BS-SP-BS entire line on line kill
FLUSHO Output being flushed
PENDIN Retype pending input at next read or input char
TOSTOP Send SIGTTOU for background output
规范输入(或称为标准输入)是面向行的。
输入字符被放到一个缓冲区中,可以被用户交互式地编辑,直到收到一个CR(回车)或(换行)字符。
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.

原始输入流是未经过加工的。输入字符在接收时完全按照接收到的字符进行传递。
通常,在使用原始输入时,您将取消选择ICANON、ECHO、ECHOE和ISIG选项
Raw input is unprocessed. Input characters are passed
through exactly as they are received, when they are
received. Generally you’ll deselect the ICANON, ECHO,
ECHOE, and ISIG options when using raw input

【8.1】作为原始流,屏蔽终端输入(行输入)的特性
    tios.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);

####【9】输入标志设置
INPCK Enable parity check:使能奇偶校验
IGNPAR Ignore parity errors:忽略奇偶校验错误
PARMRK Mark parity errors:标记奇偶校验错误
ISTRIP Strip parity bits:跳过奇偶校验位
IXON Enable software flow control (outgoing):使能软件流控(向外)
IXOFF Enable software flow control (incoming):使能软件流控(向内)
IXANY Allow any character to start flow again:允许任何字符重新开始流(???)
IGNBRK Ignore break condition:忽略打破条件
BRKINT Send a SIGINT when a break condition is detected:当检测到中断条件时发送一个SIGINT
INLCR Map NL to CR:将换行映射为回车
IGNCR Ignore CR:忽略回车
ICRNL Map CR to NL:将回车映射为换行
IUCLC Map uppercase to lowercase:将大写映射为小写
IMAXBEL Echo BEL on input line too long:当输入行太长时,显示为BEL
#####【9.1】设置输入奇偶校验

    if (ctx_rtu->parity == 'N') {/* None */tios.c_iflag &= ~INPCK;} else {tios.c_iflag |= INPCK;}
【9.2】禁止软件流控
/* Software flow control is disabled */
tios.c_iflag &= ~(IXON | IXOFF | IXANY);

####【10】输出标志设置
OPOST Postprocess output (not set = raw output):处理后再输出(原始流不设置)
ONLCR Map NL to CR-NL:将换行映射为回车-换行

ONCLR ant others needs OPOST to be enabled:OPOST使能后,ONCLR才有效

#####【10.1】原始流输出
tios.c_oflag &=~ OPOST;

####【11】字节流控制设置
VMIN Minimum number of characters to read:读取最少的字节数

VTIME Time to wait for data (tenths of seconds):等待数据时间(单位是十分之一秒)

UNIX串行接口驱动程序提供了指定字符和包超时的能力。
c_cc数组的两个元素用于超时:VMIN和VTIME。
在规范输入模式下、open或fcntl时使用O_NDELAY选项时,上述功能将被忽略(失效)。

UNIX serial interface drivers provide the ability to specify character and packet timeouts. Two elements of the c_cc array are used for timeouts: VMIN and VTIME. Timeouts are ignored in canonical input mode or when the NDELAY option is set on the file via open or fcntl.

VMIN指定要读取的字节的最小数量。如果设置为0,在VTIME指定的时间内等待读取任意字符。
注意,这并不意味着read N个字节将等待N个字符的出现。
相反,超时后,read调用将返回立即可用的字符或read时请求的字符数量(两者取最小的那个)。

VMIN specifies the minimum number of characters to read. Ifit is set to 0, then the VTIME value specifies the time towait for every character read. Note that this does not meanthat a read call for N bytes will wait for N characters tocome in. Rather, the timeout will apply to the firstcharacter and the read call will return the number ofcharacters immediately available (up to the number yourequest).

如果VMIN不为0,VTIME指定等待第一个字符读取的时间。如果在给定的时间内读取字符,那么任何读都会阻塞(等待),直到所有的VMIN字符被读取。也就是说,一旦第一个字符被读取,串行接口驱动程序就会期望接收整包字符(VMIN字节总数)。如果在允许的时间内没有读取字符,则读取的调用返回0。该方法允许您告诉串行驱动程序,您需要确切的N字节,任何读调用将返回0或N字节。然而,超时只适用于第一个字符读取,因此如果由于某种原因,驱动程序在N字节包中丢失了一个字符,那么read调用可能会永远阻塞,等待额外的输入字符。
(注:上述为翻译,不太理解。亲测的现象总结如下:
1、VMIN小于read指定字符个数:在超时范围内获取VMIN个字符时,返回;
2、VMIN大于read指定字符个数:在超时范围内获取read指定字符个数时,返回;
3、超时会受到新数据到达时间的影响:如果在超时范围内没有新数据到达,将因为超时返回;如果在超时范围内有新数据到达,将重新计时,直到上述两种情况之一才会返回,否则会一直等待。)

   If VMIN is non-zero, VTIME specifies the time to wait for the first character read. If a character is read within the time given, any read will block (wait) until all VMIN  characters are read. That is, once the first character is read, the serial interface driver expects to receive an  entire packet of characters (VMIN bytes total). If no  character is read within the time allowed, then the call to read returns 0. This method allows you to tell the serial  driver you need exactly N bytes and any read call will  return 0 or N bytes. However, the timeout only applies to the first character read, so if for some reason the driver   misses one character inside the N byte packet then the read  call could block forever waiting for additional input characters.

VTIME指定等待输入字符的时间。
如果VTIME设置为0(默认),则读取将无限期地阻塞(等待),除非在open或fcntl中指定O_NDELAY选项。

   VTIME specifies the amount of time to wait for incoming  characters in tenths of seconds. If VTIME is set to 0 (the default), reads will block (wait) indefinitely unless the NDELAY option is set on the port with open or fcntl.
Unused because we use open with the NDELAY option
【11.1】因为已经在open中使用O_NDELAY选项,所以不再使用c_cc
    tios.c_cc[VMIN] = 0;tios.c_cc[VTIME] = 0;

#####【12】设置串口属性

   if (tcsetattr(ctx->s, TCSANOW, &tios) < 0) {close(ctx->s);ctx->s = -1;return -1;}
}
#if HAVE_DECL_TIOCSRS485/* The RS232 mode has been set by default */ctx_rtu->serial_mode = MODBUS_RTU_RS232;
#endifreturn 0;
}

【linux】串口编程(一)——配置串口相关推荐

  1. Linux——Linux系统编程之串口编程总结(串口的初始化、读写操作实践)

    目录 0 引言 1 串口编程的流程 1.1 打开串口 1.2 初始化串口 1.2.1 termios结构体 1.2.2 关键函数 1.2.3 初始化串口代码 2 串口的读写测试例程 0 引言 串口大家 ...

  2. Linux系统编程四:串口编程,控制LED和蜂鸣器

    目录 一.概述 二.串口初始化 2.1 读取当前串口的参数 参数结构体 2.2 波特率相关的函数 2.3 清空串口缓存 2.4 设置串口参数 三.串口通信 四.控制LED和蜂鸣器 五.总结 一.概述 ...

  3. 【C#串口编程计划】串口编程简介

    介绍C#串口编程的基本知识.

  4. 串口编程--C语言串口读取数据

    串口编程 1.通讯流程 2.demo 1.通讯流程 ①.打开串口 ②.设置波特率 ③.设置奇偶校验位.停止位.数据位等 ④.读写数据 ⑤.关闭串口 2.demo 本示例串口文件根据自己实际情况打开,方 ...

  5. 【LabVIEW串口编程】03 串口接收

    上一篇说到,串口发送一次数据的步骤为:打开串口-->发送数据-->关闭串口. 参照串口发送的思路,串口接收一次数据的步骤为:打开串口-->接收数据-->关闭串口.但是这里有一个 ...

  6. 深入浅出Visual C++串口编程--深入浅出VC++串口编程之DOS的串口编程

    在DOS平台下,操作串口主要有下列方式:通过BIOS调用.通过串口的硬件中断或通过对串口硬件进行轮询,本章将对以上三种方式进行具体的介绍并给出例子. 1.BIOS中断 在DOS操作系统下,IBM PC ...

  7. python3.6串口编程实例_Python3 串口接收与发送16进制数据包的实例

    Python3 串口接收与发送16进制数据包的实例 如下所示: import serial import string import binascii s=serial.Serial('com4',9 ...

  8. 串口编程-枚举遍历串口、获取PC所有串口名称、遍历注册表项、RegEnumValue用法

    在网上找了几个关于遍历串口的例子,要么代码不完整,要么就有Bug,如读不了串口号大于10以上的.  经过本人的整理,现分享最终代码,vs2008下编译通过. //此方法同样适用于遍历windows开机 ...

  9. python串口编程_- python串口编程实例

    python读取串口信息#e# 4.python简单程序读取串口信息的方法 具体分析如下: 这段代码需要调用serial模块,通过while循环不断读取串口数据 5.Python简单串口收发GUI界面 ...

  10. python串口编程视频_python 串口编程

    import binascii import sys import threading import serial # 导入模块 import serial.tools.list_ports STRG ...

最新文章

  1. iOS性能分析-Xcode Instruments Allocations 分析APP内存使用情况
  2. 删除作业计划出错(DELETE语句与 REFERENCE约束FK_subplan_job_id冲突。)
  3. 使用 Node.js、Express、AngularJS 和 MongoDB 构建一个Web程序
  4. HDD与OS的江湖恩怨
  5. C++11 std::function
  6. java判断或_Java 条件判断
  7. 天津大学仁爱学院c语言期末考试题,天津大学《C语言程序设计》2016年7月考试期末大作业...
  8. html兄弟选择器怎么用,兄弟选择器 - 选择后面相邻的所有兄弟元素 - css3普通选择器...
  9. idea创建包怎么让包分层_IDEA让包分层显示的实现方式
  10. mysql三表联合查询_求三表联合查询的SQL查询语句
  11. 使用单文档视图结构把Word嵌入到VC程序中(转)
  12. ERDAS IMAGINE 2013裁剪影像方法
  13. 脖子上长痘痘吃什么好
  14. 美团App页面视图可测性改造实践
  15. 小米手机录屏功能在哪?图文教学,轻松解决
  16. 微信小程序实现锚点效果 scroll-view的scroll-into-view属性
  17. Pulmonary--Detection6
  18. Java Service Wrapper 使用经验总结
  19. 【BZOJ1502】[NOI2005]月下柠檬树 Simpson积分
  20. css 颤动_颤动-微光效果

热门文章

  1. 【Pandas库】(1) Series的创建方法
  2. 【点云论文速读】最佳点云分割分析
  3. 线上分享会预告之深度学习在3D场景中的应用
  4. PCLVisualizer可视化类
  5. 几种和边框相关的CSS样式修改
  6. 【骚气的动效】无限循环往下往复淡入淡出运动,通常用于向下箭头,提示用户可以往下滚动或者点击展开
  7. Node.js开发WEB项目后端接口API,基于mysql5.7数据库(小试牛刀)
  8. C语言 #ifndef 引起的redefinition of xxx 问题解决
  9. Ubuntu iso镜像文件写入U盘
  10. 返回一个二维整数数组中的最大的子数组和