Unix 移植micropython串口使用

本文档介绍了如何在Unix系统上移植和使用MicroPython进行串口通信,包括安装串口模块、编写串口测试代码以及优化波特率和超时时间。通过修改MicroPython源码添加更多波特率选项,并解决超时时间设置问题,使得串口通信更加灵活和高效。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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)

再次执行,可以正常工作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值