Unix 移植micropython串口使用
unix上mpy作为串口测试工具还是很方便的,前两章我们已经移植好了arm板的linux系统上运行的mpy,没有看过的同学点击下面链接查看,现在来继续学习串口的使用。
链接:支持LVGL的micropython固件编译(二)arm板移植
1.安装串口模组
在python中我们首先会想到安装pyserial,mpy同样也可以安装,在python中我们是通过pip install 来安装管理三方模组包的。而在mpy中我们可以使用upip(mpy的很多模组前面带u是以同标准py区分开),可以执行如下指令安装:
安装命令:
./micropython-lvgl -m upip install micropython-serial
mpy默认的mod加载路径为~/.micropython/lib
或/usr/lib/micropython
,而我们刚刚执行安装后的模组代码就放在~/.micropython/lib路径里, 这个下载的串口模组是可以直接引用的。但是有点小问题,后面会讲到,以及如何修改。
2.编写代码测试
import serial
import time
def bytesToHexString(bytes):
hex_list = ['%02X ' % b for b in bytes]
str = ''
for i in range(len(hex_list)):
str += hex_list[i]
if ((i+1) % 16) == 0:
str +='\r\n'
return str
# 串口自收发测试 0x00-0XFF
def uart_test(ser):
list1 = []
for i in range(0, 256):
list1.append(i)
ser.write(bytes(list1))
print("send: 0x00...0xFF")
print("等待接收串口数据...")
while ser.inWaiting() == 0:
time.sleep(0.3)
s = ser.read(ser.inWaiting())
print(bytesToHexString(s))
# 初始化串口,入参:串口节点,波特率,超时时间
ser=serial.Serial("/dev/ttyS5",9600,timeout=1)
ser.open()
uart_test(ser)
ser.close()
以上代码用于串口回环测试,测试时需要短接串口的TX与RX。以9600的波特率测试0x00到0XFF全部数据收发。测试结果见下图:
测完9600你可能还想测一下其他所有波特率是否都能正常工作,波特率传输上限在哪,测试发现只有9600,19200,57600,115200等波特率可以带入,想来arm板不可能只支持这点波特率,那一定是我们的serial模组限制了。另外超时时间单位应该是s,但带入小数比如0.1又会报错,提示该参数需要整数而不是小数,这应当是一个bug了串口超时设置应当可以做到ms单位。下面我们就来分析下serial模组代码解决问题。
3.增加串口波特率以及超时时间的优化
3.1增加波特率
在~/.micropython/lib
目录下找到serial.py打开
看到如下代码:
BAUD_MAP = {
9600: termios.B9600,
# From Linux asm-generic/termbits.h
19200: 14,
57600: termios.B57600,
115200: termios.B115200
}
说明波特率可设范围是在这里添加的,而这个波特率值来自termios模组提供,termios模组提供的值本质上来自 Linux内核中 asm-generic/termbits.h文件。让我们找一下termios模组在哪里,./micropython-lvgl进入repl,键入help(‘modules’)查看有哪些模组
发现里面有termios,是一个内置到mpy固件里的模组,只能去mpy源码里找了。
打开mpy源码工程找到ports\unix\modtermios.c文件,里面有这样一段代码:
#define C(name) { MP_ROM_QSTR(MP_QSTR_##name), MP_ROM_INT(name) }
C(TCSANOW),
C(B9600),
#ifdef B57600
C(B57600),
#endif
#ifdef B115200
C(B115200),
#endif
这里可以看出termios只提供了三个波特率 9600,57600,115200,跟我们serial.py里引用的一致,那么只需要在这里添加自己需要的波特率就好了,但可以供我们选择的波特率在哪里找呢,这时候就需要找到你arm板的内核代码了,找到include\uapi\asm-generic\termbits.h文件里面已经定义好了很多波特率(arm跟mips这里可能会有些许差别),从其中添加我们需要的即可,下面是我添加的波特率:
#define C(name) { MP_ROM_QSTR(MP_QSTR_##name), MP_ROM_INT(name) }
C(TCSANOW),
C(B9600),
#ifdef B57600
C(B57600),
#endif
#ifdef B115200
C(B115200),
#endif
#ifdef B460800
C(B460800),
#endif
#ifdef B921600
C(B921600),
#endif
#ifdef B1152000
C(B1152000),
#endif
#ifdef B1500000
C(B1500000),
#endif
#ifdef B2000000
C(B2000000),
#endif
#ifdef B2500000
C(B2500000),
#endif
#ifdef B3000000
C(B3000000),
#endif
#undef C
};
重新编译mpy固件,在repl里可以查看我们新增的波特率是否加进来了,键入termios. 按tab键补全可以查看。
这个时候就可以改serial.py增加更多波特率了
BAUD_MAP = {
9600: termios.B9600,
# From Linux asm-generic/termbits.h
19200: 14,
57600: termios.B57600,
115200: termios.B115200,
460800: termios.B460800,
921600: termios.B921600,
1152000: termios.B1152000,
1500000: termios.B1500000,
2000000: termios.B2000000,
2500000: termios.B2500000,
3000000: termios.B3000000,
}
3.2优化超时时间
前面测试时已经提到,timeout入参单位为S,只有带入小数才能设为ms级别超时,但入参只能接受整数。
查看serial.py代码,找到如下代码:
def __init__(self, port, baudrate, timeout=None, **kwargs):
self.port = port
self.baudrate = baudrate
self.timeout = -1 if timeout is None else timeout * 1000
self.open()
这里会发现timeout入参不为空时乘了1000,意味着送给底层接口的timeout是ms单位的,小数应该允许被传入,我们自己在强转为int传给下面接口即可,修改该部分代码为:
def __init__(self, port, baudrate, timeout=None, **kwargs):
self.port = port
self.baudrate = baudrate
self.timeout = -1 if timeout is None else int(timeout * 1000)#强转为int
self.open()
可以修改下我们的串口测试代码timeout
ser=serial.Serial("/dev/ttyS5",9600,timeout=0.1)
再次执行,可以正常工作。