Unit Chain Bus

BusChainUnit 是用于 Chain 总线上的 Bus 设备的辅助类。它提供了配置 GPIO 引脚(输入、输出、外部中断)、读取 ADC 值以及与 I2C 设备通信的方法。该类支持多种工作模式,包括 GPIO 输出、GPIO 输入、外部中断、ADC 和 I2C。

支持以下产品:

Unit Chain Bus

UiFlow2 示例

GPIO 控制

在 UiFlow2 中打开 m5basic_unit_chain_bus_gpio_example.m5f2 项目。

本示例演示如何使用 Unit Chain Bus 模块配置和使用 GPIO 引脚。示例将 GPIO1 配置为带上拉的输入模式,将 GPIO2 配置为推挽输出模式。它每 200ms 连续读取 GPIO1 的输入值,并在屏幕上显示状态(高/低)。GPIO2 的输出电平每 1 秒(每 5 个周期)在高和低之间切换,演示输出控制功能。

UiFlow2 代码块:

m5basic_unit_chain_bus_gpio_example.png

示例输出:

None

ADC 读取

在 UiFlow2 中打开 m5basic_unit_chain_bus_adc_example.m5f2 项目。

本示例演示如何从 Unit Chain Bus 模块读取 ADC 值,并使用它们来控制 RGB 亮度。

UiFlow2 代码块:

m5basic_unit_chain_bus_adc_example.png

示例输出:

None

I2C 设备通信

在 UiFlow2 中打开 m5basic_unit_chain_bus_i2c_dlight_example.m5f2 项目。

本示例演示如何使用 Unit Chain Bus 模块与 I2C 设备通信。示例展示了如何将总线配置为 I2C 模式,以及如何将其与 DLight 传感器等 I2C 设备一起使用。

UiFlow2 代码块:

m5basic_unit_chain_bus_i2c_example.png

示例输出:

None

MicroPython 示例

GPIO 控制

本示例演示如何使用 Unit Chain Bus 模块配置和使用 GPIO 引脚。示例将 GPIO1 配置为带上拉的输入模式,将 GPIO2 配置为推挽输出模式。它每 200ms 连续读取 GPIO1 的输入值,并在屏幕上显示状态(高/低)。GPIO2 的输出电平每 1 秒(每 5 个周期)在高和低之间切换,演示输出控制功能。

MicroPython 代码块:

  1# SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
  2#
  3# SPDX-License-Identifier: MIT
  4
  5import os, sys, io
  6import M5
  7from M5 import *
  8from chain import ChainBus
  9from chain import BusChainUnit
 10import time
 11
 12
 13title = None
 14label_gpio1 = None
 15label_tip1 = None
 16label_tip2 = None
 17label_gpio2 = None
 18bus2 = None
 19unit_chain_bus_0 = None
 20last_time = None
 21gpio1_value = None
 22cnt = None
 23gpio2_value = None
 24
 25
 26def setup():
 27    global \
 28        title, \
 29        label_gpio1, \
 30        label_tip1, \
 31        label_tip2, \
 32        label_gpio2, \
 33        bus2, \
 34        unit_chain_bus_0, \
 35        last_time, \
 36        gpio1_value, \
 37        cnt, \
 38        gpio2_value
 39
 40    M5.begin()
 41    Widgets.setRotation(1)
 42    Widgets.fillScreen(0x222222)
 43    title = Widgets.Title(
 44        "Unit Chain Bus Example: GPIO", 3, 0xFFFFFF, 0x0000FF, Widgets.FONTS.DejaVu18
 45    )
 46    label_gpio1 = Widgets.Label(
 47        "GPIO1 Value: --", 10, 85, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18
 48    )
 49    label_tip1 = Widgets.Label(
 50        "Unit Chain Bus GPIO1: Input", 10, 55, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18
 51    )
 52    label_tip2 = Widgets.Label(
 53        "Unit Chain Bus GPIO2: Output", 10, 136, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18
 54    )
 55    label_gpio2 = Widgets.Label(
 56        "GPIO2 Value: --", 10, 165, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18
 57    )
 58
 59    bus2 = ChainBus(2, tx=21, rx=22)
 60    unit_chain_bus_0 = BusChainUnit(bus2, 1)
 61    unit_chain_bus_0.set_gpio_input(1, BusChainUnit.GPIO_PULL_UP)
 62    unit_chain_bus_0.set_gpio_output(2, BusChainUnit.GPIO_MODE_PUSHPULL, BusChainUnit.GPIO_PULL_UP)
 63    if (unit_chain_bus_0.get_work_mode(1)) == (BusChainUnit.WORK_MODE_GPIO_INPUT):
 64        print("set gpio1 as gpio input success")
 65    else:
 66        print("set gpio1 as gpio input failed")
 67    if (unit_chain_bus_0.get_work_mode(2)) == (BusChainUnit.WORK_MODE_GPIO_OUTPUT):
 68        print("set gpio2 as gpio output success")
 69    else:
 70        print("set gpio2 as gpio output failed")
 71    unit_chain_bus_0.set_rgb_color(0x000099)
 72
 73
 74def loop():
 75    global \
 76        title, \
 77        label_gpio1, \
 78        label_tip1, \
 79        label_tip2, \
 80        label_gpio2, \
 81        bus2, \
 82        unit_chain_bus_0, \
 83        last_time, \
 84        gpio1_value, \
 85        cnt, \
 86        gpio2_value
 87    M5.update()
 88    if (time.ticks_diff((time.ticks_ms()), last_time)) >= 200:
 89        last_time = time.ticks_ms()
 90        gpio1_value = unit_chain_bus_0.get_gpio_input_value(1)
 91        if gpio1_value:
 92            label_gpio1.setText(str("GPIO1 Value:  HIGH"))
 93        else:
 94            label_gpio1.setText(str("GPIO1 Value:  LOW"))
 95        cnt = (cnt if isinstance(cnt, (int, float)) else 0) + 1
 96        if cnt >= 5:
 97            cnt = 0
 98            gpio2_value = not gpio2_value
 99            if gpio2_value:
100                unit_chain_bus_0.set_gpio_output_value(2, 1)
101                label_gpio2.setText(str("GPIO2 Value:  HIGH"))
102            else:
103                unit_chain_bus_0.set_gpio_output_value(2, 0)
104                label_gpio2.setText(str("GPIO2 Value:  LOW"))
105
106
107if __name__ == "__main__":
108    try:
109        setup()
110        while True:
111            loop()
112    except (Exception, KeyboardInterrupt) as e:
113        try:
114            bus2.deinit()
115            from utility import print_error_msg
116
117            print_error_msg(e)
118        except ImportError:
119            print("please update to latest firmware")

示例输出:

None

ADC 读取

本示例演示如何从 Unit Chain Bus 模块读取 ADC 值,并使用它们来控制 RGB 亮度。

MicroPython 代码块:

 1# SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
 2#
 3# SPDX-License-Identifier: MIT
 4
 5import os, sys, io
 6import M5
 7from M5 import *
 8from chain import ChainBus
 9from chain import BusChainUnit
10import time
11import m5utils
12
13
14title = None
15label_adc = None
16label_tip = None
17bus2 = None
18unit_chain_bus_0 = None
19last_time = None
20adc_value = None
21
22
23def setup():
24    global title, label_adc, label_tip, bus2, unit_chain_bus_0, last_time, adc_value
25
26    M5.begin()
27    Widgets.setRotation(1)
28    Widgets.fillScreen(0x222222)
29    title = Widgets.Title(
30        "Unit Chain Bus Example: ADC", 3, 0xFFFFFF, 0x0000FF, Widgets.FONTS.DejaVu18
31    )
32    label_adc = Widgets.Label(
33        "ADC Value: --", 10, 85, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18
34    )
35    label_tip = Widgets.Label(
36        "Unit Chain Bus GPIO1: ADC", 10, 55, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18
37    )
38
39    bus2 = ChainBus(2, tx=21, rx=22)
40    unit_chain_bus_0 = BusChainUnit(bus2, 1)
41    unit_chain_bus_0.set_adc(1)
42    if (unit_chain_bus_0.get_work_mode(1)) == (BusChainUnit.WORK_MODE_ADC):
43        print("set gpio1 as adc input success")
44    else:
45        print("set gpio1 as adc input failed")
46    unit_chain_bus_0.set_rgb_color(0x000099)
47
48
49def loop():
50    global title, label_adc, label_tip, bus2, unit_chain_bus_0, last_time, adc_value
51    M5.update()
52    if (time.ticks_diff((time.ticks_ms()), last_time)) >= 200:
53        last_time = time.ticks_ms()
54        adc_value = unit_chain_bus_0.get_adc_input(1)
55        label_adc.setText(str((str("ADC Value: ") + str(adc_value))))
56        print((str("ADC Value: ") + str(adc_value)))
57        unit_chain_bus_0.set_rgb_brightness(
58            int(m5utils.remap(adc_value, 0, 4096, 0, 100)), save=False
59        )
60
61
62if __name__ == "__main__":
63    try:
64        setup()
65        while True:
66            loop()
67    except (Exception, KeyboardInterrupt) as e:
68        try:
69            bus2.deinit()
70            from utility import print_error_msg
71
72            print_error_msg(e)
73        except ImportError:
74            print("please update to latest firmware")

示例输出:

None

I2C 设备通信

本示例演示如何使用 Unit Chain Bus 模块与 I2C 设备通信。示例展示了如何将总线配置为 I2C 模式,以及如何将其与 DLight 传感器等 I2C 设备一起使用。

MicroPython 代码块:

 1# SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
 2#
 3# SPDX-License-Identifier: MIT
 4
 5import os, sys, io
 6import M5
 7from M5 import *
 8from hardware import Pin
 9from hardware import I2C
10from chain import ChainBus
11from chain import BusChainUnit
12import time
13from unit import DLightUnit
14
15
16title = None
17label_brightness = None
18label_mode = None
19i2c0 = None
20bus2 = None
21dlight_0 = None
22unit_chain_bus_0 = None
23last_time = None
24brightness = None
25
26
27def setup():
28    global \
29        title, \
30        label_brightness, \
31        label_mode, \
32        i2c0, \
33        bus2, \
34        dlight_0, \
35        unit_chain_bus_0, \
36        last_time, \
37        brightness
38
39    M5.begin()
40    Widgets.setRotation(1)
41    Widgets.fillScreen(0x222222)
42    title = Widgets.Title(
43        "Unit Chain Bus Example: I2C", 3, 0xFFFFFF, 0x0000FF, Widgets.FONTS.DejaVu18
44    )
45    label_brightness = Widgets.Label(
46        "Brightness: -- lux", 10, 85, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18
47    )
48    label_mode = Widgets.Label(
49        "Unit Chain Bus GPIO1&2: I2C", 10, 54, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18
50    )
51
52    i2c0 = I2C(0, scl=Pin(22), sda=Pin(21), freq=100000)
53    bus2 = ChainBus(2, tx=21, rx=22)
54    unit_chain_bus_0 = BusChainUnit(bus2, 1)
55    unit_chain_bus_0.set_i2c(BusChainUnit.I2C_SPEED_100K)
56    dlight_0 = DLightUnit(unit_chain_bus_0)
57
58
59def loop():
60    global \
61        title, \
62        label_brightness, \
63        label_mode, \
64        i2c0, \
65        bus2, \
66        dlight_0, \
67        unit_chain_bus_0, \
68        last_time, \
69        brightness
70    M5.update()
71    if (time.ticks_diff((time.ticks_ms()), last_time)) >= 500:
72        last_time = time.ticks_ms()
73        brightness = int(dlight_0.get_lux())
74        label_brightness.setText(str((str("Brightness: ") + str((str(brightness) + str(" lux"))))))
75        print((str("Brightness: ") + str((str(brightness) + str(" lux")))))
76
77
78if __name__ == "__main__":
79    try:
80        setup()
81        while True:
82            loop()
83    except (Exception, KeyboardInterrupt) as e:
84        try:
85            bus2.deinit()
86            from utility import print_error_msg
87
88            print_error_msg(e)
89        except ImportError:
90            print("please update to latest firmware")

示例输出:

None

API

BusChainUnit

class chain.unit_bus.BusChainUnit(bus, device_id)

基类:KeyChain

用于通过 Chain 总线与 Bus 设备交互的 Bus Chain Unit 类。

参数:
  • bus (ChainBus) – Chain 总线实例。

  • device_id (int) – Chain 总线上 Bus 设备的设备 ID。

UiFlow2 代码块:

init.png

MicroPython 代码块:

from chain import ChainBus
from chain import BusChainUnit

chainbus_0 = ChainBus(2, 32, 33, verbose=True)
bus_chain_unit_0 = BusChainUnit(chainbus_0, 1)
get_work_mode(gpio)

获取 Unit ChainBus 工作模式。

返回指定 GPIO 引脚的工作模式。

工作模式值:
  • BusChainUnit.WORK_MODE_UNCONFIGURED

  • BusChainUnit.WORK_MODE_GPIO_OUTPUT

  • BusChainUnit.WORK_MODE_GPIO_INPUT

  • BusChainUnit.WORK_MODE_EXIT

  • BusChainUnit.WORK_MODE_ADC

  • BusChainUnit.WORK_MODE_I2C

参数:

gpio (int) – GPIO 编号(1 或 2)。

返回:

工作模式值,如果失败则返回 None。

返回类型:

int | None

UiFlow2 代码块:

get_work_mode.png

MicroPython 代码块:

mode = unit_chain_bus.get_work_mode(1)
if mode == BusChainUnit.WORK_MODE_GPIO_OUTPUT:
    print("GPIO1 is configured as output")
set_gpio_output(gpio, mode, pull=2)

将引脚设置为输出。

参数:
  • gpio (int) – GPIO 编号(1 或 2)。

  • mode (int) – 输出模式。使用 BusChainUnit.GPIO_MODE_PUSHPULL (0) 或 BusChainUnit.GPIO_MODE_OPENDRAIN (1)。

  • pull (int) – 上拉/下拉配置。使用 BusChainUnit.GPIO_PULL_UP (0)、BusChainUnit.GPIO_PULL_DOWN (1) 或 BusChainUnit.GPIO_PULL_NONE (2)。默认值为 BusChainUnit.GPIO_PULL_NONE (2)。

返回:

如果操作成功则返回 True,否则返回 False。

返回类型:

bool

UiFlow2 代码块:

set_gpio_output.png

MicroPython 代码块:

success = unit_chain_bus.set_gpio_output(1, BusChainUnit.GPIO_MODE_PUSHPULL, BusChainUnit.GPIO_PULL_UP)
set_gpio_output_value(gpio, value)

设置 GPIO 输出值。

参数:
  • gpio (int) – GPIO 编号(1 或 2)。

  • value (int) – 输出值。0 表示低电平,1 表示高电平。

返回:

如果操作成功则返回 True,否则返回 False。

返回类型:

bool

UiFlow2 代码块:

set_gpio_output_value.png

MicroPython 代码块:

success = unit_chain_bus.set_gpio_output_value(1, 1)  # Set GPIO1 to high level
set_gpio_input(gpio, pull)

设置 GPIO 输入模式配置。

参数:
  • gpio (int) – GPIO 编号(1 或 2)。

  • pull (int) – 上拉/下拉配置。使用 BusChainUnit.GPIO_PULL_UP (0)、BusChainUnit.GPIO_PULL_DOWN (1) 或 BusChainUnit.GPIO_PULL_NONE (2)。

返回:

如果操作成功则返回 True,否则返回 False。

返回类型:

bool

UiFlow2 代码块:

set_gpio_input.png

MicroPython 代码块:

success = unit_chain_bus.set_gpio_input(1, BusChainUnit.GPIO_PULL_UP)
get_gpio_input_value(gpio)

获取 GPIO 输入值。

参数:

gpio (int) – GPIO 编号(1 或 2)。

返回:

GPIO 值。0 表示低电平,1 表示高电平。如果失败则返回 None。

返回类型:

int | None

UiFlow2 代码块:

get_gpio_input_value.png

MicroPython 代码块:

value = unit_chain_bus.get_gpio_input_value(1)
if value == 1:
    print("GPIO1 is high")
set_gpio_exit(gpio, pull, trigger_mode)

将引脚设置为外部中断输入模式。

参数:
  • gpio (int) – GPIO 编号(1 或 2)。

  • pull (int) – 上拉/下拉配置。使用 BusChainUnit.GPIO_PULL_UP (0)、BusChainUnit.GPIO_PULL_DOWN (1) 或 BusChainUnit.GPIO_PULL_NONE (2)。

  • trigger_mode (int) – 触发模式。使用 BusChainUnit.GPIO_INTR_RISING (0)、BusChainUnit.GPIO_INTR_FALLING (1) 或 BusChainUnit.GPIO_INTR_ANYEDGE (2)。

返回:

如果操作成功则返回 True,否则返回 False。

返回类型:

bool

UiFlow2 代码块:

set_gpio_exit.png

MicroPython 代码块:

success = unit_chain_bus.set_gpio_exit(1, BusChainUnit.GPIO_PULL_UP, BusChainUnit.GPIO_INTR_RISING)
set_gpio_exit_callback(gpio_num, trigger_mode, callback)

设置 GPIO 外部中断回调。

参数:
  • gpio_num (int) – GPIO 编号(1 或 2)。

  • trigger_mode (int) – 触发模式。使用 BusChainUnit.GPIO_INTR_RISING (0) 表示上升沿,或 BusChainUnit.GPIO_INTR_FALLING (1) 表示下降沿。

  • callback – 回调函数。

返回类型:

None

UiFlow2 代码块:

set_gpio_exit_callback.png

MicroPython 代码块:

def gpio_exit_callback(args):
    print("GPIO external interrupt")

unit_chain_bus.set_gpio_exit_callback(1, BusChainUnit.GPIO_INTR_RISING, gpio_exit_callback)
set_adc(channel)

设置 ADC 通道。

参数:

channel (int) – ADC 通道编号(1 或 2),对应 GPIO1 或 GPIO2。

返回:

如果操作成功则返回 True,否则返回 False。

返回类型:

bool

UiFlow2 代码块:

set_adc.png

MicroPython 代码块:

success = unit_chain_bus.set_adc(1)
get_adc_input(channel)

读取 ADC 值。

参数:

channel (int) – ADC 通道编号(1 或 2)。

返回:

ADC 值(0-4095),如果失败则返回 None。

返回类型:

int | None

UiFlow2 代码块:

get_adc_input.png

MicroPython 代码块:

value = unit_chain_bus.get_adc_input(1)
set_i2c(speed=0)

设置 I2C 模式。

参数:

speed (int) – I2C 速度。使用 BusChainUnit.I2C_SPEED_100K (0) 或 BusChainUnit.I2C_SPEED_400K (1)。默认值:0。

返回:

如果操作成功则返回 True,否则返回 False。

返回类型:

bool

UiFlow2 代码块:

set_i2c.png

MicroPython 代码块:

success = unit_chain_bus.set_i2c(BusChainUnit.I2C_SPEED_400K)
readfrom(addr, nbytes, *args, **kwargs)

从 I2C 设备读取数据。

参数:
  • addr (int) – I2C 设备地址(7位)。

  • nbytes (int) – 要读取的字节数(最大64)。

  • stop (bool) – 生成停止条件(忽略,为兼容性保留)。

返回:

以字节形式返回读取的数据。

返回类型:

bytes

UiFlow2 代码块:

readfrom.png

MicroPython 代码块:

data = unit_chain_bus.readfrom(0x48, 4)
readfrom_into(addr, buf, *args, **kwargs)

从 I2C 设备读取数据到缓冲区。

参数:
  • addr (int) – I2C 设备地址(7位)。

  • buf (bytearray) – 要读取数据的缓冲区。

  • stop (bool) – 生成停止条件(忽略,为兼容性保留)。

返回类型:

None

UiFlow2 代码块:

readfrom_into.png

MicroPython 代码块:

buf = bytearray(4)
unit_chain_bus.readfrom_into(0x48, buf)
writeto(addr, buf, *args, **kwargs)

向 I2C 设备写入数据。

参数:
  • addr (int) – I2C 设备地址(7位)。

  • buf (bytes|bytearray) – 要写入的数据。

  • stop (bool) – 生成停止条件(忽略,为兼容性保留)。

返回:

写入的字节数。

返回类型:

int

UiFlow2 代码块:

writeto.png

MicroPython 代码块:

n = unit_chain_bus.writeto(0x48, b"")
readfrom_mem(addr, memaddr, nbytes, *args, **kwargs)

从 I2C 设备存储器(寄存器)读取数据。

参数:
  • addr (int) – I2C 设备地址(7位)。

  • memaddr (int) – 存储器/寄存器地址。

  • nbytes (int) – 要读取的字节数。

  • addrsize (int) – 寄存器地址大小(8 或 16 位)。默认值:8。

返回:

以字节形式返回读取的数据。

返回类型:

bytes

UiFlow2 代码块:

readfrom_mem.png

MicroPython 代码块:

data = unit_chain_bus.readfrom_mem(0x48, 0x00, 4)
readfrom_mem_into(addr, memaddr, buf, addrsize=8, *args, **kwargs)

从 I2C 设备存储器(寄存器)读取数据到缓冲区。

参数:
  • addr (int) – I2C 设备地址(7位)。

  • memaddr (int) – 存储器/寄存器地址。

  • buf (bytearray) – 要读取数据的缓冲区。

  • addrsize (int) – 寄存器地址大小(8 或 16 位)。默认值:8。

返回类型:

None

UiFlow2 代码块:

readfrom_mem_into.png

MicroPython 代码块:

buf = bytearray(4)
unit_chain_bus.readfrom_mem_into(0x48, 0x00, buf)
writeto_mem(addr, memaddr, buf, *args, **kwargs)

向 I2C 设备存储器(寄存器)写入数据。

参数:
  • addr (int) – I2C 设备地址(7位)。

  • memaddr (int) – 存储器/寄存器地址。

  • buf (bytes|bytearray) – 要写入的数据。

  • addrsize (int) – 寄存器地址大小(8 或 16 位)。默认值:8。

返回类型:

None

UiFlow2 代码块:

writeto_mem.png

MicroPython 代码块:

unit_chain_bus.writeto_mem(0x48, 0x00, b"")
scan(*args, **kwargs)

扫描 I2C 设备。

返回:

找到的 I2C 设备地址列表,如果失败则返回空列表。

返回类型:

list

UiFlow2 代码块:

scan.png

MicroPython 代码块:

devices = unit_chain_bus.scan()
for addr in devices:
    print("Found device at 0x{:02X}".format(addr))