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线SPI

baudrate : 应该是 分频值 主频是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]))