可以通过直接读写寄存器来控制 ESP32 的外设。这就需要阅读数据手册,了解要使用哪些寄存器以及要写入哪些值。下面的示例展示了如何打开和更改 MCPWM0 外设的预分频器。
from micropython import const
from machine import mem32
# Define the register addresses that will be used.
DR_REG_DPORT_BASE = const(0x3FF00000)
DPORT_PERIP_CLK_EN_REG = const(DR_REG_DPORT_BASE + 0x0C0)
DPORT_PERIP_RST_EN_REG = const(DR_REG_DPORT_BASE + 0x0C4)
DPORT_PWM0_CLK_EN = const(1 << 17)
MCPWM0 = const(0x3FF5E000)
MCPWM1 = const(0x3FF6C000)
# Enable CLK and disable RST.
print(hex(mem32[DPORT_PERIP_CLK_EN_REG] & 0xffffffff))
print(hex(mem32[DPORT_PERIP_RST_EN_REG] & 0xffffffff))
mem32[DPORT_PERIP_CLK_EN_REG] |= DPORT_PWM0_CLK_EN
mem32[DPORT_PERIP_RST_EN_REG] &= ~DPORT_PWM0_CLK_EN
print(hex(mem32[DPORT_PERIP_CLK_EN_REG] & 0xffffffff))
print(hex(mem32[DPORT_PERIP_RST_EN_REG] & 0xffffffff))
# Change the MCPWM0 prescaler.
print(hex(mem32[MCPWM0])) # read PWM_CLK_CFG_REG (reset value = 0)
mem32[MCPWM0] = 0x55 # change PWM_CLK_PRESCALE
print(hex(mem32[MCPWM0])) # read PWM_CLK_CFG_REG
请注意,在使用外设之前,必须启用其时钟,并且必须将其从复位中取出。在上述示例中,以下寄存器用于此目的:
- DPORT_PERI_CLK_EN_REG:用于启用外设时钟
- DPORT_PERI_RST_EN_REG:用于复位(或解除复位)外设
MCPWM0 外设位于上述两个寄存器的第 17 位,因此 DPORT_PWM0_CLK_EN 的值为 17。
通过寄存器直接同步访问引脚
下面的代码展示了如何通过寄存器直接访问引脚。该代码已在通用的 ESP32 电路板上进行了测试。它通过寄存器将引脚 16、17、32 和 33 配置为输出模式,并通过寄存器切换引脚输出值。引脚 16 和 17 同时切换。
from micropython import const
from machine import mem32, Pin
GPIO_OUT_REG = const(0x3FF44004) # GPIO 0-31 输出寄存器
GPIO_OUT1_REG = const(0x3FF44010) # GPIO 32-39 输出寄存器
GPIO_ENABLE_REG = const(0x3FF44020) # GPIO 0-31 输出使能寄存器
GPIO_ENABLE1_REG = const(0x3FF4402C) # GPIO 32-39 输出使能寄存器
M16 = 1 << 16 # Pin(16) 位掩码
M17 = 1 << 17 # Pin(17) 位掩码
M32 = 1 << (32-32) # Pin(32) 位掩码
M33 = 1 << (33-32) # Pin(33) 位掩码
# 使能引脚输出模式,类似:
# p16 = Pin(16, mode=Pin.OUT)
# p17 = Pin(17, mode=Pin.OUT)
# p32 = Pin(32, mode=Pin.OUT)
# p33 = Pin(33, mode=Pin.OUT)
mem32[GPIO_ENABLE_REG] = mem32[GPIO_ENABLE_REG] | M16 | M17
mem32[GPIO_ENABLE1_REG] = mem32[GPIO_ENABLE1_REG] | M32 | M33
print(hex(mem32[GPIO_OUT_REG]), hex(mem32[GPIO_OUT1_REG]))
# 设置输出为1,类似:
# p16(1)
# p17(1)
# p32(1)
# p33(1)
mem32[GPIO_OUT_REG] = mem32[GPIO_OUT_REG] | M16 | M17
mem32[GPIO_OUT1_REG] = mem32[GPIO_OUT1_REG] | M32 | M33
print(hex(mem32[GPIO_OUT_REG]), hex(mem32[GPIO_OUT1_REG]))
# 设置输出为0,类似:
# p16(0)
# p17(0)
# p32(0)
# p33(0)
mem32[GPIO_OUT_REG] = mem32[GPIO_OUT_REG] & ~(M16 | M17)
mem32[GPIO_OUT1_REG] = mem32[GPIO_OUT1_REG] & ~(M32 | M33)
print(hex(mem32[GPIO_OUT_REG]), hex(mem32[GPIO_OUT1_REG]))
while True:
# 设置输出为1
mem32[GPIO_OUT_REG] = mem32[GPIO_OUT_REG] | M16 | M17
mem32[GPIO_OUT1_REG] = mem32[GPIO_OUT1_REG] | M32 | M33
# 设置输出为0
mem32[GPIO_OUT_REG] = mem32[GPIO_OUT_REG] & ~(M16 | M17)
mem32[GPIO_OUT1_REG] = mem32[GPIO_OUT1_REG] & ~(M32 | M33)
输出为:
0x0 0x0
0x30000 0x3
0x0 0x0
引脚 16 和 17 同步切换:
32 号和 33 号引脚上的图像相同。
请注意,引脚 34-36 和 39 仅为输入。此外,引脚 1 和 3 是 REPL UART 的 Tx 和 Rx,引脚 6-11 连接到内置 SPI 闪存。