📄 at45d041大容量ic卡 读写程序.c
字号:
/*------------------------------------------------------------------------------
*/
/*------------------------------------------------------------------------------
*/
/* 文件名: IC.c
/*
/* AT45D041大容量IC卡 读写程序
/* 存储器容量为4325376位,分为2048页,每页有264字节,与缓存器的容量相等。
/* 0~1页保存系统信息(目录表大小,文件分配表大小,数据区大小,页的大小等)
/* 2~17页文件目录表 (每条文件目录为32字节,根最大目录数为128)
/* 18~33页文件分配表 (FAT16格式,分配表长度可根据卡的容量改变,AT45D041需16页)
/* 34~47页系统保留
/* >=48页为数据区
/*------------------------------------------------------------------------------
*/
#include <Reg51.h>
#include <String.h>
#define uchar unsigned char
#define WORD unsigned int
#define DWORD unsigned long
//系统信息结构
typedef struct
{
uchar VersionName[8]; //版本名称
uchar Version[3]; //版本号
uchar ICName[10]; //IC卡名称
DWORD ICPages; //IC卡共有多少页
WORD PageBytes; //每页包含的字节数
WORD DirStart; //根文件目录表开始页
WORD DirLength; //根文件目录表页面数
WORD FatStart; //文件分配表开始页
WORD FatLength; //文件分配表页面数
WORD DataStart; //数据区起始页
WORD DataLength; //数据区页面数
} _ICSysInfo;
//文件目录表结构,每条目录项32字节
typedef struct
{
uchar FileName[8]; /* 文件名称 */
uchar FileExt[3]; /* 文件扩展名 */
uchar FileAttr; /* 文件属性 */
uchar a[10]; /* 系统保留 */
WORD UpdateTime; /* 时间=小时*2048+分钟*32+秒+2 */
WORD UpdateDate; /* (年份-1980)*512+月份*32+日 */
WORD FirstPage; /* 文件首页号 */
DWORD FileSize; /* 文件字节数 */
} ICDirInfo;
//AT45D041卡的操作命令定义
typedef enum
{
PageRead = 0x52, //直接读页,缓存不变
Buf1Read = 0x54, //缓存1读
Buf2Read = 0x56, //缓存2读
PageToBuf1 = 0x53, //页读至缓存1
PageToBuf2 = 0x55, //页读至缓存2
PageCmpBuf1 = 0x60, //页与缓存1比较,比较结果在状态寄存器第6位
PageCmpBuf2 = 0x61, //页与缓存2比较,比较结果在状态寄存器第6位
Buf1Write = 0x84, //缓存1写
Buf2Write = 0x87, //缓存2写
Buf1ToPageWithErase = 0x83, //将缓存1写入页,包含页擦除动作
Buf2ToPageWithErase = 0x86, //将缓存2写入页,包含页擦除动作
Buf1ToPageWithoutErase = 0x88, //将缓存1写入页,不包含页擦除动作
Buf2ToPageWithoutErase = 0x89, //将缓存2写入页,不包含页擦除动作
PageWriteThroughBuf1 = 0x82, //数据先写入缓存1,再写入页,包含页擦
除
PageWriteThroughBuf2 = 0x85, //数据先写入缓存2,再写入页,包含页擦
除
PageRewriteThroughBuf1 = 0x58, //页读入缓存1,然后缓存1写入页
PageRewriteThroughBuf2 = 0x59, //页读入缓存2,然后缓存2写入页
StatusRead = 0x57 //读状态寄存器
} OpCode;
//文件分配表中页标记含义
const WORD code csFree = 0x0000; //未用的页
const WORD code csReserved = 0xfff0; //系统保留的页
const WORD code csError = 0xfff7; //坏页标记
const WORD code csFileEnd = 0xfff8; //文件中最后的页
const WORD code csNextMin = 0x0003; //下一页标记最小值
const WORD code csNextMax = 0xffef; //下一页标记最大值
const WORD code csEnd = 0xffff; //文件分配表结束
const WORD code SysInfoPage = 0; //保存系统信息的页
const WORD code DirStartPage = 2; //文件目录区首页
_ICSysInfo ICSysInfo;
/*------------------------------------------------------------------------------
*/
/* 供外部模块调用函数
/*------------------------------------------------------------------------------
*/
uchar FileCreate(uchar *FileName);
uchar FileOpen(uchar *FileName);
void FileClose(uchar *Handle);
int FileRead(uchar Handle, uchar *Buffer, int Start, int Count);
int FileWrite(uchar Handle, char *Buffer, int Start, int Count);
uchar FileExists(uchar* FileName);
bit FileDelete(uchar* FileName);
bit ICFormat(); /*格式化IC卡,并清除全部数据*/
bit ICDeleteAll(); /*全部清除IC卡数据*/
DWORD ICFreeSize(); /*获取可用空间,字节数*/
DWORD ICUsedSize(); /*获取已使用空间,字节数*/
DWORD ICTotalSize(); /*获取总空间,字节数*/
/*------------------------------------------------------------------------------
*/
/* 以下为内部函数,仅供模块内部调用
/*------------------------------------------------------------------------------
*/
void ICReadDirInfo(uchar IndexOfDir, ICDirInfo *DirInfo); /*读取目录信息*/
bit ICWriteDirInfo(uchar IndexOfDir, ICDirInfo *DirInfo); /*写入目录信息*/
void ICReadSysInfo(_ICSysInfo *ICInfo, WORD SysPage); /*读取IC卡系统信息*/
bit ICWriteSysInfo(_ICSysInfo *ICInfo, WORD SysPage); /*写入IC卡系统信息*/
WORD ICReadPageSign(WORD Page);
/*读页标记*/
bit ICWritePageSign(WORD Page,WORD Sign); /*写页标记*/
WORD ICFirstFreePage();
/*从头寻找第一个空闲的页*/
WORD ICNextFreePage(WORD StartPage);
/*寻找下一个空闲的页*/
uchar ICReadPageByte(WORD Page, WORD ByteAddr);
/*直接读页内容*/
uchar ICReadBuf1Byte(WORD ByteAddr);
/*读缓存1字节*/
uchar ICReadBuf2Byte(WORD ByteAddr);
/*读缓存2字节*/
void ICWriteBuf1Byte(WORD ByteAddr, uchar b);
/*写缓存1字节*/
void ICWriteBuf2Byte(WORD ByteAddr, uchar b);
/*写缓存2字节*/
bit ICBuf1CmpPage(WORD Page); /*比
较缓存1和页内容*/
bit ICBuf2CmpPage(WORD Page); /*比
较缓存2和页内容*/
void ICBuf1ToPage(WORD Page); /*缓
存1写入页*/
void ICBuf2ToPage(WORD Page); /*缓
存2写入页*/
void ICPageToBuf1(WORD Page); /*页
内容至缓存1*/
void ICPageToBuf2(WORD Page); /*页
内容至缓存2*/
// 根据根目录项索引获得页面号及页内字节地址
void ICDirIndexToPageByteAddr(uchar DirIndex, WORD *Page,WORD *ByteAddr);
bit ICWriteToPage(uchar *p, uchar Count, WORD Page, WORD ByteAddr);/* 将字符串
写入页*/
void ICWaitReady(); /*等
待IC卡准备好*/
uchar ICCommand(OpCode cmd, WORD Page,WORD ByteAddr); /* 所有命令的执行 */
uchar ICStatus(); /*读
IC卡状态*/
/*------------------------------------------------------------------------------
*/
/* 底层硬件操作函数
/*------------------------------------------------------------------------------
*/
sbit sCLK = P0^0;
sbit sDO = P0^1;
sbit sDI = P0^2;
sbit sCS = P0^3;
sbit a0 = ACC^0;
sbit a1 = ACC^1;
sbit a2 = ACC^2;
sbit a3 = ACC^3;
sbit a4 = ACC^4;
sbit a5 = ACC^5;
sbit a6 = ACC^6;
sbit a7 = ACC^7;
void ICWriteNextByte(uchar b); /*连续写下一个字节*/
uchar ICReadNextByte(); /*连续读下一个字节*/
void ICOutOpCode(OpCode cmd); /*发送命令字*/
void ICOutPage(WORD Page); /*发送页面地址*/
void ICOutByteAddr(WORD ByteAddr); /*发送字节地址*/
void ICOutXBits(uchar N); /*发送N个任意字符*/
/*------------------------------------------------------------------------------
*/
/* 以下为函数实现部分
/*------------------------------------------------------------------------------
*/
//----------------------------------------------------------------------------
uchar FileExists(uchar *FileName)
{
uchar i = 1;
char c;
ICDirInfo tempDir;
uchar *p = (uchar*)(&tempDir);
do
{
ICReadDirInfo(i,&tempDir);
c = strncmp(p,FileName,sizeof(tempDir.FileName));//+sizeof
(ICDirInfo->FileExt));
if (c==0)
return (i);
else
i++;
}while(i<128);
return (0);
}
//----------------------------------------------------------------------------
uchar FileCreate(uchar *FileName)
{
uchar i ;
ICDirInfo tempDir;
uchar *p = (uchar*)(&tempDir);
i = FileExists(FileName);
if (i!=0)
{
FileDelete(FileName);
}
do
{
ICReadDirInfo(i,&tempDir);
if (*p == 0x00)
{
//找到空闲的页
//设置文件名称,然后写入
ICWriteDirInfo(i,&tempDir);
return (i);
}
} while(i<128);
return (0);
}
//----------------------------------------------------------------------------
uchar FileOpen(uchar *FileName)
{
return (FileExists(FileName));
}
//----------------------------------------------------------------------------
void FileClose(uchar *Handle)
{
*Handle = 0x00;
}
//----------------------------------------------------------------------------
int FileRead(uchar Handle, uchar *Buffer, int Start, int Count)
{
int iResult = 0;
WORD iTemp,curPage,oldPage=0,numPage=0;
DWORD filelen;
ICDirInfo tempDir;
//判断文件句柄是否有效
if (Handle == 0x00)
return (-1);
//读取文件目录信息
ICReadDirInfo(Handle,&tempDir);
filelen = tempDir.FileSize;
curPage = tempDir.FirstPage;
//读取文件字节数据
while(Count>0 && Start<filelen)
{
do
{
iTemp = (numPage+1)*ICSysInfo.PageBytes;
if (Start > iTemp)
{
curPage = ICReadPageSign(curPage);
numPage++;
}
else
break;
} while(1);
if (oldPage != curPage) //判断是否在同一页
{
*Buffer++ = ICReadPageByte(curPage,(Start%
ICSysInfo.PageBytes));
oldPage = curPage;
}
else
{
*Buffer++ = ICReadNextByte();
}
Start++;
Count--;
iResult++; //读取字节数加一
}
return (iResult);
}
//----------------------------------------------------------------------------
int FileWrite(uchar Handle, char *Buffer, int Start, int Count)
{
int iResult = 0;
WORD iTemp,curPage,oldPage=0,numPage=0;
DWORD filelen;
ICDirInfo tempDir;
//判断文件句柄是否有效
if (Handle == 0x00)
return (-1);
//读取文件目录信息
ICReadDirInfo(Handle,&tempDir);
filelen = tempDir.FileSize;
curPage = tempDir.FirstPage;
//如果文件长度增加,分配空间,改变文件长度
//读取文件字节数据
while(Count>0)
{
do
{
iTemp = (numPage+1)*ICSysInfo.PageBytes;
if (Start > iTemp)
{
curPage = ICReadPageSign(curPage);
numPage++;
}
else
{
break;
}
} while(1);
if (oldPage != curPage) //判断是否在同一页
{
//更新缓存1数据至页
if (oldPage!=0)
{
ICBuf1ToPage(oldPage);
}
//读取新页内容至缓存1
ICPageToBuf1(curPage);
ICWriteBuf1Byte(Start%
ICSysInfo.PageBytes,*Buffer++);
oldPage = curPage;
}
else
{
ICWriteNextByte(*Buffer++);
}
Start++;
Count--;
iResult++; //读取字节数加一
}
return (iResult);
}
//----------------------------------------------------------------------------
bit FileDelete(uchar* FileName)
{
uchar i;
ICDirInfo tempDir;
uchar *p = (uchar *)(&tempDir);
WORD w,w1;
i = FileExists(FileName);
if (i!=0)
{
//根据文件分配表,将文件使用的页标记为空闲
ICReadDirInfo(i,&tempDir);
w = tempDir.FirstPage;
w1 = ICReadPageSign(w);
while (w1 != csFileEnd)
{
ICWritePageSign(w,csFree);
w = w1;
w1 = ICReadPageSign(w);
}
ICWritePageSign(w,csFree);
ICWritePageSign(w1,csFree);
//目录区标记文件删除,首字节置零
*p = 0x00;
ICWriteDirInfo(i,&tempDir);
}
return (1);
}
//----------------------------------------------------------------------------
bit ICFormat() /*格式化IC卡,并清除全部数据*/
{
bit b;
ICWriteSysInfo(&ICSysInfo,SysInfoPage); /*写入系统信息*/
ICDeleteAll(); /*删除全部数据*/
return (b);
}
//------------------------------------------------------------------------------
bit ICDeleteAll() /*全部清除IC卡数据*/
{
bit b = 1;
WORD i,j;
/*初始化写入文件目录表*/
for(i=ICSysInfo.DirStart;i<=ICSysInfo.DirLength;i++)
{
ICWriteBuf1Byte(i,0);
for(j=1;j<ICSysInfo.PageBytes;j++)
ICWriteNextByte(0);
ICBuf1ToPage(i);
ICWaitReady();
if (! ICBuf1CmpPage(i))
{
b = 0;
break;
}
}
if (!b) return (b);
/*初始化写入文件分配表*/
for(i=ICSysInfo.FatStart;i<=ICSysInfo.FatLength;i++)
{
ICWriteBuf1Byte(i,0);
for(j=1;j<ICSysInfo.PageBytes;j++)
ICWriteNextByte(0);
ICBuf1ToPage(i);
ICWaitReady();
if (! ICBuf1CmpPage(i))
{
b = 0;
break;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -