from pyb import SPI spi = SPI(1) print(spi) spi = SPI(1, SPI.MASTER) spi = SPI(1, SPI.MASTER, baudrate=500000) spi = SPI(1, SPI.MASTER, 500000, polarity=1, phase=0, bits=8, firstbit=SPI.MSB, ti=False, crc=None) print(spi) spi.init(SPI.SLAVE, phase=1) print(spi) spi.init(SPI.MASTER) spi.send(1, timeout=100) print(spi.recv(1, timeout=100)) print(spi.send_recv(1, timeout=100))
class LIS302DL: def __init__(self): self.cs_pin = Pin('PE3', Pin.OUT_PP, Pin.PULL_NONE) self.cs_pin.high() self.spi = SPI(1, SPI.MASTER, baudrate=328125, polarity=0, phase=1, bits=8) def rd(self, addr, nbytes): if nbytes > 1: addr |= READWRITE_CMD | MULTIPLEBYTE_CMD else: addr |= READWRITE_CMD self.cs_pin.low() self.spi.send(addr) buf = self.spi.send_recv(bytearray(nbytes * [0])) # read data, MSB first self.cs_pin.high() return buf def wr(self, addr, buf): if len(buf) > 1: addr |= MULTIPLEBYTE_CMD self.cs_pin.low() self.spi.send(addr) for b in buf: self.spi.send(b) self.cs_pin.high() def read_id(self): return self.rd(LIS302DL_WHO_AM_I_ADDR, 1) def init(self, init_param=0x47, filter_param=0x2D): self.wr(LIS302DL_CTRL_REG1_ADDR, bytearray([init_param])) self.wr(LIS302DL_CTRL_REG2_ADDR, bytearray([filter_param])) def getx(self): buf = (self.rd(0x29, 1)[0]) - 1 if buf > 127: return ((256 - buf) * (-1)) / 5.81 else: return buf / 5.81 def gety(self): buf = (self.rd(0x2B, 1)[0]) - 4 if buf > 127: return ((256 - buf) * (-1)) / 5.81 else: return buf / 5.81 def getz(self): buf = (self.rd(0x2D, 1)[0]) + 8 if buf > 127: return ((256 - buf) * (-1)) / 5.81 else: return buf / 5.81
class STAccel: def __init__(self): self.cs_pin = Pin('PE3', Pin.OUT_PP, Pin.PULL_NONE) self.cs_pin.high() self.spi = SPI(1, SPI.MASTER, baudrate=328125, polarity=0, phase=1, bits=8) self.who_am_i = self.read_id() if self.who_am_i == LIS302DL_WHO_AM_I_VAL: self.write_bytes(LIS302DL_CTRL_REG1_ADDR, bytearray([LIS302DL_CONF])) self.sensitivity = 18 elif self.who_am_i == LIS3DSH_WHO_AM_I_VAL: self.write_bytes(LIS3DSH_CTRL_REG4_ADDR, bytearray([LIS3DSH_CTRL_REG4_CONF])) self.write_bytes(LIS3DSH_CTRL_REG5_ADDR, bytearray([LIS3DSH_CTRL_REG5_CONF])) self.sensitivity = 0.06 * 256 else: raise Exception('LIS302DL or LIS3DSH accelerometer not present') def convert_raw_to_g(self, x): if x & 0x80: x = x - 256 return x * self.sensitivity / 1000 def read_bytes(self, addr, nbytes): if nbytes > 1: addr |= READWRITE_CMD | MULTIPLEBYTE_CMD else: addr |= READWRITE_CMD self.cs_pin.low() self.spi.send(addr) #buf = self.spi.send_recv(bytearray(nbytes * [0])) # read data, MSB first buf = self.spi.recv(nbytes) self.cs_pin.high() return buf def write_bytes(self, addr, buf): if len(buf) > 1: addr |= MULTIPLEBYTE_CMD self.cs_pin.low() self.spi.send(addr) for b in buf: self.spi.send(b) self.cs_pin.high() def read_id(self): return self.read_bytes(WHO_AM_I_ADDR, 1)[0] def x(self): return self.convert_raw_to_g(self.read_bytes(OUT_X_ADDR, 1)[0]) def y(self): return self.convert_raw_to_g(self.read_bytes(OUT_Y_ADDR, 1)[0]) def z(self): return self.convert_raw_to_g(self.read_bytes(OUT_Z_ADDR, 1)[0]) def xyz(self): return (self.x(), self.y(), self.z())
class L3GD20: def __init__(self): self.csPin = Pin('PE3', Pin.OUT_PP, Pin.PULL_NONE) self.csPin.high() self.spi = SPI(1, SPI.MASTER, baudrate=328125, polarity=0, phase=1, bits=8) def read(self, address, nbytes): if nbytes > 1: address |= READWRITE_CMD | MULTIPLEBYTE_CMD else: address |= READWRITE_CMD self.csPin.low() self.spi.send(address) buf = self.spi.send_recv(bytearray(nbytes * [0])) # read data, MSB first self.csPin.high() return buf def write(self, address, buf): if len(buf) > 1: address |= MULTIPLEBYTE_CMD self.csPin.low() self.spi.send(address) for b in buf: self.spi.send(b) self.csPin.high() def readID(self): return (self.read(L3GD20_WHO_AM_I_ADDR, 1)[0]) def initGyro(self, reg1Param = 0x3F, reg2Param = 0x00, reg4Param = 0x10): self.write(L3GD20_CTRL_REG1_ADDR, bytearray([reg1Param])) self.write(L3GD20_CTRL_REG2_ADDR, bytearray([reg2Param])) self.write(L3GD20_CTRL_REG4_ADDR, bytearray([reg4Param])) def getXGyro(self): buf = (self.read(L3GD20_OUT_X_L_ADDR,2)) num = buf[1] << 8 | buf[0] return (s16(num)*17.50*0.001) def getYGyro(self): buf = (self.read(L3GD20_OUT_Y_L_ADDR,2)) num = buf[1] << 8 | buf[0] return (s16(num)*17.50*0.001) def getZGyro(self): buf = (self.read(L3GD20_OUT_Z_L_ADDR,2)) num = buf[1] << 8 | buf[0] return (s16(num)*17.50*0.001) def getTempGyro(self): buf = (self.read(L3GD20_OUT_TEMP_ADDR,1)[0]) return s16(buf)
class STAccel: def __init__(self): self.cs_pin = Pin('PE3', Pin.OUT_PP, Pin.PULL_NONE) self.cs_pin.high() self.spi = SPI(1, SPI.MASTER, baudrate=328125, polarity=0, phase=1, bits=8) self.write_bytes(LIS302DL_CTRL_REG1_ADDR, bytearray([LIS302DL_CONF])) if self.read_id() != LIS302DL_WHO_AM_I_VAL: raise Exception('LIS302DL accelerometer not present') def read_bytes(self, addr, nbytes): if nbytes > 1: addr |= READWRITE_CMD | MULTIPLEBYTE_CMD else: addr |= READWRITE_CMD self.cs_pin.low() self.spi.send(addr) #buf = self.spi.send_recv(bytearray(nbytes * [0])) # read data, MSB first buf = self.spi.recv(nbytes) self.cs_pin.high() return buf def write_bytes(self, addr, buf): if len(buf) > 1: addr |= MULTIPLEBYTE_CMD self.cs_pin.low() self.spi.send(addr) for b in buf: self.spi.send(b) self.cs_pin.high() def read_id(self): return self.read_bytes(LIS302DL_WHO_AM_I_ADDR, 1)[0] def x(self): return convert_raw_to_g(self.read_bytes(LIS302DL_OUT_X, 1)[0]) def y(self): return convert_raw_to_g(self.read_bytes(LIS302DL_OUT_Y, 1)[0]) def z(self): return convert_raw_to_g(self.read_bytes(LIS302DL_OUT_Z, 1)[0]) def xyz(self): val = self.read_bytes(LIS302DL_OUT_X, 5) return [convert_raw_to_g(val[0]), convert_raw_to_g(val[2]), convert_raw_to_g(val[4])]
class STAccel: def __init__(self): self.cs_pin = Pin('PE3', Pin.OUT_PP, Pin.PULL_NONE) self.cs_pin.high() self.spi = SPI(1, SPI.MASTER, baudrate=328125, polarity=0, phase=1, bits=8) self.wr(LIS302DL_CTRL_REG1_ADDR, bytearray([LIS302DL_CONF])) def rd(self, addr, nbytes): if nbytes > 1: addr |= READWRITE_CMD | MULTIPLEBYTE_CMD else: addr |= READWRITE_CMD self.cs_pin.low() self.spi.send(addr) buf = self.spi.send_recv(bytearray(nbytes * [0])) # read data, MSB first self.cs_pin.high() return buf def wr(self, addr, buf): if len(buf) > 1: addr |= MULTIPLEBYTE_CMD self.cs_pin.low() self.spi.send(addr) for b in buf: self.spi.send(b) self.cs_pin.high() def read_id(self): return self.rd(LIS302DL_WHO_AM_I_ADDR, 1) def get_xyz(self): val = self.rd(LIS302DL_OUT_X, 5) x = signed8(val[0]) * 18.0 / 1000 y = signed8(val[2]) * 18.0 / 1000 z = signed8(val[4]) * 18.0 / 1000 return [x, y, z]
# ADC/DAC from pyb import Pin, ADC adc = ADC(Pin('X19')) adc.read() # read value, 0-4095 from pyb import Pin, DAC dac = DAC(Pin('X5')) dac.write(120) # output between 0 and 255 # SPI from pyb import SPI spi = SPI(1, SPI.MASTER, baudrate=200000, polarity=1, phase=0) spi.send('hello') spi.recv(5) # receive 5 bytes on the bus spi.send_recv('hello') # send a receive 5 bytes # I2C from pyb import I2C i2c = I2C(1, I2C.MASTER, baudrate=100000) i2c.scan() # returns list of slave addresses i2c.send('hello', 0x42) # send 5 bytes to slave with address 0x42 i2c.recv(5, 0x42) # receive 5 bytes from slave i2c.mem_read(2, 0x42, 0x10) # read 2 bytes from slave 0x42, slave memory 0x10 i2c.mem_write('xy', 0x42, 0x10) # write 2 bytes to slave 0x42, slave memory 0x10 ''' To enter safe mode, do the following steps:
class SPIMgr(): """ This class provides an interface to the hardware level SPI object which it encapsulates as a member. When creating an instance you must provide the pyboard side and the latch pin's name, eg. >>> from spiMgr import SPIMgr >>> from state import State >>> s = SPIMgr(State.spiOnX,State.spiLatchPinName) >>> print(s) SPIMgr: SPI: BoardSide: 1 MasterOrSlave: Master STCP: Pin: LatchPin: X5 PinOut: OUT_PP Value: 0 ++ The class only provides one method: update(bitArray). This method is called with an array of ints representing the bits to be set to one via an SPI call. The process is 1. set the latch pin LOW 2. send the bits, int by int 3. set the latch pin to high Note that when doing Off-board tests, the 'send' message will appear twice. usage: >>> s.update([0,1,2,4,8,16]) Pin: LatchPin: X5 PinOut: OUT_PP Value: 0 set: LOW Simulated: send: 0b0 send: 0b0 Simulated: send: 0b1 send: 0b1 Simulated: send: 0b10 send: 0b10 Simulated: send: 0b100 send: 0b100 Simulated: send: 0b1000 send: 0b1000 Simulated: send: 0b10000 send: 0b10000 Pin: LatchPin: X5 PinOut: OUT_PP Value: 1 set: HIGH """ def __init__(self,spiOnX,latchPin): # create an SPI.MASTER instance on the 'X' side of the board, # first arg=1 means 'X side' of the board boardSide = 1 if not spiOnX: boardSide = 2 self.spi = SPI(boardSide,SPI.MASTER) # create the stcp pin on the "latch" pin self.stcp = Pin(latchPin, Pin.OUT_PP) def update(self,bitArray): # send the data bits to the shift register # unset the latch self.stcp.low() # send the bits i=0 # remove for production for r in bitArray: self.spi.send(r) #### COMMENT NEXT LINE FOR Off-Board TESTS! #State.printT('send reg:\t' + str(i)+ '\t{0:08b}'.format(r)) i += 1 # remove for production # turn on the latch self.stcp.high() def __repr__(self): return 'SPIMgr:' + \ '\n' + str(self.spi) + \ '\nSTCP:\n' + str(self.stcp)
class SharpMemLCD: ''' MicroPython driver to write to Sharp's Memory LCD. Should works with any standard pyboard Uses the built-in framebuffer class to format the buffer Custom parameters (display pin, cs pin, screen's x and y dimensions, SPI channel) can be changed below ''' CS = "C4" DISP = "A7" XDIM = 144 YDIM = 168 CHANNEL = 2 BAUDRATE = 1100000 def __init__(self): # define pins self.spi = SPI(self.CHANNEL, SPI.MASTER, self.BAUDRATE, polarity=0, phase=0, firstbit=SPI.LSB) self.cs = Pin(self.CS, Pin.OUT_PP) self.set_cs(0) self.disp = Pin(self.DISP, Pin.OUT_PP) self.disp.value(1) # define structures, related info self._xdim = self.XDIM self._ydim = self.YDIM self.buffer = bytearray((self._xdim//8) * self._ydim) self.framebuffer = framebuf.FrameBuffer(self.buffer, self._xdim, self._ydim, framebuf.MONO_HMSB) self.vcom = 2 # begin by clearing screen self.clear_screen() @property def xdim(self): return self._xdim @property def ydim(self): return self._ydim def clear_buffer(self): self.framebuffer.fill(0) # format framebuffer with text, starting at the x,y coords # each character is an 8 by 8 pixel array # written on the next line def write(self, text, x, y): self.framebuffer.text(text, x, y) # draw horizontal line in the buffer def horizontal_line(self, x, y, length): self.framebuffer.hline(x, y, length, 1) # draw vertial line in the buffer def vertical_line(self, x, y, height): self.framebuffer.vline(x, y, height, 1) # draw empty rectangle in the buffer (i.e. just the outline) def empty_rectangle(self, x, y, width, height): self.framebuffer.rect(x, y, width, height, 1) def solid_rectangle(self, x, y, width, height): self.framebuffer.fill_rect(x, y, width, height, 1) def toggle_vcom(self): self.vcom ^= 2 # send lcd command to clear screen def clear_screen(self): self.set_cs(1) udelay(6) self.send(4 | self.vcom) self.send(0) udelay(2) self.set_cs(0) udelay(6) self.toggle_vcom() def set_cs(self, logic_level): self.cs.value(logic_level) def send(self, value): self.spi.send(value) # sync up screen with framebuffer contents # done by implementing the lcd command to write a single line, for every line in the buffer def sync(self): index = 0 for line in range(self._ydim): self.set_cs(1) udelay(6) # tsSCS self.send(1 | self.vcom) self.send(line+1) for j in range(self._xdim//8): self.send(self.buffer[index]) index += 1 self.send(0) udelay(2) # thSCS self.set_cs(0) udelay(6) # twSCSL
class SerialFlash25: """Class to communicate Serial Flash Memory 25xxxx series with.""" def __init__(self, name: str, size: int, page_size: int, addr_bytes_num: int, spi: int, cs: str, wp: str, block_size=None, sector_size=None, is_chip_erase=False, conn_chk: bool = False) -> None: self.name = name self.size = size self.sector_size = sector_size self.block_size = block_size self.page_size = page_size self.addr_bytes_num = addr_bytes_num self.cs = Pin(cs, Pin.OUT_PP) self.wp = Pin(wp, Pin.OUT_PP) self.spi = SPI(spi, SPI.MASTER, prescaler=128, polarity=0, phase=0) self.conn_chk = conn_chk self.is_chip_erase = is_chip_erase self._pages_count = size // page_size self._sectors_count = size // sector_size if sector_size is not None else None self._blocks_count = size // block_size if block_size is not None else None @_is_available() def read_id(self) -> str: """Read device JEDEC Id.""" self.cs.value(False) result = bytearray(4) self.spi.send_recv(bytearray([CMD_RDID] + [DUMMY_BYTE] * 3), result) # Id always contains 3 bytes self.cs.value(True) res_id = " ".join(["0x%02X" % x for x in result[1:]]) if res_id == "0x00 0x00 0x00": raise RuntimeError( "Either IC is connected incorrectly " "or it doesn't support Read ID (0x%02X) command." % CMD_RDID) return res_id def dump(self, path: str) -> None: """Dump all device contents to binary file.""" if self.conn_chk: self.read_id() if self.sector_size is not None: read_cnt, read_item_size = self._sectors_count, self.sector_size else: read_cnt, read_item_size = self._pages_count, self.page_size makedirs(dirname(path)) with open(path, 'wb') as f: for i in range(0, read_cnt): # dumping is implemented by sectors/pages # because it may be impossible to allocate buffer size of full flash buf = self.read(i * read_item_size, read_item_size) f.write(buf) del buf log.info("Dump finished. %s image -> %s" % (self.name, path)) def program(self, path: str): """Flash binary to device.""" if self.conn_chk: self.read_id() if not isfile(path): raise FileNotFoundError("File not found: '%s'" % path) filesize = getsize(path) if filesize != self.size: raise ValueError( "File size (0x%02X bytes) doesn't equal IC size (0x%02X bytes)" % (filesize, self.size)) self.chip_erase() with open(path, 'rb') as f: for i in range(0, self._pages_count): buf = bytearray(f.read(self.page_size)) self.page_program(i, buf) log.info("Program finished. %s image -> %s" % (path, self.name)) def chip_erase(self) -> None: """Erase chip.""" if self.is_chip_erase: self._wait_wip_reset() self._write_enable() self.cs.value(False) self.spi.send(bytearray([CMD_CE])) self.cs.value(True) self._write_disable() self._wait_wip_reset() else: for i in range(0, self._pages_count): self.page_program(i, bytearray([0xFF] * self.page_size)) log.info("Chip erase finished.") @_is_available("sector_size") def sector_program(self, sector_num: int, bytebuffer: bytearray) -> None: """Program sector with bytes in bytebuffer.""" bytebuffer_len = len(bytebuffer) if sector_num > self._sectors_count: raise ValueError( "Sector number (%d) is more than total sectors number (%d)." % (sector_num, self._sectors_count)) if bytebuffer_len > self.page_size: raise ValueError( "Bytebuffer length (%d) is more than sector size (%d)." % (len(bytebuffer), self.page_size)) self.sector_erase(sector_num) pages_count = bytebuffer_len // self.page_size remain_bytes = bytebuffer_len % self.page_size if remain_bytes != 0: log.warning("sector_program: Bytebuffer is not sector aligned.") start_page = sector_num * self.sector_size // self.page_size for i in range(0, pages_count): self.page_program( start_page + i, bytebuffer[self.page_size * i:self.page_size * (i + 1) + 1]) if remain_bytes != 0: self.page_program(start_page + pages_count, bytebuffer[self.page_size * pages_count:]) log.info('Sector %d program finished.' % sector_num) @_is_available("sector_size") def sector_erase(self, sector_num: int) -> None: """Erase specified sector.""" if sector_num > self._sectors_count: raise ValueError( "Sector number (%d) is more than total sectors number (%d)." % (sector_num, self._sectors_count)) addr = sector_num * self.sector_size self._wait_wip_reset() self._write_enable() self.cs.value(False) self.spi.send( bytearray([CMD_SE]) + addr.to_bytes(self.addr_bytes_num, "big")) self.cs.value(True) self._write_disable() self._wait_wip_reset() log.info("Sector %d erase finished." % sector_num) @_is_available("block_size") def block_erase(self, block_num: int) -> None: """Erase specified block.""" if block_num > self._blocks_count: raise ValueError( "Block number (%d) is more than total block number (%d)." % (block_num, self._blocks_count)) addr = block_num * self.sector_size self._wait_wip_reset() self._write_enable() self.cs.value(False) self.spi.send( bytearray([CMD_BE]) + addr.to_bytes(self.addr_bytes_num, "big")) self.cs.value(True) self._write_disable() self._wait_wip_reset() log.info("Block %d erase finished." % block_num) def read(self, offset: int, size: int) -> bytearray: """Read data from specified offset using specified size.""" if (offset > self.size) or (offset + size > self.size): raise ValueError( "Read data from 0x%02X-0x%02X is out of range. Max address is 0x%02X." % (offset, offset + size, self.size)) self.cs.value(False) self.spi.send( bytearray([CMD_READ]) + offset.to_bytes(self.addr_bytes_num, "big")) result = bytearray(size) self.spi.send_recv(bytearray([DUMMY_BYTE] * size), result) self.cs.value(True) log.info("Data read 0x%02X-0x%02X finished." % (offset, offset + size)) return result def page_program(self, page_num: int, bytebuffer: bytearray) -> None: """Program page with bytes in bytebuffer""" if page_num > self._pages_count: raise ValueError( "Page number (%d) is more than total pages number (%d)." % (page_num, self._pages_count)) if len(bytebuffer) > self.page_size: raise ValueError( "Bytebuffer length (%d) is more than page size (%d)." % (len(bytebuffer), self.page_size)) addr = page_num * self.page_size self._wait_wip_reset() self._write_enable() self.cs.value(False) self.spi.send( bytearray([CMD_PP]) + addr.to_bytes(self.addr_bytes_num, "big")) self.spi.send(bytebuffer) self.cs.value(True) self._write_disable() self._wait_wip_reset() log.info('Page %d program finished.' % page_num) def _wait_wip_reset(self) -> None: """Wait for WIP=0. WIP is bit0 in Status Register.""" sr = self.read_sr() while sr & SR_WIP: sr = self.read_sr() def _write_enable(self) -> None: """Enable Write operation via command.""" self.cs.value(False) self.spi.send(bytearray([CMD_WREN])) self.cs.value(True) def _write_disable(self) -> None: """Disable Write operation via command.""" self.cs.value(False) self.spi.send(bytearray([CMD_WRDI])) self.cs.value(True) def read_sr(self): """Read status register.""" result = bytearray(2) self.cs.value(False) self.spi.send_recv(bytearray([CMD_RDSR, DUMMY_BYTE]), result) self.cs.value(True) return result[1] def write_sr(self, sr_val: int) -> None: """Write status register.""" self._write_enable() self.cs.value(False) self.spi.send(bytearray([CMD_WRSR, sr_val & 0xFF])) self.cs.value(True) self._write_disable()
class STAccel: def __init__(self, cs='PE3', spi=1, debug=False): self._debug = debug self.cs_pin = Pin(cs, Pin.OUT_PP, Pin.PULL_NONE) self.cs_pin.high() self.spi = SPI(spi, SPI.MASTER, baudrate=328125, polarity=0, phase=1, bits=8) self.read_id() # First SPI read always returns 255 --> discard and read ID again self.who_am_i = self.read_id() self.debug("Accel-ID: %s" % self.who_am_i) if self.who_am_i == LIS302DL_WHO_AM_I_VAL: self.write_bytes(LIS302DL_CTRL_REG1_ADDR, LIS302DL_CONF) self.sensitivity = 18 elif self.who_am_i == LIS3DSH_WHO_AM_I_VAL: self.write_bytes(LIS3DSH_CTRL_REG4_ADDR, LIS3DSH_CTRL_REG4_CONF) self.write_bytes(LIS3DSH_CTRL_REG5_ADDR, LIS3DSH_CTRL_REG5_CONF) self.sensitivity = 0.06 * 256 else: msg = 'LIS302DL or LIS3DSH accelerometer not present' if self._debug: self.debug(msg) else: raise IOError(msg) def debug(self, *msg): if self._debug: print(" ".join(str(m) for m in msg)) def _convert_raw_to_g(self, x): if x & 0x80: x -= 256 return x * self.sensitivity / 1000 def read_bytes(self, addr, nbytes): self.cs_pin.low() if nbytes > 1: self.spi.send(addr | READWRITE_CMD | MULTIPLEBYTE_CMD) else: self.spi.send(addr | READWRITE_CMD) # read data, MSB first buf = self.spi.recv(nbytes) self.cs_pin.high() return buf def write_bytes(self, addr, buf): if not isinstance(buf, (int, bytes, bytearray)): buf = bytes(buf) if not isinstance(buf, int) and len(buf) > 1: addr |= MULTIPLEBYTE_CMD self.cs_pin.low() self.spi.send(addr) self.spi.send(buf) self.cs_pin.high() def read_id(self): return self.read_bytes(WHO_AM_I_ADDR, 1)[0] def x(self): return self._convert_raw_to_g(self.read_bytes(OUT_X_ADDR, 1)[0]) def y(self): return self._convert_raw_to_g(self.read_bytes(OUT_Y_ADDR, 1)[0]) def z(self): return self._convert_raw_to_g(self.read_bytes(OUT_Z_ADDR, 1)[0]) def xyz(self): return (self.x(), self.y(), self.z())
class SpiMaster: def __init__(self, bus=1, baudrate=328125, polarity=0, phase=0, ss='A4'): self.ss = Pin(ss, Pin.OUT) self.ss.high() self.spi = SPI(bus, SPI.MASTER, baudrate=baudrate, polarity=polarity, phase=phase) self.msgbuf = bytearray(32) self.status = bytearray(4) def write_status(self, status): self.ss.low() self.spi.send(0x01) self.spi.send(status & 0xFF) self.spi.send((status >> 8) & 0xFF) self.spi.send((status >> 16) & 0xFF) self.spi.send((status >> 24) & 0xFF) self.ss.high() def read_status(self): self.ss.low() self.spi.send(0x04) self.spi.recv(self.status) self.ss.high() return ( self.status[0] | (self.status[1] << 8) | (self.status[2] << 16) | (self.status[3] << 24) ) def read_data(self): self.ss.low() self.spi.send(0x03) self.spi.send(0x00) self.spi.recv(self.msgbuf) self.ss.high() return self.msgbuf def read_msg(self, encoding='utf-8'): return bytes(self.read_data()).strip('\0').decode(encoding) def write_data(self, data): self.msgbuf[:] = data[:32] + b'\0' * (32 - len(data[:32])) self.ss.low() self.spi.send(0x02) self.spi.send(0x00) self.spi.send(self.msgbuf) self.ss.high()
baud_rates = [328125, 656250, 1312500, 2625000, 5250000, 10500000, 21000000] spi = SPI(2, SPI.MASTER, baud_rates[0]) '''Since MISO is not connected, disable SPI for MISO by setting Pin as normal Pin input''' miso_dummy = Pin('Y7', Pin.IN) # May help prevent OS error 5 ? """ Test SPI with data similar to graphical TFT traffic; Slow for some baudrates (10.5 Mbits/s) """ print("\nGraphical type data (2048 bursts of 4 bytes):") for baud in baud_rates: spi.init(SPI.MASTER, baud) # Change baud rate start = micros() for a in range(128): for x in range(16): spi.send(bytearray([0, x, 0, a])) print_elapsed_time(baud, start, 2048, 4) """ Test SPI with generic data in ONE long buffer; Always(?) fast! """ print("\nGeneric data (8192 bytes pre-prepared as ONE long buffer):") for baud in baud_rates: spi.init(SPI.MASTER, baud) # Change baud rate data = bytearray([0, rng() & 0xFF, 0, rng() & 0xFF] * 2048) start = micros() spi.send(data) print_elapsed_time(baud, start, 1, 8192) """ Test SPI with generic data; Slow for some baudrate and data sizes """ for nr_bytes in range(1, 17): data = [0] * nr_bytes bursts = 8192 // nr_bytes
print(spi) spi = SPI(1, SPI.CONTROLLER) spi = SPI(1, SPI.CONTROLLER, baudrate=500000) spi = SPI(1, SPI.CONTROLLER, 500000, polarity=1, phase=0, bits=8, firstbit=SPI.MSB, ti=False, crc=None) print(str(spi)[:32], str(spi)[53:]) # don't print baudrate/prescaler spi.init(SPI.PERIPHERAL, phase=1) print(spi) try: # need to flush input before we get an error (error is what we want to test) for i in range(10): spi.recv(1, timeout=100) except OSError: print("OSError") spi.init(SPI.CONTROLLER) spi.send(1, timeout=100) print(spi.recv(1, timeout=100)) print(spi.send_recv(1, timeout=100)) spi.deinit()
dac.write(120) # output between 0 and 255 ''' 1.11 UART ''' from pyb import UART uart1 = UART(1, 9600) uart1.write('hello') uart1.read(5) # read up to 5 bytes ''' 1.12 SPI Bus ''' from pyb import SPI spi1 = SPI(1, SPI.MASTER, baudrate=200000, polarity=1, phase=0) spi1.send('hello') spi1.recv(5) # receive 5 bytes on the bus spi1.sedn_recv('hello') # send a receive 5 byrtes ''' 1.13 I2C Bus ''' from pyb import I2C i2c1 = I2C(1, I2C.MASTER, baudrate=100000) i2c1.sacn() # returns list of slave address i2c1.send('hello', 0x42) # send 5 bytes to slave with address ox42 i2c1.recv(5, 0x42) i2c1.mem_read(2, 0x42, 0x10) # read 2 bytes from slave 0x42, slave memory 0x10 i2c1.mem_write('xy', 0x42, 0x10) # write 2 bytes to slave 0x42, slave memory 0x10
size_buffer = bytearray(len( str(image_size))) # str() converts num 2 str, len() produces numeric input # send that size to the MCU in a robust way # print(str(image_size)) # print for troubleshooting spi.send_recv(bytearray(str(image_size)), size_buffer) # print message received from MCU print(''.join(chr(b) for b in size_buffer)) # send image # spi.send_recv(img, bytearray(image_size)) # spi.send(img) # a straight send works # spi.send_recv(img_data, bytearray(image_size)) spi.send( img_data ) # straight send SHOULD work and is the best because it's not limited by camera RAM # print completion message to serial monitor print("Done!") # turn SPI indicator off pyb.LED(RED_LED_PIN).off() ## Optional Code Blocks ''' ### Original "hello" communication code block # prepare buffer buf = bytearray(5) # print for troubleshooting:
class SpiMaster: def __init__(self, bus=1, baudrate=328125, polarity=0, phase=0, ss='A4'): self.ss = Pin(ss, Pin.OUT) self.ss.high() self.spi = SPI(bus, SPI.MASTER, baudrate=baudrate, polarity=polarity, phase=phase) self.msgbuf = bytearray(32) self.status = bytearray(4) def write_status(self, status): self.ss.low() self.spi.send(0x01) self.spi.send(status & 0xFF) self.spi.send((status >> 8) & 0xFF) self.spi.send((status >> 16) & 0xFF) self.spi.send((status >> 24) & 0xFF) self.ss.high() def read_status(self): self.ss.low() self.spi.send(0x04) self.spi.recv(self.status) self.ss.high() return (self.status[0] | (self.status[1] << 8) | (self.status[2] << 16) | (self.status[3] << 24)) def read_data(self): self.ss.low() self.spi.send(0x03) self.spi.send(0x00) self.spi.recv(self.msgbuf) self.ss.high() return self.msgbuf def read_msg(self, encoding='utf-8'): return bytes(self.read_data()).strip('\0').decode(encoding) def write_data(self, data): self.msgbuf[:] = data[:32] + b'\0' * (32 - len(data[:32])) self.ss.low() self.spi.send(0x02) self.spi.send(0x00) self.spi.send(self.msgbuf) self.ss.high()
class RFM69: def __init__(self, reset_pin=None, dio0_pin=None, spi_channel=None, config=None): self.reset_pin = reset_pin self.nss = Pin('X5', Pin.OUT_PP) self.reset = self.reset() self.spi_channel = spi_channel self.spi = SPI(1, SPI.MASTER, baudrate=50000, polarity=0, phase=0, firstbit=SPI.MSB, crc=None) self.dio0_pin = 'X3' self.conf = self.configure() self.mode = self.set_mode() self.txBufLen = 0 self.txBuf = bytearray(registers["RFM69_MAX_MESSAGE_LEN"]) self.rxBufLen = 0 self.rxBuf = bytearray(registers["RFM69_MAX_MESSAGE_LEN"]) self.version = self.getVersion() self.lastRssi = -(self.spi_read(registers["RFM69_REG_24_RSSI_VALUE"])/2) self.paLevel = 15 def configure(self): print ("Configuring...") for reg, value in config.items(): self.spi_write(registers.get(reg), value) return True def getVersion(self): self.version = self.spi_read(registers["RFM69_REG_10_VERSION"]) return self.version def set_mode(self, newMode=registers["RFM69_MODE_RX"]): self.spi_write(registers["RFM69_REG_01_OPMODE"], (self.spi_read(registers["RFM69_REG_01_OPMODE"]) & 0xE3) | newMode) while(self.spi_read(registers["RFM69_REG_01_OPMODE"]) != newMode): self.spi_write(registers["RFM69_REG_01_OPMODE"], (self.spi_read(registers["RFM69_REG_01_OPMODE"]) & 0xE3) | newMode) print ("Waiting... Attempted mode: %d" % newMode) sleep(1) pass self.mode = newMode return newMode def get_mode(self): #self.mode = self.spi_read(registers["RFM69_REG_01_OPMODE"]) return self.mode def init_gpio(self): self.dio0_pin = Pin('X3', Pin.IN, Pin.PULL_DOWN) def init_spi(self): self.spi = SPI(1, SPI.MASTER, baudrate=50000, polarity=0, phase=0, firstbit=SPI.MSB, crc=None) def reset(self): """ Reset the module, then check it's working. """ print ("Initialising RFM...") self.nss.high() self.reset_pin = Pin('X4', Pin.OUT_PP) self.reset_pin.low() sleep(0.1) self.reset_pin.high() sleep(0.1) self.reset_pin.low() sleep(0.1) def checkRx(self): print ("MODE: %d" % self.get_mode()) print ("Waiting for Payload") while ((self.spi_read(registers["RFM69_REG_28_IRQ_FLAGS2"]) & registers["RF_IRQFLAGS2_PAYLOADREADY"]) != registers["RF_IRQFLAGS2_PAYLOADREADY"]): pass print ("MODE: %d" % self.spi_read(registers["RFM69_REG_01_OPMODE"])) print ("IRQ Flag: %d" % self.spi_read(registers["RFM69_REG_28_IRQ_FLAGS2"])) self.rxBufLen = self.spi_read(registers["RFM69_REG_00_FIFO"])+1 print ("RX Buffer Length: %d" % self.rxBufLen) self.rxBuf = self.spi_burst_read(registers["RFM69_REG_00_FIFO"], registers["RFM69_FIFO_SIZE"]) self.lastRssi = -(self.spi_read(registers["RFM69_REG_24_RSSI_VALUE"])/2) self.clearFifo() def recv(self): # Store received data for return rxTuple = (self.rxBuf, self.rxBufLen, self.lastRssi) # Clear RX buffer self.rxBufLen = 0 self.rxBuf = bytearray(registers["RFM69_MAX_MESSAGE_LEN"]) # Return received telemetry return rxTuple def send(self, data, length, power): if (power<2 or power > 20): return False #Dangerous power levels oldMode = self.mode # Copy into TX buffer self.txBuf = data self.txBufLen = length # Start Transmitter print ("OLD MODE: %d" % self.mode) self.set_mode(registers["RFM69_MODE_TX"]) print ("NEW MODE: %d" % self.mode) #Setup PA if (power <= 17): # Set PA Level self.paLevel = power + 14 self.spi_write(registers["RFM69_REG_11_PA_LEVEL"], registers["RF_PALEVEL_PA0_OFF"] | registers["RF_PALEVEL_PA1_ON"] | registers["RF_PALEVEL_PA2_ON"] | self.paLevel ) else: # Disable Over Current Protection self.spi_write(registers["RFM69_REG_13_OCP"], registers["RF_OCP_OFF"]) # Enable High Power Registers self.spi_write(registers["RFM69_REG_5A_TEST_PA1"], 0x5D) self.spi_write(registers["RFM69_REG_5C_TEST_PA2"], 0x7C) # Set PA Level self.paLevel = power + 11 self.spi_write(registers["RFM69_REG_11_PA_LEVEL"], registers["RF_PALEVEL_PA0_OFF"] | registers["RF_PALEVEL_PA1_ON"] | registers["RF_PALEVEL_PA2_ON"] | self.paLevel ) # Wait for PA ramp-up print ("Waiting for PA ramp-up") while((self.spi_read(registers["RFM69_REG_27_IRQ_FLAGS1"]) & registers["RF_IRQFLAGS1_TXREADY"]) != registers["RF_IRQFLAGS1_TXREADY"]): pass # Transmit self.write_fifo(self.txBuf) # Wait for packet to be sent print ("Waiting for packet to be sent") while ((self.spi_read(registers["RFM69_REG_28_IRQ_FLAGS2"]) & registers["RF_IRQFLAGS2_PACKETSENT"]) != registers["RF_IRQFLAGS2_PACKETSENT"]): pass # Return Transceiver to original mode print ("OLD MODE: %d" % self.mode) self.set_mode(oldMode) print ("NEW MODE: %d" % self.mode) # If we were in high power, switch off High Power Registers if (power > 17): self.spi_write(registers["RFM69_REG_5A_TEST_PA1"], 0x55) self.spi_write(registers["RFM69_REG_5C_TEST_PA2"], 0x70) self.spi_write(registers["RFM69_REG_13_OCP"], (registers["RF_OCP_ON"] | registers["RF_OCP_TRIM_95"])) # Clear TX buffer self.txBufLen = 0 self.txBuf = bytearray(registers["RFM69_MAX_MESSAGE_LEN"]) print ("Transmission complete!") def setLnaMode(self, lnaMode): self.spi_write(registers["RFM69_REG_58_TEST_LNA"], lnaMode) def clearFifo(self): self.set_mode(registers["RFM69_MODE_STDBY"]) self.set_mode(registers["RFM69_MODE_RX"]) def readTemp(self): oldMode = self.mode self.set_mode(registers["RFM69_MODE_STDBY"]) self.spi_write(registers["RFM69_REG_4E_TEMP1"], registers["RF_TEMP1_MEAS_START"]) print ("Temp Measurement Running") while (self.spi_read(registers["RFM69_REG_4E_TEMP1"]) == registers["RF_TEMP1_MEAS_RUNNING"]): pass rawTemp = self.spi_read(registers["RFM69_REG_4F_TEMP2"]) self.set_mode(oldMode) return (168 - rawTemp) - 5 # Offset and compensate for self-heating def lastRssi(self): return self.lastRssi def sampleRssi(self): # Must only be called in RX mode if (self.mode != registers["RFM69_MODE_RX"]): # Not sure what happens otherwise, so check this return 0 # Trigger RSSI Measurement self.spi_write(registers["RFM69_REG_23_RSSI_CONFIG"], registers["RF_RSSI_START"]) # Wait for Measurement to complete print ("Wait for RSSI") while((self.spi_read(registers["RFM69_REG_23_RSSI_CONFIG"]) & registers["RF_RSSI_DONE"]) != registers["RF_RSSI_DONE"]): pass # Read, store in _lastRssi and return RSSI Value self.lastRssi = -(self.spi_read(registers["RFM69_REG_24_RSSI_VALUE"])/2) return self.lastRssi # Read/Write Functions def spi_read(self, register): data = bytearray(2) data[0] = register & ~0x80 data[1] = 0 resp = bytearray(2) self.nss.low() self.spi.send_recv(data, resp, timeout=5000) self.nss.high() return resp[1] def spi_burst_read(self, register, length): data = bytearray(length+1) data[0] = register & ~0x80 for i in range(1,length+1): data[i] = 0 # We get the length again as the first character of the buffer buf = bytearray(length+1) self.nss.low() self.spi.send_recv(data, buf, timeout=5000) self.nss.high() return buf[1:] def spi_write(self, register, value): data = bytearray(2) data[0] = register | 0x80 data[1] = value self.nss.low() self.spi.send(data, timeout=5000) self.nss.high() def write_fifo(self, data): fifo_data = bytearray(len(data)+2) fifo_data[0] = registers["RFM69_REG_00_FIFO"] | 0x80 fifo_data[1] = len(data) for i in range(2,len(data)+2): fifo_data[i] = data[i-2] self.nss.low() self.spi.send(fifo_data, timeout=5000) self.nss.high()
# main.py -- put your code here! from pyb import SPI, Pin, LED, delay, UART push_button = pyb.Pin("PA0", pyb.Pin.IN, pyb.Pin.PULL_DOWN) uart = UART(2, 115200) CS = Pin("PE3", Pin.OUT_PP) SPI_1 = SPI( 1, SPI.MASTER, baudrate=50000, polarity=0, phase=0, ) CS.low() SPI_1.send(0x0F | 0x80) tab_values = SPI_1.recv(1) CS.high() value = tab_values[0] while True: uart.write(value)
class SPIFlash: """ MicroPython for SPI Flash. Parameters ---------- nss : (str) CS pin. bus : (int) 1 -> The physical pins of the SPI busses 1 : (NSS, SCK, MISO, MOSI) = (X5, X6, X7, X8) = (PA4, PA5, PA6, PA7) 2 : (NSS, SCK, MISO, MOSI) = (Y5, Y6, Y7, Y8) = (PB12, PB13, PB14, PB15) mode : SPI.MASTER or SPI.SLAVE. baudrate : (int) default=42000000 Returns ------- None Examples -------- >>> import spiflash >>> flash = spiflash.SPIFlash() """ def __init__(self, nss='A4', bus=1, mode=SPI.MASTER, baudrate=42000000): self.__nss = pyb.Pin(nss) self.__nss.init(pyb.Pin.OUT_PP) self.__nss.high() self.spi = SPI(bus, mode, baudrate=baudrate, polarity=0, phase=0) self.__device_id = self.read_id() def __generic_command(self, cmd): self.__nss.low() self.spi.send(cmd) self.__nss.high() def __write_enable(self): self.__generic_command(__SFLASH_WRITE_ENABLE) self.__read_status_register() def __read_status_register(self): """ Status Register bit definitions STATUS_REGISTER_BUSY 0x01 STATUS_REGISTER_WRITE_ENABLED 0x02 STATUS_REGISTER_BLOCK_PROTECTED_0 0x04 STATUS_REGISTER_BLOCK_PROTECTED_1 0x08 STATUS_REGISTER_BLOCK_PROTECTED_2 0x10 [SST & Macronix Only] STATUS_REGISTER_BLOCK_PROTECTED_3 0x20 [SST & Macronix Only] STATUS_REGISTER_AUTO_ADDRESS_INCREMENT 0x40 [SST Only] STATUS_REGISTER_BLOCK_PROTECT_BITS_READ_ONLY 0x80 [SST Only] STATUS_REGISTER_QUAD_ENABLE 0x40 [Macronix Only] STATUS_REGISTER_WRITE_PROTECT_PIN_ENABLE 0x80 [Macronix Only] """ buf = bytearray(1) self.__nss.low() self.spi.send_recv(__SFLASH_READ_STATUS_REGISTER, buf) self.__nss.high() # print('__read_status_register: %s'%ubinascii.hexlify(buf).decode('UTF-8').upper()) return buf[0] def read_id(self): """ Read SPI Flash ID. """ self.wait() self.__nss.low() self.spi.send(__SFLASH_READ_JEDEC_ID) ret = self.spi.recv(3) self.__nss.high() return ubinascii.hexlify(ret).decode('UTF-8').upper() def wait(self, timeout=0): """ Wait. """ while timeout < 1000: if self.__read_status_register() == 0: return True else: timeout += 1 return False def sector_erase(self, addr): """ Sector Erase. """ self.__write_enable() self.__nss.low() self.spi.send(__SFLASH_SECTOR_ERASE) self.spi.send(bytearray([(addr&0x00FF0000)>>16, (addr&0x0000FF00)>>8, addr&0x000000FF])) self.__nss.high() return self.__read_status_register() def chip_erase(self): """ Chip Erase. """ self.__write_enable() self.__generic_command(__SFLASH_CHIP_ERASE2) return self.__read_status_register() def write(self, addr, buf): """ Write data to flash. """ pos = 0 write_size = len(buf) max_write_size = self.page_size() while pos < write_size: size = min(write_size-pos, max_write_size) self.__write_enable() self.__nss.low() self.spi.send(__SFLASH_WRITE) self.spi.send(bytearray([(addr&0x00FF0000)>>16, (addr&0x0000FF00)>>8, addr&0x000000FF])) self.spi.send(buf[pos:pos+size]) self.__nss.high() self.wait() addr += size pos += size return True def read(self, addr, size): """ Read data from flash. """ self.__nss.low() self.spi.send(__SFLASH_READ) self.spi.send(bytearray([(addr&0x00FF0000)>>16, (addr&0x0000FF00)>>8, addr&0x000000FF])) ret = self.spi.recv(size) self.__nss.high() return ret def chip_size(self): """ Get flash size. """ try: return SFLASH_ID_SIZE[self.__device_id] except KeyError: return 0 def page_size(self): """ Read Page Size. Parameters ---------- Returns ------- Flash page size. Examples -------- >>> spi.page_size() 128 """ # Some manufacturers support programming an entire page in one command. try: return SFLASH_PAGE_SIZE[self.__device_id[:2]] except KeyError: return 1
# MicroPython example for controlling one WS2812 LED. # Method similar to http://www.espruino.com/WS2811 # Attribution to Markus Gritsch from pyb import SPI spi = SPI(1, SPI.MASTER, baudrate=6400000, polarity=0, phase=1) spi.send(chr(0x00)) def byte2bits(byte): b0 = chr(0x03) b1 = chr(0x0F) bits = '' mask = 0x80 while mask != 0: bits += b0 if ( byte & mask ) == 0 else b1 mask >>= 1 return bits def sendColor(red, green, blue): spi.send(byte2bits(green)+byte2bits(red)+byte2bits(blue)) import math n = 0 while True: r = int((1 + math.sin(n * 0.1324)) * 127) g = int((1 + math.sin(n * 0.1654)) * 127) b = int((1 + math.sin(n * 0.1)) * 127) sendColor(r, g, b) n += 1
class St: DC = "Y4" CS_TFT = "Y5" CS_SD = "Y3" LITE = "Y2" RST = "Y1" XSIZE = 128 YSIZE = 160 XMAX = XSIZE-1 YMAX = YSIZE-1 X0 = int(XSIZE/2) Y0 = int(YSIZE/2) SW_RESET = 0x01 SLPIN = 0x10 SLP_OUT = 0x11 PTLON = 0x12 NORON = 0x13 INVOFF = 0x20 INVON = 0x21 DISPOFF = 0x28 DISP_ON = 0x29 CA_SET = 0x2A RA_SET = 0x2B RAM_WR = 0x2C RAMRD = 0x2E PTLAR = 0x30 MAD_CTL = 0x36 COL_MOD = 0x3A FRMCT1 = 0xB1 FRMCT2 = 0xB2 FRMCT3 = 0xB3 INVCTR = 0xB4 DISSET = 0xB6 PWRCT1 = 0xC0 PWRCT2 = 0xC1 PWRCT3 = 0xC2 PWRCT4 = 0xC3 PWRCT5 = 0xC4 VMCTR1 = 0xC5 PWRCT6 = 0xFC GAMCTP = 0xE0 GAMCTN = 0xE1 def __init__(self): self.dbg = Pin("X9", Pin.OUT_PP) self.dbg.low() self.spi = SPI(2, SPI.MASTER, baudrate=5250000) ss = Pin(self.CS_TFT, Pin.OUT_PP) ss.low() self.dc = Pin(self.DC, Pin.OUT_PP) self.dc.low() self.DC_flag = False cs_sd = Pin(self.CS_SD, Pin.OUT_PP) cs_sd.high() self.lite = Pin(self.LITE, Pin.OUT_PP) self.lite.high() reset = Pin(self.RST, Pin.OUT_PP) reset.low() delay(2) reset.high() delay(200) def FastDrawPixel(self, x, y, color): self.dc.low() self.spi.send(self.CA_SET) self.dc.high() self.spi.send(bytearray([0, x, 0, x])) self.dc.low() self.spi.send(self.RA_SET) self.dc.high() self.spi.send(bytearray([0, y, 0, y])) self.dc.low() self.spi.send(self.RAM_WR) self.dc.high() self.DC_flag = True self.spi.send(bytearray([color >> 8, color & 0xFF])) def init_display(self): self.write_cmd(self.SW_RESET) delay(200) self.write_cmd(self.SLP_OUT) self.write_cmd(self.COL_MOD, 0x05) delay(200) self.dbg.high() self.dbg.low() self.write_cmd(self.DISP_ON) def fill_rect(self, x0, y0, x1, y1, color): width = x1 - x0 + 1 height = y1 - y0 + 1 self.set_addr_window(x0, y0, x1, y1) self.write_bulk(color, width, height) def fill_screen(self, color): self.fill_rect(0, 0, 127, 159, color) def clear_screen(self): self.fill_rect(0, 0, 127, 159, self.rgb(255, 255, 255)) def rgb(self, r, g, b): r &= 0xF8 g &= 0xFC b &= 0xF8 return r << 8 | g << 3 | b >> 3 def write_cmd(self, cmd, *value): if self.DC_flag: self.dc.low() self.DC_flag = False self.spi.send(cmd) if len(value): self.dc.high() self.DC_flag = True self.spi.send(bytearray(value)) def write_bulk(self, value, reps, count=1): if self.DC_flag: self.dc.low() self.spi.send(self.RAM_WR) self.dc.high() self.DC_flag = True val_hi = value >> 8 val_lo = value & 0xFF byte_arr = bytearray([val_hi, val_lo] * reps) self.dbg.high() for a in range(count): self.spi.send(byte_arr) self.dbg.low() def set_addr_window(self, x0, y0, x1, y1): self.write_cmd(self.CA_SET, 0, x0, 0, x1) self.write_cmd(self.RA_SET, 0, y0, 0, y1)
# UART (serial bus) # See pyb.UART. from pyb import UART uart = UART(1, 9600) uart.write("hello") uart.read(5) # read up to 5 bytes # SPI bus from pyb import SPI spi = SPI(1, SPI.CONTROLLER, baudrate=200000, polarity=1, phase=0) spi.send("hello") spi.recv(5) # receive 5 bytes on the bus spi.send_recv("hello") # send and receive 5 bytes # I2C bus from machine import I2C i2c = I2C("X", freq=400000) # create hardware I2c object i2c = I2C(scl="X1", sda="X2", freq=100000) # create software I2C object i2c.scan() # returns list of peripheral addresses i2c.writeto(0x42, "hello") # write 5 bytes to peripheral with address 0x42 i2c.readfrom(0x42, 5) # read 5 bytes from peripheral i2c.readfrom_mem(