1、下载最新驱动
- 下载CH34x最新驱动。下载地址
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口传过来的四路超声波数据