基于亚博K210开发板——内存卡读写文件

开发板

亚博K210开发板
在这里插入图片描述

实验目的

本实验主要学习 K210 通过 SPI 读写内存卡文件的功能

实验准备

实验元件

开发板自带的 TF 卡、LCD 显示屏
提前准备好 FAT32 格式的TF 卡。TF 插入 TF 卡槽的时候注意方向,TF 卡的金手指那一面需要面向开发板,如果方向插反了是无法读写数据的。TF卡尺寸小,性能好,传输速度快,最初是用于支持内存扩展的手机上,比较适合储存高清摄像和高音质音频内容,因而被广泛应用于各种多媒体设备上)

硬件连接

K210 开发板出厂默认已经焊接 TF 卡槽,需要插入 TF 卡才可以使用,其中TF 卡槽的 TF_MISO 连接到 IO26,TF_CLK 连接到 IO27,TF_MOSI 连接到 IO28,TF_CSO连接 IO29。
在这里插入图片描述

在这里插入图片描述

SDK中相关API

SPI 是一种高速、高效率的串行接口技术。通常由一个主模块和一个或多个从模块组成,主模块选择一个从模块进行同步通信,从而完成数据的交换。SPI是一个环形结构,通信时需要至少 4 根线(事实上在单向传输时 3 根线也可以),它们是 MISO(主设备数据输入)、MOSI(主设备数据输出)、SCLK(时钟)、CS(片选)。

  • MISO– Master Input Slave Output,主设备数据输入,从设备数据输出;
  • MOSI– Master Output Slave Input,主设备数据输出,从设备数据输入;
  • SCLK – Serial Clock,时钟信号,由主设备产生;
  • CS – Chip Select,从设备使能信号,由主设备控制。当有多个从设备的时候,因为每个从设备上都有一个片选引脚接入到主设备机中,当我们的主设备和某个从设备通信时将需要将从设备对应的片选引脚电平拉低或者是拉高。

在这里插入图片描述

相关接口

spi_init:设置 SPI 工作模式、多线模式和位宽。
spi_init_non_standard:多线模式下设置指令长度、地址长度、等待时钟数、指令地址传输模式。
spi_send_data_standard:SPI 标准模式传输数据。
spi_send_data_standard_dma:SPI 标准模式下使用 DMA 传输数据。
spi_receive_data_standard:标准模式下接收数据。
spi_receive_data_standard_dma:标准模式下通过 DMA 接收数据。
spi_send_data_multiple:多线模式发送数据。
spi_send_data_multiple_dma:多线模式使用 DMA 发送数据。
spi_receive_data_multiple:多线模式接收数据。
spi_receive_data_multiple_dma:多线模式通过 DMA 接收。
spi_fill_data_dma:通过 DMA 始终发送同一个数据,可以用于刷新数据。
spi_send_data_normal_dma:通过 DMA 发送数据。不用设置指令地址。
spi_set_clk_rate:设置 SPI 的时钟频率。
spi_handle_data_dma:SPI 通过 DMA 传输数据。

实验原理

TF 有 4 个数据传输端,DAT0,DAT1,DAT2,DAT3。还有一个 CMD 脚,是用来读取卡内信息的。
TF 卡主要管脚的功能:
CLK:时钟信号,每个时钟周期传输一个命令或数据位,频率可在 0~25MHz之间变化,TF 卡的总线管理器可以不受任何限制的自由产生 0~25MHz 的频率;
CMD:双向命令和回复线,命令是主机到从卡操作的开始,命令可以是从主机到单卡寻址,也可以是到所有卡;回复是对之前命令的回答,回复可以来自单卡或所有卡;
DAT0~3:数据线,数据可以从 TF 卡传向主机也可以从主机传向 TF 卡。TF 卡传输数据一般有两种模式,SD 模式和 SPI 模式,这里我们以 SPI 模式的方式传输数据。SPI 模式引脚如下:1:CS,2:DI,3:VSS,4:VDD,5:SCLK,6:VSS2,7:DO,8:RSV,9:RSV。
在这里插入图片描述

实验过程

  1. 首先初始化 K210 的硬件引脚和软件功能使用的是 FPIOA 映射关系。
void hardware_init(void)
{/*** io26--miso--d1** io27--clk---sclk** io28--mosi--d0** io29--cs----cs*/fpioa_set_function(PIN_TF_MISO, FUNC_TF_SPI_MISO);fpioa_set_function(PIN_TF_CLK,  FUNC_TF_SPI_CLK);fpioa_set_function(PIN_TF_MOSI, FUNC_TF_SPI_MOSI);fpioa_set_function(PIN_TF_CS,   FUNC_TF_SPI_CS);
}
// 硬件IO口,与原理图对应
#define PIN_TF_MISO            (26)
#define PIN_TF_CLK             (27)
#define PIN_TF_MOSI            (28)
#define PIN_TF_CS              (29)/*****************************SOFTWARE-GPIO********************************/
// 软件GPIO口,与程序对应
#define TF_CS_GPIONUM          (2)/*****************************FUNC-GPIO************************************/
// GPIO口的功能,绑定到硬件IO口
#define FUNC_TF_SPI_MISO        (FUNC_SPI1_D1)
#define FUNC_TF_SPI_CLK         (FUNC_SPI1_SCLK)
#define FUNC_TF_SPI_MOSI        (FUNC_SPI1_D0)
#define FUNC_TF_SPI_CS          (FUNC_GPIOHS0 + TF_CS_GPIONUM)
  1. 设置系统时钟频率,由于 uarths 的时钟来自 PLL0,所以设置 PLL0 之后需
    要重新初始化以下 uarths,否则 printf 可能会打印乱码。
/* 设置系统时钟频率 */
sysctl_pll_set_freq(SYSCTL_PLL0, 800000000UL);
sysctl_pll_set_freq(SYSCTL_PLL1, 300000000UL);
sysctl_pll_set_freq(SYSCTL_PLL2, 45158400UL);
uarths_init();
  1. 检测是否有 TF 卡,或者 TF 卡是否正常,如果不正常则退出。
if (check_sdcard())
{printf("SD card err\n");return -1;
}

如果初始化 TF 卡成功,则把 TF 的容量打印出来,单位为 G。

static int check_sdcard(void)
{uint8_t status;printf("/******************check_sdcard*****************/\n");status = sd_init();printf("sd init :%d\n", status);if (status != 0){return status;}printf("CardCapacity:%.1fG \n", (double)cardinfo.CardCapacity / 1024 / 1024 / 1024);printf("CardBlockSize:%d\n", cardinfo.CardBlockSize);return 0;
}
  1. 检测 TF 卡的格式是否是 FAT32,如果不是则退出。
if (check_fat32())
{printf("FAT32 err\n");return -1;
}

如果检测符合 FAT32 格式的 TF 卡,则把 TF 卡挂在到“0:”,并且把 TF 卡根
目录下的文件和文件夹的名称都打印出来。

static int check_fat32(void)
{static FATFS sdcard_fs;FRESULT status;DIR dj;FILINFO fno;printf("/********************check_fat32*******************/\n");status = f_mount(&sdcard_fs, _T("0:"), 1);printf("mount sdcard:%d\n", status);if (status != FR_OK)return status;printf("printf filename\n");status = f_findfirst(&dj, &fno, _T("0:"), _T("*"));while (status == FR_OK && fno.fname[0]){if (fno.fattrib & AM_DIR)printf("dir:%s\n", fno.fname);elseprintf("file:%s\n", fno.fname);status = f_findnext(&dj, &fno);}f_closedir(&dj);return 0;
}
  1. 向 TF 卡写入文件,保存在 TF 卡跟目录下的 test.txt,如果写入失败则退
    出。
sleep(1);
if (sd_write_file(_T("0:test.txt")))
{printf("SD write err\n");return -1;
}

在写入文件之前需要先打开文件,如果文件不存在则需要创建新文件,写入的数据都需要转化成 uint8_t 类型,写完数据后必须执行 f_close 关闭文件。

FRESULT sd_write_file(TCHAR *path)
{FIL file;FRESULT ret = FR_OK;printf("/*******************sd_write_file*******************/\n");uint32_t v_ret_len = 0;/* 打开文件,如果文件不存在,则新建 */if ((ret = f_open(&file, path, FA_CREATE_ALWAYS | FA_WRITE)) != FR_OK){printf("open file %s err[%d]\n", path, ret);return ret;}else{printf("Open %s ok\n", path);}/* 要写入的数据 */uint8_t data[] = {'H','i',',','D','a','t','a',' ','W','r','i','t','e',' ','O','k','!'};/* 写入数据 */ret = f_write(&file, data, sizeof(data), &v_ret_len);if (ret != FR_OK){printf("Write %s err[%d]\n", path, ret);}else{printf("Write %d bytes to %s ok\n", v_ret_len, path);}/* 关闭文件 */f_close(&file);return ret;
}
  1. 从 TF 卡读取文件,文件为在 TF 卡根目录下的 test.txt。
if (sd_read_file(_T("0:test.txt")))
{printf("SD read err\n");return -1;}

读文件前需要判断文件的状态,并且打开文件,如果文件不存在或者出错,则返回,如果正常则以只读方式打开文件,并且把读到的数据通过串口发送出来。

FRESULT sd_read_file(TCHAR *path)
{FIL file;FRESULT ret = FR_OK;printf("/*******************sd_read_file*******************/\n");uint32_t v_ret_len = 0;/* 检测文件状态 */FILINFO v_fileinfo;if ((ret = f_stat(path, &v_fileinfo)) == FR_OK){printf("%s length is %lld\n", path, v_fileinfo.fsize);}else{printf("%s fstat err [%d]\n", path, ret);return ret;}/* 只读方式打开文件 */if ((ret = f_open(&file, path, FA_READ)) == FR_OK){char v_buf[64] = {0};ret = f_read(&file, (void *)v_buf, 64, &v_ret_len);if (ret != FR_OK){printf("Read %s err[%d]\n", path, ret);}else{printf("Read :> %s \n", v_buf);printf("total %d bytes lenth\n", v_ret_len);}/* 关闭文件 */f_close(&file);}return ret;
}
  1. 编译调试,烧录运行
    进入 build 目录,运行以下命令编译。
cmake .. -DPROJ=sdcard -G "MinGW Makefiles"
make

编译完成后,在 build 文件夹下会生成 sdcard.bin 文件。使用type-C 数据线连接电脑与 K210开发板,打开kflash,选择对应的设备,再将程序固件烧录到 K210 开发板上。

实验现象

烧录完成固件后,系统会弹出一个终端界面,如果没有弹出终端界面的可以打开串口助手显示调试内容。
在这里插入图片描述

实验总结

1.TF 读或写文件前都必须先打开文件,读写操作结束后也必须关闭文件。
2.TF 卡通过 SPI 通讯的方式,读写数据以 uint8_t 为基本单位。
3.每次烧录完固件后,都需要重新给 K210 开发板上电,否则会出现 TF 卡初始化
失败而退出系统的问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/901942.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

51单片机实验五:A/D和D/A转换

一、实验环境与实验器材 环境:Keli,STC-ISP烧写软件,Proteus. 器材:TX-1C单片机(STC89C52RC)、电脑。 二、 实验内容及实验步骤 1.A/D转换 概念:模数转换是将连续的模拟信号转换为离散的数字信…

C++ 常用的智能指针

C 智能指针 一、智能指针类型概览 C 标准库提供以下智能指针&#xff08;需包含头文件 <memory>&#xff09;&#xff1a; unique_ptr&#xff1a;独占所有权&#xff0c;不可复制&#xff0c; 可移动shared_ptr&#xff1a;共享所有权&#xff0c;用于引用计数weak_pt…

6.8.最小生成树

一.复习&#xff1a; 1.生成树&#xff1a; 对于一个连通的无向图&#xff0c;假设图中有n个顶点&#xff0c;如果能找到一个符合以下要求的子图&#xff1a; 子图中包含图中所有的顶点&#xff0c;同时各个顶点保持连通&#xff0c; 而且子图的边的数量只有n-1条&#xff0…

Spring Boot 集成金蝶 API 演示

✨ Spring Boot 集成金蝶 API 演示&#xff1a;登录 / 注销 Cookie 保存 本文将通过 Spring Boot 完整实现一套金蝶接口集成模型&#xff0c;包括&#xff1a; ✅ 普通登录✅ AppSecret 登录✅ 注销✅ Cookie 保存与复用 &#x1f4c5; 项目结构 src/ ├── controller/ │…

React 受控表单绑定基础

React 中最常见的几个需求是&#xff1a; 渲染一组列表绑定点击事件表单数据与组件状态之间的绑定 受控表单绑定是理解表单交互的关键之一。 &#x1f4cd;什么是受控组件&#xff1f; 在 React 中&#xff0c;所谓“受控组件”&#xff0c;指的是表单元素&#xff08;如 &l…

基于FPGA的AES加解密系统verilog实现,包含testbench和开发板硬件测试

目录 1.课题概述 2.系统测试效果 3.核心程序与模型 4.系统原理简介 4.1 字节替换&#xff08;SubBytes&#xff09; 4.2 行移位&#xff08;ShiftRows&#xff09; 4.3 列混合&#xff08;MixColumns&#xff09; 4.4 轮密钥加&#xff08;AddRoundKey&#xff09; 4.…

6.5 GitHub监控系统实战:双通道采集+动态调度打造高效运维体系

GitHub Sentinel Agent 定期更新功能设计与实现 关键词:GitHub API 集成、定时任务调度、Python 爬虫开发、SMTP 邮件通知、系统稳定性保障 1. GitHub 项目数据获取功能 1.1 双通道数据采集架构设计 #mermaid-svg-ZHJIMXcMAyDHVhmV {font-family:"trebuchet ms",v…

Explorer++:轻量级高效文件管理器!!

项目简介 Explorer 是一款专为Windows操作系统设计的轻量级且高效的文件管理器。作为Windows资源管理器的强大替代方案&#xff0c;它提供了丰富的特性和优化的用户体验&#xff0c;使得文件管理和组织变得更加便捷高效。无论是专业用户还是普通用户&#xff0c;都能从中受益&a…

7、生命周期:魔法的呼吸节奏——React 19 新版钩子

一、魔法呼吸的本质 "每个组件都是活体魔法生物&#xff0c;呼吸节奏贯穿其生命始终&#xff0c;"邓布利多的冥想盆中浮现三维相位图&#xff0c;"React 19的呼吸式钩子&#xff0c;让组件能量流转如尼可勒梅的炼金术&#xff01;" ——以霍格沃茨魔法生理…

理解计算篇--正则表达式转NFA--理论部分

空正则表达式转NFA单字符正则表达式转NFA拼接正则表达式转NFA选择正则表达式转NFA重复正则表达式转NFA 正则表达式转NFA–实战部分 空正则表达式转NFA 转换步骤&#xff1a; 构建1个只有1个状态的NFA起始状态也是接受状态没有规则&#xff0c;即规则集为空 单字符正则表达式…

稳态模型下的异步电机调速【运动控制系统】

异步电动机&#xff1a; n1是同步转速&#xff08;电机和磁芯同步时候的转速&#xff09; n&#xff1a;电机的实际转速 异步电动机恒压频比的概念&#xff0c;为什么基频以下可以采取恒压频率&#xff0c;基频以上不可以采用恒压频比&#xff1a; 异步电动机的恒压频比&…

【KWDB 创作者计划】_算法篇---Stockwell变换

文章目录 前言一、Stockwell变换原理详解1.1 连续S变换定义1.2 离散S变换1.3简介 二、S变换的核心特点2.1频率自适应的时频分辨率2.1.1高频区域2.1.2低频区域 2.2无交叉项干扰2.3完全可逆2.4相位保持2.5与傅里叶谱的直接关系 三、应用领域3.1地震信号分析3.2生物医学信号处理3.…

云计算(Cloud Computing)概述——从AWS开始

李升伟 编译 无需正式介绍亚马逊网络服务&#xff08;Amazon Web Services&#xff0c;简称AWS&#xff09;。作为行业领先的云服务提供商&#xff0c;AWS为全球开发者提供了超过170项随时可用的服务。 例如&#xff0c;Adobe能够独立于IT团队开发和更新软件。通过AWS的服务&…

Python爬虫第17节-动态渲染页面抓取之Selenium使用下篇

目录 引言 一、获取节点信息 1.1 获取属性 1.2 获取文本值 1.3 获取ID、位置、标签名、大小 二、切换Frame 三、延时等待 3.1 隐式等待 3.2 显式等待 四、前进后退 五、Cookies 六、选项卡管理 七、异常处理 引言 这一节我们继续讲解Selenium的使用下篇&#xff0…

容器docker入门学习

这里写目录标题 容器容器的软件厂商 dockerdocker引擎 虚拟化虚拟化技术 docker安装详解1、安装检查2、安装yum相关的工具3、安装docker-ce软件4、查看docker版本5、启动docker服务6、设置docker开机启动7、查看有哪些docker容器运行进程8、查看容器里有哪些镜像9、下载nginx软…

文献总结:NIPS2023——车路协同自动驾驶感知中的时间对齐(FFNet)

FFNet 一、文献基本信息二、背景介绍三、相关研究1. 以自车为中心的3D目标检测2. 车路协同3D目标检测3. 特征流 四、FFNet网络架构1. 车路协同3D目标检测任务定义2. 特征流网络2.1 特征流生成2.2 压缩、传输与解压缩2.3 车辆传感器数据与基础设施特征流融合 3. 特征流网络训练流…

git 出现 port 443 Connection timed out

梯子正常延迟不算严重&#xff0c;但在使用git push时反复出现 fatal: unable to access https://github.com/irvingwu5/xxxx.git/ Error in the HTTP2 framing layer Failed to connect to github.com port 443 after 136353 ms: Connection timed out 将git的网络配置与梯子…

【2025年4月18日】android studiio最新设置沉浸式状态栏教程

&#x1f62b;【2025年4月18日】搞了一整天&#xff0c;终于完美搞定 Android 沉浸式状态栏&#xff08;WebView 本地HTML&#xff09; 最近在做一个个人项目&#xff0c;用 Android 加载本地 HTML 做个小工具。按理说用 WebView 加载页面很简单嘛——结果沉浸式状态栏这个坑…

如何删除 Launchpad 中 Chrome 的图标

有一天突然在 Launchpad 中出现下面的图标&#xff0c;在 Finder 的 Applications 中也没有&#xff0c;不知道如何删除。最终在《How to remove chrome app icons from launchpad?》中找到了答案。中文互联网上并没有搜到相关帖子&#xff0c;遂作记录。 解决办法很简单&am…