树莓派pico入坑笔记,SPI使用

 关于树莓派pico和circuitpython的更多玩法,请看树莓派pico专栏

uart使用见这篇文章

调用circuitpy的busio模块来使用,除此以外,uart、iic等要需要使用该模块,使用方法见及详细信息见这篇文章

收发数据的格式是字节数组bytearray,该类型要求数据不可变,因此如果要修改,需要额外新建,然后将其转换为字节数组。

然后是注意bytearray方法,它要求输入参数是可迭代对象,建议使用列表。

代码

import busio
from board import *
import sys

# 初始化 SPI 时捕获异常
try:
    spi = busio.SPI(clock=GP10, MOSI=GP11, MISO=GP12)
    print("SPI initialized successfully.")
except Exception as e:
    print(f"Failed to initialize SPI: {e}")
    sys.exit(1)  # 使用 sys.exit() 退出程序

# 尝试获取 SPI 锁
if spi.try_lock():
    print("SPI lock acquired successfully.")
else:
    print("Failed to acquire SPI lock. Exiting.")
    spi.deinit()  # 释放 SPI 资源
    sys.exit(1)

try:
    # 配置 SPI 参数(根据实际需求调整波特率等参数)
    spi.configure(baudrate=1000000)

    # 发送数据
    data_to_send = b"hello"
    print(f"Sending data: {data_to_send}")
    

    # 接收数据(假设从设备返回相同长度的数据)
    buffer = bytearray(len(data_to_send))
    spi.write_readinto(data_to_send,buffer)
    print(f"Received data: {buffer}")

finally:
    # 释放锁并反初始化 SPI
    spi.unlock()
    spi.deinit()
    print("SPI lock released and SPI deinitialized.")

初始化和释放

在初始化时,使用busio.SPI()方法创建SPI对象,参数列表为时钟、MOSI、MISO、半双工,可以参考引脚图选择功能引脚。支持3-4 线串行协议,最少提供时钟和发送引脚。

class busio.SPI(clock: microcontroller.PinMOSI: microcontroller.Pin | None = NoneMISO: microcontroller.Pin | None = Nonehalf_duplex: bool = False)

half_duplex 仅在 STM 上可用;其他芯片没有硬件支持。

deinit()→ None
关闭释放 SPI 总线,引脚可以用于其他功能

持有锁和释放锁

在spi和i2c通信时,需要获取锁来保证通信不受干扰和打断

try_lock()→ bool
  

尝试获取 SPI 锁,成功时返回 True。

unlock()→ None
释放 SPI 锁。

在进行设置以及通信时需要获取锁,并在用完后释放

发送和接收

只限于作为主设备的情况,circuitpython以及micropython对于spi从设备没有提供支持,但是你可以通过pio功能来实现从机功能

write(buffer: circuitpython_typing.ReadableBuffer*start: int = 0end: int = sys.maxsize)→ None

写入 buffer 中的数据。SPI 对象必须被锁定。如果缓冲区为空,则不执行任何操作。
如果提供了 start 或 end ,则缓冲区将按 buffer[start:end] 传递的方式被切片,但不会复制数据。写入的字节数将是 buffer[start:end] 的长度。

参数:

  • buffer (ReadableBuffer
     从此缓冲区写入字节

  • start (int)
    缓冲区切片的起始位置

  • end (int
    缓冲区切片的末尾;如果未指定,则使用 len(buffer)

readinto(buffer: circuitpython_typing.WriteableBuffer*start: int = 0end: int = sys.maxsizewrite_value: int = 0)→ None

读取 buffer ,同时为每个读取的字节写入 write_value 。SPI 对象必须被锁定。如果要读取的字节数为 0,则不执行任何操作。
如果提供了 start 或 end ,则缓冲区将按如果传递了 buffer[start:end] 的方式被切片。读取的字节数将是 buffer[start:end] 的长度。

参数:

  • buffer (WriteableBuffer)
     将字节读入此缓冲区

  • start (int)
     缓冲区切片的起始位置

  • end (int
    缓冲区切片的末尾;如果未指定,则等同于 len(buffer) 的值,对于任何提供的值,它将取 min(end, len(buffer)) 的值

  • write_value (int
    读取时写入的值

write_readinto(out_buffer: circuitpython_typing.ReadableBufferin_buffer: circuitpython_typing.WriteableBuffer*out_start: int = 0out_end: int = sys.maxsizein_start: int = 0in_end: int = sys.maxsize)→ None

同时将数据写入 out_buffer ,并从 in_buffer 读取数据。SPI 对象必须被锁定。
如果提供了 out_start 或 out_end ,则缓冲区将按 out_buffer[out_start:out_end] 传递的方式被切片,但不会复制数据。写入的字节数将是 out_buffer[out_start:out_end] 的长度。
如果提供了 in_start 或 in_end ,则输入缓冲区将按 in_buffer[in_start:in_end] 传递的方式被切片,读取的字节数将是 out_buffer[in_start:in_end] 的长度。
切片的长度必须由 out_buffer[out_start:out_end] 和 in_buffer[in_start:in_end] 定义相等。如果缓冲区切片长度都为 0,则不执行任何操作。

参数:

  • out_buffer (ReadableBuffer)
    从此缓冲区写入字节数据

  • in_buffer (WriteableBuffer
    将字节读入此缓冲区

  • out_start (int
     out_buffer 切片的起始位置

  • out_end (int)
     out_buffer 切片的结束;如未指定,则使用 len(out_buffer)

  • in_start (int)
    in_buffer 切片的起始位置

  • in_end (None
    结束位置 in_buffer slice ; 如果未指定,使用 len(in_buffer)

这里写入和读取都是通过发送数据实现,也就是说,把发送和接收引脚短接进行实验时,使用write和readinto都是不能看到实验现象的,这和spi通信的特点有关,在读取接收的数据时,是写入数据发送,这样就可以接收到从机发送的数据,所以是读取的从机还没有发送的数据,而使用write_readinto就可以看到通信实验现象,因为它同时进行写入和读取操作。

 

posted @ 2025-01-22 10:51  CV小能手chh  阅读(8)  评论(0)    收藏  举报  来源