【雕爷学编程】MicroPython手册之 SAMD21 UART(串行总线)

在这里插入图片描述
MicroPython是为了在嵌入式系统中运行Python 3编程语言而设计的轻量级版本解释器。与常规Python相比,MicroPython解释器体积小(仅100KB左右),通过编译成二进制Executable文件运行,执行效率较高。它使用了轻量级的垃圾回收机制并移除了大部分Python标准库,以适应资源限制的微控制器。

MicroPython主要特点包括:
1、语法和功能与标准Python兼容,易学易用。支持Python大多数核心语法。
2、对硬件直接访问和控制,像Arduino一样控制GPIO、I2C、SPI等。
3、强大的模块系统,提供文件系统、网络、图形界面等功能。
4、支持交叉编译生成高效的原生代码,速度比解释器快10-100倍。
5、代码量少,内存占用小,适合运行在MCU和内存小的开发板上。
6、开源许可,免费使用。Shell交互环境为开发测试提供便利。
7、内置I/O驱动支持大量微控制器平台,如ESP8266、ESP32、STM32、micro:bit、掌控板和PyBoard等。有活跃的社区。

MicroPython的应用场景包括:
1、为嵌入式产品快速构建原型和用户交互。
2、制作一些小型的可 programmable 硬件项目。
3、作为教育工具,帮助初学者学习Python和物联网编程。
4、构建智能设备固件,实现高级控制和云连接。
5、各种微控制器应用如物联网、嵌入式智能、机器人等。

使用MicroPython需要注意:
1、内存和Flash空间有限。
2、解释执行效率不如C语言。
3、部分库函数与标准版有差异。
4、针对平台优化语法,订正与标准Python的差异。
5、合理使用内存资源,避免频繁分配大内存块。
6、利用原生代码提升速度关键部位的性能。
7、适当使用抽象来封装底层硬件操作。

总体来说,MicroPython让Python进入了微控制器领域,是一项重要的创新,既降低了编程门槛,又提供了良好的硬件控制能力。非常适合各类物联网和智能硬件的开发。
在这里插入图片描述
SAMD21是一系列使用32位ARM® Cortex®-M0+处理器的低功耗微控制器,由Microchip Technology公司开发。SAMD21的技术参数如下:

1、处理器:32位ARM® Cortex®-M0+,最高工作频率为48MHz,每兆赫兹可达2.46 Coremark。
2、存储器:闪存容量从32KB到256KB不等,SRAM容量从4KB到32KB不等。
3、电源管理:支持多种低功耗模式,如空闲和待机模式,最低功耗为3.5μA/MHz。
4、外设:拥有丰富的智能和灵活的外设,如直接内存访问控制器(DMAC)、事件系统、定时器/计数器(TC/TCC)、实时时钟(RTC)、看门狗定时器(WDT)、CRC-32生成器、通用串行总线(USB)2.0接口、串行通信接口(SERCOM)、Inter-IC Sound(I2S)接口、模数转换器(ADC/DAC)、模拟比较器(AC)和外设触摸控制器(PTC)。
5、封装:支持多种封装形式,从32引脚到64引脚不等,包括TQFP、QFN、UFBGA和WLCSP。
6、标准:符合AEC-Q100 Grade 1的汽车级标准,工作温度范围为-40°C到+125°C。

在这里插入图片描述
MicroPython的SAMD21 UART(串行总线)是指在SAMD21微控制器上使用MicroPython语言进行串行通信的功能模块。

主要特点:

串行通信协议支持:SAMD21 UART模块支持常见的串行通信协议,如UART、USART和SPI等。这使得开发者可以使用UART模块与其他设备进行可靠的串行数据传输。
多个串口通道:SAMD21微控制器通常具有多个串口通道,每个通道都可以独立配置和控制。这些通道可以同时进行不同的串行通信任务,提供灵活的通信能力。
可编程性:通过MicroPython语言,开发者可以使用简洁的语法对SAMD21 UART进行编程控制。可以设置波特率、数据位数、校验位和停止位等参数,实现灵活的串行通信配置。

应用场景:

与外部设备通信:SAMD21 UART模块常用于与外部设备进行通信,如传感器、显示屏、无线模块等。通过串行通信,可以实现与这些设备之间的数据交换和控制操作。
与计算机通信:SAMD21 UART模块可以用于与计算机进行串行通信,如通过USB转串口模块连接计算机。这样可以实现与计算机之间的数据传输和通信,便于调试和数据交互。
系统调试和日志记录:通过SAMD21 UART模块,可以将系统的调试信息和日志记录输出到串行口。这对于调试和故障排除非常有帮助,特别是在没有其他外部显示设备的情况下。

注意事项:

波特率匹配:在进行串行通信时,需要确保两个设备的波特率设置相匹配。波特率不匹配可能导致数据传输错误或无法正常通信。
电平适配:SAMD21 UART模块的引脚电平通常为TTL电平(如3.3V),与其他设备的电平要求可能不同。在与其他设备通信时,需要注意电平适配问题,以避免损坏设备。
数据完整性校验:对于需要保证数据完整性的应用,可以在UART通信中使用校验位。开发者需要正确设置和验证校验位,以确保数据的准确传输和接收。

综上所述,MicroPython的SAMD21 UART模块利用SAMD21微控制器的丰富资源和MicroPython语言的支持,提供了灵活的串行通信功能。适用于与外部设备通信、与计算机通信以及系统调试和日志记录等应用场景。在使用UART模块时,需要注意波特率匹配、电平适配以及数据完整性校验等问题,以确保串行通信的可靠性和稳定性。

在这里插入图片描述

以下是几个实际运用程序参考代码案例,分别演示了如何使用MicroPython的SAMD21UART功能进行串行通信:

案例一:使用machine.UART()创建UART对象

import machine
uart = machine.UART(2, baudrate=9600)  # 创建一个UART对象,波特率为9600

重点解读:这个程序使用machine.UART()函数创建一个UART对象,并指定串口号和波特率。在这个例子中,我们将串口号设置为2,波特率设置为9600。

案例二:使用uart.write()发送数据

uart.write('Hello, world!')  # 向串口发送字符串"Hello, world!"

重点解读:这个程序使用UART对象的write()方法向串口发送数据。在这个例子中,我们向串口发送了一个字符串"Hello, world!"。

案例三:使用uart.read()接收数据

data = uart.read()  # 从串口读取数据
print("接收到的数据:", data)

重点解读:这个程序使用UART对象的read()方法从串口读取数据。在这个例子中,我们从串口读取了数据,并将其打印出来。

案例四:通过串行总线发送和接收数据

import machine  
import utime  
  
uart = machine.UART(0, 115200)  # 初始化串行总线,设置波特率为115200  
  
while True:  
    data_to_send = "Hello, SAMD21!"  # 要发送的数据  
    uart.write(data_to_send.encode())  # 将数据编码后发送到串行总线  
    print("Sent:", data_to_send)  # 打印已发送的数据  
      
    data_received = uart.read(10)  # 从串行总线读取10个字节的数据  
    print("Received:", data_received.decode())  # 解码并打印接收到的数据  
    utime.sleep(1)  # 延时1秒

要点解读:
通过machine.UART()函数初始化串行总线,并指定使用UART0接口,波特率为115200。
在一个无限循环中,首先将要发送的数据存储在data_to_send变量中,然后使用uart.write()函数将其编码后发送到串行总线。同时打印已发送的数据。
然后使用uart.read()函数从串行总线读取10个字节的数据,并将其存储在data_received变量中。接着使用decode()函数对接收到的数据进行解码,并打印接收到的数据。
最后使用utime.sleep()函数进行延时,以确保读取的数据足够稳定。

案例五:通过串行总线实现主从设备通信

import machine  
import utime  
  
uart = machine.UART(0, 115200)  # 初始化串行总线,设置波特率为115200  
  
master_address = 0x1234  # 主设备地址  
slave_address = 0x5678  # 从设备地址  
  
master = machine.UART(uart, baudrate=115200, address=master_address)  # 创建主设备对象  
slave = machine.UART(uart, baudrate=115200, address=slave_address)  # 创建从设备对象  
  
while True:  
    master.write(b"Hello from master!")  # 主设备发送数据到从设备  
    data_received = slave.read(10)  # 从设备读取接收到的数据  
    print("Received from slave:", data_received)  # 打印接收到的数据  
    utime.sleep(1)  # 延时1秒

要点解读:
通过machine.UART()函数初始化串行总线,并指定使用UART0接口,波特率为115200。同时定义了主设备和从设备的地址。
使用machine.UART()函数创建主设备和从设备对象,并将它们连接到相同的串行总线上。为每个设备指定相应的波特率和地址。
在一个无限循环中,主设备使用master.write()函数向从设备发送数据。同时打印一条消息以指示已发送的数据。
从设备使用slave.read()函数读取接收到的数据,并将其存储在data_received变量中。接着打印已接收到的数据。
最后使用utime.sleep()函数进行延时,以确保读取的数据足够稳定。

案例三:通过串行总线实现简单的RSA加密解密通信

import machine  
import utime  
from crypto import rsa_keypair, rsa_encrypt, rsa_decrypt  
  
uart = machine.UART(0, 9600)  # 初始化串行总线,设置波特率为9600  
  
(public_key, private_key) = rsa_keypair(256)  # 生成RSA密钥对  
  
while True:  
    data_to_encrypt = b"Hello, world!"  # 要加密的数据  
    encrypted_data = rsa_encrypt(data_to_encrypt, public_key)  # 使用公钥加密数据  
    print("Encrypted:", encrypted_data)  # 打印加密后的数据  
      
    decrypted_data = rsa_decrypt(encrypted_data, private_key)  # 使用私钥解密数据  
    print("Decrypted:", decrypted_data)  # 打印解密后的数据

案例的解读:
首先,导入需要的模块。在这个例子中,导入了machine和utime模块,以及自定义的crypto模块。machine模块是用于硬件控制的,而utime模块则提供了一些时间相关的函数。crypto模块包含RSA的密钥生成、加密和解密功能。
初始化串行总线,并设置波特率为9600。这意味着串行总线的通信速率为每秒9600比特。
生成RSA密钥对。在这个案例中,使用256位密钥对进行加密和解密。密钥对的生成通过rsa_keypair()函数实现。该函数返回一对公钥和私钥,用于加密和解密数据。
在一个无限循环中,首先将要加密的数据存储在data_to_encrypt变量中。使用rsa_encrypt()函数对数据进行加密,该函数使用公钥对数据进行加密。加密后的数据存储在encrypted_data变量中,并通过打印语句输出。
然后,使用rsa_decrypt()函数对加密数据进行解密,该函数使用私钥对数据进行解密。解密后的数据存储在decrypted_data变量中,并通过打印语句输出。
这个案例展示了如何使用RSA算法通过串行总线进行简单的加密和解密通信。它使用了硬件控制模块(machine)和时间相关模块(utime),并引入了一个自定义的加密解密模块(crypto)。通过循环不断地对数据进行加密和解密操作,可以实现在串行总线上的安全通信。

案例六:使用SAMD21的UART与电脑通信

SAMD21设备可以使用UART与电脑或其他设备进行串行通信。以下是一个使用MicroPython的代码示例,它可以从PA04引脚接收数据,并通过PA05引脚发送数据:

from machine import UART, Pin

uart = UART(0, 9600) # 创建UART对象,使用SERCOM0,波特率为9600
uart.init(9600, tx=Pin('PA05'), rx=Pin('PA04')) # 初始化UART,指定TX和RX引脚

while True:
    if uart.any(): # 如果有数据可读
        data = uart.read() # 读取数据,返回一个字节对象
        print(data) # 打印数据
        uart.write(data) # 回写数据

要点解读:
UART类可以用来创建一个UART对象,它可以实现双工串行通信协议。
UART对象的init方法可以用来初始化UART,指定波特率、数据位、校验位、停止位等参数。
UART对象的any方法可以用来检查是否有数据可读。
UART对象的read方法可以用来读取数据,返回一个字节对象。
UART对象的write方法可以用来写入数据,接受一个字节对象。

案例七:使用SAMD21的UART读取温湿度传感器DHT11的数据

DHT11是一种常用的温湿度传感器,它使用一根数据线与外部设备通信。以下是一个使用MicroPython的代码示例,它可以通过PA06引脚读取DHT11的数据,并打印出温度和湿度:

from machine import UART, Pin
import time

uart = UART(1, 9600) # 创建UART对象,使用SERCOM1,波特率为9600
uart.init(9600, tx=Pin('PA06'), rx=Pin('PA06')) # 初始化UART,将TX和RX引脚短接,并连接到DHT11的数据线

def read_dht11():
    uart.write(b'\x00') # 向DHT11发送开始信号
    time.sleep_ms(20) # 延时20毫秒
    uart.write(b'\xff') # 向DHT11发送结束信号
    data = uart.read(5) # 读取DHT11返回的5个字节的数据
    if data and len(data) == 5 and data[4] == (data[0] + data[1] + data[2] + data[3]) & 0xff: # 如果数据有效且校验和正确
        humidity = data[0] + data[1] / 10 # 计算湿度,单位为%
        temperature = data[2] + data[3] / 10 # 计算温度,单位为摄氏度
        return humidity, temperature # 返回湿度和温度
    else: # 如果数据无效或校验和错误
        return None, None # 返回None

while True:
    humidity, temperature = read_dht11() # 调用函数读取DHT11的数据
    if humidity is not None: # 如果数据有效
        print('Humidity: {:.1f}%, Temperature: {:.1f}C'.format(humidity, temperature)) # 打印湿度和温度
    else: # 如果数据无效
        print('Invalid data') # 打印错误信息
    time.sleep(2) # 延时2秒

要点解读:
DHT11使用一种特殊的通信协议,需要通过UART模拟时序信号。
DHT11返回的5个字节的数据分别表示湿度整数部分、湿度小数部分、温度整数部分、温度小数部分和校验和。
校验和等于前四个字节的和的低八位,用来检查数据是否正确。
读取DHT11的数据之前,需要向它发送一个开始信号和一个结束信号,分别为0x00和0xff。

案例九:使用SAMD21的UART与GPS模块通信

GPS模块是一种可以接收卫星信号并提供位置信息的设备,它通常使用UART与外部设备通信,并发送NMEA格式的数据。以下是一个使用MicroPython的代码示例,它可以通过PA08引脚接收GPS模块的数据,并解析出经度和纬度:

from machine import UART, Pin
import time

uart = UART(2, 9600) # 创建UART对象,使用SERCOM2,波特率为9600
uart.init(9600, rx=Pin('PA08')) # 初始化UART,指定RX引脚,并连接到GPS模块的TX引脚

def parse_gprmc(data):
    fields = data.split(b',') # 以逗号分隔数据字段
    if fields[0] == b'$GPRMC' and fields[2] == b'A': # 如果是GPRMC语句且定位有效
        latitude = float(fields[3]) # 获取纬度值,单位为度分
        latitude = int(latitude / 100) + (latitude % 100) / 60 # 转换为度
        if fields[4] == b'S': # 如果是南纬
            latitude = -latitude # 取负值
        longitude = float(fields[5]) # 获取经度值,单位为度分
        longitude = int(longitude / 100) + (longitude % 100) / 60 # 转换为度
        if fields[6] == b'W': # 如果是西经
            longitude = -longitude # 取负值
        return latitude, longitude # 返回纬度和经度
    else: # 如果不是GPRMC语句或定位无效
        return None, None # 返回None

while True:
    if uart.any(): # 如果有数据可读
        data = uart.readline() # 读取一行数据,返回一个字节对象
        print(data) # 打印数据
        latitude, longitude = parse_gprmc(data) # 调用函数解析GPRMC语句
        if latitude is not None: # 如果数据有效
            print('Latitude: {:.6f}, Longitude: {:.6f}'.format(latitude, longitude)) # 打印纬度和经度
    time.sleep(1) # 延时1秒

要点解读:
GPS模块发送的NMEA格式的数据是一种标准的文本协议,每行以$开头,以*结束,包含多个字段。
GPRMC语句是一种常用的NMEA语句,它包含了时间、日期、位置、速度、航向等信息。
GPRMC语句的第三个字段表示定位状态,A表示有效,V表示无效。
GPRMC语句的第四个字段表示纬度值,第五个字段表示纬度方向,N表示北纬,S表示南纬。
GPRMC语句的第六个字段表示经度值,第七个字段表示经度方向,E表示东经,W表示西经。
纬度和经度值的单位是度分(ddmm.mmmm),需要转换为度(dd.dddddd)才能使用。

请注意,以上案例只是为了拓展思路,可能存在错误或不适用的情况。不同的硬件平台、使用场景和MicroPython版本可能会导致不同的使用方法。在实际编程中,您需要根据您的硬件配置和具体需求进行调整,并进行多次实际测试。确保正确连接硬件并了解所使用的传感器和设备的规范和特性非常重要。

猜你喜欢

转载自blog.csdn.net/weixin_41659040/article/details/133434133