python模拟SPI
来源:互联网 发布:js slibings 编辑:程序博客网 时间:2024/06/08 13:12
SPI是串行外设接口(Serial Peripheral Interface)的缩写I,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,如今越来越多的芯片集成了这种通信协议。
下面给个用python写的软件模拟SPI通信程序。程序如下:
import operator
import time
MSBFIRST = 0
LSBFIRST = 1
class BitBang(object):
"""在GPIO口上用软件模拟实现SPI通信协议"""
def __init__(self, gpio, sclk, mosi=None, miso=None, ss=None):
"""初始化基于软件的SPI。需要提供一个关于GPIO的基类,一个SPI时钟以及可以选择的MOSI,MISO和SS(片选)。"""
self._gpio = gpio
self._sclk = sclk
self._mosi = mosi
self._miso = miso
self._ss = ss
# Set pins as outputs/inputs.
gpio.setup(sclk, GPIO.OUT)
if mosi is not None:
gpio.setup(mosi, GPIO.OUT)
if miso is not None:
gpio.setup(miso, GPIO.IN)
if ss is not None:
gpio.setup(ss, GPIO.OUT)
# Assert SS high to start with device communication off.
gpio.set_high(ss)
# Assume mode 0.
self.set_mode(0)
# Assume most significant bit first order.
self.set_bit_order(MSBFIRST)
#SPI通信中的四种模式,一般情况下使用模式0(时钟线先拉低,当时钟线上升沿到来时,输入输出数据)
def set_mode(self, mode):
"""Set SPI mode which controls clock polarity and phase. Should be a
numeric value 0, 1, 2, or 3. See wikipedia page for details on meaning:
http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus
"""
if mode < 0 or mode > 3:
raise ValueError('Mode must be a value 0, 1, 2, or 3.')
if mode & 0x02:
# Clock is normally high in mode 2 and 3.
self._clock_base = GPIO.HIGH
else:
# Clock is normally low in mode 0 and 1.
self._clock_base = GPIO.LOW
if mode & 0x01:
# Read on trailing edge in mode 1 and 3.
self._read_leading = False
else:
# Read on leading edge in mode 0 and 2.
self._read_leading = True
# Put clock into its base state.
self._gpio.output(self._sclk, self._clock_base)
def set_bit_order(self, order):
"""Set order of bits to be read/written over serial lines. Should be
either MSBFIRST for most-significant first, or LSBFIRST for
least-signifcant first.
"""
# Set self._mask to the bitmask which points at the appropriate bit to
# read or write, and appropriate left/right shift operator function for
# reading/writing.
if order == MSBFIRST:
self._mask = 0x80
self._write_shift = operator.lshift
self._read_shift = operator.rshift
elif order == LSBFIRST:
self._mask = 0x01
self._write_shift = operator.rshift
self._read_shift = operator.lshift
else:
raise ValueError('Order must be MSBFIRST or LSBFIRST.')
def close(self):
"""Close the SPI connection. Unused in the bit bang implementation."""
pass
#半双工写,主机只往从机写数据,不接收数据
def write(self, data, assert_ss=True, deassert_ss=True):
"""Half-duplex SPI write. If assert_ss is True, the SS line will be
asserted low, the specified bytes will be clocked out the MOSI line, and
if deassert_ss is True the SS line be put back high.
"""
# Fail MOSI is not specified.
if self._mosi is None:
raise RuntimeError('Write attempted with no MOSI pin specified.')
if assert_ss and self._ss is not None:
self._gpio.set_low(self._ss)
for byte in data:
for i in range(8):
# Write bit to MOSI.
if self._write_shift(byte, i) & self._mask:
self._gpio.set_high(self._mosi)
else:
self._gpio.set_low(self._mosi)
# Flip clock off base.
self._gpio.output(self._sclk, not self._clock_base)
# Return clock to base.
self._gpio.output(self._sclk, self._clock_base)
if deassert_ss and self._ss is not None:
self._gpio.set_high(self._ss)
def read(self, length, assert_ss=True, deassert_ss=True):
"""Half-duplex SPI read. If assert_ss is true, the SS line will be
asserted low, the specified length of bytes will be clocked in the MISO
line, and if deassert_ss is true the SS line will be put back high.
Bytes which are read will be returned as a bytearray object.
"""
if self._miso is None:
raise RuntimeError('Read attempted with no MISO pin specified.')
if assert_ss and self._ss is not None:
self._gpio.set_low(self._ss)
result = bytearray(length)
for i in range(length):
for j in range(8):
# Flip clock off base.
self._gpio.output(self._sclk, not self._clock_base)
# Handle read on leading edge of clock.
if self._read_leading:
if self._gpio.is_high(self._miso):
# Set bit to 1 at appropriate location.
result[i] |= self._read_shift(self._mask, j)
else:
# Set bit to 0 at appropriate location.
result[i] &= ~self._read_shift(self._mask, j)
# Return clock to base.
self._gpio.output(self._sclk, self._clock_base)
# Handle read on trailing edge of clock.
if not self._read_leading:
if self._gpio.is_high(self._miso):
# Set bit to 1 at appropriate location.
result[i] |= self._read_shift(self._mask, j)
else:
# Set bit to 0 at appropriate location.
result[i] &= ~self._read_shift(self._mask, j)
if deassert_ss and self._ss is not None:
self._gpio.set_high(self._ss)
return result
#全双工读写数据
def transfer(self, data, assert_ss=True, deassert_ss=True):
"""Full-duplex SPI read and write. If assert_ss is true, the SS line
will be asserted low, the specified bytes will be clocked out the MOSI
line while bytes will also be read from the MISO line, and if
deassert_ss is true the SS line will be put back high. Bytes which are
read will be returned as a bytearray object.
"""
if self._mosi is None:
raise RuntimeError('Write attempted with no MOSI pin specified.')
if self._mosi is None:
raise RuntimeError('Read attempted with no MISO pin specified.')
if assert_ss and self._ss is not None:
self._gpio.set_low(self._ss)
result = bytearray(len(data))
for i in range(len(data)):
for j in range(8):
# Write bit to MOSI.
if self._write_shift(data[i], j) & self._mask:
self._gpio.set_high(self._mosi)
else:
self._gpio.set_low(self._mosi)
# Flip clock off base.
self._gpio.output(self._sclk, not self._clock_base)
# Handle read on leading edge of clock.
if self._read_leading:
if self._gpio.is_high(self._miso):
# Set bit to 1 at appropriate location.
result[i] |= self._read_shift(self._mask, j)
else:
# Set bit to 0 at appropriate location.
result[i] &= ~self._read_shift(self._mask, j)
# Return clock to base.
self._gpio.output(self._sclk, self._clock_base)
# Handle read on trailing edge of clock.
if not self._read_leading:
if self._gpio.is_high(self._miso):
# Set bit to 1 at appropriate location.
result[i] |= self._read_shift(self._mask, j)
else:
# Set bit to 0 at appropriate location.
result[i] &= ~self._read_shift(self._mask, j)
if deassert_ss and self._ss is not None:
self._gpio.set_high(self._ss)
return result
- python模拟SPI
- SPI模拟:
- 模拟SPI
- GPIO模拟SPI
- GPIO模拟SPI
- SPI的模拟驱动
- IO口模拟SPI
- 单片机 模拟SPI程序
- GPIO口模拟SPI
- GPIO模拟SPI
- C51 模拟spi协议
- IO口模拟SPI
- STM32模拟SPI接口
- 总结GPIO模拟SPI
- GPIO模拟SPI
- DM642 模拟SPI通信
- IO 模拟 SPI协议
- MCU GPIO模拟spi
- vim编辑器---批量注释与反注释
- 浅析Java线程的正确停止
- 写了一个ios缓存模块,非常方便好用,欢迎使用~
- 如何查看JDK以及JAVA框架的源码
- Android自定义属性详解
- python模拟SPI
- iOS笔记:第十篇 OC 内存管理
- 递归算法的时间复杂度终结篇
- 3.1 2
- LUA 学习1
- 贪心算法之——过河问题(nyoj47)
- 你可能不知道的一些JavaScript 奇技淫巧
- 第六周项目6-2:复数模版类
- Kakuro Extension (hdu 3338 最大流 建图难)