CircuitPython数据描述符类,用于表示I2C和SPI设备上的硬件寄存器。
项目描述
简介
此库为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."""
最后,我们需要添加一个类型为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。此对象为我们做了两件事
等待公交车空闲,使用时锁定它,使用后释放。
保存设备地址和其他设置,以便我们不必重复操作。
注意,我们充分利用了 i2c 函数的 start 和 end 参数来切割缓冲区,而不实际分配任何额外的资源。它们的功能就像 self.buffer[start:end] 而不进行额外的分配。
就这样!现在您可以使用您的新寄存器类,就像上面的例子一样。只需记住,将成员数量保持在最低限度,因为该类可能会被多次使用。
文档
此库的 API 文档可在 Read the Docs 上找到。
有关构建库文档的信息,请参阅 此指南。
贡献
欢迎贡献!请在贡献之前阅读我们的 行为准则,以帮助本项目保持友好。
项目详情
哈希值 for adafruit_circuitpython_register-1.10.0.tar.gz
算法 | 哈希摘要 | |
---|---|---|
SHA256 | bc7eb5f757766f102a8726573e0ca5c29ea1d7e501c1e3759c6c4e9e13660f7a |
|
MD5 | 01cde723ec87ec594c7768b2a72c4718 |
|
BLAKE2b-256 | 0ff1b7e16545dac1056227ca9c612966ec26d69a04a99df6892aec27a71884af |
哈希值 for adafruit_circuitpython_register-1.10.0-py3-none-any.whl
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 83073b873dbcb8f2dc3dc3648fcca518a8dbf820de1864422eb3aab015c0ae14 |
|
MD5 | 648eae7c89fb431b2a54ddd9a939a01d |
|
BLAKE2b-256 | 20a7e0e08a2605e00b054b5071115c03cb4138cc977401a909cc94f829200f28 |