OneNET麒麟座应用开发之九:与SD卡通讯并保存数据
由于需要记录的数据量比较大,而且有些时候,有的用户不方便实时上传数据,所以要求使用SD卡存储数据然后人工收取上传。为此我们选择了一种通用的SD卡读写器。
1、读卡器简介
该读卡器整合 SD 卡规范和 FAT 文件格式规范,只要通过本模块规定的通讯协议就可以把数据存储在 SD 卡中的文件中。该读卡器连接方便采用串口通讯方式,如下图:
该读卡器摸块通讯协议比较简单,本模块的通讯协议分为命令发送和命令的应答两部分,其中命令格式由4个部分组成:命令识别码(0x55 0xAA),命令号,字节数(参数的个数,占2个字节,先发送低位字节,再发送高位字节),参数(根据命令的不同而不同),校验和(除命令识别码和校验和本身,所有发送数据之和的低 8 位数据)。命令格式如图:
应答分为两部分:命令的执行情况(编码将附录 1),数据。数据根据命令的不同而不同。
2、硬件连接
因为采用的是串口通讯,所以硬件的连接比较简单。麒麟座上的USART1(PA9:USART1_TX,PA10:USART1_RX)端口已经引到了J2端子排的J2_6和J2_5,所以我们就是用这一接口,至于5V电源和接地以及控制及状态信号悬着相应的引脚即可。
3、软件设计
接下来我们根据协议编写读写SD卡的软件,主要实现状态检测、创建文件、打开文件、写文件、关闭文件、保存文件以及获取文件信息等。
(1)获取系统的状态命令
获取系统的状态命令是用来获取模块当前的状态。命令编码是:0x01,命令格式如下:
//检测系统SD卡的状态 uint8_t GetSDCardStatus(void){uint8_t CommandText[6]={0x55,0xAA,0x01,0x00,0x00,0x01};uint8_t StatusByte=0xaa;StatusByte = SendCommand(CommandText,6);Delayms(50);return StatusByte;}
(2)创建文件命令
创建文件命令提供给主机创建文件的功能。参数为 N 字节 8.3 文件格式的文件名(字符串格式,即文件名以 0 结尾),即 8 字节的基本文件名(模块不支持汉字编码,字母不区分大小写),3 字节扩展名。命令编码是:0x02,命令格式如下:
//创建文件,返回操作状态 uint8_t CreateFile(uint8_t fileName[8]){uint8_t CommandText[19]={0x55,0xAA,0x02,0x0D,0x00,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x2E,0x74,0x78,0x74,0x00,0x41};uint8_t StatusByte;StatusByte=0xaa;uint16_t i;for(i=0;i<8;i++){CommandText[i+5]=fileName[i];}uint8_t checksum=0x00;for(i=2;i<18;i++){checksum+=CommandText[i];}CommandText[18]=checksum;StatusByte = SendCommand(CommandText,19);return StatusByte;}
(3)打开文件命令
该命令为主机提供打开文件的功能。参数为 N 字节 8.3 文件格式的文件名(字符串格式,即文件名以0 结尾),即 8 字节的基本文件名(模块不支持汉字编码,字母不区分大小写),3 字节扩展名。命令编码是:0x06命令格式如下,其中个数占 2 字节,低字节先发送:
//打开文件 uint8_t OpenFile(uint8_t fileName[8]){uint8_t CommandText[19]={0x55,0xAA,0x06,0x0D,0x00,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x2E,0x74,0x78,0x74,0x00,0x45};//打开文件命令 0x06 uint8_t StatusByte=0xaa;uint16_t i;for(i=0;i<8;i++){CommandText[i+5]=fileName[i];}uint8_t checksum=0x00;for(i=2;i<18;i++){checksum+=CommandText[i];}CommandText[18]=checksum;StatusByte = SendCommand(CommandText,19);return StatusByte;}
(4)获取文件信息命令
本命令为主机提供了读取当前打开文件的文件指针值和文件大小的功能。命令编码是:0x09,其命令格式如下:
//获取文件信息命令void GetFileStatus(uint8_t rxData[]){uint8_t CommandText[6]={0x55,0xAA,0x09,0x00,0x00,0x09};//获取文件信息命令0x09 uint16_t i;for(i=0;i<6;i++){//等待传送结束while(USART_GetFlagStatus(UART4, USART_FLAG_TXE) == RESET){}// 写一个字节到对应的串口传送数据寄存器 USART_SendData(UART4, CommandText[i]);}Delayms(20);for(i=0;i<9;i++){// 等待字节被对应的串口完全接收//while(USART_GetFlagStatus(UART4, USART_FLAG_RXNE) == RESET)//{//}// 获取接收到的字节 rxData[i] = USART_ReceiveData(UART4);}}
(5)写文件命令
该命令为主机提供向已打开文件中写入数据的功能。每写一个数据文件指针自动加1,当数据写完,文件指针指向最后一个数据地址加1的位置。命令编码是:0x05,命令格式如下,其中个数占2字节,低字节先发送,起始地址占4字节,低字节先发送:
//写文件,返回写操作的状态 uint8_t WriteToFile(uint8_t * address,uint8_t data[],uint16_t datalength){uint16_t count=datalength+10+19;uint8_t CommandText[70];uint8_t StatusByte=0xaa;uint16_t i;CommandText[0]=0x55;CommandText[1]=0xAA;CommandText[2]=0x05;CommandText[3]=datalength+4+19;CommandText[4]=0x00;CommandText[5]=0xFF;CommandText[6]=0xFF;CommandText[7]=0xFF;CommandText[8]=0xFF;for(i=0;i<datalength;i++){CommandText[i+9]=data[i];}CommandText[datalength+9]=(saveDate[0]/10)+0x30;CommandText[datalength+10]=(saveDate[0]%10)+0x30;CommandText[datalength+11]=0x2D;CommandText[datalength+12]=(saveDate[1]/10)+0x30;CommandText[datalength+13]=(saveDate[1]%10)+0x30;CommandText[datalength+14]=0x2D;CommandText[datalength+15]=(saveDate[2]/10)+0x30;CommandText[datalength+16]=(saveDate[2]%10)+0x30;CommandText[datalength+17]=0x20;CommandText[datalength+18]=(saveDate[3]/10)+0x30;CommandText[datalength+19]=(saveDate[3]%10)+0x30;CommandText[datalength+20]=0x3A;CommandText[datalength+21]=(saveDate[4]/10)+0x30;CommandText[datalength+22]=(saveDate[4]%10)+0x30;CommandText[datalength+23]=0x3A;CommandText[datalength+24]=(saveDate[5]/10)+0x30;CommandText[datalength+25]=(saveDate[5]%10)+0x30;CommandText[datalength+26]=0x0D;CommandText[datalength+27]=0x0A;uint8_t checksum=0x00;for(i=2;i<count-1;i++){checksum+=CommandText[i];}CommandText[count-1]=checksum;StatusByte = SendCommand(CommandText,count);return StatusByte;}
(6)保存文件命令
该命令为主机提供保存当前打开文件的功能,为了防止频繁写 SD 卡,每次送入模块的数据先是保存在模块的 512 字节的扇区缓冲中,所以为了防止数据丢失,完成所有数据的传输后,要发送保存文件命令来保存文件。命令编码是:0x04,命令格式如下:
//保存文件,返回操作执行状态 uint8_t SaveFile(void){uint8_t CommandText[6]={0x55,0xAA,0x04,0x00,0x00,0x04};//保存文件命令 0x04 uint8_t StatusByte=0xaa;StatusByte = SendCommand(CommandText,6);return StatusByte;}
(7)关闭文件命令
该命令为主机提供关闭当前打开的文件的功能。在创建文件、创建文件夹、打开文件之前要求关闭当前打开的文件,才可以执行这些命令,否则返回失败。命令编码是:0x08,命令格式如下:
//关闭文件,返回操作执行状态 uint8_t CloseFile(void){uint8_t CommandText[19]={0x55,0xAA,0x08,0x00,0x00,0x08};//关闭文件命令 0x08 uint8_t StatusByte=0xaa;StatusByte = SendCommand(CommandText,6);return StatusByte;}
编写完程序,我们测试以我们想要的格式写一些数据下去文件被保存为文本文件,以时间为文件名,数据格式与预期一致。至此SD卡读写完成。
转载于:https://www.cnblogs.com/foxclever/p/6958639.html
OneNET麒麟座应用开发之九:与SD卡通讯并保存数据相关推荐
- OneNET麒麟座应用开发之十:空气质量数据监测站项目总结
大气质量数据监测站用于测试空气质量监测及数据采集,实现野外或者室内空气质量的检测. 1.项目概述 本项目是一个定制项目,要求采集大气的压力.温度.湿度.PM25.位置等数据并上传到指定的后台服务器.但 ...
- OneNET麒麟座应用开发之二:串口读取PM25传感器数据
作为环境数据监测站首先要获取大气中可吸入颗粒物的数据.为了检测PM25数据,我们采用北京海联信为的HLPM025K3型号传感器,该传感器使用激光法测量PM25和PM10的数据. 该型传感器的检测对象如 ...
- MapReduce基础开发之九JDBC连接Hive
1.eclipse建工程,引入$HIVE_HOME/lib的包和$Hadoop_HOME/lib的包(一般核心包就可以,具体根据开发需求),导出jar包(不带第三方jar): 这里是Hive2,代码如 ...
- Android 开发之九:Camera 基础
有效像素 数码相机的像素数包括有效像素(Effective Pixels)和最大像素(Maximum Pixels).与最大像素不同的是有效像素数是指真正参与感光成像的像素值,而最高像素的数值是感光器 ...
- JAVAWEB开发之SpringMVC详解(二)——高级开发、数据回显、参数绑定集合、图片上传、json交互、validation校验、异常处理、RESTful支持、拦截器
知识回顾 springmvc框架 用户请求url到DispatcherServlet前端控制器,相当于中央调度器,降低系统各组件之间的耦合度. DispatcherServlet前端控制器通过Hand ...
- 区块链开发之Solidity编程基础(三)合约数据存储
Solidity编程基础三 概要 以太坊虚拟机 EVM 数据位置 storage/存储 memory/内存 calldata/调用数据 Stack 栈 数据赋值成本 概要 本章将进行太坊虚拟机EVM的 ...
- android 视频开发sd卡,Android开发之SD卡文件操作分析
本文实例讲述了Android开发之SD卡文件操作.分享给大家供大家参考,具体如下: 前面的文章中写过直接操作手机自带存储器的程序,这次就接着上次文章协议下对sd卡的文件操作.与自带存储不同的是使用sd ...
- FPGA开发之SD卡初始化
终于找到一篇说人话的了.使用下面的东西进行SD卡初始化,接着用命令进行读写操作看下一篇博客! 1.SD卡的官方资料(我承认这个资料很垃圾,比起民间的技术总结它的内容可谓又臭又长,但是作为基础也要了解一 ...
- 十六.linux开发之Kernel移植——内核的配置和编译原理
有道云笔记地址: 详情看这里链接,记录太多,就不一一排版了. http://note.youdao.com/noteshare?id=d25dbce79566963e3699574a74048154& ...
最新文章
- リストに項番をつける
- Java并发基础:了解无锁CAS就从源码分析 1
- 成田机场坐access到品川_@马大哈们:北京有三座机场了,以后订票别选错哦!大兴机场今试飞...
- 如何使用Gradle外部脚本进行项目构建
- 大二上学期数据结构课程设计
- 自媒体人本质是互联网公司内容运营的角色
- SMART PLC PID仿真 (SMART PID仿真库使用说明)
- 华为云内网DNS地址大全(不同区域DNS地址)
- android qq存储方式,android(5)(模拟QQ登录,文件存储,SD卡存储,SharedPreferences存储)...
- 这个 api 管理工具悄悄开源了,快来看看
- Layui数据表格的引用
- android语音控制歌曲播放,发条 - 支持音乐聚合搜索,歌单导入,语音控制的 APP - Android 应用 - 【最美应用】...
- 教你用Ossim平台检测网络的Shellcode攻击
- session里保存什么信息
- springboot文件上传报错:Required request part ‘file‘ is not present
- 稳压二极管工作原理、重要参数意义和典型电路参数计算
- npm编译报错You may need an additional loader to handle the result of these loaders
- 立创EDA入门3 通过51单片机最小板学习PCB设计
- 用matlab画饼状图和相量图
- 学校计算机语音室管理制度,多媒体、语音室管理制度
热门文章
- cdr 表格自动填充文字_极速office中表格的七个最常用技巧
- WebDAV之葫芦儿·派盘+Ever play播放器
- 【推荐】jquery开发的大型web应用—H5编辑器工具
- 二元函数最大最小值定理证明_求函数最小最大值定理的证明
- godaddy生成https 域名证书
- 【00】伪类选择符-魔芋的理解
- Flex使用ribbit.com的服务给手机发送短信SMS
- STM32F103C8T6在Arduino框架下驱动SH1106 1.3“ IIC OLED显示
- 利用WinPcap模拟网络包伪造飞秋闪屏报文
- 儿童发烧、高热,警惕病毒性感冒【程序员爸爸们学着点】