2024年10月3日发(作者:丙雁凡)
#include "stm8s.h"
#include "uart.h"
void Delay(u32 nCount);
extern u8 RxBuffer[RxBufferSize];
extern u8 UART_RX_NUM;
unsigned char CT[2];//卡类型
unsigned char SN[4]; //卡号
unsigned char write[16] =
{0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0
x0E,0x0F,0x10}; unsigned char read[16] =
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0
x00,0x00,0x00}; unsigned char key[6] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
#define countof(a) (sizeof(a) / sizeof(*(a)))
#define BufferSize (countof(Tx_Buffer)-1)
u8 Tx_Buffer[] = "STM8S RFID TEST";
u8 Rx_Buffer[BufferSize];
u32 FLASH_ID ;
void cardNo2String(u8 *cardNo, u8 *str);
void main(void)
{
unsigned char status;
/*设置内部时钟16M为主时钟*/
CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);
status = memcmp(read,write,16);
GPIO_DeInit(GPIOA);
GPIO_DeInit(GPIOC);
Uart_Init();
GPIO_Init( GPIOA, GPIO_PIN_4, GPIO_MODE_OUT_PP_HIGH_FAST);
InitRc522();
UART2_SendString(Tx_Buffer,BufferSize);
while(1)
{
status = PcdRequest(PICC_REQALL,CT); /*扫描卡*/
status = PcdAnticoll(SN); /*防冲撞*/
if (status==MI_OK)
{
GPIO_LOW(GPIOA, GPIO_PIN_4); //寻卡成功
UART2_SendString("The card Id is:",15); //串口发送卡号
cardNo2String(SN, Tx_Buffer);
UART2_SendString(Tx_Buffer, 17);
Reset_RC522();
}
else
{
GPIO_HIGH(GPIOA, GPIO_PIN_4);
}
}
}
void Delay(u32 nCount)
{
while (nCount != 0)
{
nCount--;
}
}
void Hex2String(u8 hex,u8 *str)
{
str[0] = (hex / 100) + '0';
str[1] = (hex % 100 / 10) + '0';
str[2] = (hex % 10) + '0';
}
void cardNo2String(u8 *cardNo, u8 *str)
{
u8 Count = 0;
for(Count = 0; Count < 4; Count++)
{
Hex2String(cardNo[Count], str + Count * 4);
if(Count == 3)
{
str[15] = 'n';
}
else
{
str[Count * 4 + 3] = ':';
}
}
}
void delay_ns(u32 ns)
{
u32 i;
for(i=0;i
{
asm("nop");
asm("nop");
asm("nop");
}
}
u8 SPIWriteByte(u8 Byte)
{
u8 tmp;
while (SPI_GetFlagStatus( SPI_FLAG_TXE) == RESET);
SPI_SendData(Byte);
if (SPI_GetFlagStatus(SPI_FLAG_RXNE))
{
tmp = SPI_ReceiveData();
}
return tmp;
}
void SPI2_Init(void)
{
SPI_DeInit();
SPI_Init(
SPI_FIRSTBIT_MSB, //帧模式,先发送MSB还是LSB
SPI_BAUDRATEPRESCALER_8, //波特率分频值
SPI_MODE_MASTER, //模式,主从模式
SPI_CLOCKPOLARITY_LOW, //时钟极性,空闲时SCK为高/空闲时SCK为低
SPI_CLOCKPHASE_1EDGE, //数据采样的边沿选择
SPI_DATADIRECTION_2LINES_FULLDUPLEX, //双线单向数据模式,使用C6/C7
两条线,数据传输方向位单向
SPI_NSS_SOFT, //软件从设备
0x07);
SPI_Cmd(ENABLE);
}
void InitRc522(void)
{
SPI2_Init();
PcdReset();
PcdAntennaOff();
PcdAntennaOn();
M500PcdConfigISOType( 'A' );
}
void Reset_RC522(void)
{
PcdReset();
PcdAntennaOff();
PcdAntennaOn();
}
///////////////////////////////////////////////////////////////////
//
//功能:寻卡
//参数说明: req_code[IN]:寻卡方式
// 0x52 = 寻感应区内所有符合14443A标准的卡
// 0x26 = 寻未进入休眠状态的卡
// pTagType[OUT]:卡片类型代码
// 0x4400 = Mifare_UltraLight
// 0x0400 = Mifare_One(S50)
// 0x0200 = Mifare_One(S70)
// 0x0800 = Mifare_Pro(X)
// 0x4403 = Mifare_DESFire
//返回: 成功返回MI_OK
///////////////////////////////////////////////////////////////////
//
char PcdRequest(u8 req_code,u8 *pTagType)
{
char status;
u8 unLen;
u8 ucComMF522Buf[MAXRLEN];
ClearBitMask(Status2Reg,0x08);
WriteRawRC(BitFramingReg,0x07);
SetBitMask(TxControlReg,0x03);
ucComMF522Buf[0] = req_code;
status =
PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,1,ucComMF522Buf,&unLen);
if ((status == MI_OK) && (unLen == 0x10))
{
*pTagType = ucComMF522Buf[0];
*(pTagType+1) = ucComMF522Buf[1];
}
else
{ status = MI_ERR; }
return status;
}
///////////////////////////////////////////////////////////////////
//
//功能:防冲撞
//参数说明: pSnr[OUT]:卡片序列号,4字节
//返回: 成功返回MI_OK
///////////////////////////////////////////////////////////////////
//
char PcdAnticoll(u8 *pSnr)
{
char status;
u8 i,snr_check=0;
u8 unLen;
u8 ucComMF522Buf[MAXRLEN];
ClearBitMask(Status2Reg,0x08);
WriteRawRC(BitFramingReg,0x00);
ClearBitMask(CollReg,0x80);
ucComMF522Buf[0] = PICC_ANTICOLL1;
ucComMF522Buf[1] = 0x20;
status =
PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,2,ucComMF522Buf,&unLen);
if (status == MI_OK)
{
for (i=0; i<4; i++)
{
*(pSnr+i) = ucComMF522Buf[i];
snr_check ^= ucComMF522Buf[i];
}
if (snr_check != ucComMF522Buf[i])
{ status = MI_ERR; }
}
SetBitMask(CollReg,0x80);
return status;
}
///////////////////////////////////////////////////////////////////
//
//功能:选定卡片
//参数说明: pSnr[IN]:卡片序列号,4字节
//返回: 成功返回MI_OK
///////////////////////////////////////////////////////////////////
//
char PcdSelect(u8 *pSnr)
{
char status;
u8 i;
u8 unLen;
u8 ucComMF522Buf[MAXRLEN];
ucComMF522Buf[0] = PICC_ANTICOLL1;
ucComMF522Buf[1] = 0x70;
ucComMF522Buf[6] = 0;
for (i=0; i<4; i++)
{
ucComMF522Buf[i+2] = *(pSnr+i);
ucComMF522Buf[6] ^= *(pSnr+i);
}
CalulateCRC(ucComMF522Buf,7,&ucComMF522Buf[7]);
ClearBitMask(Status2Reg,0x08);
status =
PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,9,ucComMF522Buf,&unLen);
if ((status == MI_OK) && (unLen == 0x18))
{ status = MI_OK; }
else
{ status = MI_ERR; }
return status;
}
///////////////////////////////////////////////////////////////////
//
//功能:验证卡片密码
//参数说明: auth_mode[IN]: 密码验证模式
// 0x60 = 验证A密钥
// 0x61 = 验证B密钥
// addr[IN]:块地址
// pKey[IN]:密码
// pSnr[IN]:卡片序列号,4字节
//返回: 成功返回MI_OK
///////////////////////////////////////////////////////////////////
//
char PcdAuthState(u8 auth_mode,u8 addr,u8 *pKey,u8 *pSnr)
{
char status;
u8 unLen;
u8 ucComMF522Buf[MAXRLEN];
ucComMF522Buf[0] = auth_mode;
ucComMF522Buf[1] = addr;
memcpy(&ucComMF522Buf[2], pKey, 6);
memcpy(&ucComMF522Buf[8], pSnr, 4);
status =
PcdComMF522(PCD_AUTHENT,ucComMF522Buf,12,ucComMF522Buf,&unLen);
if ((status != MI_OK) || (!(ReadRawRC(Status2Reg) & 0x08)))
{ status = MI_ERR; }
return status;
}
///////////////////////////////////////////////////////////////////
//
//功能:读取M1卡一块数据
//参数说明: addr[IN]:块地址
// p [OUT]:读出的数据,16字节
//返回: 成功返回MI_OK
///////////////////////////////////////////////////////////////////
//
char PcdRead(u8 addr,u8 *p )
char status;
u8 unLen;
u8 i,ucComMF522Buf[MAXRLEN];
ucComMF522Buf[0] = PICC_READ;
ucComMF522Buf[1] = addr;
CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
status =
PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
if ((status == MI_OK) && (unLen == 0x90))
{
for (i=0; i<16; i++)
{ *(p +i) = ucComMF522Buf[i]; }
}
else
{ status = MI_ERR; }
return status;
}
///////////////////////////////////////////////////////////////////
//
//功能:写数据到M1卡一块
//参数说明: addr[IN]:块地址
// p [IN]:写入的数据,16字节
//返回: 成功返回MI_OK
///////////////////////////////////////////////////////////////////
//
char PcdWrite(u8 addr,u8 *p )
{
char status;
u8 unLen;
u8 i,ucComMF522Buf[MAXRLEN];
ucComMF522Buf[0] = PICC_WRITE;
ucComMF522Buf[1] = addr;
CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
status =
PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] &
0x0F) != 0x0A))
{ status = MI_ERR; }
if (status == MI_OK)
{
for (i=0; i<16; i++)
{
ucComMF522Buf[i] = *(p +i);
}
CalulateCRC(ucComMF522Buf,16,&ucComMF522Buf[16]);
status =
PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,18,ucComMF522Buf,&unLen);
if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] &
0x0F) != 0x0A))
{ status = MI_ERR; }
}
return status;
}
///////////////////////////////////////////////////////////////////
//
//功能:命令卡片进入休眠状态
//返回: 成功返回MI_OK
///////////////////////////////////////////////////////////////////
//
char PcdHalt(void)
{
u8 status;
u8 unLen;
u8 ucComMF522Buf[MAXRLEN];
ucComMF522Buf[0] = PICC_HALT;
ucComMF522Buf[1] = 0;
CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
status =
PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
return MI_OK;
}
///////////////////////////////////////////////////////////////////
//
//用MF522计算CRC16函数
///////////////////////////////////////////////////////////////////
//
void CalulateCRC(u8 *pIn ,u8 len,u8 *pOut )
{
u8 i,n;
ClearBitMask(DivIrqReg,0x04);
WriteRawRC(CommandReg,PCD_IDLE);
SetBitMask(FIFOLevelReg,0x80);
for (i=0; i
{ WriteRawRC(FIFODataReg, *(pIn +i)); }
WriteRawRC(CommandReg, PCD_CALCCRC);
i = 0xFF;
do
{
n = ReadRawRC(DivIrqReg);
i--;
}
while ((i!=0) && !(n&0x04));
pOut [0] = ReadRawRC(CRCResultRegL);
pOut [1] = ReadRawRC(CRCResultRegM);
///////////////////////////////////////////////////////////////////
//
//功能:复位RC522
//返回: 成功返回MI_OK
///////////////////////////////////////////////////////////////////
//
char PcdReset(void)
{
GPIO_HIGH(RC522RST_GPIO_PORT,RC522RST_GPIO_PIN);
delay_ns(10);
GPIO_LOW(RC522RST_GPIO_PORT,RC522RST_GPIO_PIN);
delay_ns(10);
GPIO_HIGH(RC522RST_GPIO_PORT,RC522RST_GPIO_PIN);
delay_ns(10);
WriteRawRC(CommandReg,PCD_RESETPHASE);
delay_ns(10);
WriteRawRC(ModeReg,0x3D); //和Mifare卡通讯,CRC初始值0x6363
WriteRawRC(TReloadRegL,30);
WriteRawRC(TReloadRegH,0);
WriteRawRC(TModeReg,0x8D);
WriteRawRC(TPrescalerReg,0x3E);
WriteRawRC(TxAutoReg,0x40);//必须要
return MI_OK;
}
///////////////////////////////////////////////////////////////////
///
//设置RC632的工作方式
///////////////////////////////////////////////////////////////////
///
char M500PcdConfigISOType(u8 type)
{
if (type == 'A') //ISO14443_A
{
ClearBitMask(Status2Reg,0x08);
WriteRawRC(ModeReg,0x3D);
WriteRawRC(RxSelReg,0x86);
WriteRawRC(RFCfgReg,0x7F);
WriteRawRC(TReloadRegL,30);
WriteRawRC(TReloadRegH,0);
WriteRawRC(TModeReg,0x8D);
WriteRawRC(TPrescalerReg,0x3E);
delay_ns(1000);
PcdAntennaOn();
else
{
return 1;
}
return MI_OK;
}
///////////////////////////////////////////////////////////////////
//
//功能:读RC632寄存器
//参数说明:Address[IN]:寄存器地址
//返回:读出的值
///////////////////////////////////////////////////////////////////
//
u8 ReadRawRC(u8 Address)
{
u8 ucAddr;
u8 ucResult=0;
GPIO_LOW(RC522NSS_GPIO_PORT,RC522NSS_GPIO_PIN);
ucAddr = ((Address<<1)&0x7E)|0x80;
SPIWriteByte(ucAddr);
ucResult=SPIReadByte();
GPIO_HIGH(RC522NSS_GPIO_PORT,RC522NSS_GPIO_PIN);
return ucResult;
}
///////////////////////////////////////////////////////////////////
//
//功能:写RC632寄存器
//参数说明:Address[IN]:寄存器地址
// value[IN]:写入的值
///////////////////////////////////////////////////////////////////
//
void WriteRawRC(u8 Address, u8 value)
{
u8 ucAddr;
GPIO_LOW(RC522NSS_GPIO_PORT,RC522NSS_GPIO_PIN);
ucAddr = ((Address<<1)&0x7E);
SPIWriteByte(ucAddr);
SPIWriteByte(value);
GPIO_HIGH(RC522NSS_GPIO_PORT,RC522NSS_GPIO_PIN);
}
///////////////////////////////////////////////////////////////////
//
//功能:置RC522寄存器位
//参数说明:reg[IN]:寄存器地址
// mask[IN]:置位值
///////////////////////////////////////////////////////////////////
//
{
char tmp = 0x0;
tmp = ReadRawRC(reg);
WriteRawRC(reg,tmp | mask); // set bit mask
}
///////////////////////////////////////////////////////////////////
//
//功能:清RC522寄存器位
//参数说明:reg[IN]:寄存器地址
// mask[IN]:清位值
///////////////////////////////////////////////////////////////////
//
void ClearBitMask(u8 reg,u8 mask)
{
char tmp = 0x0;
tmp = ReadRawRC(reg);
WriteRawRC(reg, tmp & ~mask); // clear bit mask }
///////////////////////////////////////////////////////////////////
//
//功能:通过RC522和ISO14443卡通讯
//参数说明:Command[IN]:RC522命令字
// pIn [IN]:通过RC522发送到卡片的数据// InLenByte[IN]:发送数据的字
节长度
// pOut [OUT]:接收到的卡片返回数据
// *pOutLenBit[OUT]:返回数据的位长度
///////////////////////////////////////////////////////////////////
//
char PcdComMF522(u8 Command,
u8 *pIn ,
u8 InLenByte,
u8 *pOut ,
u8 *pOutLenBit)
{
char status = MI_ERR;
u8 irqEn = 0x00;
u8 waitFor = 0x00;
u8 lastBits;
u8 n;
u16 i;
switch (Command)
{
case PCD_AUTHENT:
irqEn = 0x12;
waitFor = 0x10;
break;
case PCD_TRANSCEIVE:
irqEn = 0x77;
waitFor = 0x30;
break;
default:
break;
}
WriteRawRC(ComIEnReg,irqEn|0x80);
ClearBitMask(ComIrqReg,0x80); //清所有中断位
WriteRawRC(CommandReg,PCD_IDLE);
SetBitMask(FIFOLevelReg,0x80); //清FIFO缓存
for (i=0; i
{
WriteRawRC(FIFODataReg, pIn [i]);
}
WriteRawRC(CommandReg, Command);
// n = ReadRawRC(CommandReg);
if (Command == PCD_TRANSCEIVE)
{
SetBitMask(BitFramingReg,0x80); //开始传送
}
//i = 600;//根据时钟频率调整,操作M1卡最大等待时间25ms
i = 10000;
do
{
n = ReadRawRC(ComIrqReg);
i--;
}
while ((i!=0) && !(n&0x01) && !(n&waitFor));
ClearBitMask(BitFramingReg,0x80);
if (i!=0)
{
if(!(ReadRawRC(ErrorReg)&0x1B))
{
status = MI_OK;
if (n & irqEn & 0x01)
{
status = MI_NOTAGERR;
}
if (Command == PCD_TRANSCEIVE)
{
n = ReadRawRC(FIFOLevelReg);
lastBits = ReadRawRC(ControlReg) & 0x07;
if (lastBits)
{
*pOutLenBit = (n-1)*8 + lastBits;
}
else
{
*pOutLenBit = n*8;
}
if (n == 0)
{
n = 1;
}
if (n > MAXRLEN)
{
n = MAXRLEN;
}
for (i=0; i
{
pOut[i] = ReadRawRC(FIFODataReg);
}
}
}
else
{
status = MI_ERR;
}
}
SetBitMask(ControlReg,0x80); // stop timer now
WriteRawRC(CommandReg,PCD_IDLE);
return status;
}
///////////////////////////////////////////////////////////////////
//
//开启天线
//每次启动或关闭天险发射之间应至少有1ms的间隔
///////////////////////////////////////////////////////////////////
//
void PcdAntennaOn(void)
{
u8 i;
i = ReadRawRC(TxControlReg);
if (!(i & 0x03))
{
SetBitMask(TxControlReg, 0x03);
}
}
///////////////////////////////////////////////////////////////////
//
//关闭天线
///////////////////////////////////////////////////////////////////
//
void PcdAntennaOff(void)
{
ClearBitMask(TxControlReg, 0x03);
}
///////////////////////////////////////////////////////////////////
//
//功能:扣款和充值
//参数说明: dd_mode[IN]:命令字
// 0xC0 = 扣款
// 0xC1 = 充值
// addr[IN]:钱包地址
// pValue[IN]:4字节增(减)值,低位在前
//返回: 成功返回MI_OK
///////////////////////////////////////////////////////////////////
//
char PcdValue(u8 dd_mode,u8 addr,u8 *pValue)
{
char status;
u8 unLen;
u8 ucComMF522Buf[MAXRLEN];
//u8 i;
ucComMF522Buf[0] = dd_mode;
ucComMF522Buf[1] = addr;
CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
status =
PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] &
0x0F) != 0x0A))
{
status = MI_ERR;
}
if (status == MI_OK)
{
memcpy(ucComMF522Buf, pValue, 4);
//for (i=0; i<16; i++)
//{ ucComMF522Buf[i] = *(pValue+i); }
CalulateCRC(ucComMF522Buf,4,&ucComMF522Buf[4]);
unLen = 0;
status =
PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,6,ucComMF522Buf,&unLen);
if (status != MI_ERR)
{ status = MI_OK; }
}
if (status == MI_OK)
{
ucComMF522Buf[0] = PICC_TRANSFER;
ucComMF522Buf[1] = addr;
CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
status =
PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] &
0x0F) != 0x0A))
{ status = MI_ERR; }
}
return status;
}
2024年10月3日发(作者:丙雁凡)
#include "stm8s.h"
#include "uart.h"
void Delay(u32 nCount);
extern u8 RxBuffer[RxBufferSize];
extern u8 UART_RX_NUM;
unsigned char CT[2];//卡类型
unsigned char SN[4]; //卡号
unsigned char write[16] =
{0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0
x0E,0x0F,0x10}; unsigned char read[16] =
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0
x00,0x00,0x00}; unsigned char key[6] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
#define countof(a) (sizeof(a) / sizeof(*(a)))
#define BufferSize (countof(Tx_Buffer)-1)
u8 Tx_Buffer[] = "STM8S RFID TEST";
u8 Rx_Buffer[BufferSize];
u32 FLASH_ID ;
void cardNo2String(u8 *cardNo, u8 *str);
void main(void)
{
unsigned char status;
/*设置内部时钟16M为主时钟*/
CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);
status = memcmp(read,write,16);
GPIO_DeInit(GPIOA);
GPIO_DeInit(GPIOC);
Uart_Init();
GPIO_Init( GPIOA, GPIO_PIN_4, GPIO_MODE_OUT_PP_HIGH_FAST);
InitRc522();
UART2_SendString(Tx_Buffer,BufferSize);
while(1)
{
status = PcdRequest(PICC_REQALL,CT); /*扫描卡*/
status = PcdAnticoll(SN); /*防冲撞*/
if (status==MI_OK)
{
GPIO_LOW(GPIOA, GPIO_PIN_4); //寻卡成功
UART2_SendString("The card Id is:",15); //串口发送卡号
cardNo2String(SN, Tx_Buffer);
UART2_SendString(Tx_Buffer, 17);
Reset_RC522();
}
else
{
GPIO_HIGH(GPIOA, GPIO_PIN_4);
}
}
}
void Delay(u32 nCount)
{
while (nCount != 0)
{
nCount--;
}
}
void Hex2String(u8 hex,u8 *str)
{
str[0] = (hex / 100) + '0';
str[1] = (hex % 100 / 10) + '0';
str[2] = (hex % 10) + '0';
}
void cardNo2String(u8 *cardNo, u8 *str)
{
u8 Count = 0;
for(Count = 0; Count < 4; Count++)
{
Hex2String(cardNo[Count], str + Count * 4);
if(Count == 3)
{
str[15] = 'n';
}
else
{
str[Count * 4 + 3] = ':';
}
}
}
void delay_ns(u32 ns)
{
u32 i;
for(i=0;i
{
asm("nop");
asm("nop");
asm("nop");
}
}
u8 SPIWriteByte(u8 Byte)
{
u8 tmp;
while (SPI_GetFlagStatus( SPI_FLAG_TXE) == RESET);
SPI_SendData(Byte);
if (SPI_GetFlagStatus(SPI_FLAG_RXNE))
{
tmp = SPI_ReceiveData();
}
return tmp;
}
void SPI2_Init(void)
{
SPI_DeInit();
SPI_Init(
SPI_FIRSTBIT_MSB, //帧模式,先发送MSB还是LSB
SPI_BAUDRATEPRESCALER_8, //波特率分频值
SPI_MODE_MASTER, //模式,主从模式
SPI_CLOCKPOLARITY_LOW, //时钟极性,空闲时SCK为高/空闲时SCK为低
SPI_CLOCKPHASE_1EDGE, //数据采样的边沿选择
SPI_DATADIRECTION_2LINES_FULLDUPLEX, //双线单向数据模式,使用C6/C7
两条线,数据传输方向位单向
SPI_NSS_SOFT, //软件从设备
0x07);
SPI_Cmd(ENABLE);
}
void InitRc522(void)
{
SPI2_Init();
PcdReset();
PcdAntennaOff();
PcdAntennaOn();
M500PcdConfigISOType( 'A' );
}
void Reset_RC522(void)
{
PcdReset();
PcdAntennaOff();
PcdAntennaOn();
}
///////////////////////////////////////////////////////////////////
//
//功能:寻卡
//参数说明: req_code[IN]:寻卡方式
// 0x52 = 寻感应区内所有符合14443A标准的卡
// 0x26 = 寻未进入休眠状态的卡
// pTagType[OUT]:卡片类型代码
// 0x4400 = Mifare_UltraLight
// 0x0400 = Mifare_One(S50)
// 0x0200 = Mifare_One(S70)
// 0x0800 = Mifare_Pro(X)
// 0x4403 = Mifare_DESFire
//返回: 成功返回MI_OK
///////////////////////////////////////////////////////////////////
//
char PcdRequest(u8 req_code,u8 *pTagType)
{
char status;
u8 unLen;
u8 ucComMF522Buf[MAXRLEN];
ClearBitMask(Status2Reg,0x08);
WriteRawRC(BitFramingReg,0x07);
SetBitMask(TxControlReg,0x03);
ucComMF522Buf[0] = req_code;
status =
PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,1,ucComMF522Buf,&unLen);
if ((status == MI_OK) && (unLen == 0x10))
{
*pTagType = ucComMF522Buf[0];
*(pTagType+1) = ucComMF522Buf[1];
}
else
{ status = MI_ERR; }
return status;
}
///////////////////////////////////////////////////////////////////
//
//功能:防冲撞
//参数说明: pSnr[OUT]:卡片序列号,4字节
//返回: 成功返回MI_OK
///////////////////////////////////////////////////////////////////
//
char PcdAnticoll(u8 *pSnr)
{
char status;
u8 i,snr_check=0;
u8 unLen;
u8 ucComMF522Buf[MAXRLEN];
ClearBitMask(Status2Reg,0x08);
WriteRawRC(BitFramingReg,0x00);
ClearBitMask(CollReg,0x80);
ucComMF522Buf[0] = PICC_ANTICOLL1;
ucComMF522Buf[1] = 0x20;
status =
PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,2,ucComMF522Buf,&unLen);
if (status == MI_OK)
{
for (i=0; i<4; i++)
{
*(pSnr+i) = ucComMF522Buf[i];
snr_check ^= ucComMF522Buf[i];
}
if (snr_check != ucComMF522Buf[i])
{ status = MI_ERR; }
}
SetBitMask(CollReg,0x80);
return status;
}
///////////////////////////////////////////////////////////////////
//
//功能:选定卡片
//参数说明: pSnr[IN]:卡片序列号,4字节
//返回: 成功返回MI_OK
///////////////////////////////////////////////////////////////////
//
char PcdSelect(u8 *pSnr)
{
char status;
u8 i;
u8 unLen;
u8 ucComMF522Buf[MAXRLEN];
ucComMF522Buf[0] = PICC_ANTICOLL1;
ucComMF522Buf[1] = 0x70;
ucComMF522Buf[6] = 0;
for (i=0; i<4; i++)
{
ucComMF522Buf[i+2] = *(pSnr+i);
ucComMF522Buf[6] ^= *(pSnr+i);
}
CalulateCRC(ucComMF522Buf,7,&ucComMF522Buf[7]);
ClearBitMask(Status2Reg,0x08);
status =
PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,9,ucComMF522Buf,&unLen);
if ((status == MI_OK) && (unLen == 0x18))
{ status = MI_OK; }
else
{ status = MI_ERR; }
return status;
}
///////////////////////////////////////////////////////////////////
//
//功能:验证卡片密码
//参数说明: auth_mode[IN]: 密码验证模式
// 0x60 = 验证A密钥
// 0x61 = 验证B密钥
// addr[IN]:块地址
// pKey[IN]:密码
// pSnr[IN]:卡片序列号,4字节
//返回: 成功返回MI_OK
///////////////////////////////////////////////////////////////////
//
char PcdAuthState(u8 auth_mode,u8 addr,u8 *pKey,u8 *pSnr)
{
char status;
u8 unLen;
u8 ucComMF522Buf[MAXRLEN];
ucComMF522Buf[0] = auth_mode;
ucComMF522Buf[1] = addr;
memcpy(&ucComMF522Buf[2], pKey, 6);
memcpy(&ucComMF522Buf[8], pSnr, 4);
status =
PcdComMF522(PCD_AUTHENT,ucComMF522Buf,12,ucComMF522Buf,&unLen);
if ((status != MI_OK) || (!(ReadRawRC(Status2Reg) & 0x08)))
{ status = MI_ERR; }
return status;
}
///////////////////////////////////////////////////////////////////
//
//功能:读取M1卡一块数据
//参数说明: addr[IN]:块地址
// p [OUT]:读出的数据,16字节
//返回: 成功返回MI_OK
///////////////////////////////////////////////////////////////////
//
char PcdRead(u8 addr,u8 *p )
char status;
u8 unLen;
u8 i,ucComMF522Buf[MAXRLEN];
ucComMF522Buf[0] = PICC_READ;
ucComMF522Buf[1] = addr;
CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
status =
PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
if ((status == MI_OK) && (unLen == 0x90))
{
for (i=0; i<16; i++)
{ *(p +i) = ucComMF522Buf[i]; }
}
else
{ status = MI_ERR; }
return status;
}
///////////////////////////////////////////////////////////////////
//
//功能:写数据到M1卡一块
//参数说明: addr[IN]:块地址
// p [IN]:写入的数据,16字节
//返回: 成功返回MI_OK
///////////////////////////////////////////////////////////////////
//
char PcdWrite(u8 addr,u8 *p )
{
char status;
u8 unLen;
u8 i,ucComMF522Buf[MAXRLEN];
ucComMF522Buf[0] = PICC_WRITE;
ucComMF522Buf[1] = addr;
CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
status =
PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] &
0x0F) != 0x0A))
{ status = MI_ERR; }
if (status == MI_OK)
{
for (i=0; i<16; i++)
{
ucComMF522Buf[i] = *(p +i);
}
CalulateCRC(ucComMF522Buf,16,&ucComMF522Buf[16]);
status =
PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,18,ucComMF522Buf,&unLen);
if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] &
0x0F) != 0x0A))
{ status = MI_ERR; }
}
return status;
}
///////////////////////////////////////////////////////////////////
//
//功能:命令卡片进入休眠状态
//返回: 成功返回MI_OK
///////////////////////////////////////////////////////////////////
//
char PcdHalt(void)
{
u8 status;
u8 unLen;
u8 ucComMF522Buf[MAXRLEN];
ucComMF522Buf[0] = PICC_HALT;
ucComMF522Buf[1] = 0;
CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
status =
PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
return MI_OK;
}
///////////////////////////////////////////////////////////////////
//
//用MF522计算CRC16函数
///////////////////////////////////////////////////////////////////
//
void CalulateCRC(u8 *pIn ,u8 len,u8 *pOut )
{
u8 i,n;
ClearBitMask(DivIrqReg,0x04);
WriteRawRC(CommandReg,PCD_IDLE);
SetBitMask(FIFOLevelReg,0x80);
for (i=0; i
{ WriteRawRC(FIFODataReg, *(pIn +i)); }
WriteRawRC(CommandReg, PCD_CALCCRC);
i = 0xFF;
do
{
n = ReadRawRC(DivIrqReg);
i--;
}
while ((i!=0) && !(n&0x04));
pOut [0] = ReadRawRC(CRCResultRegL);
pOut [1] = ReadRawRC(CRCResultRegM);
///////////////////////////////////////////////////////////////////
//
//功能:复位RC522
//返回: 成功返回MI_OK
///////////////////////////////////////////////////////////////////
//
char PcdReset(void)
{
GPIO_HIGH(RC522RST_GPIO_PORT,RC522RST_GPIO_PIN);
delay_ns(10);
GPIO_LOW(RC522RST_GPIO_PORT,RC522RST_GPIO_PIN);
delay_ns(10);
GPIO_HIGH(RC522RST_GPIO_PORT,RC522RST_GPIO_PIN);
delay_ns(10);
WriteRawRC(CommandReg,PCD_RESETPHASE);
delay_ns(10);
WriteRawRC(ModeReg,0x3D); //和Mifare卡通讯,CRC初始值0x6363
WriteRawRC(TReloadRegL,30);
WriteRawRC(TReloadRegH,0);
WriteRawRC(TModeReg,0x8D);
WriteRawRC(TPrescalerReg,0x3E);
WriteRawRC(TxAutoReg,0x40);//必须要
return MI_OK;
}
///////////////////////////////////////////////////////////////////
///
//设置RC632的工作方式
///////////////////////////////////////////////////////////////////
///
char M500PcdConfigISOType(u8 type)
{
if (type == 'A') //ISO14443_A
{
ClearBitMask(Status2Reg,0x08);
WriteRawRC(ModeReg,0x3D);
WriteRawRC(RxSelReg,0x86);
WriteRawRC(RFCfgReg,0x7F);
WriteRawRC(TReloadRegL,30);
WriteRawRC(TReloadRegH,0);
WriteRawRC(TModeReg,0x8D);
WriteRawRC(TPrescalerReg,0x3E);
delay_ns(1000);
PcdAntennaOn();
else
{
return 1;
}
return MI_OK;
}
///////////////////////////////////////////////////////////////////
//
//功能:读RC632寄存器
//参数说明:Address[IN]:寄存器地址
//返回:读出的值
///////////////////////////////////////////////////////////////////
//
u8 ReadRawRC(u8 Address)
{
u8 ucAddr;
u8 ucResult=0;
GPIO_LOW(RC522NSS_GPIO_PORT,RC522NSS_GPIO_PIN);
ucAddr = ((Address<<1)&0x7E)|0x80;
SPIWriteByte(ucAddr);
ucResult=SPIReadByte();
GPIO_HIGH(RC522NSS_GPIO_PORT,RC522NSS_GPIO_PIN);
return ucResult;
}
///////////////////////////////////////////////////////////////////
//
//功能:写RC632寄存器
//参数说明:Address[IN]:寄存器地址
// value[IN]:写入的值
///////////////////////////////////////////////////////////////////
//
void WriteRawRC(u8 Address, u8 value)
{
u8 ucAddr;
GPIO_LOW(RC522NSS_GPIO_PORT,RC522NSS_GPIO_PIN);
ucAddr = ((Address<<1)&0x7E);
SPIWriteByte(ucAddr);
SPIWriteByte(value);
GPIO_HIGH(RC522NSS_GPIO_PORT,RC522NSS_GPIO_PIN);
}
///////////////////////////////////////////////////////////////////
//
//功能:置RC522寄存器位
//参数说明:reg[IN]:寄存器地址
// mask[IN]:置位值
///////////////////////////////////////////////////////////////////
//
{
char tmp = 0x0;
tmp = ReadRawRC(reg);
WriteRawRC(reg,tmp | mask); // set bit mask
}
///////////////////////////////////////////////////////////////////
//
//功能:清RC522寄存器位
//参数说明:reg[IN]:寄存器地址
// mask[IN]:清位值
///////////////////////////////////////////////////////////////////
//
void ClearBitMask(u8 reg,u8 mask)
{
char tmp = 0x0;
tmp = ReadRawRC(reg);
WriteRawRC(reg, tmp & ~mask); // clear bit mask }
///////////////////////////////////////////////////////////////////
//
//功能:通过RC522和ISO14443卡通讯
//参数说明:Command[IN]:RC522命令字
// pIn [IN]:通过RC522发送到卡片的数据// InLenByte[IN]:发送数据的字
节长度
// pOut [OUT]:接收到的卡片返回数据
// *pOutLenBit[OUT]:返回数据的位长度
///////////////////////////////////////////////////////////////////
//
char PcdComMF522(u8 Command,
u8 *pIn ,
u8 InLenByte,
u8 *pOut ,
u8 *pOutLenBit)
{
char status = MI_ERR;
u8 irqEn = 0x00;
u8 waitFor = 0x00;
u8 lastBits;
u8 n;
u16 i;
switch (Command)
{
case PCD_AUTHENT:
irqEn = 0x12;
waitFor = 0x10;
break;
case PCD_TRANSCEIVE:
irqEn = 0x77;
waitFor = 0x30;
break;
default:
break;
}
WriteRawRC(ComIEnReg,irqEn|0x80);
ClearBitMask(ComIrqReg,0x80); //清所有中断位
WriteRawRC(CommandReg,PCD_IDLE);
SetBitMask(FIFOLevelReg,0x80); //清FIFO缓存
for (i=0; i
{
WriteRawRC(FIFODataReg, pIn [i]);
}
WriteRawRC(CommandReg, Command);
// n = ReadRawRC(CommandReg);
if (Command == PCD_TRANSCEIVE)
{
SetBitMask(BitFramingReg,0x80); //开始传送
}
//i = 600;//根据时钟频率调整,操作M1卡最大等待时间25ms
i = 10000;
do
{
n = ReadRawRC(ComIrqReg);
i--;
}
while ((i!=0) && !(n&0x01) && !(n&waitFor));
ClearBitMask(BitFramingReg,0x80);
if (i!=0)
{
if(!(ReadRawRC(ErrorReg)&0x1B))
{
status = MI_OK;
if (n & irqEn & 0x01)
{
status = MI_NOTAGERR;
}
if (Command == PCD_TRANSCEIVE)
{
n = ReadRawRC(FIFOLevelReg);
lastBits = ReadRawRC(ControlReg) & 0x07;
if (lastBits)
{
*pOutLenBit = (n-1)*8 + lastBits;
}
else
{
*pOutLenBit = n*8;
}
if (n == 0)
{
n = 1;
}
if (n > MAXRLEN)
{
n = MAXRLEN;
}
for (i=0; i
{
pOut[i] = ReadRawRC(FIFODataReg);
}
}
}
else
{
status = MI_ERR;
}
}
SetBitMask(ControlReg,0x80); // stop timer now
WriteRawRC(CommandReg,PCD_IDLE);
return status;
}
///////////////////////////////////////////////////////////////////
//
//开启天线
//每次启动或关闭天险发射之间应至少有1ms的间隔
///////////////////////////////////////////////////////////////////
//
void PcdAntennaOn(void)
{
u8 i;
i = ReadRawRC(TxControlReg);
if (!(i & 0x03))
{
SetBitMask(TxControlReg, 0x03);
}
}
///////////////////////////////////////////////////////////////////
//
//关闭天线
///////////////////////////////////////////////////////////////////
//
void PcdAntennaOff(void)
{
ClearBitMask(TxControlReg, 0x03);
}
///////////////////////////////////////////////////////////////////
//
//功能:扣款和充值
//参数说明: dd_mode[IN]:命令字
// 0xC0 = 扣款
// 0xC1 = 充值
// addr[IN]:钱包地址
// pValue[IN]:4字节增(减)值,低位在前
//返回: 成功返回MI_OK
///////////////////////////////////////////////////////////////////
//
char PcdValue(u8 dd_mode,u8 addr,u8 *pValue)
{
char status;
u8 unLen;
u8 ucComMF522Buf[MAXRLEN];
//u8 i;
ucComMF522Buf[0] = dd_mode;
ucComMF522Buf[1] = addr;
CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
status =
PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] &
0x0F) != 0x0A))
{
status = MI_ERR;
}
if (status == MI_OK)
{
memcpy(ucComMF522Buf, pValue, 4);
//for (i=0; i<16; i++)
//{ ucComMF522Buf[i] = *(pValue+i); }
CalulateCRC(ucComMF522Buf,4,&ucComMF522Buf[4]);
unLen = 0;
status =
PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,6,ucComMF522Buf,&unLen);
if (status != MI_ERR)
{ status = MI_OK; }
}
if (status == MI_OK)
{
ucComMF522Buf[0] = PICC_TRANSFER;
ucComMF522Buf[1] = addr;
CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
status =
PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] &
0x0F) != 0x0A))
{ status = MI_ERR; }
}
return status;
}