📄 test800m.c
字号:
/*******************************************************************************
* MF-800M模块测试程序
*功能:将Mifare_One卡的第一块写入数据0x00--0xFF
将第二块初始化为钱包,做充值扣款
*现象:所有操作成功后,指示灯闪烁提示
*条件:Mifare_One卡的A密钥为6字节0xFF,且具有读写权限
*******************************************************************************/
#include <reg52.h>
#include <string.h>
#define OSC_FREQ 11059200L
#define TIME0_10ms 65536L - OSC_FREQ/1200L
/*****************************************************************************
*端口定义
*****************************************************************************/
sbit LEDR = P2^0; //指示灯
sbit LEDG = P2^1; //指示灯
void InitializeSystem(); //系统初始化
void SendCom(unsigned char *g_cCommand); //向模块发送指令
void StartTime(unsigned int _MS); //启动计时,单位10ms
void StopTime();
//命令列表,不包含命令头0xaabb
// 长度字/命令码/数据
unsigned char code ComGetCsn[2]= {0x02, 0x10 }; //寻卡指令
unsigned char code ComReadBlock1[10]= {0x0A,0x11,0x00,0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; //读块指令:读第一块
unsigned char code ComWriteBlock1[26] = {0x1A,0x12,0x00,0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,
0xAA,0xBB,0xCC,0xDD,0xEE,0xFF}; //写块指令:写第一块,写入数据0x00--0xFF
unsigned char code ComIntiPurse2[14] = {0x0E,0x13,0x00,0x02,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0x78,0x56,0x34,0x12}; //初始化钱包:将第二块初始化为钱包格式,初始值为0x12345678
unsigned char code ComReadPurse2[10] = {0x0A,0x14,0x00,0x02,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; //读钱包值:读第二块钱包值
unsigned char code ComIncrPurse2[14] = {0x0E,0x15,0x00,0x02,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0x02,0x00,0x00,0x00}; //充值指令:将第二块钱包值加2
unsigned char code ComDecrPurse2[14] = {0x0E,0x16,0x00,0x02,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0x01,0x00,0x00,0x00}; //扣款指令:将第二块钱包值减1
unsigned char code ComRstMifarePro[2] = {0x02,0x20}; //复位Mifare_pro
unsigned char code ComCosMifarePro[7] = {0x07,0x21,0x00,0x84,0x00,0x00,0x04}; //取随机数指令
unsigned char code pursevalue[4]={0x79,0x56,0x34,0x12};
unsigned char g_cReceBuf[60]; //接收通讯缓冲区
unsigned char g_cReceNum; //接收的字节数
unsigned char g_cCommand; //接收到的命令字
unsigned char g_cStatus; //返回的状态字
unsigned char g_cWatchTime; //计时参数
unsigned char g_cCardType; //卡类型
bit g_bReceCommandOk; //接收到模块返回标志
bit g_bReceAA; //接收到AA字节标志
bit g_bSTI;
bit g_bTimeOut; //计时溢出标记
void main()
{
InitializeSystem();
//延时1S以等待模块可靠复位
StartTime(100);
while(!g_bTimeOut);
StopTime();
while(1)
{
//1.向模块发送寻卡指令,如果天线区内有M1卡执行步骤2,Mifare_Pro卡执行步骤8
//2.将Mifare_One卡的第一块写入数据0x00--0xFF
//2.读第一块并与写入的数据比较
//3.将第二块初始化为钱包格式,初始值为0x12345678
//4.将第二块钱包值加2
//5.将第二块钱包值减1
//6.读第二块钱包值并检查值的正确性
//7.红色指示灯闪烁提示,返回步骤1循环
//8.复位Mifare_Pro卡
//9.向Mifare_Pro卡发送取随机数指令
//10.绿色指示灯闪烁提示,返回步骤1循环
//1.向模块发送寻卡指令,如果天线区内有M1卡执行步骤2,Mifare_Pro卡执行步骤6
g_cCardType = 0xFF;
SendCom(ComGetCsn); //发送寻卡指令
StartTime(8); //启动计时
while (!g_bReceCommandOk && !g_bTimeOut); //等待接收,最大等待时间80ms
StopTime(); //停止计时
if ((g_cCommand==0x10) && (g_cStatus==0) && !g_bTimeOut)
{ g_cCardType = g_cReceBuf[7]; } //收到正确的返回
while ((g_cCardType == 0) || (g_cCardType == 1)) //对Mifare_One卡操作
{
//1.写第一块
SendCom(ComWriteBlock1);
StartTime(8);
while (!g_bReceCommandOk && !g_bTimeOut);
StopTime();
if ((g_cCommand!=0x12) || (g_cStatus!=0) || g_bTimeOut)
{ break; }
//2.读第一块并与上一步写入的数据比较
SendCom(ComReadBlock1);
StartTime(8);
while (!g_bReceCommandOk && !g_bTimeOut);
StopTime();
if ((g_cCommand!=0x11) || (g_cStatus!=0) || g_bTimeOut)
{ break; }
if (memcmp(&ComWriteBlock1[10], &g_cReceBuf[3], 16) != 0)
{ break; }
//3.将第二块初始化为钱包格式,初始值为0x12345678
SendCom(ComIntiPurse2);
StartTime(8);
while (!g_bReceCommandOk && !g_bTimeOut);
StopTime();
if ((g_cCommand!=0x13) || (g_cStatus!=0) || g_bTimeOut)
{ break; }
//4.将第二块钱包值加2
SendCom(ComIncrPurse2);
StartTime(8);
while (!g_bReceCommandOk && !g_bTimeOut);
StopTime();
if ((g_cCommand!=0x15) || (g_cStatus!=0) || g_bTimeOut)
{ break; }
//5.将第二块钱包值减1
SendCom(ComDecrPurse2);
StartTime(8);
while (!g_bReceCommandOk && !g_bTimeOut);
StopTime();
if ((g_cCommand!=0x16) || (g_cStatus!=0) || g_bTimeOut)
{ break; }
//6.读第二块钱包值
SendCom(ComReadPurse2);
StartTime(8);
while (!g_bReceCommandOk && !g_bTimeOut);
StopTime();
if ((g_cCommand!=0x14) || (g_cStatus!=0) || g_bTimeOut)
{ break; }
if (memcmp(&pursevalue[0],&g_cReceBuf[3],4) != 0)
{ break; }
//7.指示灯闪烁提示,返回步骤1循环
LEDR = 0;
StartTime(20);
while(!g_bTimeOut);
LEDR = 1;
StopTime();
break;
}
while (g_cCardType == 2)
{
//8.复位Mifare_Pro卡
SendCom(ComRstMifarePro);
StartTime(8);
while (!g_bReceCommandOk && !g_bTimeOut);
StopTime();
if ((g_cCommand!=0x20) || (g_cStatus != 0) || g_bTimeOut)
{ break; }
//9.向Mifare_Pro卡发送取随机数指令
SendCom(ComCosMifarePro);
StartTime(8);
while (!g_bReceCommandOk && !g_bTimeOut);
StopTime();
if ((g_cCommand!=0x21) || (g_cStatus != 0) || g_bTimeOut)
{ break; }
//10.指示灯闪烁提示,返回步骤1循环
LEDG = 0;
StartTime(20);
while(!g_bTimeOut);
LEDG = 1;
StopTime();
break;
}
}
}
/*****************************************************************************
* 系统初始化
*功能:BOUD=19200,由定时器1产生
* T0设为16位计时器
*****************************************************************************/
void InitializeSystem()
{
TMOD &= 0x0F;
TMOD |= 0x21;
PCON |= 0x80;
SCON = 0x50;
TH1 = 0xFD;
TL1 = 0xFD;
TR1 = 1;
IE |= 0x90;
}
/*****************************************************************************
*功能:启动计时
*****************************************************************************/
void StartTime(unsigned int _MS)
{
TH0 = (unsigned char)((TIME0_10ms>>8)&0xFF);
TL0 = (unsigned char)(TIME0_10ms&0xFF);
g_cWatchTime = _MS;
g_bTimeOut = 0;
ET0 = 1;
TR0 = 1;
}
/*****************************************************************************
*功能:T0中断-10MS
*****************************************************************************/
time0_int () interrupt 1 using 1
{
IT0 = 0;
TH0 = (unsigned char)((TIME0_10ms>>8) & 0xFF);
TL0 = (unsigned char)(TIME0_10ms & 0xFF);
if (g_cWatchTime--==0)
{ g_bTimeOut = 1; }
}
/*****************************************************************************
*功能:关闭计时
*****************************************************************************/
void StopTime()
{
ET0 = 0;
TR0 = 0;
}
/*****************************************************************************
*功能:向模块发送指令
*****************************************************************************/
void SendCom(unsigned char *g_cCommand)
{
unsigned char i,chkdata,sendleg;
g_bReceCommandOk = 0;
sendleg = *g_cCommand;
g_bSTI = 0;
SBUF = 0xAA;
while (!g_bSTI);
g_bSTI = 0;
SBUF = 0xBB;
while(!g_bSTI);
chkdata = 0;
for(i=0; i<sendleg; i++)
{
chkdata ^= *(g_cCommand+i);
g_bSTI = 0;
SBUF = *(g_cCommand+i);
while(!g_bSTI);
if (*(g_cCommand+i) == 0xAA) //除命令头外如遇到0xaa后跟一字节0x00以区分名头,长度字不变
{
g_bSTI = 0;
SBUF = 0;
while(!g_bSTI);
}
}
g_bSTI = 0;
SBUF = chkdata;
while (!g_bSTI);
if (chkdata == 0xAA)
{
g_bSTI = 0;
SBUF = 0;
while (!g_bSTI);
}
}
/*****************************************************************************
*功能:串行中断,接收模块返回的数据
* 将接收到的命令去掉命令头及数据中补零的字节,存入g_cReceBuf
*****************************************************************************/
seri_int () interrupt 4 using 1
{
unsigned char i;
unsigned char rece_data = SBUF;
unsigned char verify = 0;
if(RI)
{
RI=0;
if (g_bReceAA) //前一个接收到的字节=AA
{
g_bReceAA = 0;
switch (rece_data)
{
case 0x00:
break;
case 0xbb:
g_cReceNum = 0;
break;
default:
i = g_cReceNum;
g_cReceBuf[i] = rece_data;
break;
}
}
else
{
switch(rece_data)
{
case 0xaa:
g_bReceAA = 1;
default:
i = g_cReceNum++;
g_cReceBuf[i] = rece_data;
break;
}
}
i = g_cReceBuf[0];
if(g_cReceNum==i+1) //接收到的数据等于长度字,判断校验字
{
for (i=0; i<g_cReceBuf[0]+1; i++)
{
verify ^= g_cReceBuf[i];
}
if(!verify) //校验字正确取命令码
{
g_bReceCommandOk = 1;
g_cCommand = g_cReceBuf[1];
g_cStatus = g_cReceBuf[2];
g_cReceNum = 0;
}
}
if (g_cReceNum > sizeof(g_cReceBuf)) //接收数据溢出,清除
{ g_cReceNum = 0; }
}
if(TI)
{
TI = 0;
g_bSTI = 1;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -