跳转到主要内容

CircuitPython数据描述符类,用于表示I2C和SPI设备上的硬件寄存器。

项目描述

简介

Documentation Status Discord Build Status Code Style: Black

此库为Adafruit CircuitPython提供各种数据描述符类,使得编写基于I2C和SPI寄存器的设备驱动程序变得非常简单。数据描述符在外部表现如基本属性,这使得使用它们变得非常容易。

依赖项

此驱动程序依赖于

请确保所有依赖项都可在CircuitPython文件系统中使用。这可以通过下载Adafruit库和驱动程序包轻松实现。

从PyPI安装

在支持GNU/Linux系统(如Raspberry Pi)上,您可以从PyPI本地安装驱动程序(此处)。要为当前用户安装

pip3 install adafruit-circuitpython-register

全局安装(在某些情况下可能需要)

sudo pip3 install adafruit-circuitpython-register

在当前项目虚拟环境中安装

mkdir project-name && cd project-name
python3 -m venv .venv
source .venv/bin/activate
pip3 install adafruit-circuitpython-register

使用示例

创建驱动程序

使用寄存器库创建驱动程序非常简单。首先,从可用模块导入所需的register模块

from adafruit_register import i2c_bit
from adafruit_bus_device import i2c_device

接下来,定义位在设备内存映射中的位置

class HelloWorldDevice:
    """Device with two bits to control when the words 'hello' and 'world' are lit."""

    hello = i2c_bit.RWBit(0x0, 0x0)
    """Bit to indicate if hello is lit."""

    world = i2c_bit.RWBit(0x1, 0x0)
    """Bit to indicate if world is lit."""

最后,我们需要添加一个类型为I2CDevicei2c_device成员,它为我们管理I2C总线的共享。确保名称准确,否则寄存器将无法找到它。同时,确保i2c设备实现了busio.I2C接口。

def __init__(self, i2c, device_address=0x0):
    self.i2c_device = i2c_device.I2CDevice(i2c, device_address)

就是这样!现在我们有一个可以用来与这些寄存器通信的类

import busio
from board import *

with busio.I2C(SCL, SDA) as i2c:
    device = HelloWorldDevice(i2c)
    device.hello = True
    device.world = True

添加寄存器类型

添加新的寄存器类型稍微复杂一些,因为您需要小心并尽量减少类占用的内存量。如果不这样做,那么具有五个寄存器类型的驱动程序可能会占用五倍的额外内存。

首先,确定新的寄存器类是否应该放在现有模块中。如果有疑问,请选择新模块。模块越细粒度,驱动程序需要加载的额外类就越少。

以下是RWBit类的开始

class RWBit:
    """
    Single bit register that is readable and writeable.

    Values are `bool`

    :param int register_address: The register address to read the bit from
    :param type bit: The bit index within the byte at ``register_address``
    """
    def __init__(self, register_address, bit):
        self.bit_mask = 1 << bit
        self.buffer = bytearray(2)
        self.buffer[0] = register_address

首先做的事情是编写一个RST格式的类注释,说明寄存器类的功能以及寄存器布局的要求。它还记录了传递给构造函数(__init__)的参数,这些参数配置了寄存器在设备映射中的位置。它不包括设备地址或i2c对象,因为它们在设备类实例上是共享的。这样,如果您在同一个总线上有多个相同的设备,寄存器类将共享。

__init__中,我们只使用两个成员变量,因为每个变量都占用8个字节的内存加上值的内存。请记住,这会乘以驱动程序中此类型寄存器的数量!这就是为什么我们将寄存器地址和数据字节打包到一个bytearray中。我们可以使用两个大小为1的字节array,但每个MicroPython对象至少占用16个字节,因为存在垃圾回收器。因此,通过共享bytearray,我们将内存保持在16字节的最小值,而不是32字节。每个memoryview也至少占用16个字节,所以我们避免使用它们。

我们还可以在需要时仅分配bytearray。这种做法的优点是初始占用的内存较少,但缺点是每次访问时都会分配它,并冒着失败的风险。如果您想添加一个名为Foo的版本,该版本延迟分配底层缓冲区,请将其称为FooLazy

好了,继续前进。为了创建数据描述符,我们必须实现__get____set__

def __get__(self, obj, objtype=None):
    with obj.i2c_device as i2c:
        i2c.write_then_readinto(self.buffer, self.buffer, out_end=1, in_start=1)
    return bool(self.buffer[1] & self.bit_mask)

def __set__(self, obj, value):
    with obj.i2c_device as i2c:
        i2c.write_then_readinto(self.buffer, self.buffer, out_end=1, in_start=1)
        if value:
            self.buffer[1] |= self.bit_mask
        else:
            self.buffer[1] &= ~self.bit_mask
        obj.i2c_device.write(self.buffer)

如您所见,我们有两个地方可以从中获取状态。首先,self存储了寄存器类的成员,它们位于设备内存映射中。其次,obj是使用寄存器类的驱动程序类,它必须定义为提供I2CDevice兼容对象作为i2c_device。此对象为我们做了两件事

  1. 等待公交车空闲,使用时锁定它,使用后释放。

  2. 保存设备地址和其他设置,以便我们不必重复操作。

注意,我们充分利用了 i2c 函数的 startend 参数来切割缓冲区,而不实际分配任何额外的资源。它们的功能就像 self.buffer[start:end] 而不进行额外的分配。

就这样!现在您可以使用您的新寄存器类,就像上面的例子一样。只需记住,将成员数量保持在最低限度,因为该类可能会被多次使用。

文档

此库的 API 文档可在 Read the Docs 上找到。

有关构建库文档的信息,请参阅 此指南

贡献

欢迎贡献!请在贡献之前阅读我们的 行为准则,以帮助本项目保持友好。

项目详情


下载文件

下载适用于您平台的应用程序。如果您不确定要选择哪一个,请了解有关 安装包 的更多信息。

源代码分发

adafruit_circuitpython_register-1.10.0.tar.gz (32.7 kB 查看哈希值)

上传时间 源代码

构建分发

adafruit_circuitpython_register-1.10.0-py3-none-any.whl (15.0 kB 查看哈希值)

上传时间 Python 3

由以下组织支持

AWS AWS 云计算和安全赞助商 Datadog Datadog 监控 Fastly Fastly CDN Google Google 下载分析 Microsoft Microsoft PSF 赞助商 Pingdom Pingdom 监控 Sentry Sentry 错误日志 StatusPage StatusPage 状态页面