/******************************************************************************
I2C协议
模块I2C地址为0xA0
通讯速率为:400K。
发送数据格式:
模块地址+W/R 长度字 命令字 数据域 校验字
模块地址+W/R:
模块地址为:0xA0,写bit0为0,则写指令为:0xA0 + 0x0 = 0xA0
模块地址为:0xA0,读bit0为1,则读指令为:0xA0 + 0x1 = 0xA1
长度字:指明从长度字到数据域最后一字节的字节数。
命令字:本条命令的含义。
数据域:此项可以为空。
校验字:从长度字到数据域最后一字节的逐字节异或值(最后一字节)。
返回数据格式:
成功: 长度字 接收到的命令字+数据域 校验字
失败: 长度字 接收到的命令字取反 校验字
******************************************************************************/
#include "reg51.h"
#include "intrins.h"
#include "string.h"
#include "yy.h"
#define SUCCESS 0
#define FAILURE 1
/******************************************************************************
端口定义
******************************************************************************/
sbit LED_UART = P3^2; //串口循检指示
sbit LED_error = P3^4; //错误指示
sbit LED_ok = P3^5; //测试成功指示
sbit LED_zhishi = P3^3; //卡片进入射频场有效指示
sbit CARDPIN = P1^4; //检测模块的有卡指示
sbit SDA = P3^0;//P1^6; //IIC 数据
sbit SCL = P3^1;//P1^7; //IIC 时钟
sbit BEEP = P0^4; //蜂鸣器控制
void InitializeSystem();
void SendUart(unsigned char *g_cCommand);
void Err();
void ShowError(unsigned char cTimes);
unsigned char IicTesting(void);
void I2CStart(void);
void I2CStop(void);
bit I2CWaitAck(void);
void I2CSendAck(void);
void I2CSendNotAck(void);
void I2CSendByte(unsigned char cSendByte);
unsigned char I2CReceiveByte(void);
unsigned char Read_Iic_Data(unsigned char *cP);
unsigned char Send_IIC_Command(unsigned char *cP);
#include "main.h"
#define READ_M101XX 0xb1
#define WRITE_M101XX 0xb0
unsigned char g_cReceBuf[43]; //接收缓冲区
unsigned char g_cReceNum; //接收字节计数
bit g_bReceCommandOk; //接收命令正确标志
bit g_bCard; //卡片进入射频场标志
unsigned char ComSet[]
= {0x03,
COMM_CONTROL_ANTENNA,
0x11};
//设置打开天线和关闭自动循卡
unsigned char code ComSearchCard[]
= {0x03,
COMM_MIFARE_SEARCH_CARD,
0x00};
//循卡后读出卡号
unsigned char cReadBlock[13]
= {0x0A,
COMM_READ_BLOCK,
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
//读块No.4
unsigned char code ComReadBlock4[]
= {0x0A,
COMM_READ_BLOCK,
0x00, 0x04, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
//读块No.6
unsigned char code ComReadBlock6[]
= {0x0A,
COMM_READ_BLOCK,
0x00, 0x06, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
//写块No.4
unsigned char code ComWriteBlock4[]
= {0X1A,
COMM_WRITE_BLOCK,
0x00, 0x04, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
//初始化钱包No.5 的值为0x12345678
unsigned char code ComIntiPurse5[]
= {0x0E,
COMM_INIT_PURSE,
0x00, 0x05, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff , 0x78, 0x56, 0x34, 0x12};
//读钱包的值No.6
unsigned char code ComReadPurse6[]
= {0x0A,
COMM_READ_PURSE,
0x00, 0x06, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
//钱包值加2
unsigned char code ComIncrPurse5[]
= {0x0E,
COMM_INC_VALUE,
0x00, 0x05, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x00, 0x00, 0x00};
//钱包值减1
unsigned char code ComDecrPurse5[]
= {0x0E,
COMM_DEC_VALUE,
0x00, 0x05, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00};
// restore purse in block No.5 to block No.6
unsigned char code ComBakPurse56[]
= {0x0B,
COMM_BAK_PURSE,
0x00, 0x05, 0x06, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
// 卡片休眠
unsigned char code ComHaltCard[]
= {0x02,
COMM_CARD_HALT,
};
unsigned char code ComHaltMCU[]
= {0x02,
COMM_SET_MCU_IDLE,
};
// 钱包在 INC & DEC 后的结果
unsigned char code pursevalue[]
= {0x79,0x56,0x34, 0x12};
unsigned char code ComClrPA[]
= {0X03 ,
COMM_PA_OUT_CLR ,
0XFF};
unsigned char code ComSetPA[]
= {0X03 ,
COMM_PA_OUT_SET ,
0XFF};
unsigned char code ComClrPB[]
= {0X03 ,
COMM_PB_OUT_CLR ,
0X1F};
unsigned char code ComSetPB[]
= {0X03 ,
COMM_PB_OUT_SET ,
0X1F};
void Delay100uS(unsigned int i)
{
unsigned char m;
while(i--)
{
for(m = 0; m < 13; m++)
{
LED_zhishi = CARDPIN;
}
}
}
void main()*******************************************************
{
unsigned char i;
unsigned char cStatus;
InitializeSystem();
i=16;
BEEP = 0;
P0 = 0XFF;
P1 = 0XFF;
P2 = 0XFF;
P3 = 0XFF;
while(i--)
{
LED_ok = ~LED_ok;
LED_UART = ~LED_UART;
LED_error = ~LED_error;
LED_zhishi = ~LED_zhishi;
Delay100uS(500);
}
while (1)
{
g_bCard = !CARDPIN;
LED_zhishi = CARDPIN;
ES = 0;
cStatus = IicTesting(); // do IIC testing by AutoSearchCard
if (SUCCESS != cStatus) // if did not success, alarm error and show error code
{
Err(); //测试失败
g_bCard = !CARDPIN;
LED_zhishi = CARDPIN;
ShowError(cStatus);
continue;
}
LED_ok = 0; //测试成功
Delay100uS(500);
LED_ok = 1;
g_bCard = !CARDPIN;
LED_zhishi = CARDPIN;
i++;
}
}
unsigned char IicTesting(void)********************************
{
unsigned char cReadBlock[10]={0x0a, 0x21, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
unsigned char *cPa, *cPb;
unsigned char i;
unsigned char cStatus;
Send_IIC_Command(ComSet);
cStatus = Read_Iic_Data(g_cReceBuf);
if ((g_cReceBuf[1] != ComSet[1]) || cStatus != SUCCESS)
{
return 1;
}
//寻卡
cPa = ComSearchCard;
Send_IIC_Command(cPa);
cStatus = Read_Iic_Data(g_cReceBuf);
if ((g_cReceBuf[1] != cPa[1]) || cStatus != SUCCESS)
{
return 2;
}
cPa = ComSearchCard;
Send_IIC_Command(cPa);
cStatus = Read_Iic_Data(g_cReceBuf);
if ((g_cReceBuf[1] != cPa[1]) || cStatus != SUCCESS)
{
return 2;
}
//依次读出s50卡片中的16个扇区,64块的数据
for(i=0; i<64 ;i++)
{
cReadBlock[3] = i;
cPa = cReadBlock;
Send_IIC_Command(cPa);
cStatus = Read_Iic_Data(g_cReceBuf);
if ((g_cReceBuf[1] != cPa[1]) || cStatus != SUCCESS)
{
return 3;
}
Delay100uS(50);
}
//写块No.4
cPa = ComWriteBlock4;
Send_IIC_Command(cPa);
cStatus = Read_Iic_Data(g_cReceBuf);
if ((g_cReceBuf[1] != cPa[1]) || cStatus != SUCCESS)
{
return 4;
}
//读块No.4
cPa = ComReadBlock4;
Send_IIC_Command(cPa);
cStatus = Read_Iic_Data(g_cReceBuf);
if ((g_cReceBuf[1] != cPa[1]) || cStatus != SUCCESS)
{
return 5;
}
//比较数据
cPa = &ComWriteBlock4[10];
cPb = &g_cReceBuf[2];
if (memcmp(cPa, cPb, 16) != 0)
{
return 6;
}
//初始化No.5 作为钱包初值为0x12345678
cPa = ComIntiPurse5;
Send_IIC_Command(cPa);
cStatus = Read_Iic_Data(g_cReceBuf);
if ((g_cReceBuf[1] != cPa[1]) || cStatus != SUCCESS)
{
return 7;
}
//增值No.5 = "2"
cPa = ComIncrPurse5;
Send_IIC_Command(cPa);
cStatus = Read_Iic_Data(g_cReceBuf);
if ((g_cReceBuf[1] != cPa[1]) || cStatus != SUCCESS)
{
return 8;
}
//减值 "1"
cPa = ComDecrPurse5;
Send_IIC_Command(cPa);
cStatus = Read_Iic_Data(g_cReceBuf);
if ((g_cReceBuf[1] != cPa[1]) || cStatus != SUCCESS)
{
return 9;
}
//restore the purse in block No.5 to block No.6
cPa = ComBakPurse56;
Send_IIC_Command(cPa);
cStatus = Read_Iic_Data(g_cReceBuf);
if ((g_cReceBuf[1] != cPa[1]) || cStatus != SUCCESS)
{
return 10;
}
//读最后的值No.6
cPa = ComReadPurse6;
Send_IIC_Command(cPa);
cStatus = Read_Iic_Data(g_cReceBuf);
if ((g_cReceBuf[1] != cPa[1]) || cStatus != SUCCESS)
{
return 11;
}
*******************
cPa = pursevalue;
cPb = &g_cReceBuf[2];
if (memcmp(cPa, cPb, 4) != 0)
{
return 12;
}
***************************
cPa = ComHaltMCU;
Send_IIC_Command(cPa);
cStatus = Read_Iic_Data(g_cReceBuf);
if ((g_cReceBuf[1] != cPa[1]) || cStatus != SUCCESS)
{
return 13;
}
return SUCCESS;
}
/****************** 发光管错误指示******************************/
void ShowError(unsigned char cTimes)
{
Delay100uS(5000);
while (cTimes--)
{
LED_error = 0;
Delay100uS(1000);
LED_error = 1;
Delay100uS(1000);
}
}
/*******************************错误,蜂鸣器1s*****************************/
void Err()
{
BEEP = 1;
Delay100uS(1000);
BEEP = 0;
}
/*****************系统初始化***************************************/
void InitializeSystem()
{
TMOD = 0x21;
PCON |= 0x80;
SCON = 0xD0;
TH1 = 0xFD;
TL1 = TH1;
TR1 = 0;
IE |= 0x00;
}
/***************************IIC start condition***********************************/
void I2CStart(void)
{
SDA = 1;
_nop_();
SCL = 1;
_nop_();
SDA = 0;
_nop_();
_nop_();
SCL = 0;
}
/**************************IIC stop condition***********************************/
void I2CStop(void)
{
SCL = 0;
_nop_();
SDA = 0;
_nop_();
_nop_();
SCL = 1;
_nop_();
SDA = 1;
}
/*****************************************************************************
*IIC wait ACK
*****************************************************************************/
bit I2CWaitAck(void)
{
unsigned char cErrTime = 255;
SDA = 1;
_nop_();
_nop_();
SCL = 1;
_nop_();
while(SDA)
{
cErrTime--;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
if (0 == cErrTime)
{
I2CStop();
return FAILURE;
}
}
SCL = 0;
return SUCCESS;
}
/*****************************************************************************
*IC send ACK
*****************************************************************************/
void I2CSendAck(void)
{
_nop_();
SDA = 0;
_nop_();
_nop_();
SCL = 1;
_nop_();
SCL = 0;
}
/*****************************************************************************
*IIC send Not ACK
*****************************************************************************/
void I2CSendNotAck(void)
{
_nop_();
SDA = 1;
_nop_();
_nop_();
SCL = 1;
_nop_();
SCL = 0;
}
/*****************************************************************************
*IIC发送一个字节
*****************************************************************************/
void I2CSendByte(unsigned char cSendByte)
{
unsigned char data i = 8;
while (i--)
{
SCL = 0;
_nop_();
SDA = (bit)(cSendByte & 0x80);
cSendByte += cSendByte;
_nop_();
_nop_();
SCL = 1;
_nop_();
}
SCL = 0;
_nop_();
}
/*****************************************************************************
接收IIC一个字节
*****************************************************************************/
unsigned char I2CReceiveByte(void)
{
unsigned char data i = 8;
unsigned char data cR_Byte = 0;
SDA = 1;
while (i--)
{
cR_Byte += cR_Byte;
SCL = 0;
_nop_();
_nop_();
SCL = 1;
_nop_();
cR_Byte |= (unsigned char)SDA;
_nop_();
}
SCL = 0;
return cR_Byte;
}
/*****************************************************************************
读取IIC返回的数据
*****************************************************************************/
unsigned char Read_Iic_Data(unsigned char *cP)
{
unsigned char cCnt;
unsigned char cCheckSum = 0;
for (cCnt=0; cCnt<0xFF; cCnt++)
{
Delay100uS(1);
I2CStart();
I2CSendByte(READ_M101XX);
if (I2CWaitAck() == SUCCESS)
{
LED_UART = ~LED_UART;
break;
}
}
if (0xFF == cCnt)
{
return FAILURE;
}
cP[0]=2;
for (cCnt=0; cCnt<cP[0]; cCnt++) // in the protocol, cP[0] is the length of this data package
{
cP[cCnt] = I2CReceiveByte();
I2CSendAck();
cCheckSum ^= cP[cCnt];
}
cP[cCnt] = I2CReceiveByte();
I2CSendNotAck();
I2CStop();
if (cCheckSum != cP[cCnt])
{
return FAILURE;
}
else
{
return SUCCESS;
}
}
/*****************************************************************************
发送控制器命令
*****************************************************************************/
unsigned char Send_IIC_Command(unsigned char *cP)
{
unsigned char i;
unsigned char cCheckSum = 0;
I2CStart();
I2CSendByte(WRITE_M101XX);
if (I2CWaitAck() == SUCCESS)
{
for(i=0; i<cP[0]; i++)
{
cCheckSum ^= cP[i];
I2CSendByte(cP[i]);
if (I2CWaitAck() != SUCCESS)
{
return FAILURE;
}
}
I2CSendByte(cCheckSum);
if (I2CWaitAck() != SUCCESS)
{
return FAILURE;
}
I2CStop();
return SUCCESS;
}
else
{
return FAILURE;
}
}
//*******************************yy.h********************************************
#define COMM_MODULE_LOGIN_ON 0X00 //登记
#define COMM_SET_MCU_IDLE 0X04 //设置模块空闲睡眠模式
#define COMM_CONTROL_ANTENNA 0X05 //模块天线控制、自动寻卡设置
#define COMM_PA_OUT_SET 0X06 //PA口输出置位
#define COMM_PB_OUT_SET 0X07 //PB口输出置位
#define COMM_PA_OUT_CLR 0X08 //PA口输出清0
#define COMM_PB_OUT_CLR 0X09 //PB口输出清0
#define COMM_PA_DRAIN_OPEN 0X0A //PA口漏极开路设置
#define COMM_PB_DRAIN_OPEN 0X0B //PB口漏极开路设置
#define COMM_PA_INPUT 0X0C //PA口输入
#define COMM_PB_INPUT 0X0D //PB口输入
#define COMM_RS485_MODE 0X0E //RS485工作模式
#define COMM_INSIDE_CARD_CODE 0X0F //内部1000个卡号启动设置
#define COMM_WRITE_CARD_INTO 0X10 //写入卡号到模块内
#define COMM_READ_CARD_OUT 0X11 //读出卡号到模块内
#define COMM_WRITE_MODULE_ID 0X13 //设置设备标识
#define COMM_READ_MODULE_ID 0X14 //读取设备标识
#define COMM_SET_COM_BPS 0X15 //串口波特率设置
#define COMM_READ_HARDWARE_VERSION 0X16 //读取产品硬件版本
#define COMM_READ_SEARIAL_NUMBER 0X17 //读取产品序列号
#define COMM_WRITE_SEARIAL_NUMBER 0X18 //设置产品序列号
#define COMM_SELF_SEARCH_CARD 0X19 //主动寻卡
#define COMM_CONTROL_RED_LED 0X1A //控制红灯
#define COMM_CONTROL_GREEN_LED 0X1B //控制绿灯
#define COMM_CONTROL_YELLOW_LED 0X1C //控制黄灯
#define COMM_CONTROL_BUZZER 0X1D //控制蜂鸣器
#define COMM_CONTROL_CLR_KEY 0X1E //清除键值
#define COMM_CONTROL_DAT_DISPLAY 0X1F //发显示数据到显示终端
#define COMM_MIFARE_SEARCH_CARD 0X20 //TYPE-A寻卡
#define COMM_READ_BLOCK 0X21 //读块
#define COMM_READ_SECTOR 0X22 //读扇区
#define COMM_WRITE_BLOCK 0X23 //写块
#define COMM_INIT_PURSE 0X24 //初始化钱包
#define COMM_READ_PURSE 0X25 //读钱包
#define COMM_INC_VALUE 0X26 //充值
#define COMM_DEC_VALUE 0X27 //扣款
#define COMM_BAK_PURSE 0X28 //备份钱包值
#define COMM_CARD_HALT 0X29 //卡休眠
#define COMM_LOAD_KEY_AB 0X2A //下载密钥
#define COMM_READ_EEPROM 0X2B //读RC500EEPROM
#define COMM_WRITE_EEPROM 0X2C //写RC500EEPROM
#define COMM_HALT_ULTRA_LIGHT 0X32 //Halt Ultra Light卡
#define COMM_SEL_ULTRA_LIGHT 0X33 //选定一张Ultra Light卡
#define COMM_READ_ULTRA_LIGHT 0X34 //Ultra Light读卡
#define COMM_WRITE_ULTRA_LIGHT 0X35 //Ultra Light写卡
#define COMM_SET_SAM_BPS 0X36 //设置SAM卡波特率
#define COMM_RET_SAM 0X37 //SAM 卡复位1 字节波特率代码,0:9600;1:38400
#define COMM_SAM_COS 0X38 //SAM 卡COS 命令
#define COMM_SAM_CONFIGE 0X39 //SAM 卡硬件配置
#define COMM_SET_TYPE_AB_OTHER 0X3A //设定读卡模式TYPE A/B
#define COMM_SEARCH_AT88RF020 0X3E //寻卡88RF020
#define COMM_CHECK_AT88RF020_KEY 0X3F //验证88RF020密钥
#define COMM_READ_AT88RF020_BLOCK 0X40 //88RF020读块
#define COMM_WRITE_AT88RF020_BLOCK 0X41 //88RF020写块
#define COMM_AT88RF020_LOCK 0X42 //88RF020锁定
#define COMM_AT88RF020_COUNT 0X43 //88RF020计数
#define COMM_AT88RF020_HALT 0X44 //88RF020卡休眠
#define COMM_MIFARE1_CONFIG_RESTORE 0X45 //mifare one 恢复出厂
#define COMM_MIFARE1_PCD_REQUEST 0X46 //mifare one 寻卡
#define COMM_MIFARE1_PCD_ANTICOLL 0X47 //mifare one 防冲撞
#define COMM_MIFARE1_PCD_SELECT 0X48 //mifare one 选卡
#define COMM_AUTHENTICATION1 0X49 //认证1
#define COMM_AUTHENTICATION2 0X4A //认证2
#define COMM_PCD_READ_BLOCK 0X4B //无密码读块
#define COMM_PCD_WRITE_BLOCK 0X4C //无密码写块
#define COMM_PCD_INIT_PURSE 0X4D //无密码初始化钱包
#define COMM_PCD_READ_PURSE 0X4E //无密码读钱包
#define COMM_PCD_DEC_VALUE 0X4F //无密码减值
#define COMM_PCD_INC_VALUE 0X50 //无密码充值
#define COMM_PCD_RESTORE 0X51 //无密码将钱包值调入缓冲区
#define COMM_PCD_TRANSFER 0X52 //无密码保存缓冲区的值
#define COMM_PCD_TYPEA_HIGH_RST 0X53 //TYPEA CPU复位命令
#define COMM_PCD_TYPEA_HIGH_COS 0X54 //TYPEA CPU的COS命令
#define COMM_PCD_TYPEB_ATTRIB 0X55 //激活TYPE卡
#define COMM_RET_TYPE_B_CPU 0X3B //TYPE-BCPU 卡复位
#define COMM_TYPE_B_CPU_COS 0X3C //TYPE-B COS 命令
#define COMM_TYPE_B_CPU_HALT 0X3D //TYPE-B卡休眠
#define COMM_TYPE_B_ST_SELECT 0X60 //锁定一张ST卡
#define COMM_TYPE_B_ST_COMPLETION 0X61 //命令ST卡进入DESACTIVED状态
#define COMM_TYPE_B_READ_SR176 0X62 //读SR176卡1块数据
#define COMM_TYPE_B_WRITE_SR176 0X63 //写SR176卡1块数据
#define COMM_TYPE_B_PROTECT_SR176 0X64 //SR176卡块锁定
#define COMM_TYPE_B_READ_SRIX4K 0X65 //读SRIX4K卡1块数据
#define COMM_TYPE_B_WRITE_SRIX4K 0X66 //写SRIX4K卡1块数据
#define COMM_TYPE_B_AUATHENTICATE_SRIX4K 0X67 //SRIX4K卡鉴别操作
#define COMM_TYPE_B_GET_UID_SRIX4K 0X68 //获取SRIX4K卡UID
#define COMM_TYPE_B_LOCK_SRIX4K 0X69 //SRIX4K卡块锁定
#define COMM_CARD_LIGHT 0X6A
#define COMM_CARD_CL_DESELECT 0X6B
#define COMM_ISO15693_Inventory 0X70 //
#define COMM_ISO15693_Stay_Quiet 0X71 //
#define COMM_ISO15693_Select 0X72 //
#define COMM_ISO15693_Reset_Ready 0X73 //
#define COMM_ISO15693_Read 0X74 //
#define COMM_ISO15693_Write 0X75 //
#define COMM_ISO15693_Lock_Block 0X76 //
#define COMM_ISO15693_Write_AFI 0X77 //
#define COMM_ISO15693_Lock_AFI 0X78 //
#define COMM_ISO15693_Write_DSFID 0X79 //
#define COMM_ISO15693_Lock_DSFID 0X7A //
#define COMM_ISO15693_Get_System_Info 0X7B //
#define COMM_ISO15693_Get_Block_Security 0X7C //
#define COMM_125K_SEARCH_CARD 0x80
#define COMM_SET_3686KHZ 0XF1 //设置频率输出
#define COMM_PROGRAME_ISP 0xf2 //isp
#define COMM_PRODUCT_NAME 0xf3 //产品名字