📄 rc500.c
字号:
//ICC-AVR application builder : 2008-04-18 08:36:23
//Target : M64
//Crystal: 8.0000Mhz
#include <iom64v.h>
#include <macros.h>
#include "RC500.h"
#include "uart.h"
/*****************************变量定义*****************************************/
MfCmdInfo Info;
/*****************************延时程序*****************************************/
void Delay_1us(void)
{
asm("nop");
}
void Delay_us(uint16 n)
{
uint16 i;
for(i=0; i<n; i++)Delay_1us();
}
void Delay_1ms(void)
{
uint16 i;
for(i=0; i<1142; i++);
}
void Delay_ms(uint16 n)
{
uint16 i;
for(i=0; i<n; i++)Delay_1ms();
}
/*********************************硬件驱动程序*********************************/
void WriteIO(BYTE Address,BYTE value)
{
WORD addr;
addr = 0x2000 | Address;
(*(volatile unsigned char *)0x2000) = (Address>>3) | 0x80; //选择寄存器页
(*(volatile unsigned char *)addr) = value; //写入一个字节
}
BYTE ReadIO(BYTE Address)
{
WORD addr;
addr = 0x2000 | Address;
(*(volatile unsigned char *)0x2000) = (Address>>3) | 0x80; //选择寄存器页
return (*(volatile unsigned char *)addr); //读取一个字节
}
/*****************************RC500功能程序************************************/
BYTE M500PcdReset(void)
{
uint16 timecnt;
CLR_RC500RST();
Delay_ms(25);
SET_RC500RST();
Delay_ms(20);
CLR_RC500RST();
Delay_ms(10);
timecnt=1000;
while((ReadIO(RegCommand)&0x3F) & timecnt--);
if(!timecnt)return 1;
if(ReadIO(RegCommand)!=0x00)return 1;
return 0;
}
//配置RC500内部寄存器函数
BYTE M500PcdConfig(void)
{
if (!M500PcdReset())
{
WriteIO(RegClockQControl,0x00); //Q时钟复位
WriteIO(RegClockQControl,0x40); //Q时钟写入0x40
Delay_us(150); //延时100us以上
WriteIO(RegClockQControl,0x00); //Q时钟清零
WriteIO(RegBitPhase,0xAD); //写BitPhase寄存器
WriteIO(RegRxThreshold,0xFF); //RxThreshold寄存器写入0FFH
WriteIO(RegRxControl2,0x01); //RxControl2寄存器写入01H
WriteIO(RegFIFOLevel,0x1A); //设置FIFO上溢和下溢的界限
WriteIO(RegTimerControl,0x02); //设置数据发送完成后停止定时器
WriteIO(RegIRqPinConfig,0x03); //配置IRQ管脚的输出状态
M500PcdRfReset(1); //打开天线
WriteIO(RegMfOutSelect,0x02); //选择输出到管脚MFOUT的信号为来自内部编码的调制信号
return 0;
}
else
return 1;
}
BYTE M500PcdRfReset(BYTE val)
{
if(val)
{
ClearBitMask(RegTxControl,0x03);
Delay_ms(2);
SetBitMask(RegTxControl,0x03);
}
else
{
ClearBitMask(RegTxControl,0x03);
}
return 0;
}
//置一位
BYTE SetBitMask(BYTE reg,BYTE mask)
{
BYTE tmp = 0x00;
tmp = ReadIO(reg);
WriteIO(reg,tmp | mask); // set bit mask
return 0x00;
}
//清一位
BYTE ClearBitMask(BYTE reg,BYTE mask)
{
BYTE tmp = 0x00;
tmp = ReadIO(reg);
WriteIO(reg,tmp & ~mask); // clear bit mask
return 0x00;
}
//发送命令
BYTE M500PcdCmd(void)
{
BYTE i,n;
BYTE lastBits;
BYTE irqEn = 0x00;
BYTE waitFor = 0x00;
WORD timecnt = 0;
switch(Info.cmd)
{
case PCD_IDLE:
irqEn = 0x00;
waitFor = 0x00;
break;
case PCD_WRITEE2:
irqEn = 0x11;
waitFor = 0x10;
break;
case PCD_READE2:
irqEn = 0x07;
waitFor = 0x04;
break;
case PCD_LOADCONFIG:
case PCD_LOADKEYE2:
case PCD_AUTHENT1:
irqEn = 0x05;
waitFor = 0x04;
break;
case PCD_CALCCRC:
irqEn = 0x11;
waitFor = 0x10;
break;
case PCD_AUTHENT2:
irqEn = 0x04;
waitFor = 0x04;
break;
case PCD_RECEIVE:
irqEn = 0x06;
waitFor = 0x04;
break;
case PCD_LOADKEY:
irqEn = 0x05;
waitFor = 0x04;
break;
case PCD_TRANSMIT:
irqEn = 0x05;
waitFor = 0x04;
break;
case PCD_TRANSCEIVE:
irqEn = 0x3D;
waitFor = 0x04;
break;
default: return 1;
}
WriteIO(RegInterruptEn,0x7F); //清除中断使能
WriteIO(RegInterruptRq,0x7F); //清除中断标志
WriteIO(RegCommand,PCD_IDLE); //清除Command寄存器
SetBitMask(RegControl,0x01); //清除FIFO指针
for(i=0; i<Info.nBytesToSend; i++)
WriteIO(RegFIFOData,Info.SerBuffer[i]); //将数据写入FIFO
irqEn |= 0x20;
waitFor |= 0x20;
WriteIO(RegInterruptEn,irqEn | 0x80); //打开中断
WriteIO(RegCommand,Info.cmd); //将命令写入命令寄存器
timecnt=1000;
while(!(ReadIO(RegInterruptRq) & waitFor || !(timecnt--)));
WriteIO(RegInterruptEn,0x7F); //清除中断使能
WriteIO(RegInterruptRq,0x7F); //清除中断标志寄存器
SetBitMask(RegControl,0x04); //停止定时器
WriteIO(RegCommand,PCD_IDLE); //清除命令寄存器
if(!timecnt)
{ USART_String("timeout!\n");return 1; } //超时退出,返回1
if(ReadIO(RegErrorFlag)&0x17)
{ USART_Hex(ReadIO(RegErrorFlag)&0x3F);USART_String("ERRor!\n");return 1; } //如果产生错误则返回1
if(Info.cmd == PCD_TRANSCEIVE)
{
n = ReadIO(RegFIFOLength); //读取FIFO中数据的总字节数
lastBits = ReadIO(RegSecondaryStatus) & 0x07;
Info.nBytesReceived = n;
if(lastBits)
Info.nBitsReceived = (n-1) * 8 + lastBits;
else
Info.nBitsReceived = n * 8;
if(n==0)n=1;
for(i=0; i<n; i++)
Info.SerBuffer[i]=ReadIO(RegFIFOData);
/*USART_Hex(n);
USART_Hex(lastBits);
for(i=0; i<n; i++)
USART_Hex(Info.SerBuffer[i]);*/
}
return 0;
}
//寻卡
BYTE M500PiccCommonRequest(void)
{
WriteIO(RegTimerClock,0x09); //设置定时器分频
WriteIO(RegTimerReload,0xA0); //设置定时器初值
ClearBitMask(RegControl,0x08); //寄存器Control清0
WriteIO(RegBitFraming,0x07); //寄存器BitFramming写入07H
WriteIO(RegChannelRedundancy,0x03); //选择RF信道上数据完整性检测的类型和模式
SetBitMask(RegTxControl,0x03); //打开天线
//ResetInfo(Info);
Info.cmd = PCD_TRANSCEIVE; //命令为发送命令
Info.nBytesToSend = 1; //发送字节长度为1
Info.nBytesReceived = 2; //接收字节长度为2
Info.SerBuffer[0] = PICC_REQIDL; //数据为寻卡命令
if(M500PcdCmd())return 1; //调用发送命令子函数
if(Info.nBitsReceived != 16) return 1;//判断接收到是不是16位,否则是错误的
if(Info.SerBuffer[0]==0x04) return 0; //如果第一个字节是0x04,则是One卡,寻卡成功
else return 1; //否则返回错误状态
}
//防冲突
BYTE M500PiccCascAnticoll(void)
{
BYTE i;
BYTE snr_check=0;
BYTE status=0;
WriteIO(RegTimerClock,0x07); //设置定时器分频
WriteIO(RegTimerReload,0X6A); //设置定时器初值
WriteIO(RegDecoderControl,0x28); //防冲突处理
ClearBitMask(RegControl,0x08); //
WriteIO(RegChannelRedundancy,0x03); //
Info.cmd = PCD_TRANSCEIVE; //命令为发送命令
Info.nBytesToSend = 2; //发送字节长度为1
Info.nBytesReceived = 5; //接收字节长度为2
Info.SerBuffer[0] = PICC_ANTICOLL1; //数据0为防冲突命令
Info.SerBuffer[1] = 0x20;
if(M500PcdCmd())status = 1;
else
{
for(i=0;i<4;i++)
snr_check^=Info.SerBuffer[i]; //生成校验数据
if(snr_check!=Info.SerBuffer[i]) //对比校验数据是否正确
status = 1;
else
{
for(i=0;i<5;i++)
Info.CardNumber[i] = Info.SerBuffer[i]; //将卡号和CRC装到卡号缓存
}
}
ClearBitMask(RegDecoderControl,0x20); //结束防冲突处理
return status;
}
//选卡
BYTE M500PiccCascSelect(void)
{
BYTE i;
WriteIO(RegTimerClock,0x07); //设置定时器分频
WriteIO(RegTimerReload,0X6A); //设置定时器初值
WriteIO(RegChannelRedundancy,0x0F); //
ClearBitMask(RegControl,0x08); //
Info.cmd = PCD_TRANSCEIVE; //命令为发送命令
Info.nBytesToSend = 7; //发送字节长度为1
Info.nBytesReceived = 1; //接收字节长度为2
Info.SerBuffer[0] = PICC_ANTICOLL1; //数据0为选卡命令
Info.SerBuffer[1] = 0x70;
for(i=0; i<5; i++)
Info.SerBuffer[i+2] = Info.CardNumber[i];
if(M500PcdCmd())return 1;
if(Info.SerBuffer[0] != 0x08)return 1;
return 0;
}
//直接验证密码
BYTE M500PiccAuthKey(BYTE *KEY,BYTE Sector,BYTE Block)
{
Info.cmd = PCD_LOADKEY; //命令为发送命令
Info.nBytesToSend = 0x0C; //发送字节长度为1
Info.nBytesReceived = 0; //接收字节长度为2
M500HostCodeKey(KEY,Info.SerBuffer);//将密码转换成固定格式
if(M500PcdCmd())return 1; //调用发送命令子函数
if(M500PiccAuthState(Sector*4+Block))
return 1;//Crytol卡验证子程序
return 0;
}
//密码格式转换
void M500HostCodeKey(BYTE *uncoded,BYTE *coded)
{
BYTE cnt = 0;
BYTE ln = 0;
BYTE hn = 0;
for (cnt=0; cnt<6; cnt++)
{
ln = uncoded[cnt] & 0x0F;
hn = uncoded[cnt] >> 4;
coded[cnt * 2 + 1] = (~ln << 4) | ln;
coded[cnt * 2 ] = (~hn << 4) | hn;
}
}
//Crystol卡验证
BYTE M500PiccAuthState(BYTE Block)
{
BYTE i;
Info.cmd = PCD_AUTHENT1; //命令为发送命令
Info.nBytesToSend = 0x06; //发送字节长度为1
Info.nBytesReceived = 0; //接收字节长度为2
Info.SerBuffer[0] = PICC_AUTHENT1A; //Authen1命令
Info.SerBuffer[1] = Block; //块号
for(i=0; i<4; i++) //卡号
Info.SerBuffer[i+2] = Info.CardNumber[i];
if(M500PcdCmd())return 1; //调用发送命令子函数
if(ReadIO(RegSecondaryStatus)&0x07)return 1;
Info.cmd = PCD_AUTHENT2; //Authen2命令
Info.nBytesToSend = 0; //发送数据为0字节
Info.nBytesReceived = 0; //接收数据为0字节
if(M500PcdCmd())return 1; //调用发送命令子函数
if(ReadIO(RegControl)==0x08)return 0;//值是否为0x08
else return 1;
}
//读数据
BYTE M500PiccRead(BYTE Sector,BYTE Block)
{
BYTE tmp = 0;
WriteIO(RegTimerClock,0x09); //设置定时器分频
WriteIO(RegTimerReload,0xA0); //设置定时器初值
WriteIO(RegChannelRedundancy,0x0F);
ResetInfo(Info);
Info.cmd = PCD_TRANSCEIVE;
Info.SerBuffer[0] = PICC_READ;
Info.SerBuffer[1] = Sector*4+Block;
Info.nBytesToSend = 2;
Info.nBytesReceived = 0x10; //接收字节长度为
if(M500PcdCmd())return 1; //调用发送命令子函数
if(Info.nBytesReceived != 16) return 1;
for(tmp=0;tmp<0x10;tmp++)
USART_Hex(Info.SerBuffer[tmp]);
return 0;
}
//写数据
BYTE M500PiccWrite(BYTE Sector,BYTE Block)
{
Info.cmd = PCD_TRANSCEIVE;
Info.SerBuffer[0] = PICC_WRITE;
Info.SerBuffer[1] = Sector*4+Block;
Info.nBytesToSend = 2;
Info.nBytesReceived = 0; //接收字节长度为
if(M500PcdCmd())return 1; //调用发送命令子函数
WriteIO(RegTimerClock,0x09); //设置定时器分频
WriteIO(RegTimerReload,0xA0); //设置定时器初值
WriteIO(RegChannelRedundancy,0x0F);
Info.cmd = PCD_TRANSCEIVE;
Info.nBytesToSend = 0x10;
Info.nBytesReceived = 0; //接收字节长度为
if(M500PcdCmd())return 1; //调用发送命令子函数
if(Info.SerBuffer[0]==0x0A)return 0;
return 1;
}
/*
//装载密码到EEPORM
BYTE M500PcdLoadKeyE2(WORD StartAddr)
{
BYTE key[6];
Info.cmd = PCD_LOADKEYE2; //命令为发送命令
Info.nBytesToSend = 2; //发送字节长度为1
Info.SerBuffer[0] = StartAddr & 0x0FF; //数据0为防冲突命令
Info.SerBuffer[1] = StartAddr >> 8;
M500HostCodeKey(key,&Info.SerBuffer[2]);
if(M500PcdCmd())return 1;
return 0;
}
//终止卡操作
BYTE M500PiccHalt(void)
{
ResetInfo(Info);
Info.SerBuffer[0] = PICC_HALT ; // Halt command code
Info.SerBuffer[1] = 0x00; // dummy address
Info.nBytesToSend = 2;
if(M500PcdCmd()) return 0;
WriteIO(RegCommand,PCD_IDLE);
return 1;
}
*/
/******************************************************************************/
void Device_Init(void)
{
MCUCR |= (1<<SRE); //使能总线
XMCRA = 0x00;
XMCRB = 0x00;
DDR_RC500RST();
DDR_RC500IRQ();
//LED
DDRB |= (1<<3);
PORTB &= ~(1<<3);
//A0,A1,A2
DDRE |= (1<<3) | (1<<4) | (1<<5);
PORTE |= (1<<3) | (1<<4) & ~(1<<5);
/*EICRA = 0x20; //下降沿触发
EICRB = 0x00;
EIMSK = 0x04; //外部中断2
SEI();*/
}
void main(void)
{
BYTE KEY[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
Device_Init();
USART_Init();
USART_String("Start to test RC500!\n");
//初始化并配置寄存器
if(M500PcdConfig())USART_String("Test error!\n");
else USART_String("Test OK!\n");
//寻卡
if(!M500PiccCommonRequest())USART_String("Card has found!\n");
else USART_String("Card has not found!\n");
//防冲突
if(!M500PiccCascAnticoll())USART_String("CascAnticoll success!\n");
else USART_String("CascAnticoll failure!\n");
//选卡
if(!M500PiccCascSelect())USART_String("Card Select success!\n");
else USART_String("Card Select failure!\n");
//直接验证密码
if(!M500PiccAuthKey(KEY,1,1))USART_String("Password validate success!\n");
else USART_String("Password validate failure!\n");
//读数据
M500PiccRead(1,1);
//写数据
if(!M500PiccWrite(1,1))USART_String("Write success!\n");
else USART_String("Write Failure!\n");
while(1);
}
/*
#pragma interrupt_handler int2_isr:iv_INT2
void int2_isr(void)
{
BYTE i,temp;
BYTE irqMask;
BYTE irqBits;
irqMask = ReadIO(RegInterruptEn);
irqBits = ReadIO(RegInterruptRq) & irqMask;
Info.irqSource |= irqBits;
USART_Hex(temp = ReadIO(RegInterruptRq));
if(temp&0x01)
{
for(i=0; i<Info.nBytesToSend; i++)
WriteIO(RegFIFOData,Info.SerBuffer[i]); //将数据写入FIFO
WriteIO(RegInterruptRq,0x01);
}
}
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -