跳转至

019:Air800-软件开发资料-外设驱动实现-TF 卡 副本

一、SD 卡概述

1、SD 卡

1.1 SD 卡简介

  • 定义:SD 卡(Secure Digital Card)是一种基于半导体快闪记忆器的新一代记忆设备,被广泛用于便携式设备中存储数据。
  • 特点:高存储容量、快速数据传输速度、体积小、重量轻、安全性高(支持数据加密)。

1.2 SD 卡类型与规格

  • 标准 SD 卡:原始 SD 卡规格。
  • miniSD 卡:缩小版的 SD 卡。
  • microSD 卡(又称 TF 卡):最小的 SD 卡规格,常用于智能手机和微型设备。

1.3 SD 卡工作原理

  • 文件系统:通常使用 FAT 文件系统(如 FAT16、FAT32)。
  • 通信协议:基于 SPI 协议进行数据传输。

二、演示功能概述

本 demo 展示了如何在 Air8000 整机开发板上,通过 Luat 脚本使用 FATFS 文件系统库对 SD/TF 卡进行基本的文件操作。在 demo 中介绍 SPI 初始化,fatfs 文件系统的挂载,获取可用 sd 卡空间,查看文件系统状态,还有一些文件操作测试:读取文件、写入文件、文件追加测试、按行读取测试。

三、准备硬件环境

1. Air8000 整机开发板准备环境:

在我们 Air8000 整机开发板上集成的是 microSD 卡(即 TF 卡)卡座:

淘宝购买链接:Air8000整机开发板

2. SD 卡:

本例使用的是朗科 32G TF 卡,如下图所示(可淘宝上自行选择购买。):

四、准备软件环境

1. 烧录工具 https://docs.openluat.com/air8000/luatos/common/swenv/

2. 内核固件文件(底层 core 固件文件):https://gitee.com/openLuat/LuatOS/tree/master/module/Air8000/core

3. LuatOS 需要的脚本和资源文件:https://gitee.com/openLuat/LuatOS/tree/master/module/Air8000/demo/tf

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

准备好软件环境之后,接下来查看 https://docs.openluat.com/air8000/luatos/common/download/,将本篇文章中演示使用的项目文件烧录到 Air8000 整机开发板中。

五、SD 卡软硬件参考

5.1 API 接口介绍

本教程使用 api 接口为:

https://docs.openluat.com/air8000/luatos/api/core/fatfs/

https://docs.openluat.com/air8000/luatos/api/core/fs/

https://docs.openluat.com/air8000/luatos/api/core/io/

注意:

1. luatos 的 api 接口是通用的。

2. 通常只使用 fatfs.mount 挂载 tf/sd 卡,其他操作走 io 库就可以了。

3. 挂载成 fatfs 后,可以通过 fs.fsstat 来获取文件系统信息,或 fs.fsize 来获取文件大小。

5.2 硬件设计参考

硬件设计参考 SCH__Air8000 开发板暨二次开发参考设计 V20250214.pdf

六、代码示例介绍

6.1 软件代码介绍

代码中有详细的注释,可以用来参考:

-- LuaTools需要PROJECT和VERSION这两个信息
PROJECT = "fatfs"
VERSION = "1.0.0"

-- sys库是标配
_G.sys = require("sys")

local rtos_bsp = rtos.bsp()

-- spi_id,pin_cs
local function fatfs_spi_pin()      
    return 1, 20    -- Air8000整机开发板上的pin_cs为20
end

sys.taskInit(function()
    sys.wait(1000)
    -- fatfs.debug(1) -- 若挂载失败,可以尝试打开调试信息,查找原因

    -- 此为spi方式
    local spi_id, pin_cs,tp = fatfs_spi_pin() 
    -- 仅SPI方式需要自行初始化spi, sdio不需要
    spi.setup(spi_id, nil, 0, 0, pin_cs, 400 * 1000)
    gpio.setup(pin_cs, 1)
    fatfs.mount(fatfs.SPI, "/sd", spi_id, pin_cs, 24 * 1000 * 1000)

    local data, err = fatfs.getfree("/sd")
    if data then
        log.info("fatfs", "getfree", json.encode(data))
    else
        log.info("fatfs", "err", err)
    end

    -- #################################################
    -- 文件操作测试
    -- #################################################
    local f = io.open("/sd/boottime", "rb")
    local c = 0
    if f then
        local data = f:read("*a")
        log.info("fs", "data", data, data:toHex())
        c = tonumber(data)
        f:close()
    end
    log.info("fs", "boot count", c)
    if c == nil then
        c = 0
    end
    c = c + 1
    f = io.open("/sd/boottime", "wb")
    if f ~= nil then
        log.info("fs", "write c to file", c, tostring(c))
        f:write(tostring(c))
        f:close()
    else
        log.warn("sdio", "mount not good?!")
    end
    if fs then
        log.info("fsstat", fs.fsstat("/"))
        log.info("fsstat", fs.fsstat("/sd"))
    end

    -- 测试一下追加, fix in 2021.12.21
    os.remove("/sd/test_a")
    sys.wait(50)
    f = io.open("/sd/test_a", "w")
    if f then
        f:write("ABC")
        f:close()
    end
    f = io.open("/sd/test_a", "a+")
    if f then
        f:write("def")
        f:close()
    end
    f = io.open("/sd/test_a", "r")
    if  f then
        local data = f:read("*a")
        log.info("data", data, data == "ABCdef")
        f:close()
    end

    -- 测试一下按行读取, fix in 2022-01-16
    f = io.open("/sd/testline", "w")
    if f then
        f:write("abc\n")
        f:write("123\n")
        f:write("wendal\n")
        f:close()
    end
    sys.wait(100)
    f = io.open("/sd/testline", "r")
    if f then
        log.info("sdio", "line1", f:read("*l"))
        log.info("sdio", "line2", f:read("*l"))
        log.info("sdio", "line3", f:read("*l"))
        f:close()
    end

    -- #################################################

end)

-- 用户代码已结束---------------------------------------------
-- 结尾总是这一句
sys.run()
-- sys.run()之后后面不要加任何语句!!!!!

6.2 效果展示

通过日志可以查看到 sd 卡已经挂载成功,并且打印了可用空间大小和文件系统的信息,文件系统操作的操作也都成功。

七、总结

至此,我们已使用 Air8000 整机开发板通过 SPI 方式,完成了对 SD 卡挂载 fatfs、以及对 SD 卡中文件读写操作。

八、常见问题

1. 为什么 air8000 不能识别新购买的 sd 卡:

文件系为 FAT32 格式(windows、linux 都可以正常识别),所以非 FAT 格式的 SD 卡会挂载失败,而无法正常识别。

2. SD 卡的读写路径是什么?

SD 卡文件访问通过路径前加上"/sd",如果 sd 卡中有一个文件 test.txt ,那这个文件的路径就是"/sd/test.txt"。

3. http 下载的文件可以直接保存到 sd 卡里吗?

支持,http.request 接口支持直接下载到文件系统中,下载到 sd 卡中的时候只需要注意路径设置。参考 demo 中注释掉的部分。