單片機(jī)實(shí)現(xiàn)接觸式的IC卡讀寫控制
主要器件:
1、AT89S8252單片機(jī)芯片,此芯片具有SPI接口,可以用來讀寫IC卡芯片。
2、使用與SPI接口兼容的串行數(shù)據(jù)接口的IC卡芯片AT45D041A,支持在系統(tǒng)重編程,可用于數(shù)字語音、圖像和數(shù)據(jù)的存儲(chǔ)。
試驗(yàn)流程圖:
試驗(yàn)電路圖:
試驗(yàn)程序代碼:
//ICRdWr.h程序
#ifndef_ICRDWR_H//防止ICRdWr.h被重復(fù)引用
#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寫主內(nèi)存頁指令代碼
#define MM_PAGE_READ 0xD2//主內(nèi)存頁讀指令代碼
#define STAT_REG_READ 0xD7//狀態(tài)寄存器讀指令代碼
#define DATA_IN_MAX_LEN 8
#define DATA_OUT_MAX_LEN 8
uint page_start_addr;//頁中起始字節(jié)地址
uint page_addr;//頁地址,16位中低9位為有效位
uint buf_start_addr;// buffer中起始字節(jié)地址,16位中低11位為有效位
uchar data_in[DATA_IN_MAX_LEN];//要寫入IC卡的數(shù)據(jù)
uchar data_out[DATA_OUT_MAX_LEN];//要從IC卡中讀出的數(shù)據(jù)
#endif
//ICRdWr.c程序
#include "ICRdWr.h"
/*延時(shí)t毫秒*/
void delay(uint t)
{
uint i;
while(t--)
{
/*對(duì)于11.0592M時(shí)鐘,約延時(shí)1ms */
for (i=0;i<125;i++)
{}
}
}
/*獲取需要存入IC卡數(shù)據(jù)的函數(shù)*/
void getdata()
{
//此函數(shù)簡化如下:
uchar i;
for (i=0;i<8;i++)
data_in[i]=i+1;
}
/*寫單片機(jī)AT89S8252的SPDR寄存器,數(shù)據(jù)通過SPI口串行輸出給IC卡芯片*/
void write_spi(uchar dat)
{
SPDR = dat;
while (!(SPSR & 0x80)) ;//等待一次傳輸完成
}
/*獲取IC卡芯片狀態(tài)函數(shù)*/
uchar IC_stat(void)
{
P1_1 = 0;//使能IC卡芯片;/cs=0
write_spi(STAT_REG_READ);//寫入讀IC卡芯片狀態(tài)指令
write_spi(0x00);//寫無關(guān)比特
P1_1 = 1;//禁用IC卡芯片;/cs=1
return SPDR;//返回IC卡芯片狀態(tài)字節(jié)
}
/*寫IC卡芯片函數(shù):將數(shù)據(jù)寫入buffer,如果buffer滿,
則將buffer中數(shù)據(jù)寫入主內(nèi)存頁*/
void write_to_IC(uchar dat)
{
uchar stat;
/*檢查IC卡芯片是否忙*/
stat = IC_stat();
while ((stat&0x80)==0x00);
/*數(shù)據(jù)寫入buffer */
P1_1 = 0;//使能IC卡芯片;/cs=0
write_spi(BUFFER_1_WRITE);// buffer1寫指令代碼
write_spi(0x00);//寫入8位無關(guān)位
write_spi((uchar)(buf_start_addr>>8));//寫入7位無關(guān)位加上9位buffer起始字節(jié)地址的第1位
write_spi((uchar)buf_start_addr);//寫入9位buffer起始字節(jié)地址的后8位
write_spi(dat);//寫入數(shù)據(jù)
P1_1 = 1;//禁用IC卡芯片;結(jié)束buffer write指令
buf_start_addr++;//下一buffer起始字節(jié)地址
/*如果buffer寫滿,則將buffer中數(shù)據(jù)寫入主內(nèi)存頁*/
if (buf_start_addr > 263)
{
buf_start_addr = 0;// buffer起始字節(jié)地址重置0
if (page_addr < 2047)//如果主內(nèi)存頁不滿
{
/* buffer數(shù)據(jù)寫入主內(nèi)存頁*/
P1_1 = 0;//使能IC卡芯片;/cs=0
write_spi(B1_TO_MM_PAGE_NO_ERA);//寫入無在線擦除的buffer1寫主內(nèi)存頁指令代碼
write_spi((uchar)(page_addr>>7));//寫入4位保留位加上11位頁地址的高4位
write_spi((uchar)(page_addr<<1));//寫入11位頁地址的低7位和1位無關(guān)位
write_spi(0x00);//再寫入8位無關(guān)位
P1_1 = 1;//禁用IC卡芯片;結(jié)束無在線擦除的buffer寫主內(nèi)存頁指令
page_addr++;//下一頁地址
}
}
}
/*讀IC卡芯片函數(shù),如果一頁讀完,則讀取下一頁*/
uchar read_from_IC()
{
uchar stat;
uchar tmp;
/*檢查IC卡芯片是否忙*/
stat = IC_stat();
while ((stat&0x80)==0x00);
/*從主內(nèi)存頁中讀出數(shù)據(jù)*/
P1_1 = 0;//使能IC卡芯片;/cs=0
write_spi(MM_PAGE_READ) ;//寫入主內(nèi)存頁讀指令代碼
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位頁起始字節(jié)地址的最高位
tmp = (uchar)(page_start_addr);
write_spi(tmp);//寫入9位頁起始字節(jié)地址的低8位
write_spi(0x00) ;//寫入8位無關(guān)位
write_spi(0x00) ;//寫入8位無關(guān)位
write_spi(0x00) ;//寫入8位無關(guān)位
write_spi(0x00) ;//再寫入8位無關(guān)位,共寫入32位無關(guān)位
write_spi(0xff) ;//寫入8位無意義值以確保完成一字節(jié)數(shù)據(jù)的讀出
P1_1 = 1;//禁用IC卡芯片;結(jié)束主內(nèi)存頁讀指令
page_start_addr++;//下一頁中起始字節(jié)地址
/*如果讀完一頁,則讀取下一頁*/
if (page_start_addr > 263)
{
page_start_addr = 0;//頁起始字節(jié)地址重置0
if (page_addr < 2047)//如果主內(nèi)存頁沒有讀完
page_addr++;//下一頁地址
}
return SPDR;//返回讀出數(shù)據(jù)
}
接上篇程序:
/*主函數(shù)*/
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卡的數(shù)據(jù),存放在data_in[]中*/
getdata();
/*將data_in[]中存放數(shù)據(jù)寫入IC卡*/
for (i=0;i { write_to_IC(data_in[i]); delay(2);//延時(shí)2ms } delay(10);//延時(shí)10ms buf_start_addr = 0; page_start_addr = 0; page_addr = 0; /*數(shù)據(jù)讀出IC卡,存放在data_out[]中*/ for (i=0;i { data_out[i] = read_from_IC(); delay(2);//延時(shí)2ms } while(1); }
評(píng)論