6. 串口通信

本章介绍在Android中使用串口与外部设备的通讯。

6.1. UART引脚使能

参考“40pin引脚对照图”章节,查看需要使用的UART引脚, 大部分板卡的UART复用功能默认是开启的,如果需要使用默认关闭的接口则需要修改设备树源码来使能,并重新编译镜像

如果对设备树不熟悉的用户,请学习野火配套的《嵌入式Linux驱动开发实战指南》的 Linux设备树 章节内容。

以使能LubanCat-4-V1的UART7_M2为例,修改SDK源码/kernel-5.10/arch/arm64/boot/dts/rockchip/rk3588s-lubancat-4-v1.dtsi (其他板卡修改板卡对应的设备树),在设备树中添加以下节点:

1
2
3
4
5
6
&uart7{
    status = "okay";
    pinctrl-names = "default";
    // pinctrl-0 = <&uart7m1_xfer>;
    pinctrl-0 = <&uart7m2_xfer>;
};

提示

如果不清楚选定的引脚节点怎么写,可以参考Linux内核对应的 设备树插件源码

修改为如下图所示,如果与其他节点冲突需关闭冲突节点再添加(此处修改就是存在冲突,默认开启了uart7并使用uart7m1_xfer,因此要使用uart7m2_xfer,则需注释uart7m1_xfer)

uart节点

参考 编译 Android 镜像 章节重新编译镜像并将编译出来的镜像烧录到板卡。

6.2. 检查UART设备

可以通过以下命令查看UART接口有没有开启,存在/dev/ttyS7则开启成功。

1
2
3
4
5
#进入shell终端
adb shell

#查看uart接口
ls /dev/ttyS*

注:UART0~UART9对应/dev/ttyS0~/dev/ttyS9

6.3. 连接串口

通过USB转串口模块与板卡UART接口进行连接,实现板卡与电脑通信,接线如下所示:

1
2
3
4
5
6
#板卡与USB转串口模块连接

板卡  ------  USB转串口模块
GND   ------  GND
RX    ------  TX
TX    ------  RX

6.4. 使用shell命令收发数据

使用板卡上的串口7进行实验,对应的设备文件为/dev/ttyS7。

对tty的设备文件直接读写就可以控制设备通过串口接收或发送数据,下面我们使用板卡配合Windows下的串口调试助手进行测试。

6.4.1. 查询串口的通信参数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#进入shell终端
adb shell

#切换root
su root

#串口参数
stty -F /dev/ttyS7

#信息输出如下
speed 9600 baud; line = 0;
hupcl clocal
-brkint ixon -imaxbel

6.4.2. 修改串口波特率

1
2
3
4
5
6
7
8
9
#设置通讯速率,其中ispeed为输入速率,ospeed为输出速率
stty -F /dev/ttyS7 ispeed 115200 ospeed 115200

#查看修改后波特率
stty -F /dev/ttyS7
#信息输出如下
speed 115200 baud; line = 0;
hupcl clocal
-brkint ixon -imaxbel

6.4.3. 关闭回显

默认串口是开启回显的 可以使用以下命令关闭回显。

1
2
#关闭回显
stty -F /dev/ttyS7 -echo

6.4.4. 与Windows主机通讯

1
2
3
4
5
6
7
#使用echo命令向终端设备文件写入字符串"Hello!"、"I'm lubancat"
echo Hello! > /dev/ttyS7
echo "I'm lubancat" > /dev/ttyS7


#使用cat命令读取终端设备文件
cat /dev/ttyS7

效果如下图所示:

uart发送接收

6.5. 使用安卓应用收发数据

野火提供的安卓综合测试应用能很方便的实现收发串口数据。

6.5.1. 应用测试

可参考“野火安卓综合测试应用”章节的“UART测试”小节进行测试,如下图:

uart发送接收

6.5.2. 实现方式

串口数据收发调用jni接口方式,参考野火应用源码ebf_android_app/app/src/main/cpp/uart.cpp

在Activity中声明JNI方法进行使用:

ebf_android_app/app/src/main/java/com/example/ebf_android_app/UartActivity.java
1
2
3
4
5
6
7
8
// 打开串口(参数:端口路径、波特率、数据位、停止位、校验位)
public native int uart_open(String portPath, int baudRate, int dataBits, int stopBits, int parity);
// 关闭串口
public native int uart_close();
// 发送数据
public native int uart_send(String data);
// 接收数据
public native String uart_receive();

值得注意的是普通用户没有读写UART接口的权限,需要添加权限,在野火应用源码的UartActivity.java中提供了executeRootCommand函数用来执行root命令, 通过executeRootCommand函数执行chmod命令为UART接口添加权限。

ebf_android_app/app/src/main/java/com/example/ebf_android_app/UartActivity.java
1
private boolean executeRootCommand(String command)

那么串口发送数据的流程为:

1
2
3
4
5
6
7
8
// 添加权限
boolean permResult = executeRootCommand("chmod 777 /dev/ttyS*");

// 打开串口
int openResult = uart_open(portPath, baudRate, dataBits, stopBits, parity);

// 发送数据
int sendResult = uart_send(sendData);

由于野火测试应用是不确定用户选择的UART接口是哪个,那么必须根据用户选择及时添加权限, 如果自己的项目中明确使用哪些UART接口,也可以在系统shell脚本中提前添加权限,在Activity中省去添加权限步骤。

系统自启动的shell脚本位于/system/bin/android_shell.sh,由/vendor/etc/init/init.rk3588.rc调用执行(如果是其他芯片则是[对应芯片名字].rc),以提前添加/dev/ttyS7权限为例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#重新挂载系统
adb root && adb remount

#拉取系统中的android_shell.sh
adb pull system/bin/android_shell.sh



#电脑文本软件打开android_shell.sh,在其末尾添加权限命令
chmod 777 /dev/ttyS7



#将修改后的android_shell.sh的覆盖到系统system/bin/
adb push android_shell.sh system/bin/

#重启系统
adb reboot

#查看目录权限
adb shell ls -l /dev/ttyS7
#信息输出如下
crwxrwxrwx 1 root system 4,  71 2025-07-29 15:12 /dev/ttyS7

最终可以看到重启系统后,/dev/ttyS7文件普通用户也具有读写权限。

如需修改SDK源码来修改android_shell.sh,该文件位于SDK源码/device/rockchip/rk[具体芯片]/android_shell.sh,由SDK源码/device/rockchip/rk[具体芯片]/init.rk[具体芯片].rc中调用脚本, 由SDK源码/device/rockchip/rk[具体芯片]/device.mk中拷贝脚本进系统。