本帖最后由 lbq691477940 于 2014-11-18 23:56 编辑
由STC12C5A60S2+RC522构成的IC卡读卡器
读出的卡号从串口返回
RC522 非接触式IC卡读卡模块 采用I2C接口通信方式占用CPU I/O口最少,非SPI通信接口方式。
外观尺下:62X34mm
插针间距: 7Pin x 2.54mm
本模块非SPI通信接口方式,采用I2C接口通信方式占用CPU I/O口最少;从机器件地址为:0x00H
有需要IC卡读卡模块的点这:RC522 非接触式IC卡读卡模块
http://item.taobao.com/item.htm?spm=686.1000925.0.0.zmdRBz&id=42037523587
有此模块的可以提供完整的读写卡源码
/***********************************************************************************************************/
#include <STC12C5A60S2.h>
#define uchar unsigned char
#define uint unsigned int
/***********************************************************************************************************/
//端口定义
//MFRC522
sbit SDA = P1^4;
sbit SCL = P1^5;
// sbit SDA = P0^4;//IO2
// sbit SCL = P0^5;//IO1
sbit BEEP = P2^3; //BZ
sbit LED_GREEN = P1^7;
/***********************************************************************************************************/
void InitializeSystem(); //系统初始化
#define BAUD_115200 256 - (OSC_FREQ / 192L) / 115200L // 255
#define BAUD_57600 256 - (OSC_FREQ / 192L) / 57600L // 254
#define BAUD_38400 256 - (OSC_FREQ / 192L) / 38400L // 253
#define BAUD_28800 256 - (OSC_FREQ / 192L) / 28800L // 252
#define BAUD_19200 256 - (OSC_FREQ / 192L) / 19200L // 250
#define BAUD_14400 256 - (OSC_FREQ / 192L) / 14400L // 248
#define BAUD_9600 256 - (OSC_FREQ / 192L) / 9600L // 244
#define OSC_FREQ 22118400L
#define RCAP2_50us 65536L - OSC_FREQ / 40417L
#define RCAP2_1ms 65536L - OSC_FREQ / 2000L
#define RCAP2_10ms 65536L - OSC_FREQ / 1200L
#define TIME0_500us 65536L - OSC_FREQ / 8000L
#define TIME0_10ms 65536L - OSC_FREQ / 200
#define CALL_isr_UART() TI = 1
#define TRUE 1
#define FALSE 0
/***********************************************************************************************************/
/***********************************************************************************************************
由STC12C5A60S2+RC522构成的IC卡读卡器
CPU = STC12C5A60S2
OSC = 22.1184Mhz
功能简介:
具有串口波特率可更改和同一张卡防重读功能,即如果同一张卡如果一直放在感应区域中只读一次,只有离开感应区域
再次进入时才重新读取每成功读一次会返回扇区0的块0~3的内容即共64个字节,和蜂鸣器响一声,LED闪一次。
串口通信协议:串口波特率(默认为115200)
发送 0x02 0x0B + 0xXX 为打开蜂鸣器,后跟的参数0xXX为响的时长(可选值为1~255).并返回OK
发送 0x02 0x0D + 0xXX为更改波特率,后跟的参数(可选值为0~6)如下介绍.并返回OK
分别为:
0x00 = 9600
0x01 = 14400
0x02 = 19200
0x03 = 28800
0x04 = 38400
0x05 = 57600
0x06 = 115200
程序编辑:红尘有你 2014-11-18
/***********************************************************************************************************/
#include "STC12C5A60S2.H"
#include "main.H"
#include "mfrc522.H"
#include <string.H>
uchar code DefaultKey[6] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
uchar idata MLastSelectedSnr[4]; //存放4个字节的卡片序列号
uchar idata RevBuffer[70];
uchar data SerBuffer[4];
bit CmdValid; //串口接收完成标志位
/***********************************************************************************************************/
void InitializeSystem() //系统初始化
{
//P0 = P1 = P3 = 0xFF;
//P0M0 = 0x08;
BEEP = 1;
PCON = 0x80;
SCON = 0x70;
TMOD = 0x21; //TMOD = 0x22;
//TH1 = BAUD_9600;
TH1 = BAUD_115200;
TL1 = TH1;
TR1 = EA = ES = LED_GREEN = 1; //
PcdReset(); //复位RC522
PcdAntennaOff(); //关闭天线
PcdAntennaOn(); //开启天线
M500PcdConfigISOType('A'); //设置RC522的工作方式
BEEP = 1;
LED_GREEN = 0;
delay_10ms(5);
BEEP = 0;
LED_GREEN = 1;
delay_10ms(5);
BEEP = 1;
LED_GREEN = 0;
CmdValid = 0; //串口接收完成标志位清0
}
/***********************************************************************************************************/
void isr_UART(void) interrupt 4 using 1 //接收和发送中断
{
uchar len,i;
uint j = 0;
if(RI == 1) //接收中断
{
len = SBUF;
RI = 0;
for(i = 0;i < len;i++)
{
while(!RI)
{
j++;
if(j > 2000) //j的大小取值与晶体振荡器有关
{
break;
}
}
if(j < 2000) //j的大小取值与晶体振荡器有关
{
RevBuffer = SBUF;
RI = j = 0;
}
else
{
break;
}
}
if(i == len)
{
REN = 0; //禁止串口接收
CmdValid = 1; //串口接收完成标志位置1
}
}
else if(!RI && TI) //发送中断
{
TI = 0;
len = RevBuffer[0];
for(i = 1;i < len + 1;i++)
{
SBUF = RevBuffer;
while(!TI);
TI = 0;
}
REN = 1; //允许串口接收
}
}
/***********************************************************************************************************/
void main()
{
uchar baud,UltraLight;
InitializeSystem(); //系统初始化
// SBUF = ReadRawRC(VersionReg); //读取RC522芯片版本号,返回到串口输出
// while(!TI); //读取RC522芯片版本号,返回到串口输出
// TI = 0; //读取RC522芯片版本号,返回到串口输出
while(1)
{
/**********************************************************************************************************/
baud = PcdRequest(PICC_REQALL,&RevBuffer[1]); //寻卡/成功返回MI_OK
if(baud != MI_OK)//不为0表明无卡在感应区域内
{
baud = PcdRequest(PICC_REQALL,&RevBuffer[1]); //寻卡/成功返回MI_OK
if(baud != MI_OK)//表明无卡在感应区域内则将以下内存填上FF使其能进行下一次读卡
{
SerBuffer[0] = SerBuffer[1] = 0xff;
SerBuffer[2] = SerBuffer[3] = 0xff;
UltraLight = 0;
}
}
/**********************************************************************************************************
if(baud == MI_OK)//寻到卡后返回卡类型
{
ES = 0;
SBUF = RevBuffer[1];
while(!TI);
TI = 0;
SBUF = RevBuffer[2];
while(!TI);
TI = 0;
ES = 1;
}
/**********************************************************************************************************/
if((RevBuffer[1] == 0x44) && (RevBuffer[2] == 0x00)) //判断是否为超薄卡识别码为0x4400(例:深圳地铁卡)
{
UltraLight = 1; //超薄卡识别标志位置1
}
baud = PcdAnticoll(&RevBuffer[1]); //防冲撞/成功返回MI_OK以及将卡号存在RevBuffer数组内
/*********************************************************************************************************
if(baud == MI_OK)//防冲撞/成功返回
{
ES = 0;
SBUF = 0x11;
while(!TI);
TI = 0;
SBUF = 0x22;
while(!TI);
TI = 0;
ES = 1;
}
/**********************************************************************************************************/
memcpy(MLastSelectedSnr,&RevBuffer[1],4); //将RevBuffer[1]开始4个地址中的卡号复制到MLastSelectedSnr中
baud = PcdSelect(MLastSelectedSnr); //选定卡片/成功返回MI_OK
/**********************************************************************************************************
if(baud == MI_OK)//选定卡片/成功返回
{
ES = 0;
SBUF = 0x33;
while(!TI);
TI = 0;
SBUF = 0x44;
while(!TI);
TI = 0;
ES = 1;
}
/**********************************************************************************************************/
if(UltraLight) //如果是超薄卡不要密码验证就能读取扇区内数据
{
baud = PcdRead(0,&RevBuffer[1]); //读扇区0的页0~3
baud = PcdRead(4,&RevBuffer[17]); //读扇区0的页4~7
baud = PcdRead(8,&RevBuffer[33]); //读扇区0的页8~11
baud = PcdRead(12,&RevBuffer[49]); //读扇区0的页12~15
}
else //如果不是超薄卡要密码验证后才能读取扇区内数据
{
baud = PcdAuthState(PICC_AUTHENT1A,0,DefaultKey,MLastSelectedSnr); //0x60为校验卡A组密码、0x61则校验卡B组密码
/**********************************************************************************************************
if(baud == MI_OK)//校验卡A组密码成功后返回
{
ES = 0;
SBUF = 0x55;
while(!TI);
TI = 0;
SBUF = 0x66;
while(!TI);
TI = 0;
ES = 1;
}
/**********************************************************************************************************/
baud = PcdRead(0,&RevBuffer[1]); //读扇区0的块0
/**********************************************************************************************************
if(baud == MI_OK)//读扇区0的块0成功后返回
{
ES = 0;
SBUF = 0x77;
while(!TI);
TI = 0;
SBUF = 0x88;
while(!TI);
TI = 0;
ES = 1;
}
/**********************************************************************************************************/
baud = PcdRead(1,&RevBuffer[17]); //读扇区0的块1
baud = PcdRead(2,&RevBuffer[33]); //读扇区0的块2
baud = PcdRead(3,&RevBuffer[49]); //读扇区0的块3
}
if((memcmp(MLastSelectedSnr,SerBuffer,4) != 0) && (baud == 0))//相同为0
{
memcpy(SerBuffer,MLastSelectedSnr,4);//将MLastSelectedSnr中的4个值复制到SerBuffer中
RevBuffer[0] = 64; //共发送64个字节
CALL_isr_UART(); //将发送结束中断位置1
BEEP = 0;
LED_GREEN = 1;
delay_10ms(3);
BEEP = 1;
LED_GREEN = 0;
baud = PcdHalt(); //命令卡片进入休眠状态/成功返回MI_OK
}
/**********************************************************************************************************/
if(CmdValid) //串口接收完成标志位=1
{
CmdValid = 0; //串口接收完成标志位清0
if(RevBuffer[0] == 0x0B) //测试读卡器
{
baud = RevBuffer[1]; //先将上位机发来的蜂鸣时间暂存
RevBuffer[0] = 4; //共发送4个字节
RevBuffer[1] = 'O';
RevBuffer[2] = 'K';
RevBuffer[3] = 0x0D; //回车转行
RevBuffer[4] = 0x0A; //回车转行
CALL_isr_UART(); //将串口通信的TI标志位置1
LED_GREEN = 1;
BEEP = 0;
delay_10ms(baud);
LED_GREEN = 0;
BEEP = 1;
}
else if(RevBuffer[0] == 0x0D) //设置通讯波特率
{
switch(RevBuffer[1])
{
case 0:
baud = BAUD_9600;
break;
case 1:
baud = BAUD_14400;
break;
case 2:
baud = BAUD_19200;
break;
case 3:
baud = BAUD_28800;
break;
case 4:
baud = BAUD_38400;
break;
case 5:
baud = BAUD_57600;
break;
case 6:
baud = BAUD_115200;
break;
default:
baud = BAUD_9600;
break;
}
RevBuffer[0] = 4; //共发送4个字节
RevBuffer[1] = 'O';
RevBuffer[2] = 'K';
RevBuffer[3] = 0x0D; //回车转行
RevBuffer[4] = 0x0A; //回车转行
CALL_isr_UART();
BEEP = 0;
delay_10ms(3);
BEEP = 1;
TR1 = 0;
TH1 = baud;
TL1 = TH1;
delay_10ms(2);
TR1 = TRUE;
}
else //如果不是以上二种情况则执行如下语句
{
RevBuffer[0] = 5; //共发送5个字节
RevBuffer[1] = 'E';
RevBuffer[2] = 'R';
RevBuffer[3] = 'R';
RevBuffer[4] = 0x0D; //回车转行
RevBuffer[5] = 0x0A; //回车转行
CALL_isr_UART();
BEEP = 0;
delay_10ms(3);
BEEP = 1;
delay_10ms(2);
BEEP = 0;
delay_10ms(2);
BEEP = 1;
delay_10ms(2);
BEEP = 0;
delay_10ms(2);
BEEP = 1;
}
}
/**********************************************************************************************************/
}
}
/***********************************************************************************************************/
|