当前位置:   article > 正文

【雕爷学编程】MicroPython手册之 ESP32-S3 硬件SPI总线

esp32-s3

在这里插入图片描述
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、适当使用抽象来封装底层硬件操作。

在这里插入图片描述

总体来说,ESP32-S3在功耗、硬件资源和功能支持方面进行了优化,非常适合作为低功耗物联网设备的处理平台。相比ESP32,ESP32-S3在无线、安全性和稳定性等方面有所提升。

1、搭载 Xtensa® 32 位 LX7 双核处理器,主频 240 MHz,内置 512 KB SRAM (TCM),具有 45 个可编程 GPIO 管脚和丰富的通信接口。
2、支持更大容量的高速 Octal SPI flash 和片外 RAM,支持用户配置数据缓存与指令缓存。
3、加入了用于加速神经网络计算和信号处理等工作的向量指令 (vector instructions),性能对比 ESP32 有可观的提升。
4、集成 2.4 GHz Wi-Fi (802.11 b/g/n),支持 40 MHz 带宽;其低功耗蓝牙子系统支持 Bluetooth 5 (LE) 和 Bluetooth Mesh,可通过 Coded PHY 与广播扩展实现远距离通信。它还支持 2 Mbps PHY,用于提高传输速度和数据吞吐量。
5、外设新增 LCD 接口、USB、SD/MMC 主机控制器和 TWAI TM 控制器等常用外设接口。
6、拥有完善的安全机制和保护措施,支持基于 AES-XTS 算法的 flash 加密、基于 RSA 算法的安全启动、数字签名和 HMAC。还新增了一个“世界控制器 (World Controller)”模块,提供了两个互不干扰的执行环境,实现可信执行环境或权限分离机制。

在这里插入图片描述
MicroPython的ESP32-S3芯片支持硬件SPI总线,以下是关于其主要特点、应用场景和需要注意的事项的详细解释:

主要特点:

高速传输:ESP32-S3的硬件SPI总线通过专用的SPI控制器实现,具有较高的传输速度。它可以在较短的时间内完成数据传输,适用于对速度要求较高的应用场景。

低资源占用:硬件SPI总线使用专用的硬件控制器,减轻了处理器的负担。相对于软件SPI,硬件SPI总线在传输数据时占用的处理器资源更少。

多通道支持:ESP32-S3的硬件SPI总线支持多个SPI通道。每个通道都有独立的寄存器和引脚,可以同时连接和控制多个SPI设备。

应用场景:

外围设备交互:硬件SPI总线适用于与各种外围设备进行高速数据交互。例如,与传感器、存储器、显示屏等设备进行数据传输。通过硬件SPI总线,可以快速读取传感器数据、存储数据或控制显示屏的刷新。

无线通信模块:硬件SPI总线可以用于连接无线通信模块,如WiFi模块或蓝牙模块。这些模块通常需要快速数据传输,硬件SPI能够满足其高速通信的需求。

SD卡读写:硬件SPI总线可以用于与SD卡进行快速的读写操作。SD卡通常需要高速的数据传输以支持实时数据记录和存储。

显示屏驱动:硬件SPI总线可以用于驱动液晶显示屏。通过硬件SPI总线,可以高效地传输图像数据和控制命令,实现显示屏的快速刷新和操作。

需要注意的事项:

引脚分配:使用硬件SPI总线时,需要合理分配GPIO引脚。确保所选的引脚与硬件SPI总线的通信需求相匹配,并避免与其他外设冲突。

时钟和模式配置:硬件SPI总线的时钟频率和数据传输模式可以配置。在使用硬件SPI总线之前,需要根据外设的要求和系统的稳定性来配置适当的时钟频率和传输模式。

电压兼容性:在与外部设备进行SPI通信时,需要确保设备之间的电压兼容性。确认ESP32-S3芯片和外设之间的电压级别匹配,以避免损坏设备或数据传输错误。

信号干扰:在使用硬件SPI总线时,需要注意信号干扰的问题。尽量减少长距离或高速传输时的干扰源,并采取适当的电路布局和屏蔽措施,以确保数据传输的可靠性。

综上所述,MicroPython的ESP32-S3芯片的硬件SPI总线具有高速传输、低资源占用和多通道支持等特点。它适用于外围设备交互、无线通信模块、SD卡读写和显示屏驱动等应用场景。在使用硬件SPI总线时,需要注意引脚分配、时钟和模式配置、电压兼容性和信号干扰等事项,以确保通信的可靠性和性能满足要求。

案例一:使用MicroPython的ESP32-S3硬件SPI总线读取传感器数据

from machine import Pin, SPI
import time

# 定义SPI引脚
sck = Pin(18, Pin.OUT)
mosi = Pin(23, Pin.OUT)
miso = Pin(19, Pin.IN)
cs = Pin(5, Pin.OUT)

# 创建SPI对象
spi = SPI(2, baudrate=1000000, polarity=0, phase=0, sck=sck, mosi=mosi, miso=miso)

# 读取传感器数据
def read_sensor_data():
    cs.value(1)  # 片选信号置低,开始通信
    data = spi.read(4)  # 读取4个字节的数据
    cs.value(0)  # 片选信号置高,结束通信
    return data

while True:
    sensor_data = read_sensor_data()
    print("Sensor data:", sensor_data)
    time.sleep(1)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

要点解读:在这个程序中,我们首先导入了machine模块中的Pin和SPI类,以及time模块。然后,我们定义了SPI总线的四个引脚:sck(时钟)、mosi(主数据线)、miso(从数据线)和cs(片选)。接下来,我们创建了一个SPI对象,并设置了相应的参数。在read_sensor_data函数中,我们通过将片选信号置低来开始通信,然后读取4个字节的数据,最后将片选信号置高以结束通信。在主循环中,我们不断地读取传感器数据并打印出来。

案例二:使用MicroPython的ESP32-S3硬件SPI总线发送数据到另一个设备

from machine import Pin, SPI
import time

# 定义SPI引脚
sck = Pin(18, Pin.OUT)
mosi = Pin(23, Pin.OUT)
miso = Pin(19, Pin.IN)
cs = Pin(5, Pin.OUT)

# 创建SPI对象
spi = SPI(2, baudrate=1000000, polarity=0, phase=0, sck=sck, mosi=mosi, miso=miso)

# 发送数据到另一个设备
def send_data_to_device(data):
    cs.value(1)  # 片选信号置低,开始通信
    spi.write(data)  # 写入数据
    cs.value(0)  # 片选信号置高,结束通信

while True:
    data_to_send = bytearray([0x01, 0x02, 0x03, 0x04])  # 要发送的数据
    send_data_to_device(data_to_send)
    print("Data sent:", data_to_send)
    time.sleep(1)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

要点解读:在这个程序中,我们与案例一类似地定义了SPI总线的引脚,并创建了一个SPI对象。在send_data_to_device函数中,我们同样通过将片选信号置低来开始通信,然后写入数据,最后将片选信号置高以结束通信。在主循环中,我们不断地发送数据并打印出来。

案例三:使用MicroPython的ESP32-S3硬件SPI总线进行通信协议解析

from machine import Pin, SPI
import time

# 定义SPI引脚
sck = Pin(18, Pin.OUT)
mosi = Pin(23, Pin.OUT)
miso = Pin(19, Pin.IN)
cs = Pin(5, Pin.OUT)

# 创建SPI对象
spi = SPI(2, baudrate=1000000, polarity=0, phase=0, sck=sck, mosi=mosi, miso=miso)

# 解析通信协议数据
def parse_protocol_data(data):
    # 在这里添加解析通信协议数据的代码
    pass

while True:
    received_data = bytearray()
    while len(received_data) < 4:  # 假设接收到的数据长度为4字节
        received_data += spi.read(1)  # 读取一个字节的数据
    parsed_data = parse_protocol_data(received_data)
    print("Parsed data:", parsed_data)
    time.sleep(1)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

要点解读:在这个程序中,我们与案例一类似地定义了SPI总线的引脚,并创建了一个SPI对象。在主循环中,我们不断地读取数据,直到接收到足够的数据长度。然后,我们调用parse_protocol_data函数来解析通信协议数据,并将解析后的数据打印出来。请注意,你需要根据具体的通信协议来实现parse_protocol_data函数。

案例四:使用SPI总线与外部设备通信
在这个程序中,我们将使用ESP32-S3的硬件SPI总线与外部设备进行通信。具体来说,我们将使用spi.init()函数初始化SPI总线,并设置通信参数。然后,我们将使用spi.write()函数向外部设备发送数据,并使用spi.read()函数从外部设备读取数据。需要注意的是,在通信之前,我们需要先使用spi.select()函数将SPI设备选择为指定设备。

import machine  
import time  
  
# 初始化SPI总线  
spi = machine.SPI(1, mode=0, polarity=0, phase=0) # 使用SPI1总线,工作模式为Master,数据传输格式为SPI格式  
spi.init() # 初始化SPI总线  
  
# 设置通信参数  
spi.max_speed_hz = 1000000 # 设置最大时钟频率为1MHz  
spi.bits_per_word = 8 # 设置数据位数为8位  
spi.select(0) # 选择SPI设备为指定设备,这里选择设备编号为0的设备  
  
# 向外部设备发送数据,并从外部设备读取数据  
data = [0x01, 0x02, 0x03, 0x04] # 要发送的数据  
spi.write(data) # 向外部设备发送数据  
response = spi.read(len(data)) # 从外部设备读取数据  
print(response) # 将返回数据打印到串口
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

在这个程序中,我们首先导入了machine模块和time模块。然后,我们使用machine.SPI()函数创建了一个SPI对象,并指定使用SPI1总线、工作模式为Master、数据传输格式为SPI格式。接下来,我们使用spi.init()函数初始化SPI总线,并使用spi.configure()函数设置通信参数,包括最大时钟频率、数据位数和起始位等。然后,我们使用spi.select()函数将SPI设备选择为指定设备,这里选择设备编号为0的设备。最后,我们定义了一个列表data,包含了要发送给外部设备的四个字节的数据。我们使用spi.write()函数向外部设备发送数据,并使用spi.read()函数从外部设备读取同样长度的数据。然后我们将返回的数据打印到串口以进行调试和验证。需要注意的是,在通信之前,我们需要先使用spi.select()函数将SPI设备选择为指定设备。在实际应用中,我们需要根据具体的外部设备和通信协议来调整通信参数和数据格式,以确保通信的正确性。同时我们还需要注意处理异常情况和错误检测等以保证程序的健壮性。

案例五:控制LED灯的亮灭
在这个程序中,我们将使用ESP32-S3的硬件SPI总线控制LED灯的亮灭。具体来说,我们将使用gpio.pinMode()函数将GPIO2配置为输出引脚。然后,我们将使用spi.init()函数初始化SPI总线,并将GPIO2引脚作为SPI设备的MOSI引脚。最后,我们将使用spi.writebytes()函数向LED灯发送控制指令,控制LED灯的亮灭。

import machine  
import time  
  
# 设置GPIO2为输出引脚  
pin2 = machine.Pin(2, machine.Pin.OUT)  
  
# 初始化SPI总线,并将GPIO2引脚作为SPI设备的MOSI引脚  
spi = machine.SPI(1, mode=0, polarity=0, phase=0, mosi=pin2)  
spi.init()  
  
# 控制LED灯的亮灭  
while True:  
    pin2.value(1) # 向LED灯发送控制指令,点亮LED灯  
    time.sleep(1) # 等待1秒钟  
    pin2.value(0) # 向LED灯发送控制指令,熄灭LED灯  
    time.sleep(1) # 等待1秒钟
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

在这个程序中,我们首先导入了machine模块和time模块。然后,我们使用machine.Pin()函数将GPIO2配置为输出引脚,并将其赋值给变量pin2。接下来,我们使用machine.SPI()函数创建了一个SPI对象,并指定使用SPI1总线、工作模式为Master、数据传输格式为SPI格式,并将GPIO2引脚作为SPI设备的MOSI引脚。然后,我们使用spi.init()函数初始化SPI总线。在主循环中,我们使用pin2.value()函数向LED灯发送控制指令,控制LED灯的亮灭。然后我们使用time.sleep()函数等待1秒钟,再发送相反的控制指令,以实现LED灯的闪烁效果。需要注意的是,在实际应用中,我们需要根据具体的硬件设备和通信协议来调整通信参数和数据格式,以确保通信的正确性。同时我们还需要注意处理异常情况和错误检测等以保证程序的健壮性。

案例六:使用SPI总线读取传感器数据
在这个程序中,我们将使用ESP32-S3的硬件SPI总线读取传感器数据。具体来说,我们将使用spi.init()函数初始化SPI总线,并设置通信参数。然后,我们将使用spi.readbytes()函数从传感器读取数据。需要注意的是,在读取数据之前,我们需要先使用spi.select()函数将SPI设备选择为指定设备。

import machine  
import time  
  
# 初始化SPI总线  
spi = machine.SPI(1, mode=0, polarity=0, phase=0) # 使用SPI1总线,工作模式为Master,数据传输格式为SPI格式  
spi.init() # 初始化SPI总线  
  
# 设置通信参数  
spi.max_speed_hz = 1000000 # 设置最大时钟频率为1MHz  
spi.bits_per_word = 8 # 设置数据位数为8位  
spi.select(0) # 选择SPI设备为指定设备,这里选择设备编号为0的设备  
  
# 从传感器读取数据  
response = spi.readbytes(4) # 从传感器读取4个字节的数据  
print(response) # 将返回数据打印到串口
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

在这个程序中,我们首先导入了machine模块和time模块。然后,我们使用machine.SPI()函数创建了一个SPI对象,并指定使用SPI1总线、工作模式为Master、数据传输格式为SPI格式。接下来,我们使用spi.init()函数初始化SPI总线,并使用spi.configure()函数设置通信参数,包括最大时钟频率、数据位数和起始位等。然后,我们使用spi.select()函数将SPI设备选择为指定设备,这里选择设备编号为0的设备。最后,我们使用spi.readbytes()函数从传感器读取4个字节的数据,并将返回的数据打印到串口以进行调试和验证。需要注意的是,在读取数据之前,我们需要先使用spi.select()函数将SPI设备选择为指定设备。在实际应用中,我们需要根据具体的传感器和通信协议来调整通信参数和数据格式,以确保通信的正确性。同时我们还需要注意处理异常情况和错误检测等以保证程序的健壮性。

案例七:与SPI设备通信:

import machine
import utime

spi = machine.SPI(2, baudrate=1000000, polarity=0, phase=0)
spi.init()

def read_spi_data():
    cs = machine.Pin(5, machine.Pin.OUT)
    cs.value(0)
    spi.write(b"\x01\x02\x03")
    data = spi.read(3)
    cs.value(1)
    return data

while True:
    data = read_spi_data()
    print("SPI Data:", data)
    utime.sleep(1)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

要点解读:
该代码片段演示了如何使用MicroPython在ESP32-S3上通过硬件SPI总线与SPI设备进行通信。
使用machine.SPI()函数创建一个SPI对象,并指定SPI总线编号、波特率、极性和相位。
在这个示例中,SPI总线编号为2,波特率为1,000,000,极性为0,相位为0。
使用spi.init()方法初始化SPI总线。
使用machine.Pin()函数创建引脚对象,用于控制SPI设备的片选引脚。
read_spi_data()函数用于与SPI设备进行通信。
在一个无限循环中,通过调用read_spi_data()函数来读取SPI设备发送的数据。

案例八:与LCD显示屏交互:

import machine
import utime

spi = machine.SPI(2, baudrate=4000000, polarity=0, phase=0)
spi.init()

lcd_cs = machine.Pin(5, machine.Pin.OUT)
lcd_dc = machine.Pin(4, machine.Pin.OUT)
lcd_rst = machine.Pin(2, machine.Pin.OUT)

def send_command(cmd):
    lcd_dc.value(0)
    lcd_cs.value(0)
    spi.write(cmd)
    lcd_cs.value(1)

def send_data(data):
    lcd_dc.value(1)
    lcd_cs.value(0)
    spi.write(data)
    lcd_cs.value(1)

def init_lcd():
    lcd_rst.value(0)
    utime.sleep_ms(100)
    lcd_rst.value(1)
    send_command(b"\x01")
    utime.sleep_ms(10)
    send_command(b"\x28")
    utime.sleep_ms(10)
    send_command(b"\x08")
    utime.sleep_ms(10)
    send_command(b"\x0C")
    utime.sleep_ms(10)

init_lcd()

while True:
    send_command(b"\x80")
    send_data(b"Hello, LCD!")
    utime.sleep(1)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

要点解读:
该代码片段演示了如何使用MicroPython在ESP32-S3上通过硬件SPI总线与LCD显示屏进行交互。
使用machine.SPI()函数创建一个SPI对象,并指定SPI总线编号、波特率、极性和相位。
在这个示例中,SPI总线编号为2,波特率为4,000,000,极性为0,相位为0。
使用spi.init()方法初始化SPI总线。
使用machine.Pin()函数创建引脚对象,用于控制LCD显示屏的片选引脚、数据/命令引脚和复位引脚。
send_command()函数用于向LCD发送命令。
send_data()函数用于向LCD发送数据。
init_lcd()函数用于初始化LCD显示屏。
在一个无限循环中,通过调用send_command()和send_data()函数来向LCD显示屏发送命令和数据。

案例九:与AD转换器交互:

import machine
import utime

spi = machine.SPI(2, baudrate=1000000, polarity=0, phase=0)
spi.init()

adc_cs = machine.Pin(5, machine.Pin.OUT)

def read_adc(channel):
    adc_cs.value(0)
    cmd = bytes([0x80 | (channel << 4), 0x00])
    data = spi.write_readinto(cmd, bytearray(2))
    adc_cs.value(1)
    value = (data[0] & 0x03) << 8 | data[1]
    return value

while True:
    adc_value = readADC(0)
    print("ADC Value:", adc_value)
    utime.sleep(1)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

要点解读:
该代码片段演示了如何使用MicroPython在ESP32-S3上通过硬件SPI总线与AD转换器进行交互。
使用machine.SPI()函数创建一个SPI对象,并指定SPI总线编号、波特率、极性和相位。
在这个示例中,SPI总线编号为2,波特率为1,000,000,极性为0,相位为0。
使用spi.init()方法初始化SPI总线。
使用machine.Pin()函数创建引脚对象,用于控制AD转换器的片选引脚。
read_adc()函数用于从AD转换器读取指定通道的模拟值。
在一个无限循环中,通过调用read_adc()函数来读取AD转换器的模拟值,并打印输出。

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

在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/码创造者/article/detail/801154
推荐阅读
相关标签
  

闽ICP备14008679号