我们在做一些人工智能的应用开发时往往使用人工智能开发板作为上位机(比如我们的小滕),Arduino、stm32等作为下位机控制板,通过上位机进行人工智能模型的推理之后进而给下位机传输对应的控制命令实现智能控制。那么如何实现两者的通信呢?这个问题可以通过UART串口通信完成,这篇博客会回答这个问题,并给出具体的案例和详细的实现步骤。
1.什么是UART串口通信?
UART(Universal Asynchronous Receiver/Transmitter,通用异步收发器)串口通信是一种串行通信协议。它是一种异步通信方式,即发送端和接收端不需要提前约定好通信的时间,而是通过特定的起始位和结束位来标识数据的开始和结束。
UART串口通信主要由三个部分组成:发送器、接收器和波特率发生器。发送器负责将并行数据转换为串行数据并发送出去;接收器负责将接收到的串行数据转换为并行数据;波特率发生器负责生成用于控制数据传输速率的时钟信号。
UART串口通信的主要特点是简单、易用,但是传输距离较短,通常在几米到几十米之间。它广泛应用于各种设备之间的短距离通信,如计算机与打印机、鼠标等外设的通信,以及嵌入式系统中的设备间通信等。
UART 是通用异步接收器/发送器。它不同于 SPI、I2C 那样的通信协议,而是微控制器中的物理电路,或者说是独立的 IC。UART 的主要用途是传输和接收串行数据。在UART通信中,两个UART直接相互通信。发送端 UART 将来自微控制器设备的并行数据转换为串行形式,将其串行数据传输到接收端 UART。
然后接收端UART将串行数据转换回并行数据。在两个 UART 之间传输数据只需要两根线。数据从发送端UART的TX引脚流向接收端UART的RX引脚。
2.如何完成Atlas200 DK A2与Arduino的UART串口通信
2.1 准备硬件
Atlas 200DK A2,Arduino 开发板,三根公母线
2.2 在Arduino上烧录测试程序
void setup() {
Serial.begin(115200); // 启动串行连接,波特率为115200
}
void loop() {
if(Serial.available() > 0){
String str = Serial.readString();
if(str.equals("1\n")){
Serial.println("Arduino: 1\n");
}
}
}
2.3 连线
将小滕的TX引脚连接Arduino的RX引脚,将小滕的RX引脚连接Arduino的TX引脚,将小滕的GND引脚连接Arduino的GND引脚,如下图。
2.4 配置开发板的/dev/ttyAMA0
之前也是一直卡在了这一步。
在开发板上root用户下输入下面的命令:
ls -l /dev/ttyAMA0
如果该设备节点存在并且具有相应的权限,表示该串口设备已被占用。如果没有显示任何结果,表示该串口设备当前没有被占用。
执行下面的命令查看是被哪个进程占用了
fuser /dev/ttyAMA0
查看这个进程的信息
ps 1423
经查询它是一个终端登录程序,用于在串行接口上提供终端登录功能。我们需要禁用它用/dev/ttyAMA0提供终端登录功能,进而让/dev/ttyAMA0空闲下来用来进行两个开发板的UART通信
执行以下命令以停止终端登录程序:
sudo systemctl stop serial-getty@ttyAMA0.service
执行以下命令以禁用终端登录程序的自动启动:
sudo systemctl disable serial-getty@ttyAMA0.service
再次执行
fuser /dev/ttyAMA0
可以看到没有信息返回,也就是说/dev/ttyAMA0空闲下来了。
2.5 编写小滕侧通信代码
cd /home/HwHiAiUser/samples/notebooks/
bash start_notebook.sh
新建一个00-test_uart文件夹
在这个文件夹下新建一个test.ipython写入代码
from periphery import Serial
import time
ser = Serial("/dev/ttyAMA0", 115200)
flag = True
while flag:
ser.write(b"1\n")
readdata = ser.read(32, 2).decode('gbk')
print(f'Received reply: {readdata}')
运行代码
代码的逻辑功能很简单,就是首先通过小滕在串口中写入一个“1\n”,Arduino开发板侧会一直判断串口中是不是有数据,如果有数据且数据是“1\n”,那么表明Arduino收到了小滕的信息,Arduino向串口写入"Arduino: 1\n"向小滕告知它收到了数据,此时小滕将会打印收到的数据,也就是Received reply: Arduino: 1。由此一直循环,便实现了两者的通信。