串口通信

串口通信

串口在网络通信中经常用到,最近在学习串口通信的编程。所以要对串口操作,就要了解串口的原理等。串口是串行接口的简称,也称串行通信接口或串行通讯接口(通常指COM接口),是采用串行通信方式的扩展接口。串行接口 (Serial Interface) 是指数据一位一位地顺序传送,其特点是通信线路简单,只要一对传输线就可以实现双向通信(可以直接利用电话线作为传输线),从而大大降低了成本,特别适用于远距离通信,但传送速度较慢。串口是计算机上一种非常通用的设备通信协议。大多数计算机(不包括笔记本电脑)包含两个基于RS-232的串口。串口同时也是仪器仪表设备通用的通信协议;很多GPIB兼容的设备也带有RS-232口。同时,串口通信协议也可以用于获取远程采集设备的数据
串口通信是指外设和计算机间,通过数据信号线 、地线、控制线等,按位进行传输数据的一种通讯方式。这种通信方式使用的数据线少,在远距离通信中可以节约通信成本,但其传输速度比并行传输低。
电脑DB9的线,分为公头和母头:对应有九个针脚在这里插入图片描述
在这里插入图片描述
9针脚的功能为:
数据:
GND(pin 5):地线
TXD(pin 3):串口数据输出(Transmit Data)
RXD(pin 2):串口数据输入(Receive Data)
握手:
RTS(pin 7):发送数据请求(Request to Send)
CTS(pin 8):清除发送(Clear to Send)
DSR(pin 6):数据发送就绪(Data Send Ready)
DCD(pin 1):数据载波检测(Data Carrier Detect)
DTR(pin 4):数据终端就绪(Data Terminal Ready)
其它
RI(pin 9):铃声指示
进行数据通信最善需要三根线:TxD RxD GND
在这里插入图片描述
TTL电平和RS232电平:
(一)、TTL电平标准
  输出 L:<0.8V ;H:>2.4V。
  输入 L:<1.2V ;H:>2.0V
  TTL器件输出低电平要小于0.8V,高电平要大于2.4V。输入,低于1.2V就认为是0,高于2.0就认为是1。
(三)、RS232标准
  逻辑1的电平为-3~-15V,逻辑0的电平为+3~+15V,注意电平的定义反相了一次。
串口通信的分类:
1.按照数据传送方向,分为:
单工:数据传输只支持数据在一个方向上传输;
半双工:允许数据在两个方向上传输。但是,在某一时刻,只允许数据在一个方向上传输,它实际上是一种切换方向的单工通信;它不需要独立的接收端和发送端,两者可以合并一起使用一个端口。
全双工:允许数据同时在两个方向上传输。因此,全双工通信是两个单工通信方式的结合,需要独立的接收端和发送端
2、按照通信方式,分为:
同步通信:带时钟同步信号传输。比如:SPI,IIC通信接口。
异步通信:不带时钟同步信号。比如:UART(通用异步收发器),单总线。

Linux串口编程

Linux下所有的设备都是以文件形式存储的,串口也是。串口编程的流程图如下:
在这里插入图片描述

  1. 打开串口
    打开串口就是对文件进行操作,用open()函数。
  2. 配置串口
    串口的配置参数主要有波特率、奇偶校验、数据位和停止位等。串口设置主要使用termios.h头文件中定义的termios结构,如下:
    struct termios
    {
    tcflag_t c_iflag; //输入模式标志
    tcflag_t c_oflag; //输出模式标志
    tcflag_t c_cflag; //控制模式标志
    tcflag_t c_lflag; //本地模式标志
    cc_t c_line; //line discipline
    cc_t c_cc[NCC]; //control characters
    }
    注意:设置波特率时要是输入和输出的速率相同。
    设置波特率用到的两个函数:
cfsetispeed(&newopt, B2400);
cfsetospeed(&newopt, B2400);

校验方式有:无校验位、奇校验、偶校验、空格校验。
数据位有:CS5/CS6/CS7/CS8。
停止位有:一位或者两位。
设置完成之后记得激活配置:

/* 激活配置使其生效*/
145     if((tcsetattr( fd, TCSANOW,&newopt))!=0)
146     {
147         perror("com set error");
148         return -1;
149     }

注意tcsetattr函数中使用的标志:
TCSANOW:立即执行而不等待数据发送或者接受完成。
TCSADRAIN:等待所有数据传递完成后执行。
TCSAFLUSH:Flush input and output buffers and make the change
3 读写串口
对串口的读写操作很简单,用read()和write()函数进行读写操作即可,无特别之处。
4. 关闭串口
使用close()关闭设备文件描述符fd即可。
以下为代码:

 53 /*设置波特率,设置数据位、停止位和校验位*/
 54 int port_set(int fd,int baudrate,int databit,int stopbit,char parity)
 55 {
 56     struct termios oldopt,newopt;/*定义指向结构体stermios的指针opt*/
 57 
 58     /*保存原有串口配置*/
 59     if( tcgetattr( fd,&oldopt )!=0 )
 60     {
 61         printf("set serial 1\n");
 62         return 0;
 63     }
 64     memset(&newopt,0,sizeof(newopt));
 65     newopt.c_cflag|=(CLOCAL|CREAD ); /* CREAD 开启串行数据接收,CLOCAL并打开本地连接模式*/
 66     newopt.c_cflag&=~CSIZE;/*设置数据位*/
 67     switch(databit)
 68     {
 69         case 5:
 70             newopt.c_cflag|=CS5;
 71             break;
 72         case 6:
 73             newopt.c_cflag|=CS6;
 74             break;
 75         case 7:
 76             newopt.c_cflag|=CS7;
 77             break;
 78         case 8:
 79             newopt.c_cflag|=CS8;
 80             break;
 81         default:
 82             printf("Unknow databit!\n");
 83             return -1;
 84     }
 85 /* 0 50 75 110 134 150 200 300 600 1200 1800 2400 4800 9600 19200 38400 57600 115200 230400 */
 86     /* 设置波特率 */
 87     switch(baudrate)
 88     {
 89         case 2400:
 90             cfsetispeed(&newopt, B2400);
 91             cfsetospeed(&newopt, B2400);
 92             break;
 93         case 4800:
 94             cfsetispeed(&newopt, B4800);
 95             cfsetospeed(&newopt, B4800);
 96             break;
 97         case 9600:
 98             cfsetispeed(&newopt, B9600);
 99             cfsetospeed(&newopt, B9600);
100             break;
101         case 115200:
102             cfsetispeed(&newopt, B115200);
103             cfsetospeed(&newopt, B115200);
104             break;
105         default:
106             cfsetispeed(&newopt, B9600);
107             cfsetospeed(&newopt, B9600);
108             break;
109     }
          switch(parity)
 55     {
 56         case 'n':
 57         case 'N':/*  无奇偶校验 */
 58             newopt.c_cflag&= ~PARENB;
 59             newopt.c_iflag&= ~INPCK;
 60             break;
 61         case 'o':
 62         case 'O':/*  奇校验 */
 63             newopt.c_cflag|= (PARODD | PARENB);
 64             newopt.c_iflag|= INPCK;
 65             break;
 66         case 'e':
 67         case 'E':/*  偶校验 */
 68             newopt.c_cflag|= PARENB;
 69             newopt.c_cflag&= ~PARODD;
 70             newopt.c_iflag|= INPCK;
 71             break;
 72         case 's':
 73         case 'S':/*  设置为空格 */
 74             newopt.c_cflag&= ~PARENB;
 75             newopt.c_cflag&= ~CSTOPB;
 76             break;
 77         default:
 78             printf("Unsupported parity\n");
 79             return -1;
 80     }
          newopt.c_cflag&=~CSIZE;/*设置数据位*/
 67     switch(databit)
 68     {
 69         case 5:
 70             newopt.c_cflag|=CS5;
 71             break;
 72         case 6:
 73             newopt.c_cflag|=CS6;
 74             break;
 75         case 7:
 76             newopt.c_cflag|=CS7;
 77             break;
 78         case 8:
 79             newopt.c_cflag|=CS8;
 80             break;
 81         default:
 82             printf("Unknow databit!\n");
 83             return -1;
 84     }
            /* 设置停止位 */
130     if( stopbit==1 )/*若停止位为1,则清除CSTOPB,若停止位为2,则激活CSTOPB*/
131     {
132         newopt.c_cflag &=~CSTOPB;/* 默认为一位停止位 */
133     }
134     else if( stopbit==2 )
135     {
136         newopt.c_cflag |=CSTOPB;/*CSTOPB表示送两位停止位*/
137     }
            /* 设置最少字符和等待时间,对于接收字符和等待时间没有特别的要求时*/
140     newopt.c_cc[VTIME] = 0;/* 非规范模式读取时的超时时间;*/
141     newopt.c_cc[VMIN]  = 0; /* 非规范模式读取时的最小字符数*/
142     tcflush(fd ,TCIFLUSH);/* tcflush清空终端未完成的输入/输出请求及数据;TCIFLUSH表示清空正收到的数据,且不读取出来 */
143 
144     /* 激活配置使其生效*/
145     if((tcsetattr( fd, TCSANOW,&newopt))!=0)
146     {
147         perror("com set error");
148         return -1;
149     }
150 }

将每个步骤写成一个函数,直接进行调用即可。也可以将串口的路径、波特率等参数封装成一个结构体,用结构体指针传参,每次使用只需调用即可。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值