CH340 CH341 Linux驱动最完整使用教程(永久解决/dev/ttyUSB0 permission denied问题,USB设备读写C++实现)

1、下载最新驱动

2、卸载老驱动

  • 首先执行 uname -r 查看操作系统发行版本
    在这里插入图片描述
    我的系统发行版本为4.15.0-123-generic
  • 进入驱动路径:cd /lib/modules/4.15.0-123-generic/kernel/drivers/usb/serial/ 如下图所示在这里插入图片描述
    卸载老驱动 sudo rm -rf ch341.ko

3、安装新驱动

  • 解压下载好的驱动安装包
    在这里插入图片描述
    执行命令 unzip CH341SER_LINUX.ZIP

  • 编译安装
    在这里插入图片描述 执行make的时候出现两个报错!!
    解决办法:
    1、增加一个头文件
    在这里插入图片描述
    2、注释掉591行的wait变量
    在这里插入图片描述

  • 再次编译安装
    依次执行
    make
    sudo make load

总结一下安装步骤就四步
unzip CH341SER_LINUX.ZIP
cd CH341SER_LINUX/
make
sudo make load

4、开机自动加载驱动

  • 安装完以后,驱动 ch34x.ko 在 CH341SER_LINUX 目录下,需移动到系统默认驱动目录下
sudo scp ch34x.ko /lib/modules/4.15.0-123-generic/kernel/drivers/usb/serial/
sudo depmod
  • 重启系统

5、永久解决ttyUSB0权限问题

  • 一般使用USB口,启动时容易出现 /dev/ttyUSB0 permission denied.
    因为一般情况下不是root用户,对端口没有权限.
    遇到这种情况,我一般这样做:
sudo chmod 777 /dev/ttyUSB0
  • 修改权限为可读可写可执行,但是这种设置电脑重启后,又会出现这种问题,还要重新设置。
sudo usermod -aG dialout wangmj
其中wangmj是我的用户名,换成你的用户名即可。这样下次重启也不用修改权限了。

6、读取ttyUSB0数据,C++代码实现

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <termios.h>
#include <unistd.h>
#include <chrono>
#include <iostream>
#include <thread>

using namespace std;

int speed_arr[] = {B115200, B57600, B38400, B19200, B9600,
                   B4800,   B2400,  B1200,  B300};

int name_arr[] = {115200, 57600, 38400, 19200, 9600, 4800, 2400, 1200, 300};

//配置串口设备,参数依次为,设备名,波特率设置,数据位设置,停止位设置,校验位设置
int libtty_setopt(int fd, int speed, int databits, int stopbits, char parity) {
  struct termios newtio;
  struct termios oldtio;
  int i;
  bzero(&newtio, sizeof(newtio));
  bzero(&oldtio, sizeof(oldtio));
  if (tcgetattr(fd, &oldtio) != 0) {
    perror("tcgetattr");
    return -1;
  }
  newtio.c_cflag |= CLOCAL | CREAD;
  newtio.c_cflag &= ~CSIZE;

  /* set tty speed */
  for (i = 0; i < sizeof(speed_arr) / sizeof(int); i++) {
    if (speed == name_arr[i]) {
      cfsetispeed(&newtio, speed_arr[i]);
      cfsetospeed(&newtio, speed_arr[i]);
    }
  }

  /* set data bits */
  switch (databits) {
    case 5:
      newtio.c_cflag |= CS5;
      break;
    case 6:
      newtio.c_cflag |= CS6;
      break;
    case 7:
      newtio.c_cflag |= CS7;
      break;
    case 8:
      newtio.c_cflag |= CS8;
      break;
    default:
      fprintf(stderr, "unsupported data size\n");
      return -1;
  }

  /* set parity */
  switch (parity) {
    case 'n':
    case 'N':
      newtio.c_cflag &= ~PARENB; /* Clear parity enable */
      newtio.c_iflag &= ~INPCK;  /* Disable input parity check */
      break;
    case 'o':
    case 'O':
      newtio.c_cflag |= (PARODD | PARENB); /* Odd parity instead of even */
      newtio.c_iflag |= INPCK;             /* Enable input parity check */
      break;
    case 'e':
    case 'E':
      newtio.c_cflag |= PARENB;  /* Enable parity */
      newtio.c_cflag &= ~PARODD; /* Even parity instead of odd */
      newtio.c_iflag |= INPCK;   /* Enable input parity check */
      break;
    default:
      fprintf(stderr, "unsupported parity\n");
      return -1;
  }

  /* set stop bits */
  switch (stopbits) {
    case 1:
      newtio.c_cflag &= ~CSTOPB;
      break;
    case 2:
      newtio.c_cflag |= CSTOPB;
      break;
    default:
      perror("unsupported stop bits\n");
      return -1;
  }

  newtio.c_cc[VTIME] = 0; /* Time-out value (tenths of a second) [!ICANON]. */
  newtio.c_cc[VMIN] = 0;  /* Minimum number of bytes read at once [!ICANON]. */

  tcflush(fd, TCIOFLUSH);

  if (tcsetattr(fd, TCSANOW, &newtio) != 0) {
    perror("tcsetattr");
    return -1;
  }
  return 0;
}

// 打开设备
int libtty_open(const char *devname) {
  int fd = open(devname, O_RDWR | O_NOCTTY | O_NDELAY);
  int flags = 0;

  if (fd == -1) {
    perror("open device failed");
    return -1;
  }

  flags = fcntl(fd, F_GETFL, 0);
  flags &= ~O_NONBLOCK;
  if (fcntl(fd, F_SETFL, flags) < 0) {
    printf("fcntl failed.\n");
    return -1;
  }

  if (isatty(fd) == 0) {
    printf("not tty device.\n");
    return -1;
  } else
    printf("tty device test ok.\n");

  return fd;
}

//设备关闭
int libtty_close(int fd) { return close(fd); }

void tty_test(int fd) {
  int nwrite, nread;
  char buf[5];
  double length1, length2, length3, length4;
  memset(buf, 0x32, sizeof(buf));
  while (1) {
    std::this_thread::sleep_for(std::chrono::milliseconds(60));
    nread = read(fd, buf, sizeof(buf));
    printf("read %d bytes already.\n", nread);
    if (buf[0] == 0xffffffff && buf[1] == 0x01) {
      length1 = ((buf[2] << 8) + buf[3]) / 1000.;
      if (length1 < 0.2) {
        length1 = 0.2;
      }
      cout << "length1: " << length1 << endl;
    }

    if (buf[0] == 0xffffffff && buf[1] == 0x02) {
      length2 = ((buf[2] << 8) + buf[3]) / 1000.;
      if (length2 < 0.2) {
        length2 = 0.2;
      }
      cout << "length2: " << length2 << endl;
    }

    if (buf[0] == 0xffffffff && buf[1] == 0x03) {
      length3 = ((buf[2] << 8) + buf[3]) / 1000.;
      if (length3 < 0.2) {
        length3 = 0.2;
      }
      cout << "length3: " << length3 << endl;
    }

    if (buf[0] == 0xffffffff && buf[1] == 0x04) {
      length4 = ((buf[2] << 8) + buf[3]) / 1000.;
      if (length4 < 0.2) {
        length4 = 0.2;
      }
      cout << "length4: " << length4 << endl;
    }
  }
}

int main(int argc, char *argv[]) {
  int fd;
  int ret;

  fd = libtty_open("/dev/ttyUSB0");
  if (fd < 0) {
    printf("libtty_open error.\n");
    exit(0);
  }

  ret = libtty_setopt(fd, 9600, 8, 1, 'n');
  if (ret != 0) {
    printf("libtty_setopt error.\n");
    exit(0);
  }

  tty_test(fd);

  ret = libtty_close(fd);
  if (ret != 0) {
    printf("libtty_close error.\n");
    exit(0);
  }
}

实现读取DJLK-4Y模块usb口传过来的四路超声波数据

7、参考

CH340 Linux驱动使用教程
Linux系统开机自动加载驱动module
ttyUSB0权限问题

  • 14
    点赞
  • 101
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值