micropython-samples/rp2/spi/spi_master.py

47 wiersze
1.6 KiB
Python
Czysty Zwykły widok Historia

2025-07-24 16:09:18 +00:00
# spi_mater.py A nonblocking SPI master for RP2040/RP2350
2025-07-13 12:11:09 +00:00
# Inspired by
# https://github.com/raspberrypi/pico-micropython-examples/blob/master/pio/pio_spi.py
# Released under the MIT License (MIT). See LICENSE.
# Copyright (c) 2025 Peter Hinch
2025-07-11 17:26:16 +00:00
2025-07-13 12:11:09 +00:00
import rp2
2025-07-11 17:26:16 +00:00
2025-07-12 17:04:29 +00:00
@rp2.asm_pio(autopull=True, pull_thresh=8, sideset_init=rp2.PIO.OUT_LOW, out_init=rp2.PIO.OUT_LOW)
2025-07-13 12:11:09 +00:00
def spi_out():
2025-07-11 17:26:16 +00:00
wrap_target()
2025-07-13 12:11:09 +00:00
set(x, 7).side(0x0)
2025-07-11 17:26:16 +00:00
label("bitloop")
2025-07-13 12:11:09 +00:00
out(pins, 1).side(0x0) # Stalls with CLK low while FIFO is empty
jmp(x_dec, "bitloop").side(0x1)
2025-07-11 17:26:16 +00:00
wrap()
2025-07-12 17:04:29 +00:00
# Get data request channel for a SM: RP2040 datasheet 2.5.3 RP2350 12.6.4.1
def dreq(sm, rx=False):
d = (sm & 3) + ((sm >> 2) << 3)
return 4 + d if rx else d
2025-07-13 12:11:09 +00:00
# The callback runs when DMA is complete. This may be up to four byte times prior to
# the SM running out of data (FIFO depth).
class SpiMaster:
2025-07-12 17:04:29 +00:00
def __init__(self, sm_num, freq, sck, mosi, callback):
self._sm_num = sm_num
self._dma = rp2.DMA()
self._dma.irq(handler=callback, hard=True) # Assign callback
dc = dreq(sm_num) # Data request channel
# Transfer bytes, don't increment the write address, irq at end, and pace the transfer.
self._ctrl = self._dma.pack_ctrl(size=0, inc_write=False, irq_quiet=False, treq_sel=dc)
2025-07-13 12:11:09 +00:00
f = 2 * freq # 2 clock cycles per bit
self._sm = rp2.StateMachine(sm_num, spi_out, freq=f, sideset_base=sck, out_base=mosi)
2025-07-12 17:04:29 +00:00
self._sm.active(1)
2025-07-13 12:11:09 +00:00
def deinit(self):
2025-07-12 17:04:29 +00:00
self._dma.active(0)
self._sm.active(0)
def write(self, data):
self._dma.config(read=data, write=self._sm, count=len(data), ctrl=self._ctrl, trigger=True)