简介

串口也称串行通信接口(通常指COM接口),是实际工作中经常使用的一个接口,比如Linux下使用的debug串口,它用来登录Linux系统,输出log。另外也会使用串口和外部的一些模块通信,比如GPS模块、RS485等。串口通信的两种最基本的方式:同步串行通信方式和异步串行通信方式。异步串行是指UART(UniversalAsynchronous Receiver/Transmitter)通用异步收发传输器,通信双方接三根线,RX、TX和GND,TX用于发送数据,RX用于接受数据,双方收发交叉对接,支持全双工方式,包含TTL电平的串口和RS232电平的串口。TTL电平是3.3V的,而RS232是负逻辑电平。一般软件配置串口,有波特率,数据位、停止位、校验位、流控。分别表示传输速度,一帧数据的长度,以及发完告知停止,发完是否校验,是否进行发送控制。默认是固定8位数据位,1位停止位、无校验、无流控,只需配置波特率。

RS-232

最常用的一种串行通讯接口。它的全名是“数据终端设备(DTE)和数据通讯设备(DCE)之间串行二进制数据交换接口技术标准”。传统的RS-232-C接口标准有22根线,采用标准25芯D型插头座(DB25),后来使用简化为9芯D型插座(DB9),现在应用中25芯插头座已很少采用。RS-232采取不平衡传输方式,即所谓单端通讯。由于其发送电平与接收电平的差仅为2V至3V左右,所以其共模抑制能力差,再加上双绞线上的分布电容,其传送距离最大为约15米,最高速率为20kb/s。RS-232是为点对点(即只用一对收、发设备)通讯而设计的,其驱动器负载为3~7kΩ。所以RS-232适合本地设备之间的通信。

RS-485

RS-485可以采用二线与四线方式,二线制可实现真正的多点双向通信,而采用四线连接时只能实现点对多的通信,即只能有一个主(Master)设备,其余为从设备,无论四线还是二线连接方式总线上可多接到32个设备。RS-485与RS-422的不同还在于其共模输出电压是不同的,RS-485是-7V至+12V之间,而RS-422在-7V至+7V之间,RS-485接收器最小输入阻抗为12kΩ、RS-422是4kΩ;由于RS-485满足所有RS-422的规范,所以RS-485的驱动器可以在RS-422网络中应用。RS-485与RS-422一样,其最大传输距离约为1219米,最大传输速率为10Mb/s。平衡双绞线的长度与传输速率成反比,在100kb/s速率以下,才可能使用规定最长的电缆长度。只有在很短的距离下才能获得最高速率传输。一般100米长双绞线最大传输速率仅为1Mb/s。

linux下的串口操作

Linux的串口表现为设备文件。串口设备文件命名一般为/dev/ttySn,若串口是USB扩展的,则串口设备文件命名多为/dev/ttyUSBn。不同的硬件平台对串口设备文件的命名有所区别。

linux终端操作串口

可使用microcom工具操作串口,如下:microcom -s 115200 /dev/ttyS1 /dev下的ttyS1对应的就是UART1设备。 microcom 命令后的-s 115200,表示设置波特率为115200bps。 micrcom指令退出的方式是Ctrl+x,不是Ctrl+c。

打开串口

在编写Linux串口程序时,需要包含termios.h头文件:

#include <termios.h>

在使用某个串口前,必须用open()函数打开它所对应的设备文件。如下:

int fd;
fd = open("/dev/ttyS1", O_RDWR | O_NOCTTY );
if (fd < 0) {    perror("open uart device error\n");
}

当open调用成功后,将返回文件描述符,并作为其它操作函数的参数;如果失败返回负数。在打开串口时,除了需要用到O_RDWR选项标志外,通常还需要使用O_NOCTTY,目的是告诉Linux“本程序不作为串口的‘控制终端’”。如果不使用该选项,会有一些输入字符影响进程运行(如一些产生中断信号的键盘输入字符等)。

关闭串口

当不再使用某个串口时,可用close()函数关闭串口:

close(fd); 参数fd为打开串口时得到的文件描述符。

发送数据

往串口发送数据可通过write()函数完成。

int len;
char buf[] = "hello world!";
len = write(fd, buf, sizeof(buf));
if (len< 0) {
printf("write data to serial failed! \n");
}

字符串的长度为sizeof(buf),作为write()函数的发送数据长度参数。写操作完成后,返回值为成功发送数据的长度;如果发送失败,返回负数。

设置串口参数

串口通讯波特率设置

波特率的设置定义在<termios.h>里。设置波特率使用cfsetispeed( )cfsetospeed( )函数来操作,获取波特率信息是通过cfgetispeed()和cfgetospeed()函数来完成的。

struct termios opt;
cfsetispeed(&opt,B9600 );
cfsetospeed(&opt,B9600);

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

串口属性配置

属性定义在结构体struct termios中。头文件<termbits.h>

该结构体定义如下:

// 配置串口属性结构
struct termios{
tcflag_t c_iflag;    /* 设置c_iflag可以设置输入模式标志 */
tcflag_t c_oflag;    /* 设置c_oflag可以设置输出模式标志 */
tcflag_t c_cflag;    /* 设置c_cflag可以设置控制模式标志 */
tcflag_t c_lflag;    /* c_lflag为本地模式标志* /
cc_t c_line;         / *c_line 为线规划* /
cc_t c_cc[NCCS];     / *cc_cc[NCCS]为控制字符* /
speed_t c_ispeed;    / *c_ispeed为输入速率*/
speed_t c_ospeed;    / *c_ospeed为输出速率 */  #define _HAVE_STRUCT_TERMIOS_C_ISPEED 1  #define _HAVE_STRUCT_TERMIOS_C_OSPEED 1 };
//  c_iflag取值
#define IGNBRK  0000001//ignore break 忽略break键输入
#define BRKINT  0000002//当break情况被检测到发送SIGINT信号#define IGNPAR  0000004 //忽略帧错误和奇偶校验错误
#define PARMRK  0000010//标识奇偶校验错误
#define INPCK  0000020//启用输入奇偶校验
#define ISTRIP  0000040//去除字符的第8个比特
#define INLCR  0000100//将输入的NL(换行)转换成CR(回车)
#define IGNCR  0000200//忽略输入中的回车
#define ICRNL  0000400//将CR(回车)转换成NL(换行)
#define IUCLC  0001000//将输入的大写字符转换成小写字符(非POSIX)
#define IXON  0002000//开启输入时XON/XOFF流控制
#define IXANY  0004000//输入任何字符将重启停止时的输出
#define IXOFF  0010000//关闭输入时XON/XOFF流控制
#define IMAXBEL  0020000//当输入队列满时开始响铃
#define IUTF8  0040000//使用UTF-8编码输入
// bits/termio.h中其他定义
/* tcflow() and TCXONC use these /
#define  TCOOFF    0// 挂起输出
#define  TCOON    1//重新开始被挂起的输出
#define  TCIOFF    2//发送一个 STOP 字符,停止终端设备向系统传送数据#
define  TCION    3//发送一个 START 字符,使终端设备向系统传输数据/打开一个终端设备时的默认设置是输入和输出都没有挂起。*/
/* tcflush() and TCFLSH use these  清除缓冲区数据*/
#define  TCIFLUSH  0//清除输入缓冲区
#define  TCOFLUSH  1//清除输出缓冲区
#define  TCIOFLUSH  2//清除输入输出缓冲区
/* tcsetattr uses these */
#define  TCSANOW    0//不等数据传输完毕就立即改变属性
#define  TCSADRAIN  1//等待所有数据传输结束才改变属性#define  TCSAFLUSH  2//清空输入输出缓冲区才改变属性
#define IOT_termios /* Hurd ioctl type field.  */ \  _IOT (IOTS (cflag_t), 4, _IOTS (cc_t), NCCS, _IOTS (speed_t), 2)

VTIME 和 VMIN

VTIME 定义要求等待的零到几百毫秒的值(通常是一个8位的unsigned char变量)。

VMIN 定义了要求等待的最小字节数, 这个字节数可能是0。只有设置为阻塞时这两个参数才有效,仅针对于读操作。

options.c_cc[VTIME] = 0;

options.c_cc[VMIN] = 0;

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

options.c_cc[VTIME] = 0;

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

options.c_cc[VMIN] = 4;

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

options.c_cc[VTIME] = 10; //单位百毫秒

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

options.c_cc[VTIME] = 10;

options.c_cc[VMIN] = 2;

读取数据

使用read()函数可以读取串口接收到的数据。

int len;unsigned char buf[11];
len = read(fd, buf, 11);
if (len < 0){
printf("reading data faile \n");
}

读取成功,函数返回所读数据长度;失败返回负数。

使用范例

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#define DEV_NAME "/dev/ttyS1"
int main (int argc, char *argv[])
{
int fd;
int len, i,ret;
char buf[] = "hello world!";
fd = open(DEV_NAME, O_RDWR | O_NOCTTY);if(fd < 0) {   perror(DEV_NAME);   return -1;}
struct termios uart_cfg_opt;speed_t speed = B9600;
if (-1 == tcgetattr(fd, &uart_cfg_opt))
return -1;
tcflush(fd, TCIOFLUSH);
cfsetospeed(&uart_cfg_opt, speed);cfsetispeed(&uart_cfg_opt, speed);
if (-1 == tcsetattr(fd , TCSANOW, &uart_cfg_opt))
return -1;
uart_cfg_opt.c_cc[VTIME] = 1;
uart_cfg_opt.c_cc[VMIN] = 0;
/* Data length setting section */uart_cfg_opt.c_cflag &= ~CSIZE;uart_cfg_opt.c_cflag |= CS8;
uart_cfg_opt.c_iflag &= ~INPCK;
uart_cfg_opt.c_cflag &= ~PARODD;
uart_cfg_opt.c_cflag &= ~CSTOPB;
/* Using raw data mode */
uart_cfg_opt.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);uart_cfg_opt.c_iflag &= ~(INLCR | IGNCR | ICRNL | IXON | IXOFF);uart_cfg_opt.c_oflag &= ~(INLCR | IGNCR | ICRNL);uart_cfg_opt.c_oflag &= ~(ONLCR | OCRNL);
/* Apply new settings */
if (-1 == tcsetattr(fd , TCSANOW, &uart_cfg_opt))
return -1;
tcflush(fd , TCIOFLUSH);len = write(fd, buf, sizeof(buf)); /* 向串口写入字符串 */
if (len < 0) {    printf("write data error \n");}
len = read(fd, buf, sizeof(buf)); /* 在串口读入字符串 */
if (len < 0) {   printf("read error \n");   return -1;}printf("%s", buf); /* 打印从串口读出的字符串 */return(0);
}

详解Linux下的串口相关推荐

  1. 详解linux下auto工具制作Makefile源码包(制作篇)

    2019独角兽企业重金招聘Python工程师标准>>> 详解linux下auto工具制作Makefile源码包(制作篇) 水木杨 一.     概述 为了更好的制作configure ...

  2. linux上 arm开发环境搭建,详解 LINUX下QT For ARM开发环境搭建过程

    LINUX下QT For ARM开发环境搭建过程是本文介绍的内容,不多说,先来看内容.在PC上,我们需要得到两个版本的Qt,分别是:Qt-4.5.2和QtEmbedded-4.5.2-arm.前者包括 ...

  3. linux中which命令详解,Linux下which命令使用详解(转)

    我们经常在linux要查找某个文件,但不知道放在哪里了,可以使用下面的一些命令来搜索: which 查看可执行文件的位置. whereis 查看文件的位置. locate 配合数据库查看文件位置. f ...

  4. linux环境下ps命令行,Linux下ps命令详解 Linux下ps命令的详细使用方法

    Linux下ps命令详解 Linux上进程有5种状态:1. 运行(正在运行或在运行队列中等待) 2. 中断(休眠中, 受阻, 在等待某个条件的形成或接受到信号) 3. 不可中断(收到信号不唤醒和不可运 ...

  5. linux nginx编译详解,Linux下nginx编译安装教程和编译参数详解

    这篇文章主要介绍了Linux下nginx编译安装教程和编译参数详解,需要的朋友可以参考下 一.必要软件准备 1.安装pcre 为了支持rewrite功能,我们需要安装pcre 复制代码 代码如下:# ...

  6. linux中的ps fx命令,Linux下ps命令详解 Linux下ps命令的详细使用方法

    Linux下ps命令详解 1. 运行(正在运行或在运行队列中等待) 2. 中断(休眠中, 受阻, 在等待某个条件的形成或接受到信号) 3. 不可中断(收到信号不唤醒和不可运行, 进程必须等待直到有中断 ...

  7. lunux安装多个mysql_实例详解linux下多个mysql5.7.19(tar.gz)安装图文教程

    初级第一次在Linux下安装MySQL-5.7.19版本教程请看上一篇,如果已经会安装了,那么请看这篇linux下安装多个mysql-5.7.19,本文主要为大家详细介绍了linux下多个mysql5 ...

  8. linux下的tar压缩解压缩命令详解,Linux下的tar压缩解压缩命令详解

    linux下tar gz bz2 tgz z等众多压缩文件的压缩与解压方法,需要的朋友可以参考下 Linux下最常用的打包程序就是tar了,使用tar程序打出来的包我们常称为tar包,tar包文件的命 ...

  9. linux c++ 获取时间,详解Linux下的C++时间类型:time_t

    Unix时间戳(Unix timestamp),或称Unix时间(Unix time).POSIX时间(POSIX time),是一种时间表示方式,定义为从格林威治时间1970年01月01日00时00 ...

最新文章

  1. Nginx和Tengine
  2. 负载均衡探测器lbd
  3. maven scope/site/effective-pom/assembly
  4. Blog-LOGO原型
  5. Python 爬虫知识点 - 淘宝商品检索结果抓包分析(续一)
  6. HoloLens开发手记-全息Hologram
  7. android缓存的后台进程,Android应用程序进程生命周期详解
  8. Linux shell - 按时间和文件大小排序显示文件(ll)
  9. 第二:Postman做各种类型的http接口测试
  10. 《设计模式详解》行为型模式 - 职责链模式
  11. 3D视觉——基恩士LJ-X系列线激光
  12. 持续集成学习总结(三)
  13. ws配置 zuul_微服务网关 Spring Cloud Gateway
  14. Atitit. null错误的设计 使用Optional来处理null
  15. 李炎恢html5资源,李炎恢HTML5视频资料分享
  16. HTML的学习-2|HTML 标签(上)
  17. 作为前端,如何帮帝都的朋友租到合适的房子
  18. Python实现将位图描摹为彩色矢量 svg 图片的源代码,Python实现位图转彩色矢量代码
  19. python 浮点数类型
  20. Linux驱动-字符设备驱动

热门文章

  1. 中文FOXBASE命令集-学习公社-搜狐教育
  2. 有限元求解两点边值问题之二
  3. 一张单词表!Java So Easy!
  4. 超实用4款办公应用,轻松提早下班时间
  5. 复合材料 matlab,基于Matlab的复合材料刚度分析.pdf
  6. Python文件运行说明书以及解决的过程_一蓑烟雨任平生
  7. 首都经济贸易大学计算机考研资料汇总
  8. 公岸网:公共基础知识必背内容
  9. Pr自学(抠图、调色)
  10. 监控系统计算机网络自检表,高速公路机电系统交工自检表格(全)