利用mem数组完成MicroPython中UART1的(REPL)的交互
Posted 卓晴
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了利用mem数组完成MicroPython中UART1的(REPL)的交互相关的知识,希望对你有一定的参考价值。
简 介: 利用了UART中的CSR的RXVAL标志位,可以判断有新的byte从REPL中获得,通过查询该标志位,可以实现通过REPL(UART1)上位机发送的信息。进而可以提高软件调试效率。
关键词
: mem,REPL,RXVAL
§01 mem访问REPL
在 通过mem函数在MicroPython中访问模块寄存器 可以实现对UART1,也就是用于MicroPython REPL 的串口输入的访问,但很可惜,无法对于发送过来的字符进行同步。下面希望通过特殊的交换协议来完成对于UART的输入信息的读取同步。
一、基本想法
由于无法确定现在UART1的输入寄存器是否被更新,所以可以采用一下两个方式:
- 第一个方式,就是把读入的UART1的接收寄存器修改成与当前值不同的数据,后面在进行判断;
- 第二中方式,就是使用特殊的分隔符号,比如0x0,作为分隔符号,没两次0x0之间为新的数据;
- 第三种方式:通过UART_CSR,当前状态寄存器来确定是否接收到了字符。
由于在MicroPython中最快的轮询的时间间隔为1ms,所以对于从PC发送的机制,也需要保证每个字符之间的时间间隔大于1ms。
二、初步测试
1、测试修改UART1接收寄存器
(1)测试代码
from machine import Pin,mem32
import utime
from micropython import const
APB2PERIPH_BASE = const(0x40010000)
APB1PERIPH_BASE = const(0x40000000)
UART1_BASE = const(APB2PERIPH_BASE + 0x3800)
UART1_RDR = const(UART1_BASE + 1*4)
print("Test UART.")
mem32[UART1_RDR] = 0xff
while True:
mem32[UART1_RDR] = 0xff
print("%08x"%mem32[UART1_RDR])
utime.sleep_ms(250)
(2)测试结果
读取的mem32[UART1_RDR] 仍然是 0x4,与写入的字符无关。因此可以知道,UART1的RDR是无法被改写的。
下面是数据手册中表明RXREG为只读。
▲ 图1.2.1 MM32F3277的UART 的 RDR为只读
2、测试CSR寄存器
利用UART_CSR中的RXAVL来判断是否接收到字符。
▲ 图1.2.2 MM32F3277 UART_CSR功能定义
(1)测试代码
from machine import Pin,mem32
import utime
from micropython import const
APB2PERIPH_BASE = const(0x40010000)
APB1PERIPH_BASE = const(0x40000000)
UART1_BASE = const(APB2PERIPH_BASE + 0x3800)
UART1_RDR = const(UART1_BASE + 1*4)
UART1_CSR = const(UART1_BASE + 2*4)
print("Test UART.")
mem32[UART1_RDR] = 0xff
while True:
if (mem32[UART1_CSR] & 0x2):
print("%c"%mem32[UART1_RDR])
utime.sleep_ms(10)
(2)测试结果
▲ 图1.2.3 可以接收到字符
三、UART1的交互
1、交互程序
下面是交互程序,是将UART1接收到的字符转换成整型数字显示出来。
from machine import Pin,mem32
import utime
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)
print("Test UART.")
replbuf = bytes(0)
def procREPL():
global replbuf
if mem32[UART1_CSR] & 0x2:
replbuf += bytes([mem32[UART1_RDR]])
if replbuf[-1:] == b'\\r':
print(int(replbuf[:-1]))
replbuf = bytes(0)
while True:
procREPL()
utime.sleep_ms(10)
测试结果,上述命令是可以正常运行。
2、改在STM32 Bootloader
由于在MicroPython中对于UART1的轮询最快是1ms,所以在STM32 Bootloader中增加一个发送字符间隔为1ms的命令。
(1)增加SNDCD命令
if(strncmp(szString, "SNDCD", 5) == 0)
int nLength = strlen(szString);
int i;
for(i = 5; i < nLength; i ++)
SendChar(szString[i], PORT1);
Sleep(1);
return;
(2)测试SNDCD
Ⅰ.MicroPython程序
#------------------------------------------------------------
replbuf = bytes(0)
def procREPL():
global replbuf
if mem32[UART1_CSR] & 0x2:
replbuf += bytes([mem32[UART1_RDR]])
if replbuf[-1:] == b'\\r':
print(int(replbuf[:-1]))
replbuf = bytes(0)
#------------------------------------------------------------
while True:
procREPL()
utime.sleep_ms(1)
Ⅱ.测试结果
- 使用"SENDC100\\r" 无法获得结果;
- 使用“SNDCD100\\r” 可以正常显示100的结果。
3、加快轮询
如果在 while程序中,将1ms的等待去除,可以加快轮询的速度。
while True:
procREPL()
# utime.sleep_ms(1)
通过测试可以看到无论使用 “SENDC”,还是“SNDCD”命令,都可以正常获得测试结果。
§02 测试其他模块
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)
replbuf = bytes(0)
def procREPL(f):
global replbuf
if mem32[UART1_CSR] & 0x2:
replbuf += bytes([mem32[UART1_RDR]])
if replbuf[-1:] == b'\\r':
f(replbuf[:-1])
replbuf = bytes(0)
def f(s):
print(s)
while True:
procREPL(f)
一、测试APA102C
1、MicroPython程序
from machine import UART,mem32,SPI
from micropython import const
from machine import Pin,SPI
import utime
spi = SPI(0, baudrate=100000, polarity=1, phase=1)
led = Pin('PB2', Pin.OUT_PUSHPULL)
def led3buf(l1,l2,l3):
'''
led3buf: Construct three APA102C LED data
Param l1: LED 1 (rgb)
Param l2: LED 2 (rgb)
Param l3: LED 3 (rgb)
Return: buf : 8+4*3=20bytess
'''
return bytes([0]*4) + bytes((0xff,l1[2],l1[1],l1[0])) + bytes((0xff,l2[2],l2[1],l2[0])) + bytes((0xff,l3[2],l3[1],l3[0])) + bytes([0xff]*4)
def led3light(l1,l2,l3):
return bytes([0]*4) + bytes((0xff,0, 0, l1)) + bytes((0xff,0,l2, 0)) + bytes((0xff,l3,0,0)) + bytes([0xff]*4)
APB2PERIPH_BASE = const(0x40010000)
UART1_BASE = const(APB2PERIPH_BASE + 0x3800)
UART1_RDR = const(UART1_BASE + 1*4)
UART1_CSR = const(UART1_BASE + 2*4)
replbuf = bytes(0)
def procREPL(f):
global replbuf
if mem32[UART1_CSR] & 0x2:
replbuf += bytes([mem32[UART1_RDR]])
if replbuf[-1:] == b'\\r':
f(replbuf[:-1])
replbuf = bytes(0)
def f(s):
count1 = int(s)
if count1 > 255: count1 = 255
count2 = count3 = count1
print(count1, count2, count3)
buf = led3light(count1,count2,count3)
spi.write(buf)
print('Test APA102C.')
while True:
procREPL(f)
2、Python程序
from headm import *
from tsmodule.tsstm32 import *
count = 0
while True:
count += 10
if count >= 255: count = 0
stm32cmd('SNDCD%d\\r'%count)
time.sleep(.1)
3、测试结果
▲ 图2.1.1 APA102C变化亮度
二、测试DAC
1、MicroPython程序
from machine import UART,mem32,DAC
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)
dac0 = DAC(0以上是关于利用mem数组完成MicroPython中UART1的(REPL)的交互的主要内容,如果未能解决你的问题,请参考以下文章
利用mem数组在MM32 MicroPython中实现COMP的功能
MM32F3277 MicroPython的 mem 函数对于MCU内存访问
通过mem32函数来提高MM32 MicroPython 输出PWM 频率的精度