Linux下使用C/C++获取可用串口

288 篇文章 25 订阅
10 篇文章 1 订阅

最近在Jetson Nano上发现个问题,插多个USB-TTL后,串口号会发生变化。看来笔者之前

C/C++语言读写UART或USB串口数据正在上传…重新上传取消https://blog.csdn.net/qq_25662827/article/details/122581819的同学应该都知道,笔者在代码中是将端口号写死了的。

        面对多变的串口,我们应该怎么办呢?本篇笔者就分享一下,使用C/C++获取可用串口的方法。


        之前也说过,LIUNX下万物皆文件,每个串口的注册实际上就会生成一个文件,我们要获取可用串口,也就是要查找当前的文件名。废话不多说,还是先献上代码:

 
  1. #include <stdlib.h>

  2. #include <dirent.h>

  3. #include <stdio.h>

  4. #include <sys/types.h>

  5. #include <sys/stat.h>

  6. #include <unistd.h>

  7. #include <string.h>

  8. #include <fcntl.h>

  9. #include <termios.h>

  10. #include <sys/ioctl.h>

  11. #include <linux/serial.h>

  12. #include <iostream>

  13. #include <list>

  14. using namespace std;

  15. static string get_driver(const string& tty);

  16. static void register_comport( list<string>& comList, list<string>& comList8250, const string& dir);

  17. static void probe_serial8250_comports(list<string>& comList, list<string> comList8250);

  18. list<string> getComList();

  19. int main() {

  20. list<string> l = getComList();

  21. list<string>::iterator it = l.begin();

  22. while (it != l.end()) {

  23. cout << *it << endl;

  24. it++;

  25. }

  26. return 0;

  27. }

  28. static string get_driver(const string& tty) {

  29. struct stat st;

  30. string devicedir = tty;

  31. // Append '/device' to the tty-path

  32. devicedir += "/device";

  33. // Stat the devicedir and handle it if it is a symlink

  34. if (lstat(devicedir.c_str(), &st)==0 && S_ISLNK(st.st_mode)) {

  35. char buffer[1024];

  36. memset(buffer, 0, sizeof(buffer));

  37. // Append '/driver' and return basename of the target

  38. devicedir += "/driver";

  39. if (readlink(devicedir.c_str(), buffer, sizeof(buffer)) > 0)

  40. return basename(buffer);

  41. }

  42. return "";

  43. }

  44. static void register_comport( list<string>& comList, list<string>& comList8250, const string& dir) {

  45. // Get the driver the device is using

  46. string driver = get_driver(dir);

  47. // Skip devices without a driver

  48. if (driver.size() > 0) {

  49. string devfile = string("/dev/") + basename(dir.c_str());

  50. // Put serial8250-devices in a seperate list

  51. if (driver == "serial8250") {

  52. comList8250.push_back(devfile);

  53. } else

  54. comList.push_back(devfile);

  55. }

  56. }

  57. static void probe_serial8250_comports(list<string>& comList, list<string> comList8250) {

  58. struct serial_struct serinfo;

  59. list<string>::iterator it = comList8250.begin();

  60. // Iterate over all serial8250-devices

  61. while (it != comList8250.end()) {

  62. // Try to open the device

  63. int fd = open((*it).c_str(), O_RDWR | O_NONBLOCK | O_NOCTTY);

  64. if (fd >= 0) {

  65. // Get serial_info

  66. if (ioctl(fd, TIOCGSERIAL, &serinfo)==0) {

  67. // If device type is no PORT_UNKNOWN we accept the port

  68. if (serinfo.type != PORT_UNKNOWN)

  69. comList.push_back(*it);

  70. }

  71. close(fd);

  72. }

  73. it ++;

  74. }

  75. }

  76. list<string> getComList() {

  77. int n;

  78. struct dirent **namelist;

  79. list<string> comList;

  80. list<string> comList8250;

  81. const char* sysdir = "/sys/class/tty/";

  82. // Scan through /sys/class/tty - it contains all tty-devices in the system

  83. n = scandir(sysdir, &namelist, NULL, NULL);

  84. if (n < 0)

  85. perror("scandir");

  86. else {

  87. while (n--) {

  88. if (strcmp(namelist[n]->d_name,"..") && strcmp(namelist[n]->d_name,".")) {

  89. // Construct full absolute file path

  90. string devicedir = sysdir;

  91. devicedir += namelist[n]->d_name;

  92. // Register the device

  93. register_comport(comList, comList8250, devicedir);

  94. }

  95. free(namelist[n]);

  96. }

  97. free(namelist);

  98. }

  99. // Only non-serial8250 has been added to comList without any further testing

  100. // serial8250-devices must be probe to check for validity

  101. probe_serial8250_comports(comList, comList8250);

  102. // Return the lsit of detected comports

  103. return comList;

  104. }

 笔者将代码文件命名为find.cpp,因此用命令行编译为

g++ -o find.o find.cpp

测试

在Jetson Nano B01下进行测试。

在没有插入设备的时候,由于板子自带了RX TX引脚,因此能获得三个串口设备

然后,插上了USB-TTL后,可以得到

多了个ttyUSB1。


优化

这个方法在单端口设备的时候挺有用,我们的目标仅仅是获取ttyUSB*,怎么办呢?我们只需要在main里面做改动。

 
  1. while (it != l.end()) {

  2. // cout << *it << endl;

  3. string temp = *it;

  4. cout << temp << endl;

  5. if(temp.find("/dev/ttyUSB") != string::npos)

  6. cout << "1" << endl;

  7. it++;

  8. }

这段代码,实现了当发现ttyUSB*的时候就打个1出来。测试情况如下:

 其他改动,就留给读者结合自己的项目情况自行展开了吧。


闲谈

那么多端口设备怎么办?笔者的方法的话,会再加个端口信息校验。当连接上串口后,通过接收到设备信息来进行设备身份识别。具体的实现方法就读者自己完善吧,自己动手,丰衣足食。

Linux下使用C/C++获取可用串口_linux c++检测串口是否有数据_星羽空间的博客-CSDN博客

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值