//****************************************************************************
// 文 件 名: rc522.c
// 版 本: v1.0
// 连 接:
// 功 能: RC522驱动和扫描IC卡
// 作 者: 区伟雄(Ryson)
// 日 期: 2012/11/23
//****************************************************************************
#include "rc522.h"
u8 fcnt; //响应时间
u8 Pcb; //CPU卡APDU指令分组号
//*************************************************************************
// 函数名 :RC522_Init
// 描述 :初始化引脚
// 入口 :无
// 出口 :无
// 返回 :无
//*************************************************************************
void RC522_Init(void)
{
RCC->APB2ENR|=1<<3; //使能PORTB时钟
GPIOB->CRL&=0X00000FFF;
GPIOB->CRL|=0X33383000; //PB7 6 5 3输出 4输入
GPIOB->ODR|=1<<7; //PB7输出高
GPIOB->ODR|=1<<6; //PB6输出高
GPIOB->ODR|=1<<5; //PB5输出高
GPIOB->ODR|=1<<3; //PB3输出高
PcdReset();
PcdConfigISOType('A');
fcnt = 0;
}
//*************************************************************************
// 函数名 :PcdSwitchPCB(void)
// 描述 :切换分组号
// 入口 :
// 出口 :
// 返回 :成功返回MI_OK
//*************************************************************************
void PcdSwitchPCB(void)
{
switch(Pcb)
{
case 0x00:
Pcb=0x0A;
break;
case 0x0A:
Pcb=0x0B;
break;
case 0x0B:
Pcb=0x0A;
break;
}
}
//*************************************************************************
// 函数名 :PcdConfigISOType(u8 type)
// 描述 :设置RC522的工作方式
// 入口 :type[IN]:卡片类型
// 出口 :无
// 返回 :成功返回MI_OK
//*************************************************************************
s8 PcdConfigISOType(u8 type)
{
s8 status = MI_ERR;
if(type == 'A')
{
status = MI_OK;
ClearBitMask(Status2Reg,0x08); //状态2寄存器
WriteRawRC(ModeReg,0x3D); //和Mifare卡通讯,CRC初始值0x6363
WriteRawRC(RxSelReg,0x10); //选择内部接收器设置,内部模拟部分调制信号,发送数据后,延时6个位时钟,接收
WriteRawRC(RFCfgReg,0x7F); //配置接收器,48dB最大增益
WriteRawRC(TReloadRegL,0x30); //定时器的低8位数据
WriteRawRC(TReloadRegH,0x00); //定时器的高8位数据,实际值是0xD3E这部分主要是设置定时器寄存器
WriteRawRC(TModeReg,0x8D); //实际值是0X0D3E这部分主要是设置定时器寄存器TPrescaler 分频数为0xD0
delay_us(1000);
PcdAntennaOn();
}
return status;
}
//*************************************************************************
// 函数名 :WriteRawRC
// 描述 :写RC522寄存器
// 入口 :Address[IN]:寄存器地址
// value:写入数值
// 出口 :无
// 返回 :无
//*************************************************************************
void WriteRawRC(u8 Address, u8 value)
{
u8 i, ucAddr;
SCK = 0;
NSS = 0;
ucAddr = ((Address<<1)&0x7E);
for(i=0;i<8;i++) //先发送地址
{
MOSI = ((ucAddr&0x80)==0x80);
SCK = 1;
ucAddr <<= 1;
SCK = 0;
}
for(i=0;i<8;i++)
{
MOSI = ((value&0x80)==0x80); //再发送操作数
SCK = 1;
value <<= 1;
SCK = 0;
}
NSS = 1;
SCK = 1;
}
//*************************************************************************
// 函数名 :ReadRawRC
// 描述 :读RC522寄存器
// 入口 :Address[IN]:寄存器地址
// 出口 :无
// 返回 :读出的值
//*************************************************************************
u8 ReadRawRC(u8 Address)
{
u8 i, ucAddr;
u8 ucResult=0;
SCK = 0;
NSS = 0;
ucAddr = ((Address<<1)&0x7E)|0x80;
for(i=0;i<8;i++)
{
MOSI = ((ucAddr&0x80)==0x80);
SCK = 1;
ucAddr <<= 1;
SCK = 0;
}
for(i=0;i<8;i++)
{
SCK = 1;
ucResult <<= 1;
ucResult|=MISO&0x01;
SCK = 0;
}
NSS = 1;
SCK = 1;
return ucResult;
}
//*************************************************************************
// 函数名 :SetBitMask
// 描述 :位置1
// 入口 :reg[IN]:寄存器地址
// mask[IN]:置位值
// 出口 :无
// 返回 :无
//*************************************************************************
void SetBitMask(u8 reg,u8 mask)
{
u8 tmp = 0x0;
tmp = ReadRawRC(reg);
WriteRawRC(reg,tmp | mask); // set bit mask
}
//*************************************************************************
// 函数名 :ClearBitMask
// 描述 :位置0
// 入口 :reg[IN]:寄存器地址
// mask[IN]:置位值
// 出口 :无
// 返回 :无
//*************************************************************************
void ClearBitMask(u8 reg,u8 mask)
{
u8 tmp = 0x00;
tmp = ReadRawRC(reg);
WriteRawRC(reg, tmp & ~mask); // clear bit mask
}
//*************************************************************************
// 函数名 :PcdAntennaOff
// 描述 :关闭天线
// 入口 :无
// 出口 :无
// 返回 :无
//*************************************************************************
void PcdAntennaOff(void)
{
ClearBitMask(TxControlReg, 0x03); //禁止Tx1RFEn,Tx2RFEn
}
//*************************************************************************
// 函数名 :PcdAntennaOn
// 描述 :开启天线,每次启动或关闭天险发射之间应至少有1ms的间隔
// 入口 :无
// 出口 :无
// 返回 :无
//*************************************************************************
void PcdAntennaOn(void)
{
unsigned char i;
i = ReadRawRC(TxControlReg); //读取出发送控制寄存器
if (!(i & 0x03)) //如果未开启,则
{
SetBitMask(TxControlReg, 0x03); //开启Tx1RFEn,Tx2RFEn
}
}
//*************************************************************************
// 函数名 :PcdComMF522
// 描述 :通过RC522和ISO14443卡通讯
// 入口 :Command[IN]:RC522命令字
// pDataIn[IN]:通过RC522发送到卡片的数据
// InLenByte[IN]:发送数据的字节长度
// *pOutLenBit[OUT]:返回数据的位长度
// 出口 :pDataOut[OUT]:接收到的卡片返回数据
// 返回 :无
//*************************************************************************
s8 PcdComMF522(u8 Command, u8 *pDataIn, u8 InLenByte, u8 *pDataOut, u16 *pOutLenBit)
{
s8 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<InLenByte; i++)
{
WriteRawRC(FIFODataReg, pDataIn[i]); //数据写入FIFO
}
WriteRawRC(CommandReg, Command); //写入命令,将缓冲区中的数据发送到天线,并激活自动接收器
if (Command == PCD_TRANSCEIVE) //如果命令为0C
{
SetBitMask(BitFramingReg,0x80); //相当于启动发送STARTSENG
}
i = 3000; //根据时钟频率调整,操作M1卡最大等待时间=600,操作CPU卡最大等待时间=1200
do
{
n = ReadRawRC(ComIrqReg); //读取中断标志,检查数据返回
i--;
}
while ((i!=0) && !(n&0x01) && !(n&waitFor)); // 定时器未超时,没有错误,0x01,0x30
ClearBitMask(BitFramingReg,0x80); // 相当于清除发送STARTSENG
if (i!=0) // 定时时间到,i,没有递减到0
{
if(!(ReadRawRC(ErrorReg)&0x1B)) // 判断有无出现错误标志 Buffer溢出,位冲突,接收CRC错误,奇偶校验错误,
{
status = MI_OK; // 初始化状态
if (n & irqEn & 0x01) // 若是PCD_TRANSCEIVE, irq = 0x77, 定时器为0中断产生,定时器为0时为错误
{
status = MI_NOTAGERR; // 搜索不到卡
}
if (Command == PCD_TRANSCEIVE)
- 1
- 2
- 3
前往页