跳转至

SPI

一、SPI 概述

SPI(Serial Peripheral Interface)是一种同步串行通信协议,广泛应用于微控制器和外围设备之间的数据传输。它由摩托罗拉公司开发,具有全双工通信能力,即可以同时进行数据的发送和接收。

SPI 通信通常涉及四条信号线:

  1. MOSI(Master Out Slave In):主设备发送数据,外设接收数据。
  2. MISO(Master In Slave Out):外设发送数据,主设备接收数据。
  3. SCLK(Serial Clock):由主设备生成的时钟信号,用于同步数据传输。
  4. SS(Slave Select):选择特定的从设备进行通信。

SPI 的优点包括简单的硬件连接、高速数据传输和全双工通信。其缺点是通常需要更多的引脚,尤其是在多个从设备的情况下,每个从设备需要一个独立的 SS 引脚。此外,SPI 没有标准化的协议层,因此设备间的兼容性需要仔细管理。

二、演示功能概述

本文使用 Air8101 核心板的 SPI 总线读写 FLASH。

三、准备硬件环境

“古人云:‘工欲善其事,必先利其器。’在深入介绍本功能示例之前,我们首先需要确保以下硬件环境的准备工作已经完成。” 参考:硬件环境清单 - luatos@air8101 - 合宙文档中心,准备以及组装好硬件环境。

3.1 FLASH 模块

购买链接(数量:1,注意,一定要选 W25Q64 型号,如使用其他型号,需要在代码中修改相应的芯片 ID)

四、准备软件环境

“凡事预则立,不预则废。”在详细阐述本功能示例之前,我们需先精心筹备好以下软件环境。

1. Luatools 工具

2. 内核固件文件(底层 core 固件文件):LuatOS-SoC_V10001_Air8101.soc;参考项目使用的内核固件

3. LuatOS 需要的脚本和资源文件 脚本和资源文件:https://gitee.com/openLuat/LuatOS-Air8101/tree/master/demo/SPI

lib 脚本文件:使用 Luatools 烧录时,勾选 添加默认 lib 选项,使用默认 lib 脚本文件;

准备好软件环境之后,接下来查看如何烧录项目文件到 Air8101 核心板,将本篇文章中演示使用的项目文件烧录到 Air8101 核心板中。

五、软硬件资料

5.1 实物连接图

5.1.1 线序定义与颜色对应

5.1.2 FLASH 端

5.1.3 开发板端(需替换为Air8101开发板)

六、代码示例介绍

6.1 程序流程图

6.2 完整程序清单

注:完整复制后保存为 main.lua,可直接使用

-- LuaTools需要PROJECT和VERSION这两个信息
PROJECT = "w25q_spi_demo"
VERSION = "1.0.1"

sys = require("sys")

--spi编号,请按实际情况修改!
local spiId = 1  --这里使用SPI 1

--GPIO2<----> SCK
--GPIO3<----> CS
--GPIO4<----> MOSI
--GPIO5<----> MISO

local cs = 3 -- CS使用GPIO3
local cspin = gpio.setup(cs, 1)  --配置CS为输出

--收发数据
local function sendRecv(data,len)
    local r = ""
    cspin(0)
    if data then spi.send(spiId,data) end
    if len then r = spi.recv(spiId,len) end
    cspin(1)
    return r
end


sys.taskInit(function()

    local result = spi.setup(
        spiId,--串口id
        nil,
        0,--CPHA
        0,--CPOL
        8,--数据宽度
        1000000--,--频率
        -- spi.MSB,--高低位顺序    可选,默认高位在前
        -- spi.master,--主模式     可选,默认主
        -- spi.full--全双工       可选,默认全双工
    )
    print("open",result)
    if result ~= 0 then--返回值为0,表示打开成功
        print("spi open error",result)
        return
    end

    --检查芯片型号
    local chip = sendRecv(string.char(0x9f),3)
    if chip == string.char(0xef,0x40,0x17) then
        log.info("spi", "chip id read ok 0xef,0x40,0x17")
    else
        log.info("spi", "chip id read error")
        for i=1,#chip do
            print(chip:byte(i))
        end
        return
    end

    local data = "test data 123456"

    --enable write
    sendRecv(string.char(0x06))

    --写页数据到地址0x000001
    sendRecv(string.char(0x02,0x00,0x00,0x01)..data)
    log.info("spi","write",data)

    sys.wait(500)--等写入操作完成

    --读数据
    local r = sendRecv(string.char(0x03,0x00,0x00,0x01),data:len())
    log.info("spi","read",r)

    --disable write
    sendRecv(string.char(0x04))

    spi.close(spiId)
end)

-- 结尾总是这一句哦
sys.run()

七、功能验证

八、总结

至此,我们已使用 Air8101 开发板的 SPI 接口完成了对 W25Q64 读写操作。