MicroPython内核开发笔记书内软件用例 :基于 print的程序调试

Posted 卓晴

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MicroPython内核开发笔记书内软件用例 :基于 print的程序调试相关的知识,希望对你有一定的参考价值。

简 介: 本文给出了 MicroPython内核开发笔记:书内嵌入实验任务 中的第四章软件用例部分内容。

关键词 MicroPythonMM32F3277print

书稿内容 目 录
Contents
基本实验 获得用户输入 存在的问题 解决的方法 控制LED灯 总 结

 

 

§01 稿内容


一、基本实验

在嵌入式软件开发中,下载-测试模式是常用的软件开发方法。首先软件从最简单功能编写完成,然后下载测试,如果功能正常,然后在继续增加软件功能,直道软件开发完毕。使用 print 函数在软件关键节点输出信息是判断软件是否运行正常,检查软件运行状态常用到的方法。除此之外,也可以利用嵌入式开发板上其他信息输出资源,比如 LED、LCD 、DAC 端口等来测试程序是否运行正常。

在 MicroPython 软件开发中,使用 print, dir 命令可以帮助我们查看对象属性以及可以使用的函数。 比如:

from machine                import Pin,UART
import machine
import time

print(Pin(1))
print(UART(1))
dir(machine)
dir(time)

上面代码运行可以获得 Pin(1),UART(1) 对应的管脚资源,获得 machine, time 中可以使用的函数。下面是程序运行对应的输出。

Pin(PE3)
UART(1): baudrate=9600 on RX(PA3), TX(PA2)
['__name__', 'sleep', 'sleep_ms', 'sleep_us', 'ticks_add', 'ticks_cpu', 'ticks_diff', 'ticks_ms', 'ticks_us']
['__name__', 'ADC', 'DAC', 'I2C', 'PWM', 'Pin', 'SDCard', 'SPI', 'SoftI2C', 'SoftSPI', 'Timer', 'UART', 'freq', 'mem16', 'mem32', 'mem8', 'reset']

利用 print 可以查看变量内容以及输出计算结果。 比如下面小程序可以输出列表 a 的内容以及打印出 杨辉三角形的阵列。

a = list(range(10))
print(a)

b = [1]
for i in range(10):
    strout = ' '.join([str(s) for s in b])
    print(' '*((32-len(strout))//2) + strout)
    b = [1] + [b[n]+b[n+1] for n in range(len(b)-1)] + [1]

程序运行的结果如下:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
               1
              1 1
             1 2 1
            1 3 3 1
           1 4 6 4 1
         1 5 10 10 5 1
        1 6 15 20 15 6 1
      1 7 21 35 35 21 7 1
     1 8 28 56 70 56 28 8 1
  1 9 36 84 126 126 84 36 9 1

二、获得用户输入

1、存在的问题

MicroPython 利用 REPL 开发机制,也体现了这种交互式开发的特点。巧妙利用 REPL 建立程序与外部练习,可以加快程序的开发。

程序使用 print 函数可以输出信息,但如果希望获得用户通过 REPL 输入的信息则需要另外的方案。REPL 通常情况下使用了单片机硬件 UART0,最直接的想法就是通过 UART0 读取用户通过 REPL 发送的字符。但很遗憾,MicroPython屏蔽了 UART0 的 read 命令。

比如下面程序演示了通过 UART0 读取用户输入字符的过程。

from machine                import UART,Pin
import time

uart0 = UART(0,115200)

print(uart0)
dir(uart0)

while True:
    if uart0.any() > 0:
        inb = uart0.read(uart0.any())
        print(inb)

    time.sleep_ms(200)

下面是程序执行时输出信息。当用户在 REPL 交互窗口中键入任何字符,程序判断 uart0 存在可以接收的字符,执行后面的 read 语句时,可以看到出现 OSError : UART(0) can’t read 的错误提示。

UART(0): baudrate=115200 on RX(PA10), TX(PA9)
['__next__', 'any', 'read', 'readinto', 'readline', 'write', 'PARITY_EVEN', 'PARITY_NONE', 'PARITY_ODD', 'init']
Traceback (most recent call last):
  File "<stdin>", line 19, in <module>
OSError: UART(0) can't read
>>> 

2、解决的方法

解决 MicroPython 内核禁止读取 UART0 的问题,可以使用 MicroPython 中的内存直接访问函数 mem32,mem16,mem8。关于 MicroPython 内存直接访问将会在后面第十七章专门进行讲述。下面给出基于 mem32 读取用户 REPL 输入信息的方法。

下面程序中使用 mem32 直接访问 UART1_RDR,可以读取当前输入的字符,然后利用 init 函数对串口重新进行初始化。主程序通过循环调用 procREPL 函数,读取用户通过 REPL 串口发送的字符串,知道获得回车符 b‘\\r’,便将接收到的字符串使用函数 f(s) 完成处理。

from machine                import UART,mem32
from micropython            import const

APB2PERIPH_BASE = const(0x40010000)
UART1_BASE    = const(APB2PERIPH_BASE + 0x3800)
UART1_RDR     = const(UART1_BASE + 1*4)
UART1_CSR     = const(UART1_BASE + 2*4)

uart0 = UART(0, 115200)

replbuf = bytes(0)
def procREPL(f):
    global replbuf

    if uart0.any() > 0:
        replbuf += bytes([mem32[UART1_RDR]])
        uart0.init(115200)

        if replbuf[-1:] == b'\\r':
            f(replbuf[:-1])
            replbuf = bytes(0)

def f(s):
    print(s)

while True:
    procREPL(f)

程序运行后,在 REPL 输入窗口输入任何字符串,按动回车键之后,程序便显示用户刚刚输入的字符串。

b'Test REPL'
b'Hello world.'

基于这个程序框架,可以开发出很多交互式程序应用。

3、控制LED灯

将上面交互代码中间部分修改一下,可以完成用户通过 REPL 输入命令,动态改变 PLUS-F3270 实验板上 三色LED颜色。

代码修改包括:

  • 增加了三个 LED 控制端口;
  • 在函数 f(s) 中,根据接收到的字符串对应三位数字分别设置三个 LED 的状态;
led1 = Pin('PA1', Pin.OUT_PUSHPULL, value=1)
led2 = Pin('PA2', Pin.OUT_PUSHPULL, value=1)
led3 = Pin('PA3', Pin.OUT_PUSHPULL, value =1)

def f(s):
    sn = int(s)
    if sn%10 == 1: led1(0)
    else: led1(1)

    sn //= 10
    if sn%10 == 1: led2(0)
    else: led2(1)

    sn //= 10
    if sn%10 == 1: led3(0)
    else: led3(1)

程序运行后,用户输入三个数字分别控制三个 LED 点亮状态。 111 表示全部点亮;000 表示全部熄灭;001 表示点亮第一个 LED, 其它功能以此类推。

 

  结 ※


本文给出了 MicroPython内核开发笔记:书内嵌入实验任务 中的第四章软件用例部分内容。

下面是最后一个测试程序的完整代码。

from machine                import UART,mem32,Pin
from micropython            import const

APB2PERIPH_BASE = const(0x40010000)
UART1_BASE    = const(APB2PERIPH_BASE + 0x3800)
UART1_RDR     = const(UART1_BASE + 1*4)
UART1_CSR     = const(UART1_BASE + 2*4)

uart0 = UART(0, 115200)

replbuf = bytes(0)
def procREPL(f):
    global replbuf

    if uart0.any() > 0:
        replbuf += bytes([mem32[UART1_RDR]])
        uart0.init(115200)

        if replbuf[-1:] == b'\\r':
            f(replbuf[:-1])
            replbuf = bytes(0)

led1 = Pin('PA1', Pin.OUT_PUSHPULL, value=1)
led2 = Pin('PA2', Pin.OUT_PUSHPULL, value=1)
led3 = Pin('PA3', Pin.OUT_PUSHPULL, value =1)

def f(s):
    sn = int(s)
    if sn%10 == 1: led1(0)
    else: led1(1)

    sn //= 10
    if sn%10 == 1: led2(0)
    else: led2(1)

    sn //= 10
    if sn%10 == 1: led3(0)
    else: led3(1)

while True:
    procREPL(f)


■ 相关文献链接:

以上是关于MicroPython内核开发笔记书内软件用例 :基于 print的程序调试的主要内容,如果未能解决你的问题,请参考以下文章

MicroPython内核开发笔记书内软件用例 :MEM相关实验用例

MicroPython内核开发笔记书内软件用例 :浮点数相关实验

MicroPython内核开发笔记书内软件用例 :DAC相关实验

MicroPython内核开发笔记书内软件用例 :Timer相关实验

MicroPython内核开发笔记书内软件用例 :UART相关实验

MicroPython内核开发笔记书内软件用例 :ADC 相关实验