import operator
# -*- coding: utf-8 -*-
import time
import time
try:
import RPi.GPIO as GPIO
except RuntimeError:
print(
"Error importing RPi.GPIO! This is probably because you need superuser privileges. "
"You can achieve this by using 'sudo' to run your script")
MSBFIRST = 0
LSBFIRST = 1
class BitBang(object):
def __init__(self, gpio, sclk, mosi=None, miso=None, ss=None):
self._gpio = gpio
self._sclk = sclk
self._mosi = mosi
self._miso = miso
self._ss = ss
# Set pins as outputs/inputs.
GPIO.setmode(GPIO.BCM)
gpio.setup(sclk, GPIO.OUT)
gpio.setup(mosi, GPIO.OUT)
gpio.setup(miso, GPIO.IN)
gpio.setup(ss, GPIO.OUT)
GPIO.output(ss, GPIO.HIGH)
self.set_mode(1)
# Assume most significant bit first order.
self.set_bit_order(MSBFIRST)
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.
start = time.clock()
if assert_ss and self._ss is not None:
# self._gpio.set_low(self._ss)
GPIO.output(self._ss, GPIO.LOW)
for byte in data:
for i in range(8):
# time.sleep(0.001)
# Write bit to MOSI.
if self._write_shift(byte, i) & self._mask:
# self._gpio.set_high(self._mosi)
GPIO.output(self._mosi, GPIO.HIGH)
else:
# print(i)
# self._gpio.set_low(self._mosi)
GPIO.output(self._mosi, GPIO.LOW)
# Flip clock off base.
self._gpio.output(self._sclk, not self._clock_base)
# time.sleep(0.0000001)
self._gpio.output(self._sclk, self._clock_base)
# time.sleep(0.001)
if deassert_ss and self._ss is not None:
# time.sleep(0.0000001)
# self._gpio.set_high(self._ss)
GPIO.output(self._ss, GPIO.HIGH)
# print('dss')
# time.sleep(0.001)
# print('time',time.clock()-start)
# 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
self.spi = simulation_spi.BitBang(GPIO, DAC_SCLK, DAC_MOSI, DAC_MISO, DAC_SS)
self.spi.write([self.CHAN[channel], data >> 8, data & 0xff])
SPI 4种模式