跳转到主要内容

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

项目描述

简介

Documentation Status Discord Build Status Code Style: Black

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

依赖项

此驱动程序依赖于

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

从PyPI安装

在支持的GNU/Linux系统(如树莓派)上,您可以从PyPI本地安装驱动程序。为当前用户安装

pip3 install adafruit-circuitpython-register-spi

为系统范围安装(在某些情况下可能需要)

sudo pip3 install adafruit-circuitpython-register-spi

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

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

使用Circup在连接的CircuitPython设备上安装

请确保您已将circup安装到Python环境中。如有必要,使用以下命令安装

pip3 install circup

安装circup后,您的CircuitPython设备连接后,使用以下命令安装

circup install register_spi

或以下命令更新现有版本

circup update

使用示例

创建驱动程序

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

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."""

最后,我们需要添加一个I2CDevice类型的i2c_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函数的start和end参数来切片缓冲区,而不实际分配任何额外内容。它们的功能就像self.buffer[start:end]一样,但没有额外的分配。

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

文档

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

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

贡献

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

项目详情


下载文件

下载适用于您的平台的文件。如果您不确定选择哪个,请了解更多关于安装包的信息。

源分布

adafruit-circuitpython-register-spi-1.0.1.tar.gz (28.1 kB 查看哈希)

上传时间:

构建分布

adafruit_circuitpython_register_spi-1.0.1-py3-none-any.whl (8.1 kB 查看哈希)

上传时间: Python 3

由以下支持