日常记录

Ubuntu系统安装CH340/CH341驱动

10 09月
作者:6912809|分类:Linux

使用USB转UART模块连接设备时发现我的Ubuntu识别到设备了但是minicom链接乱码,排除了波特率的问题,查看使用的CH340芯片,在Windows主机中无乱码,所以初步判断为缺少ch340驱动。

自Linux内核版本2.6.24起,Linux主线内核已内置ch341串行驱动。其位置在:drivers/usb/serial/ch341.c,但是内置驱动无法保持更新,驱动官方建议客户安装使用新的驱动。

安装驱动 

在安装前先查看下内核版本,有些内核版本可能与下载的驱动文件存在不兼容现象:

uname -r

这里我的内核版本是 6.8.0-40-generic

6.8.0-40-generic

随后在官网下载CH340的驱动文件压缩包: 


压缩包下载地址:CH341SER_LINUX.ZIP - 南京沁恒微电子股份有限公司 (wch.cn) 


1725958776178.png

下载好 scp 传入服务器

scp -r  CH341SER_LINUX.ZIP root@192.168.11.78:/root/

在终端输入命令将压缩包解压缩到/usr/local/src文件夹:

unzip CH341SER_LINUX.ZIP -d /usr/local/src

文件解压后可以看到文件夹内有一个markdown的说明文档和driver文件夹,driver文件夹内存放着ch341的.c文件与.h、Makefile文件,其中Makefile文件主要用于自动化编译和构建程序。

1725958949061.png

driver文件夹内容如下: 

1725958980417.png

 编译驱动文件

随后在终端切换到解压后的驱动目录:

cd /root/CH341SER_LINUX/driver

输入make命令构建文件:

sudo make

我这里报错了,为CH341.C文件中在定义ch341_tty_write函数时与我的内核版本(6.8.0-40-generic)不兼容,可能是ubuntu24的问题,之前编译都没出过问题:

root@zl-QiTianM415-N000:~/CH341SER_LINUX/driver# make

make -C /lib/modules/6.8.0-40-generic/build  M=/root/CH341SER_LINUX/driver

make[1]: Entering directory '/usr/src/linux-headers-6.8.0-40-generic'

warning: the compiler differs from the one used to build the kernel

  The kernel was built by: x86_64-linux-gnu-gcc-12 (Ubuntu 12.3.0-1ubuntu1~22.04) 12.3.0

  You are using:           gcc-12 (Ubuntu 12.3.0-1ubuntu1~22.04) 12.3.0

  CC [M]  /root/CH341SER_LINUX/driver/ch341.o

/root/CH341SER_LINUX/driver/ch341.c:1460:18: error: initialization of ‘ssize_t (*)(struct tty_struct *, const u8 *, size_t)’ {aka ‘long int (*)(struct tty_struct *, const unsigned char *, long unsigned int)’} from incompatible pointer type ‘int (*)(struct tty_struct *, const unsigned char *, int)’ [-Werror=incompatible-pointer-types]

 1460 |         .write = ch341_tty_write,

      |                  ^~~~~~~~~~~~~~~

/root/CH341SER_LINUX/driver/ch341.c:1460:18: note: (near initialization for ‘ch341_ops.write’)

cc1: some warnings being treated as errors

make[3]: *** [scripts/Makefile.build:243: /root/CH341SER_LINUX/driver/ch341.o] Error 1

make[2]: *** [/usr/src/linux-headers-6.8.0-40-generic/Makefile:1926: /root/CH341SER_LINUX/driver] Error 2

make[1]: *** [Makefile:240: __sub-make] Error 2

make[1]: Leaving directory '/usr/src/linux-headers-6.8.0-40-generic'

make: *** [Makefile:5: default] Error 2

自己懒得看了,直接丢给AI,给了解释


从编译错误来看,问题出在 `ch341.c` 文件的第 1460 行,`ch341_tty_write` 函数的签名与结构体中的 `write` 函数指针的类型不兼容。这可能是因为 Linux 内核 API 发生了变化,导致原来的代码在新的内核版本中不再兼容。

错误信息指出:

error: initialization of ‘ssize_t (*)(struct tty_struct *, const u8 *, size_t)’ {aka ‘long int (*)(struct tty_struct *, const unsigned char *, long unsigned int)’} from incompatible pointer type ‘int (*)(struct tty_struct *, const unsigned char *, int)’ [-Werror=incompatible-pointer-types]

- 期望的 `write` 函数类型为:

  ssize_t (*)(struct tty_struct *, const unsigned char *, size_t)

- 而实际提供的函数签名为:

  int (*)(struct tty_struct *, const unsigned char *, int)

解决方法

你可以修改 `ch341.c` 中的 `ch341_tty_write` 函数,使其参数类型与内核期望的类型一致。

 1. 修改函数签名

找到 `ch341_tty_write` 函数的定义并修改其参数类型。

**旧的定义**:

int ch341_tty_write(struct tty_struct *tty, const unsigned char *buf, int count)

新的定义:

ssize_t ch341_tty_write(struct tty_struct *tty, const unsigned char *buf, size_t count)

- 将 `int` 改为 `ssize_t`,表示返回写入的字节数。

- 将 `int count` 改为 `size_t count`,以匹配内核期望的参数类型。

 2. 修改返回值类型

确保函数内部的返回值类型也与 `ssize_t` 匹配。如果返回的是 `int`,需要将其转换为 `ssize_t` 类型。

 3. 重新编译

修改完成后,保存文件并重新运行 `make` 命令:其他注意事项

- 如果项目使用 `-Werror` 标志(将所有警告视为错误),你可以暂时禁用该标志以跳过警告。修改 `Makefile`,移除或注释掉 `-Werror`:

  CFLAGS += -Werror

  将其修改为:

  # CFLAGS += -Werror


 AI是很强大的,再次输入make构建命令后构建成功:

root@zl-QiTianM415-N000:~/CH341SER_LINUX/driver# make

make -C /lib/modules/6.8.0-40-generic/build  M=/root/CH341SER_LINUX/driver

make[1]: Entering directory '/usr/src/linux-headers-6.8.0-40-generic'

warning: the compiler differs from the one used to build the kernel

  The kernel was built by: x86_64-linux-gnu-gcc-12 (Ubuntu 12.3.0-1ubuntu1~22.04) 12.3.0

  You are using:           gcc-12 (Ubuntu 12.3.0-1ubuntu1~22.04) 12.3.0

  CC [M]  /root/CH341SER_LINUX/driver/ch341.o

/root/CH341SER_LINUX/driver/ch341.c:646:9: warning: no previous prototype for ‘ch341_tty_write’ [-Wmissing-prototypes]

  646 | ssize_t ch341_tty_write(struct tty_struct *tty, const unsigned char *buf, size_t count)

      |         ^~~~~~~~~~~~~~~

  MODPOST /root/CH341SER_LINUX/driver/Module.symvers

  CC [M]  /root/CH341SER_LINUX/driver/ch341.mod.o

  LD [M]  /root/CH341SER_LINUX/driver/ch341.ko

  BTF [M] /root/CH341SER_LINUX/driver/ch341.ko

Skipping BTF generation for /root/CH341SER_LINUX/driver/ch341.ko due to unavailability of vmlinux

make[1]: Leaving directory '/usr/src/linux-headers-6.8.0-40-generic'

 使用modprobe加载模块,modprobe可以自动处理内核模块

 modprobe ch341

使用lsmod命令查看是否加载成功(太多了,我们grep一下),这个命令可以显示已加载到内核中的模块列表:

lsmod | grep ch

模块加载成功:

1725959488523.png

让驱动永久生效: 

make install

查看串口设备信息及端口号  

使用lsusb命令查看USB连接设备,可以显示本机USB设备列表及其详细信息: 

lsusb

这里可以看到连接到了一个CH340设备

1725959625743.png

输入以下命令可以显示特定USB设备的详细信息和树状结构显示USB设备层次


lsusb -v -d 1a86:7523 // 刚才检查出来的设备ID号

lsusb -t

1725959762946.png

1725959803490.png

输入命令列出所有以 /dev/tty开头的设备文件,我们这里为/dev/ttyCH341USB0

1725959879062.png

官方说明文件

 以下内容全部为官方的说明文件:


针对USB转UART芯片ch340、ch341等的USB串行驱动。事实上,自Linux内核版本2.6.24起,Linux主线内核已内置ch341串行驱动。其位置在:drivers/usb/serial/ch341.c,遗憾的是,内置驱动无法保持更新。我们建议客户使用此驱动。


打开“终端”

切换到“driver”目录

使用“make”编译驱动,如果成功,你将看到模块“ch341.ko”

输入“sudo make load”或“sudo insmod ch341.ko”动态加载驱动

输入“sudo make unload”或“sudo rmmod ch341.ko”卸载驱动

输入“sudo make install”使驱动永久生效

输入“sudo make uninstall”移除驱动

你可以参考以下链接获取uart应用程序,你可以使用gcc或交叉编译工具cross-gcc进行编译

GitHub - WCHSoftGroup/tty_uart: linux tty uart application

在驱动工作之前,你应确保USB设备已插入并正常工作,你可以使用shell命令“lsusb”或“dmesg”进行确认,这些设备的USB VID为[1a86],你可以在“ch341.c”中定义的id表中查看所有ID。


如果设备工作正常,驱动将在/dev目录下创建名为“ttyCH341USBx”的tty设备。



打赏
浏览865 评论64
返回
目录
返回
首页

除特别注明外,本站所有文章均为七原创,转载请注明出处来自https://qxhut.com/?id=39

本站提供的一切软件、教程和内容信息仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络收集整理,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑或手机中彻底删除上述内容。如果您喜欢该程序和内容,请支持正版,购买注册,得到更好的正版服务。我们非常重视版权问题,如有侵权请邮件与我们联系处理。敬请谅解!

Win10怎么将时间显示到秒 Win10时间显示秒数方法【详解】 骁龙 410 随身 WiFi 刷入 Debian 系统并优化

发表评论

  • 评论列表