Linux 使用C++读取串口数据并且显示16进制
目录
本文主要分享在Linux系统中(Ubutun),如何使用C++语言实现串口的数据读取,并以16进制的格式显示。
串口调试
在不知道串口是否正常工作的情况下,可用使用minicom进系调试
安装minicom
sudo apt-get install minicom
使用minicom打开串口,查看数据:
minicom -D /dev/ttyUSB0
确保串口是正常工作后,就可以开始测试代码了。
程序代码
创建一个文件,并且输入以下代码:
// 加载 打开串口并读取显示 用到的库
#include <iostream>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
// 加载 实现显示16进制 用到的库
#include <sstream>
#include <iomanip>
// 加载 使用延时时会 用到的库
#include <thread>
#include <chrono>
int main()
{
int fd;
struct termios tty;
char buffer[1024];
ssize_t bytesRead;
// 打开 /dev/ttyUSB0 串口端口
fd = open("/dev/ttyUSB0", O_RDONLY | O_NOCTTY);
if (fd == -1)
{
std::cerr << "Error opening serial port." << std::endl;
return 1;
}
// 配置串口参数
if (tcgetattr(fd, &tty) != 0)
{
std::cerr << "Error getting serial port attributes." << std::endl;
close(fd);
return 1;
}
// 配置波特率
cfsetospeed(&tty, B115200);
cfsetispeed(&tty, B115200);
tty.c_cflag |= (CLOCAL | CREAD);
tty.c_cflag &= ~PARENB;
tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~CSIZE;
tty.c_cflag |= CS8;
tty.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
tty.c_iflag &= ~(INPCK | ISTRIP);
tty.c_oflag &= ~OPOST;
tty.c_cc[VMIN] = 1;
tty.c_cc[VTIME] = 0;
if (tcsetattr(fd, TCSANOW, &tty) != 0)
{
std::cerr << "Error setting serial port attributes." << std::endl;
close(fd);
return 1;
}
// 读取串口数据并输出到控制台
while (true)
{
bytesRead = read(fd, buffer, sizeof(buffer));
if (bytesRead == -1)
{
std::cerr << "Error reading serial port." << std::endl;
close(fd);
return 1;
}
if (bytesRead > 0)
{
std::stringstream ss;
ss << std::hex;
for(int i=0; i<bytesRead; i++) {
ss << std::setw(2) << std::setfill('0') << (int)buffer[i];
std::cout << (int)buffer[i]; // 原始数据显示
}
// 16进制显示
std::string hex_str = ss.str();
std::cout << "Hex: " << hex_str << std::endl;
std::cout << '\n';
}
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
// 关闭串口
close(fd);
return 0;
}
保存文件,使用g++编译文件:
g++ <file_name.cpp> -o <function_name>
之后在当前目录会生成一个编译好的执行文件:<function_name>
运行该程序:
./<function_name>
会看到串口的输出:
错误排除
Error reading serial port.
出现 Error reading serial port.
可能是串口设备的权属问题。
方法一:更改设备属主
1,使用以下命令,查看设备的属主:
ls -l /dev/ttyUSB0
默认属主通常是root。
2,改变串口设备的属主为当前用户:
sudo chown $USER /dev/ttyUSB0
可以更改root用户为当前用户,再运行代码测试。
3,改变串口设备的属组为 dialout 或 tty :
sudo chgrp dialout /dev/ttyUSB0
4,设置串口设备的权限为660:
sudo chmod 660 /dev/ttyUSB0
这样ttyUSB0的属主就改为了bbot,属组为dialout,bbot用户就可以直接访问串口设备了。
5,重启可插拔设备服务更新规则:
sudo udevadm trigger
每次改变串口设备权限后,都需要重启udev服务使改动生效。
这样通过改变属主和属组,可以方便地将ttyUSB0的访问权限转移给当前用户。
方法二:把当前用户添加到dialout用户组
在Linux中,可以通过改变串口设备文件的用户组和权限来修改ttyUSB0的用户访问权限。
- 查看当前串口用户组和权限:
ls -l /dev/ttyUSB0
默认是root用户和dialout组拥有读写权限。
- 将当前用户加入dialout组:
sudo usermod -a -G dialout $USER
这会将当前用户加入dialout组,无需重启即可生效。
- 修改设备文件的组:
sudo chgrp dialout /dev/ttyUSB0
将串口设备文件的组改为dialout。
- 修改设备文件权限:
sudo chmod 660 /dev/ttyUSB0
设置为dialout组用户可读写,其他用户不可访问。
这样当前用户就可以通过dialout组访问该串口设备了。
也可以通过添加用户到tty组,或直接修改设备文件的用户等方式改变串口的访问权限。