本帖最后由 znmcu 于 2012-8-31 13:49 编辑
===============================================
振南的znFAT 单片机上的FAT32文件系统
关注znFAT 加入振南的文件系统技术 QQ群 106889506
===============================================
实例源代码:
recorder.rar
(482.34 KB)
znFAT移植与应用手册:
znFAT移植与使用手册.pdf
(285.28 KB)
===============================================
“数据采集记录”实验,其实是我见到过的在文件系统方面最最常见的一种应用需求。在传统或者说一般情况下,我们是如何来存储和处理采集到的数据的呢?你也许是用这种方法:
1)下位机(单片机或嵌入式平台),对数据进行采集,直接通过串口或其它接口,比如
网口、USB或无线等等,将数据传给计算机。
2)下位机采集数据,先存入E2PROM或Flash中,然后将其拿到上位机,通过专门的
读取设备对数据进行读取。
第一种方法适用于上位机与下位机距离较短、采集数据量较少、工作环境较为理想的场合;第二种方法则适用于上位机无法在现场、采集数据量比较大、工作环境比较恶劣的场合。其实很好理解,比如我们要在野外采集一年的温度湿度数据,我们总不能一直放台电脑在那吧。这种情况下,我们就先将数据暂存在E2PROM或其它存储设备中,然后再通过专用设备,比如烧录器等,对其中的数据进行读取。
我们来专注于第二种数据采集的方案。应用这种方案的人们,会提出这样一个需求:“数据存到存储器中,能不能是以文件的方式,这样在向计算机导入的数据的时候,只需要文件拷贝就行了,而不再需要专门的数据读取设备!?”这样的一个需求将使应用变得更简单。要实现这样一个功能,我们需要使用文件系统!
存储器我们使用可以很方便与计算机进行连接的SD卡。我们要在SD卡上进行文件操作,要事先使用某种文件系统对其进行格式化,通常我们使用FAT32文件系统。其实,把SD卡格式化FAT32的过程,就像是在一张纸上打上了“格子”,我们要用单片机或其它的嵌入式CPU向其中写入数据,就要按照FAT32格式的规定和协议来写,这样数据才能被识别为文件!FAT32文件系统本身是较为复杂的,我们要使数据格式遵循它的协议,本身这个编程的工作量和难度都会很大。那我们应该如何实现以文件方式来写入数据呢?
可以使用振南的znFAT,这是一种与FAT32文件系统高度兼容的嵌入式FAT文件系统解决方案。它实质是一套C代码,主要目录就是实现FAT32文件系统中的各种文件操作。有了它,我们可以轻松实现上面我们所说的数据存储功能。
下面是一个 AVR 单片机平台上的,数据采集,并以文件方式记录数据的实例。
在这个实例中,我们通过AVR单片机采集实时钟芯片PCF8563的年月日时分秒的时间信息、温度传感器DS18B20的温度数据以及一路模拟量信号,由AVR单片机的片内ADC(10位精度)直接进行采集。我们在AVR单片机中对获取的这三种数据进行整理,转换为一个字符串,形如"12 8 31 10 52 31 578 35.5",即年 月 日 时 分 秒 ADC采样值 温度值。每秒钟采集一次数据,将转换后的字符串写入到SD卡根目录下的znmcu.txt这个文件中。最终的效果如下图:
此实例的代码编写使用WINAVR(AVR GCC),以下是实例的主要源代码文件:
实现上述功能的重要代码如下:
#include "avr/io.h"
#include "pcf8563.h"
#include "uart.h"
#include "myfun.h"
#include "adc.h"
#include "ds18b20.h"
#include "znfat/znfat.h"
//=============================================================
struct Time2 time;
struct znFAT_Init_Args Init_Args; //初始化参数集合
struct FileInfo fileinfo; //文件信息集合
unsigned char str[100]; //用于存储转换后的字符串
unsigned int format_data(char *s,struct Time2 *ptime,unsigned int adc,
unsigned int temprature)
{
//将时间、AD值及温度值合成字符串
}
int main()
{
int i=0,len=0,cur_sec=0;
DDRD=0XE3; //设置IO,PCF8563 使用 PB0与PB1 DS18B20使用PC0
//模拟量使用ADC0 SD卡使用 PA7-4
DDRA=0XEe;
DDRB=0X83;
DDRC=0XFF;
//===============================================================
UART_Init();
UART_Send_Str("uart init ok.\r\n");
znFAT_Device_Init(); //存储设备初始化
UART_Send_Str("sd init ok.\r\n");
znFAT_Select_Device(0,&Init_Args); //选择设备
znFAT_Init(); //文件系统初始化
UART_Send_Str("znFAT init OK.\r\n");
//输出文件系统相关信息
time.year =12; //向time中装入要设置的时间数据 2012.8.29 23:18:50 星期3
time.month = 8;
time.day =29;
time.hour =23;
time.minute=18;
time.second=50;
time.week = 3;
P8563_Set_Time(); //设置时间,即将time中的时间数据写入PCF8563
adc_enable(); //打开AVR内部ADC采样
//===============================================================
if(!znFAT_Open_File(&fileinfo,"/znmcu.txt",0,1)) //打开SD卡根目录下的znmcu.txt文件
{
UART_Send_Str("suc. to open file.\n");
//输出文件相关信息
znFAT_WriteData(&fileinfo,26,"年 月 日 时 分 秒 ADC 温度"); //写入数据头
str[0]=0x0d;str[1]=0x0a;
znFAT_WriteData(&fileinfo,2,str); //回车换行
for(i=0;i<5000;i++) //进行5000次循环,不过只有在秒值变化时才会写入数据
//即每秒写一次
{
P8563_Read_Time(); //读取时间
if(time.second!=cur_sec)
{
ds1820_start(); //启动DS18B20温度采样
len=format_data(str,&time,read_adc(),ds1820_read_temp()); //将时间、AD值与
//温度值转为字符串
znFAT_WriteData(&fileinfo,len,str); //将字符串写入文件
cur_sec=time.second; //更新当前秒值
}
}
znFAT_Close_File(&fileinfo); //关闭文件
znFAT_Flush_FS(); //刷新文件系统
}
else
{
UART_Send_Str("fail to open file.\r\n");
}
while(1);
}
硬件平台:
|