由于需要记录的数据量比较大,而且有些时候,有的用户不方便实时上传数据,所以要求使用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[]={0x55,0xAA,0x01,0x00,0x00,0x01};

  uint8_t StatusByte=0xaa;

  StatusByte = SendCommand(CommandText,);

  Delayms();

  return StatusByte;

}

2)创建文件命令

创建文件命令提供给主机创建文件的功能。参数为 N 字节 8.3 文件格式的文件名(字符串格式,即文件名以 0 结尾),即 8 字节的基本文件名(模块不支持汉字编码,字母不区分大小写),3 字节扩展名。命令编码是:0x02,命令格式如下:

//创建文件,返回操作状态

uint8_t CreateFile(uint8_t fileName[])

{

  uint8_t CommandText[]={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=;i<;i++)

  {

    CommandText[i+]=fileName[i];

  }

  uint8_t checksum=0x00;

  for(i=;i<;i++)

  {

    checksum+=CommandText[i];

  }

  CommandText[]=checksum;

  StatusByte = SendCommand(CommandText,);

  return StatusByte;

}

(3)打开文件命令

该命令为主机提供打开文件的功能。参数为 N 字节 8.3 文件格式的文件名(字符串格式,即文件名以0 结尾),即 8 字节的基本文件名(模块不支持汉字编码,字母不区分大小写),3 字节扩展名。命令编码是:0x06命令格式如下,其中个数占 2 字节,低字节先发送:

//打开文件

uint8_t OpenFile(uint8_t fileName[])

{

  uint8_t CommandText[]={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=;i<;i++)

  {

    CommandText[i+]=fileName[i];

  }

  uint8_t checksum=0x00;

  for(i=;i<;i++)

  {

    checksum+=CommandText[i];

  }

  CommandText[]=checksum;

  StatusByte = SendCommand(CommandText,);

  return StatusByte;

}

4)获取文件信息命令

本命令为主机提供了读取当前打开文件的文件指针值和文件大小的功能。命令编码是:0x09,其命令格式如下:

//获取文件信息命令

void GetFileStatus(uint8_t rxData[])

{

  uint8_t CommandText[]={0x55,0xAA,0x09,0x00,0x00,0x09};//获取文件信息命令0x09

  uint16_t i;

  for(i=;i<;i++)

  {

    //等待传送结束

    while(USART_GetFlagStatus(UART4, USART_FLAG_TXE) == RESET)

    {

    }

    // 写一个字节到对应的串口传送数据寄存器

    USART_SendData(UART4, CommandText[i]);

  }

  Delayms();

  for(i=;i<;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++;

  uint8_t CommandText[];

  uint8_t StatusByte=0xaa;

  uint16_t i;

  CommandText[]=0x55;

  CommandText[]=0xAA;

  CommandText[]=0x05;

  CommandText[]=datalength++;

  CommandText[]=0x00;

  CommandText[]=0xFF;

  CommandText[]=0xFF;

  CommandText[]=0xFF;

  CommandText[]=0xFF;

  for(i=;i<datalength;i++)

  {

    CommandText[i+]=data[i];

  }

  CommandText[datalength+]=(saveDate[]/)+0x30;

  CommandText[datalength+]=(saveDate[]%)+0x30;

  CommandText[datalength+]=0x2D;

  CommandText[datalength+]=(saveDate[]/)+0x30;

  CommandText[datalength+]=(saveDate[]%)+0x30;

  CommandText[datalength+]=0x2D;

  CommandText[datalength+]=(saveDate[]/)+0x30;

  CommandText[datalength+]=(saveDate[]%)+0x30;

  CommandText[datalength+]=0x20;

  CommandText[datalength+]=(saveDate[]/)+0x30;

  CommandText[datalength+]=(saveDate[]%)+0x30;

  CommandText[datalength+]=0x3A;

  CommandText[datalength+]=(saveDate[]/)+0x30;

  CommandText[datalength+]=(saveDate[]%)+0x30;

  CommandText[datalength+]=0x3A;

  CommandText[datalength+]=(saveDate[]/)+0x30;

  CommandText[datalength+]=(saveDate[]%)+0x30;

  CommandText[datalength+]=0x0D;

  CommandText[datalength+]=0x0A;

  uint8_t checksum=0x00;

  for(i=;i<count-;i++)

  {

    checksum+=CommandText[i];

  }

  CommandText[count-]=checksum;

  StatusByte = SendCommand(CommandText,count);

  return StatusByte;

}

6)保存文件命令

该命令为主机提供保存当前打开文件的功能,为了防止频繁写 SD 卡,每次送入模块的数据先是保存在模块的 512 字节的扇区缓冲中,所以为了防止数据丢失,完成所有数据的传输后,要发送保存文件命令来保存文件。命令编码是:0x04,命令格式如下:

//保存文件,返回操作执行状态

uint8_t SaveFile(void)

{

  uint8_t CommandText[]={0x55,0xAA,0x04,0x00,0x00,0x04};//保存文件命令 0x04

  uint8_t StatusByte=0xaa;

  StatusByte = SendCommand(CommandText,);

  return StatusByte;

}

7)关闭文件命令

该命令为主机提供关闭当前打开的文件的功能。在创建文件、创建文件夹、打开文件之前要求关闭当前打开的文件,才可以执行这些命令,否则返回失败。命令编码是:0x08,命令格式如下:

//关闭文件,返回操作执行状态

uint8_t CloseFile(void)

{

  uint8_t CommandText[]={0x55,0xAA,0x08,0x00,0x00,0x08};//关闭文件命令 0x08

  uint8_t StatusByte=0xaa;

  StatusByte = SendCommand(CommandText,);

  return StatusByte;

}

编写完程序,我们测试以我们想要的格式写一些数据下去文件被保存为文本文件,以时间为文件名,数据格式与预期一致。至此SD卡读写完成。

OneNET麒麟座应用开发之九:与SD卡通讯并保存数据的更多相关文章

  1. OneNET麒麟座应用开发之十:空气质量数据监测站项目总结

    大气质量数据监测站用于测试空气质量监测及数据采集,实现野外或者室内空气质量的检测. 1.项目概述 本项目是一个定制项目,要求采集大气的压力.温度.湿度.PM25.位置等数据并上传到指定的后台服务器.但 ...

  2. OneNET麒麟座应用开发之二:串口读取PM25传感器数据

    作为环境数据监测站首先要获取大气中可吸入颗粒物的数据.为了检测PM25数据,我们采用北京海联信为的HLPM025K3型号传感器,该传感器使用激光法测量PM25和PM10的数据. 该型传感器的检测对象如 ...

  3. Android开发之InstanceState详解(转)---利用其保存Activity状态

    Android开发之InstanceState详解   本文介绍Android中关于Activity的两个神秘方法:onSaveInstanceState() 和 onRestoreInstanceS ...

  4. UWP开发之Mvvmlight实践七:如何查找设备(Mobile模拟器、实体手机、PC)中应用的Log等文件

    在开发中或者后期测试乃至最后交付使用的时候,如果应用出问题了我们一般的做法就是查看Log文件.上章也提到了查看Log文件,这章重点讲解下如何查看Log文件?如何找到我们需要的Packages安装包目录 ...

  5. Android安全开发之ZIP文件目录遍历

    1.ZIP文件目录遍历简介 因为ZIP压缩包文件中允许存在“../”的字符串,攻击者可以利用多个“../”在解压时改变ZIP包中某个文件的存放位置,覆盖掉应用原有的文件.如果被覆盖掉的文件是动态链接s ...

  6. Cocos2d-x 3.x游戏开发之旅

    Cocos2d-x 3.x游戏开发之旅 钟迪龙 著   ISBN 978-7-121-24276-2 2014年10月出版 定价:79.00元 516页 16开 内容提要 <Cocos2d-x ...

  7. Android安全开发之WebView中的地雷

    Android安全开发之WebView中的地雷 0X01 About WebView 在Android开发中,经常会使用WebView来实现WEB页面的展示,在Activiry中启动自己的浏览器,或者 ...

  8. Android 安全开发之 ZIP 文件目录遍历

    1.ZIP文件目录遍历简介 因为ZIP压缩包文件中允许存在"../"的字符串,攻击者可以利用多个"../"在解压时改变ZIP包中某个文件的存放位置,覆盖掉应用原 ...

  9. Android开发之MdiaPlayer详解

    Android开发之MdiaPlayer详解 MediaPlayer类可用于控制音频/视频文件或流的播放,我曾在<Android开发之基于Service的音乐播放器>一文中介绍过它的使用. ...

随机推荐

  1. 受限玻尔兹曼机(Restricted Boltzmann Machine,RBM)

    这篇写的主要是翻译网上一篇关于受限玻尔兹曼机的tutorial,看了那篇博文之后感觉算法方面讲的很清楚,自己收获很大,这里写下来作为学习之用. 原文网址为:http://imonad.com/rbm/ ...

  2. 解决IIS8中 URLRewriter 不能使用的方法

    1.把应用程序池改成集成 2.的web.config 加入代码 <system.webServer> <validation validateIntegratedModeConfig ...

  3. 【BLUESKY的NOIp模拟赛】解题报告

     昨天晚上熬夜熬得有点严重,今天比赛的时候状态不好,成绩爆炸...  不得不说BLUESKY007 出的题还是相当不错的,也为我提醒了几个需要补的漏洞方向,这里作一下整理. \(Task 1\):探索 ...

  4. MUI 当input聚焦之后,弹出自带的键盘之后,内容往上移动

    1)有时候为了用户更好的体验,当input聚焦之后,手机自带的键盘弹出的时候,页面的内容也要跟着滚动,好让键盘不遮住input 只要把input标签放到mui-content这个类里面就可以了 < ...

  5. 数据正规化 (data normalization) 的原理及实现 (Python sklearn)

    原理 数据正规化(data normalization)是将数据的每个样本(向量)变换为单位范数的向量,各样本之间是相互独立的.其实际上,是对向量中的每个分量值除以正规化因子.常用的正规化因子有 L1 ...

  6. Hadoop生态圈-通过CDH5.15.1部署spark1.6与spark2.3.0的版本兼容运行

    Hadoop生态圈-通过CDH5.15.1部署spark1.6与spark2.3.0的版本兼容运行 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 在我的CDH5.15.1集群中,默 ...

  7. 运用Zabbix实现内网服务器状态及局域网状况监控(4) —— Zabbix客户端安装

    1.  创建用户 [root@zabbix ~]# groupadd zabbix [root@zabbix ~]# useradd -g zabbix zabbix 2. 安装zabbix_3.2 ...

  8. 从匿名函数(闭包特性)到 PHP 设计模式之容器模式

    匿名函数(匿名函数) 匿名函数,也叫闭包函数,它允许临时创建一个没有指定名称的函数,常用作回调函数参数的值,也可以作为变量的值来使用.具体的使用见以下示例代码: /* 示例一:声明一个简单匿名函数,并 ...

  9. python的特殊方法介绍

    __repr__.__str__ __len__.__getitem__.__setitem__.__delitem__.__contains__ __iter__.__reversed__.__ne ...

  10. Git查看单个文件修改历史

    1 命令 git log --pretty=oneline  文件名 ➜ admin git:(feature/v1.5.0_20181202_group) git log --pretty=onel ...