从上高中开端,咱们学校用的餐卡就为触摸式的IC卡,在学校里还散布着许多的IC卡电话,上大学今后学校运用的学校一卡通,为非触摸式是射频式IC卡,因而对IC卡有了爱好,在学习单片机的过程中,了解到单片机能够完结IC卡的读写操控,在参阅有关材料的基础上,学习的运用单片机完结触摸式的IC卡读写操控。
首要器材:
1、AT89S8252单片机芯片,此芯片具有SPI接口,能够用来读写IC卡芯片。
2、运用与SPI接口兼容的串行数据接口的IC卡芯片AT45D041A,支撑在体系重编程,可用于数字语音、图画和数据的存储。
实验流程图:
实验电路图:
实验程序代码:
//ICRdWr.h程序
#ifndef_ICRDWR_H//避免ICRdWr.h被重复引证
#define_ICRDWR_H
#include //重要的头文件引证
#define uchar unsigned char
#define uint unsigned int
/*指令宏界说*/
#define BUFFER_1_WRITE 0x84// buffer1写指令代码
#define B1_TO_MM_PAGE_NO_ERA 0x88//无在线擦除的buffer1写主内存页指令代码
#define MM_PAGE_READ 0xD2//主内存页读指令代码
#define STAT_REG_READ 0xD7//状况寄存器读指令代码
#define DATA_IN_MAX_LEN 8
#define DATA_OUT_MAX_LEN 8
uint page_start_addr;//页中开始字节地址
uint page_addr;//页地址,16位中低9位为有用位
uint buf_start_addr;// buffer中开始字节地址,16位中低11位为有用位
uchar data_in[DATA_IN_MAX_LEN];//要写入IC卡的数据
uchar data_out[DATA_OUT_MAX_LEN];//要从IC卡中读出的数据
#endif
//ICRdWr.c程序
#include “ICRdWr.h”
/*延时t毫秒*/
void delay(uint t)
{
uint i;
while(t–)
{
/*关于11.0592M时钟,约延时1ms */
for (i=0;i<125;i++)
{}
}
}
/*获取需求存入IC卡数据的函数*/
void getdata()
{
//此函数简化如下:
uchar i;
for (i=0;i<8;i++)
data_in[i]=i+1;
}
/*写单片机AT89S8252的SPDR寄存器,数据经过SPI口串行输出给IC卡芯片*/
void write_spi(uchar dat)
{
SPDR = dat;
while (!(SPSR & 0x80)) ;//等候一次传输完结
}
/*获取IC卡芯片状况函数*/
uchar IC_stat(void)
{
P1_1 = 0;//使能IC卡芯片;/cs=0
write_spi(STAT_REG_READ);//写入读IC卡芯片状况指令
write_spi(0x00);//写无关比特
P1_1 = 1;//禁用IC卡芯片;/cs=1
return SPDR;//回来IC卡芯片状况字节
}
/*写IC卡芯片函数:将数据写入buffer,假如buffer满,
则将buffer中数据写入主内存页*/
void write_to_IC(uchar dat)
{
uchar stat;
/*查看IC卡芯片是否忙*/
stat = IC_stat();
while ((stat&0x80)==0x00);
/*数据写入buffer */
P1_1 = 0;//使能IC卡芯片;/cs=0
write_spi(BUFFER_1_WRITE);// buffer1写指令代码
write_spi(0x00);//写入8位无关位
write_spi((uchar)(buf_start_addr>>8));//写入7位无关位加上9位buffer开始字节地址的第1位
write_spi((uchar)buf_start_addr);//写入9位buffer开始字节地址的后8位
write_spi(dat);//写入数据
P1_1 = 1;//禁用IC卡芯片;完毕buffer write指令
buf_start_addr++;//下一buffer开始字节地址
/*假如buffer写满,则将buffer中数据写入主内存页*/
if (buf_start_addr > 263)
{
buf_start_addr = 0;// buffer开始字节地址重置0
if (page_addr < 2047)//假如主内存页不满
{
/* buffer数据写入主内存页*/
P1_1 = 0;//使能IC卡芯片;/cs=0
write_spi(B1_TO_MM_PAGE_NO_ERA);//写入无在线擦除的buffer1写主内存页指令代码
write_spi((uchar)(page_addr>>7));//写入4位保存位加上11位页地址的高4位
write_spi((uchar)(page_addr<<1));//写入11位页地址的低7位和1位无关位
write_spi(0x00);//再写入8位无关位
P1_1 = 1;//禁用IC卡芯片;完毕无在线擦除的buffer写主内存页指令
page_addr++;//下一页地址
}
}
}
/*读IC卡芯片函数,假如一页读完,则读取下一页*/
uchar read_from_IC()
{
uchar stat;
uchar tmp;
/*查看IC卡芯片是否忙*/
stat = IC_stat();
while ((stat&0x80)==0x00);
/*从主内存页中读出数据*/
P1_1 = 0;//使能IC卡芯片;/cs=0
write_spi(MM_PAGE_READ) ;//写入主内存页读指令代码
tmp = (uchar)(page_addr>>7);
write_spi(tmp);//写入4位保存位加上11位页地址的高4位
tmp = (uchar)(page_addr<<1)|((uchar)(page_start_addr>>8)&0x01);
write_spi(tmp);//写入11位页地址的低7位和9位页开始字节地址的最高位
tmp = (uchar)(page_start_addr);
write_spi(tmp);//写入9位页开始字节地址的低8位
write_spi(0x00) ;//写入8位无关位
write_spi(0x00) ;//写入8位无关位
write_spi(0x00) ;//写入8位无关位
write_spi(0x00) ;//再写入8位无关位,共写入32位无关位
write_spi(0xff) ;//写入8位无意义值以保证完结一字节数据的读出
P1_1 = 1;//禁用IC卡芯片;完毕主内存页读指令
page_start_addr++;//下一页中开始字节地址
/*假如读完一页,则读取下一页*/
if (page_start_addr > 263)
{
page_start_addr = 0;//页开始字节地址重置0
if (page_addr < 2047)//假如主内存页没有读完
page_addr++;//下一页地址
}
return SPDR;//回来读出数据
}
接上篇程序:
/*主函数*/
void main()
{
uchar i;
P1_0 = 1;// /RST引脚置高
/* SPIE=0,SPE=1,DORD=0,MSTR=1,CPOL=CPHA=1,SPR1=0,SPR0=1*/
SPCR=0x5d;
buf_start_addr = 0;
page_start_addr = 0;
page_addr = 0;
/*获取需求写入IC卡的数据,寄存在data_in[]中*/
getdata();
/*将data_in[]中寄存数据写入IC卡*/
for (i=0;i { write_to_IC(data_in[i]); delay(2);//延时2ms }
delay(10);//延时10ms
buf_start_addr = 0;
page_start_addr = 0;
page_addr = 0;
/*数据读出IC卡,寄存在data_out[]中*/
for (i=0;i { data_out[i] = read_from_%&&&&&%(); delay(2);//延时2ms }
while(1);
}