6. SPI
SPI 是一个由主机驱动的同步串行协议。在物理层,总线有三根:SCK、MOSI、MISO。多个设备可以共享同一总线,每个设备都由一个单独的信号 NSS 来选中,也称片选信号。 主机通过片选信号选定一个设备进行通信。NSS 信号的管理应该由用户代码负责。
K2000最多可支持创建5组 SPI 对象。
注意
NSS 信号的管理由用户代码负责。
6.1. 构建spi
from sharp_spi_iic import * # 导入 iic 模块
from sharp_user import * # 导入 用户自定义 模块 需要从此模块里获取pin对象
# 4线8位 硬件SPI
adapter = SHARP_spi_init(id = 1,mode = 4,baudrate = 10,polarity = 1,phase = 1,sck = LCD_TP_SCK,mosi = LCD_TP_MOSI,miso = LCD_TP_MISO)
# 4线8位 软件SPI
adapter = SHARP_spi_init(id = 0,mode = 4,baudrate = 10,polarity = 1,phase = 1,sck = LCD_TP_SCK,mosi = LCD_TP_MOSI,miso = LCD_TP_MISO)
SHARP_spi_init(id,mode,baudrate,polarity,phase,sck,mosi,miso,number)此方法会构造并返回一个新的SPI对象,并用于后续的读写id: 标识特定的 SPI 外设。如果填入 id = 0,即选择软件模拟的方式实现 SPI,这时可以使用任意引脚来模拟 SPI 总线 ,这样在初始化时就必须指定 sck , mosi ,miso 。mode: 应该是 SPI 模式 3--三线SPI 4--四线SPI 5--DSPI 6--QSPI 默认是4线SPIbaudrate: 应该是 分频值 主频是50M分频polarity: 极性可以是 0 或 1,是时钟空闲时所处的电平 (可选参数)phase: 相位可以是 0 或 1,分别在第一个或者第二个时钟边缘采集数据。。(可选参数)sck: 应该是一个 Pin 对象,指定为一个用于 sck 的 Pin 对象。(可选参数)mosi: 应该是一个 Pin 对象,指定为一个用于 mosi 的 Pin 对象 。 (可选参数)miso: 应该是一个 Pin 对象,指定为一个用于 miso 的 Pin 对象。 (可选参数)number: 应该是为 多组SPI对象的序列号,多组SPI的时候使用,单组SPI可以忽略 (可选参数) 。
6.2. spi发送
为了应对SPI多变的时序要求,特地定制了一个针对SPI传输的类对象SPI_message,此对象包含以下几个参数。
spi_type: 读写类型,具体有以下三种类型。
SPI_WR: 收发双向传输
SPI_OnlyW: 只发送
SPI_OnlyR: 只接收
spi_len: 读写长度。
spi_dc: dc 数据位,9位的SPI的时候使用
RX_Buffer: 接收缓冲区。
TX_Buffer: 发送缓冲区。
# SPI写数据,可复用
def spi_write_data(adapter,cmd,data,data_len):
message = [spi_message() for i in range(2)]
cmd_buf = bytearray(1)
byte_buf = bytearray(data_len+1)
cmd_buf[0] = cmd
message[0].spi_dc = 0x00
message[0].spi_type = SPI_OnlyW
message[0].spi_len = 1
message[0].TX_Buffer = cmd_buf
for i in range(data_len):
byte_buf[i] = data[i]
message[1].spi_dc = 0xff
message[1].spi_type = SPI_OnlyW
message[1].spi_len = data_len
message[1].TX_Buffer = byte_buf
CS_0() #片选信号
SHARP_SPI_transfer(adapter,message,2)
CS_1()
byte_buf = bytearray(10)
byte_buf[0] = 0xB6
spi_write_data(spi_adap,0xFE,byte_buf,1)
6.3. spi接收
# SPI读数据,可复用
def spi_read(adapter,data_len):
byte_buf = bytearray(data_len)
message = spi_message()
byte_buf[0] = 0xff
message.spi_dc = 0x00
message.spi_type = SPI_OnlyW
message.spi_len = 1
message.TX_Buffer = byte_buf
CS_0() #片选信号
SHARP_SPI_transfer(adapter,message,1) #中间片选不能断
message.spi_type = SPI_OnlyR
message.spi_len = data_len
message.RX_Buffer = byte_buf
SHARP_SPI_transfer(adapter,message,1)
CS_1()
return message.RX_Buffer
# byte_buf(字节流变量) = spi_read(地址, 读数据长度)
read_buf = spi_read(spi_adap,3)
# 将接收的值打印
print("ID = %x,%x,%x"%(read_buf[0],read_buf[1],read_buf[2]))
6.4. 示例
from sharp_spi_iic import *
# 涉及引脚配置需要添加sharp_user包
from sharp_user import *
# SPI相关IO口配置
def IO_Configuration():
user_io = str_user_io()
user_io.IO_PIN = LCD_TP_CS|LCD___IO_13
user_io.IO_Mode = OUTPUT_DIR
SHARP_UserIO_Conf(user_io)
SHARP_UserIO_BitSet(LCD_TXS_OE) #使能转换IC
CS_1()
# 片选拉高
def CS_1():
SHARP_UserIO_BitSet(LCD_TP_CS)
# 片选拉低
def CS_0():
SHARP_UserIO_BitReset(LCD_TP_CS)
# SPI初始化,可复用
def SPI_Init():
adapter = SHARP_spi_init(id = 1,mode = 3,baudrate = 10,polarity = 0,phase = 0,bits = 9) ## 三线9位 的SPI初始化
SHARP_UserIO_AF_Set(USER_TP_MOSI_AF,USER_IO_AF)
SHARP_UserIO_AF_Set(USER_TP_SCK_AF,USER_IO_AF)
SHARP_UserIO_BitSet(LCD_TP_CS) #拉高片选
return adapter
# SPI写数据,可复用
def spi_write_data(adapter,cmd,data,data_len):
SHARP_SPI_DataIo_ModeSet(1) #spi配置为输出模式
SDA_MODE_OUT() #spi转换电平配置为输出模式
SHARP_SPI_DataBit_Mode(9)
message = [spi_message() for i in range(2)]
cmd_buf = bytearray(1)
byte_buf = bytearray(data_len+1)
cmd_buf[0] = cmd
message[0].spi_dc = 0x00
message[0].spi_type = SPI_OnlyW
message[0].spi_len = 1
message[0].TX_Buffer = cmd_buf
for i in range(data_len):
byte_buf[i] = data[i]
message[1].spi_dc = 0xff
message[1].spi_type = SPI_OnlyW
message[1].spi_len = data_len
message[1].TX_Buffer = byte_buf
CS_0()
SHARP_SPI_transfer(adapter,message,2)
CS_1()
# SPI读数据,可复用
def spi_read(adapter,data_len):
SHARP_SPI_DataIo_ModeSet(1) #spi配置为输出模式
SDA_MODE_OUT() #spi转换电平配置为输出模式
SHARP_SPI_DataBit_Mode(9)
byte_buf = bytearray(data_len)
message = spi_message()
byte_buf[0] = 0xff
message.spi_dc = 0x00
message.spi_type = SPI_OnlyW
message.spi_len = 1
message.TX_Buffer = byte_buf
CS_0()
SHARP_SPI_transfer(adapter,message,1) #中间片选不能断
SHARP_SPI_DataIo_ModeSet(0) #spi配置为输入模式
SDA_MODE_INT() #spi转换电平配置为输出模式
SHARP_SPI_DataBit_Mode(8)
message.spi_type = SPI_OnlyR
message.spi_len = data_len
message.RX_Buffer = byte_buf
SHARP_SPI_transfer(adapter,message,1)
CS_1()
return message.RX_Buffer
# 该实例仅供参考,不可直接使用
if __name__ == '__main__':
print('SPI Demo...')
# 引脚模式配置
IO_Configuration()
#实例化SPI对象
spi_adap = SPI_Init() #SPI 初始化
# 申请字节流空间
byte_buf = bytearray(10)
# 单字节可用如下方式写SPI
byte_buf[0] = 0X00
# 传入对象 SPI对象 地址 数据 写入数据长度(单字节限定为1)
spi_write_data(spi_adap,0xBD,byte_buf,1)
byte_buf[0] = 0xB6
spi_write_data(spi_adap,0xFE,byte_buf,1)
# SPI读如下形式
# byte_buf(字节流变量) = spi_read(地址, 读数据长度)
read_buf = spi_read(spi_adap,3)
# 将接收的值打印
print("ID = %x,%x,%x"%(read_buf[0],read_buf[1],read_buf[2]))
# 多字节可用如下方式写SPI
byte_buf = bytearray([0x83,0x19,0x2A])
# 传入对象 SPI对象 地址 数据 写入数据长度(为byte_buf的字节长度)
spi_write_data(spi_adap,0xB9,byte_buf,3)
byte_buf = bytearray([0x00,0x00,0x00,0x00,0xA5])
spi_write_data(spi_adap,0xCF,byte_buf,5)
# SPI读如下形式
# byte_buf(字节流变量) = spi_read(地址, 读数据字节长度)
read_buf = spi_read(spi_adap, 1)
print('read buf = %x'%(read_buf[0]))