如下,左边是单片机stc11f32x,右边是rfid小板
射频小板的主控芯片是rc522,可读iso 14443 type a卡,比如s50卡,店主送了两张。简介一下s50卡吧,
注:ICC(Integrated Circuit Card)为集成电路卡,CD(Coupling Device)指读写设备
s50卡的eeprom共16扇区;每扇区4块,共64块;每块16字节,则每扇区16x4=64字节,每卡64x16=1024字节,如下
所有块统一编址,每扇区的尾块是控制块,其余为数据块,但扇区1的块0特殊一点,记录了厂家序列号之类的,只读。
本例将数据存入扇区1的块4。对某扇区进行读写需要通过密码验证,密码保存在该扇区的控制块中。
先看连线,如下,左边是单片机右边是rc522的接口,rc522支持spi i2c 串口,但是stc11f32x却没有这些接口,所以stc11f32x只能模拟spi时序与rc522通讯,模拟用的引脚是
P0.5 MF_SDA(NSS片选)
P0.6 MF_SCK(时钟)
P0.7 MF_MOSI
P4.1 MF_MISO
P2.7 MF_RST
相关单片机程序如下
void InitRc522(void)//初始化rc522
{
PcdReset();
PcdAntennaOff();
PcdAntennaOn();
M500PcdConfigISOType( 'A' );
}
void InitAll(void)
{
Dlms(100);
InitPort();
Dlms(100);
InitLcd0108();
InitRc522();
EA=0;
init_time0();
uart_init();
EA=1; //re-enable interrupts
TimeShowMenu=0;
bShowMenu=0;
// bShowTime=1;
bWarn=0;
bPass=0;
SysTime=0;
KeyTime=0;
KeyNum=0;
bTimed=1;
bMenued=0;
bShowWelcome=1;
TimeShowMenu=250;
}
void ctrlprocess(void)
{
float data money_value;
// unsigned char ConsumedData;
unsigned char data ii;
char data status;
status=PcdRequest(PICC_REQIDL,&RevBuffer[0]);//寻天线区内未进入休眠状态的卡,返回卡片类型 2字节
if(status!=MI_OK)
{
return;
}
status=PcdAnticoll(&RevBuffer[2]);//防冲撞,返回卡的序列号 4字节
if(status!=MI_OK)
{
return;
}
if(!bShowMenu)
{
bShowMenu=1;
//bShowWelcome=0;
bTimed=0;
bMenued=1;
ShowMenu();
}
TimeShowMenu=0;
//Clear88(0,5,2,8);
Clear88(2,5,2,8);
Clear88(4,5,2,8);
//Clear88(6,5,2,8);
memcpy(MLastSelectedSnr,&RevBuffer[2],4);
for(ii=0;ii<4;ii++)
{
Show816(0,5+2*ii,(MLastSelectedSnr[ii]>>4)&0x0f);
Show816(0,6+2*ii,MLastSelectedSnr[ii]&0x0f);
}
status=PcdSelect(MLastSelectedSnr);//选卡
if(status!=MI_OK)
{
return;
}
if(oprationcard==REGCARD)//注册
{
status=PcdAuthState(PICC_AUTHENT1A,7,LastKeyA,MLastSelectedSnr);//????KUAI4?
//DelayNS(1);
if(status!=MI_OK)
{
bWarn=1;
return;
}
status=PcdWrite(7,&NewKey[0]);
if(status!=MI_OK)
{
bWarn=1;
return;
}
for(ii=0;ii<16;ii++)
{
Write_First_Data[ii]=0xaa;
}
status=PcdWrite(4,&Write_First_Data[0]);
if(status!=MI_OK)
{
bWarn=1;
return;
}
bPass=1;
PcdHalt();
}
else if(oprationcard==READCARD)//读卡
{
status=PcdAuthState(PICC_AUTHENT1A,7,NewKeyA,MLastSelectedSnr);//????KUAI4?
if(status!=MI_OK)
{
return;
}
status=PcdRead(4,Read_Data);
if(status!=MI_OK)
{
bWarn=1;
return;
}
for(ii=0;ii<16;ii++)
{
Write_First_Data[ii]=0xaa;
}
status=PcdWrite(4,&Write_First_Data[0]);
for(ii=0;ii<4;ii++)
{
fltchr.chr[ii]=Read_Data[ii];
sendchar1(fltchr.chr[ii]);
}
//ShowFloat816(4,5,fltchr.flt);
ShowFloat816(4,5,fltchr.flt);
if(fltchr.flt<0)
{
bWarn=1;
}
bPass=1;
PcdHalt();
}
else if(oprationcard==CONSUME)//消费
{
status=PcdAuthState(PICC_AUTHENT1A,7,NewKeyA,MLastSelectedSnr);//????KUAI4?
if(status!=MI_OK)
{
return;
}
status=PcdRead(4,Read_Data);
if(status!=MI_OK)
{
bWarn=1;
return;
}
for(ii=0;ii<4;ii++) //
{
fltchr.chr[ii]=Read_Data[ii];
sendchar1(fltchr.chr[ii]);
}
money_value=fltchr.flt;
if(money_value<-100)
{
money_value=-100;
}
if(money_value<0)
{
money_value+=100;
}
fltchr.flt=money_value-2.5;
for(ii=0;ii<4;ii++)
{
Write_Consume_Data[ii]=fltchr.chr[ii];
}
status=PcdWrite(4,&Write_Consume_Data[0]);
for(ii=0;ii<4;ii++)
{
sendchar1(fltchr.chr[ii]);
}
if(status!=MI_OK)
{
bWarn=1;
return;
}
ShowFloat816(2,5,2.58);
ShowFloat816(4,5,fltchr.flt);
if(fltchr.flt<0)
{
bWarn=1;
}
else
{
bPass=1;
}
PcdHalt();
}
else if(oprationcard==ADDMONEY)//充值
{
status=PcdAuthState(PICC_AUTHENT1A,7,NewKeyA,MLastSelectedSnr);//????KUAI4?
if(status!=MI_OK)
{
return;
}
status=PcdRead(4,Read_Data);
if(status!=MI_OK)
{
bWarn=1;
return;
}
for(ii=0;ii<4;ii++)
{
fltchr.chr[ii]=Read_Data[ii];
}
money_value=fltchr.flt;
if(money_value<-100)
{
money_value=-100;
}
if(money_value<0)
{
money_value+=100;
}
fltchr.flt=money_value+50;
for(ii=0;ii<4;ii++)
{
Write_Consume_Data[ii]=fltchr.chr[ii];
}
//status=PcdWrite(4,&Write_Consume_Data[0]);
for(ii=0;ii<16;ii++) //向块4写入初始数值
{
Write_First_Data[ii]=0xaa;
}
status=PcdWrite(4,&Write_First_Data[0]); //
if(status!=MI_OK)
{
bWarn=1;
return;
}
ShowFloat816(2,5,50.00);
ShowFloat816(4,5,fltchr.flt);
bPass=1;
PcdHalt();
}
/*else
{
status=PcdAuthState(PICC_AUTHENT1A,7,NewKeyA,MLastSelectedSnr);//????KUAI4?
if(status!=MI_OK)
{
return;
}
status=PcdRead(4,Read_Data);
if(status!=MI_OK)
{
return;
}
for(ii=0;ii<4;ii++)
{
fltchr.chr[ii]=Read_Data[ii];
}
ShowFloat816(4,5,fltchr.flt);
PcdHalt();
}*/
}
void Warn(void)
{
uchar data ii;
for(ii=0;ii<3;ii++)
{
SET_BEEP;
delay_ms(120);
CLR_BEEP;
delay_ms(120);
}
}
void main(void)
{
InitAll();//其中调用InitRc522(),通过模拟spi输出数据初始化rfid模块
#pragma ASM
SETB P3.5
NOP
#pragma ENDASM
oprationcard=CONSUME;
//刚一上电,是消费模式。之后通过按键可以改变模式,并保存在oprationcard变量中
while(1)
{
KeyNum=GetKey();
// sendchar1(1);
if(bMenued)
{
if( (KeyNum==N_1)&&(!KeyTime) )
//if(!keytime)<=>if(keytime==0)
//当第一次按下k1时,keytime=0,所以执行之
//当第二次按下k1时, 如果此时距第一次按下k1的时间在15个time溢出周期内,不会执行之。否则执行之,
{
KeyTime=15;
TimeShowMenu=0; //卡片放在上面,从没有任何按键操作算起,超过250个time溢出周期,则会进入welcom页面,相当于待机时间
oprationcard=CONSUME;
sendchar1(KeyNum);
ShowHZ1616(2,0,4); //消
ShowHZ1616(2,2,5); //费
}
else if( (KeyNum==N_2)&&(!KeyTime) )
{
KeyTime=15;
TimeShowMenu=0;
oprationcard=ADDMONEY;
sendchar1(KeyNum);
ShowHZ1616(2,0,6); //充值
ShowHZ1616(2,2,7); //
}
else if( (KeyNum==N_3)&&(!KeyTime) )
{
KeyTime=15;
TimeShowMenu=0;
oprationcard=REGCARD;
sendchar1(KeyNum);
ShowHZ1616(2,0,10); //注册
ShowHZ1616(2,2,11); //
}
else if( (KeyNum==N_4)&&(!KeyTime) )
{
KeyTime=15;
TimeShowMenu=0;
oprationcard=READCARD;
sendchar1(KeyNum);
// sendchar1(55);
ShowHZ1616(2,0,12); //读卡
ShowHZ1616(2,2,13); //
}
}
if(bShowWelcome)
{
bShowWelcome=0;
bTimed=1;
bMenued=0;
ShowWelcome();
}
if(bWarn)
{
bWarn=0;
Warn();
}
if(bPass)
{
bPass=0;
Pass();
}
ctrlprocess();//rc522寻卡读写等函数
}
}
rc522.h
/
//MF522命令字
/
#define PCD_IDLE 0x00 //取消当前命令
#define PCD_AUTHENT 0x0E //验证密钥
#define PCD_RECEIVE 0x08 //接收数据
#define PCD_TRANSMIT 0x04 //发送数据
#define PCD_TRANSCEIVE 0x0C //发送并接收数据
#define PCD_RESETPHASE 0x0F //复位
#define PCD_CALCCRC 0x03 //CRC计算
/
//Mifare_One卡片命令字
/
#define PICC_REQIDL 0x26 //寻天线区内未进入休眠状态
#define PICC_REQALL 0x52 //寻天线区内全部卡
#define PICC_ANTICOLL1 0x93 //防冲撞
#define PICC_ANTICOLL2 0x95 //防冲撞
#define PICC_AUTHENT1A 0x60 //验证A密钥
#define PICC_AUTHENT1B 0x61 //验证B密钥
#define PICC_READ 0x30 //读块
#define PICC_WRITE 0xA0 //写块
#define PICC_DECREMENT 0xC0 //扣款
#define PICC_INCREMENT 0xC1 //充值
#define PICC_RESTORE 0xC2 //调块数据到缓冲区
#define PICC_TRANSFER 0xB0 //保存缓冲区中数据
#define PICC_HALT 0x50 //休眠
/
//MF522 FIFO长度定义
/
#define DEF_FIFO_LENGTH 64 //FIFO size=64byte
#define MAXRLEN 18
/
//MF522寄存器定义
/
// PAGE 0
#define RFU00 0x00
#define CommandReg 0x01
#define ComIEnReg 0x02
#define DivlEnReg 0x03
#define ComIrqReg 0x04
#define DivIrqReg 0x05
#define ErrorReg 0x06
#define Status1Reg 0x07
#define Status2Reg 0x08
#define FIFODataReg 0x09
#define FIFOLevelReg 0x0A
#define WaterLevelReg 0x0B
#define ControlReg 0x0C
#define BitFramingReg 0x0D
#define CollReg 0x0E
#define RFU0F 0x0F
// PAGE 1
#define RFU10 0x10
#define ModeReg 0x11
#define TxModeReg 0x12
#define RxModeReg 0x13
#define TxControlReg 0x14
#define TxAutoReg 0x15
#define TxSelReg 0x16
#define RxSelReg 0x17
#define RxThresholdReg 0x18
#define DemodReg 0x19
#define RFU1A 0x1A
#define RFU1B 0x1B
#define MifareReg 0x1C
#define RFU1D 0x1D
#define RFU1E 0x1E
#define SerialSpeedReg 0x1F
// PAGE 2
#define RFU20 0x20
#define CRCResultRegM 0x21
#define CRCResultRegL 0x22
#define RFU23 0x23
#define ModWidthReg 0x24
#define RFU25 0x25
#define RFCfgReg 0x26
#define GsNReg 0x27
#define CWGsCfgReg 0x28
#define ModGsCfgReg 0x29
#define TModeReg 0x2A
#define TPrescalerReg 0x2B
#define TReloadRegH 0x2C
#define TReloadRegL 0x2D
#define TCounterValueRegH 0x2E
#define TCounterValueRegL 0x2F
// PAGE 3
#define RFU30 0x30
#define TestSel1Reg 0x31
#define TestSel2Reg 0x32
#define TestPinEnReg 0x33
#define TestPinValueReg 0x34
#define TestBusReg 0x35
#define AutoTestReg 0x36
#define VersionReg 0x37
#define AnalogTestReg 0x38
#define TestDAC1Reg 0x39
#define TestDAC2Reg 0x3A
#define TestADCReg 0x3B
#define RFU3C 0x3C
#define RFU3D 0x3D
#define RFU3E 0x3E
#define RFU3F 0x3F
/
//和MF522通讯时返回的错误代码
/
#define MI_OK 0
#define MI_NOTAGERR (-1)
#define MI_ERR (-2)
#define SHAQU1 0X01
#define KUAI4 0X04
#define KUAI7 0X07
#define REGCARD 0xa1
#define CONSUME 0xa2
#define READCARD 0xa3
#define ADDMONEY 0xa4
sbit spi_cs=P0^5;
sbit spi_ck=P0^6;
sbit spi_mosi=P0^7;
sbit spi_miso=P4^1;
sbit spi_rst=P2^7;
#define SET_SPI_CS spi_cs=1
#define CLR_SPI_CS spi_cs=0
#define SET_SPI_CK spi_ck=1
#define CLR_SPI_CK spi_ck=0
#define SET_SPI_MOSI spi_mosi=1
#define CLR_SPI_MOSI spi_mosi=0
#define STU_SPI_MISO spi_miso
#define SET_RC522RST spi_rst=1
#define CLR_RC522RST spi_rst=0
http://download.csdn.net/detail/songqqnew/3716567