linux串口通信
Posted 神佑我调参侠
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux串口通信相关的知识,希望对你有一定的参考价值。
前言
因为最后我们要将得到的数据传给电控,传输的方式就是串口通信,然而以前我使用的都是python写的,这次开始使用c/c++去写,开始是让学弟写,但是加入工程的时候发现有很多地方都封装不了,于是我打算自己来实现一波,然后封装一下,那现在开始吧。
借鉴:https://blog.csdn.net/AAA375/article/details/100096490
串口引脚
首先我们来看一下串口的引脚,因为我们后期写的代码就是对这些引脚进行操作的,我在第一次看代码的时候也是很蒙的,因为我并不知道那些我不知道的是引脚。。。。
具体怎么用后期直接结合代码查看!
代码书写
导入库
这个吧,直接复制就好
#include <stdio.h> /*标准输入输出定义*/
#include <stdlib.h> /*标准函数库定义*/
#include <unistd.h> /*Unix 标准函数定义*/
#include <sys/types.h> /*数据类型,比如一些XXX_t的那种*/
#include <sys/stat.h> /*定义了一些返回值的结构,没看明白*/
#include <fcntl.h> /*文件控制定义*/
#include <termios.h> /*PPSIX 终端控制定义*/
#include <errno.h> /*错误号定义*/
打开串口
首先得明白个事,端口不固定,对于不同的设备是不同,对于linux下的话是位于 /dev 下的,串口一 为 /dev/ttyS0,串口二 为 /dev/ttyS1,我们这里用的串口一:
#include <stdio.h> /*标准输入输出定义*/
#include <stdlib.h> /*标准函数库定义*/
#include <unistd.h> /*Unix 标准函数定义*/
#include <sys/types.h> /*数据类型,比如一些XXX_t的那种*/
#include <sys/stat.h> /*定义了一些返回值的结构,没看明白*/
#include <fcntl.h> /*文件控制定义*/
#include <termios.h> /*PPSIX 终端控制定义*/
#include <errno.h> /*错误号定义*/
#include <iostream>
using namespace std;
int main()
int fd = -1;
/*以读写方式打开串口*/
fd = open( "/dev/ttyS0", O_RDWR);
cout<<fd<<endl;
if (-1 == fd)
/* 不能打开串口一*/
perror(" 提示错误!");
else
cout<<"打开成功!"<<endl;
可以看到我们已经成功打开串口了
设置串口(修改比特率)
在打开串口后我们要进行一些设置,如比特率,效验位等,这些设置是通过一个结构体来设置。
struct termio
unsigned short c_iflag; /* 输入模式标志 */
unsigned short c_oflag; /* 输出模式标志 */
unsigned short c_cflag; /* 控制模式标志*/
unsigned short c_lflag; /* local mode flags */
unsigned char c_line; /* line discipline */
unsigned char c_cc[NCC]; /* control characters */
;
如果要去看源码的话,是很难理解的,我也是没看懂,但是并不影响我们使用,下面是一个设置波特率的例子:
//比特率配置
int speed_arr[] = B38400, B19200, B9600, B4800, B2400, B1200, B300,
B38400, B19200, B9600, B4800, B2400, B1200, B300, ;
int name_arr[] = 38400, 19200, 9600, 4800, 2400, 1200, 300, 38400,
19200, 9600, 4800, 2400, 1200, 300, ;
void set_speed(int fd, int speed)
int status;
//定义结构体
struct termios Opt;
//tcgetattr函数用于获取与终端相关的参数。参数fd为终端的文件描述符,返回的结果保存在termios结构体中
tcgetattr(fd, &Opt);
for (int i = 0; i < sizeof(speed_arr) / sizeof(int); i++)
if (speed == name_arr[i])
//清空终端未完成的输入/输出请求及数据。TCIOFLUSH // 清除所有正在发生的I/O数据。
tcflush(fd, TCIOFLUSH);
//设置输入速度
cfsetispeed(&Opt, speed_arr[i]);
//设置输出速度
cfsetospeed(&Opt, speed_arr[i]);
//使用tcsetattr函数将修改后的终端参数设置到标准输入中
status = tcsetattr(fd, TCSANOW, &Opt);
if (status != 0)
perror("tcsetattr fd1");
return;
tcflush(fd, TCIOFLUSH);
这里面有几个函数大家可能没见过,但是注释中也写的很明白了,其实就是先获取结构体的参数,然后修改比特率参数,再设置一下,上述一大堆操作就是为了修改比特率。
#include <stdio.h> /*标准输入输出定义*/
#include <stdlib.h> /*标准函数库定义*/
#include <unistd.h> /*Unix 标准函数定义*/
#include <sys/types.h> /*数据类型,比如一些XXX_t的那种*/
#include <sys/stat.h> /*定义了一些返回值的结构,没看明白*/
#include <fcntl.h> /*文件控制定义*/
#include <termios.h> /*PPSIX 终端控制定义*/
#include <errno.h> /*错误号定义*/
#include <iostream>
using namespace std;
//串口状态变量
int fd = -1;
//比特率配置
int speed_arr[] = B38400, B19200, B9600, B4800, B2400, B1200, B300,
B38400, B19200, B9600, B4800, B2400, B1200, B300, B115200 ;
int name_arr[] = 38400, 19200, 9600, 4800, 2400, 1200, 300, 38400,
19200, 9600, 4800, 2400, 1200, 300,115200 ;
//打开串口
void open_port()
/*以读写方式打开串口*/
fd = open("/dev/ttyS0", O_RDWR);
if (-1 == fd)
/* 不能打开串口一*/
perror(" 串口打开失败!");
else
cout << "串口打开成功!" << endl;
//设置比特率速度
void set_speed(int fd, int speed)
int status;
//定义结构体
struct termios Opt;
//fd=0标准输入,该函数作用是将fd的状态放入结构体
tcgetattr(fd, &Opt);
//使用原始模式
Opt.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /*Input*/
Opt.c_oflag &= ~OPOST; /*Output*/
cout<<1<<endl;
for (int i = 0; i < sizeof(speed_arr) / sizeof(int); i++)
if (speed == name_arr[i])
tcflush(fd, TCIOFLUSH);
cfsetispeed(&Opt, speed_arr[i]);
cfsetospeed(&Opt, speed_arr[i]);
status = tcsetattr(fd, TCSANOW, &Opt);
if (status != 0)
perror("tcsetattr fd1");
return;
else
cout<<"比特率速度修改成功"<<endl;
tcflush(fd, TCIOFLUSH);
int main()
open_port();
set_speed(0,115200);
return 0;
发送数据
写串口操作是通过write函数来完成的。函数原型如下:
write(int fd, *buffer,length);
参数说明:
(1).fd:文件描述符
(2).*buffer:存储写入数据的数据缓冲区
(3).length:写入缓冲去的数据字节数
函数返回值:
成功返回写入数据的字节数,该值通常等于length,如果写入失败返回-1。
例如:向终端设备发送初始化命令
设置好串口之后,读写串口就很容易了,把串口当作文件读写就是。
#include <stdio.h> /*标准输入输出定义*/
#include <stdlib.h> /*标准函数库定义*/
#include <unistd.h> /*Unix 标准函数定义*/
#include <sys/types.h> /*数据类型,比如一些XXX_t的那种*/
#include <sys/stat.h> /*定义了一些返回值的结构,没看明白*/
#include <fcntl.h> /*文件控制定义*/
#include <termios.h> /*PPSIX 终端控制定义*/
#include <errno.h> /*错误号定义*/
#include <iostream>
using namespace std;
//串口状态变量
int fd = -1;
//比特率配置
int speed_arr[] = B38400, B19200, B9600, B4800, B2400, B1200, B300,
B38400, B19200, B9600, B4800, B2400, B1200, B300, B115200 ;
int name_arr[] = 38400, 19200, 9600, 4800, 2400, 1200, 300, 38400,
19200, 9600, 4800, 2400, 1200, 300,115200 ;
//打开串口
void open_port()
/*以读写方式打开串口*/
fd = open("/dev/ttyS0", O_RDWR);
if (-1 == fd)
/* 不能打开串口一*/
perror(" 串口打开失败!");
else
cout << "串口打开成功!" << endl;
//设置比特率速度
void set_speed(int fd, int speed)
int status;
//定义结构体
struct termios Opt;
//fd=0标准输入,该函数作用是将fd的状态放入结构体
tcgetattr(fd, &Opt);
//使用原始模式
//Opt.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /*Input*/
//Opt.c_oflag &= ~OPOST; /*Output*/
for (int i = 0; i < sizeof(speed_arr) / sizeof(int); i++)
if (speed == name_arr[i])
tcflush(fd, TCIOFLUSH);
cfsetispeed(&Opt, speed_arr[i]);
cfsetospeed(&Opt, speed_arr[i]);
status = tcsetattr(fd, TCSANOW, &Opt);
if (status != 0)
perror("tcsetattr fd1");
return;
else
cout<<"比特率速度修改成功"<<endl;
tcflush(fd, TCIOFLUSH);
void write_port(char buffer[1024])
int Length;
int nByte;
nByte = write(fd, buffer ,Length);
cout<<"nByte="<<nByte<<endl;
cout<<"Length="<<Length<<endl;
void read_port(char buffer[1024])
cout<<"123"<<endl;
int nread =read(fd, buffer, 512);
cout<<"nread"<<nread<<endl;
cout<<"buffer"<<buffer<<endl;
int main()
open_port();
set_speed(0,115200);
while(1)
char buffer[1024]="0x25";
//read_port(buffer);
write_port(buffer);
return 0;
#总结
通过上面的学习现在已经可以接送和发送了,但是有点小问题,下篇文章将结合RM来进行实战!
以上是关于linux串口通信的主要内容,如果未能解决你的问题,请参考以下文章