各位前辈,我最近在做一个用STC89C52和PN532的NFC身份识别系统,我在网上找到了一个用STC12C5A60S2做的,只是我对STC12C5A60S2了解极少,再加上我的单片机处于刚刚起步阶段,所以虽然有程序但是几乎做不到两个单片机相互翻译,时间催的又紧,所以说只能向各位大佬求助了,如果各位大佬能不吝赐教,晚辈在此不胜感激并将程序好好钻研。我看看能不能把程序贴出来。
******************************************************************************** * STC12C5A60S2控制PN532进行寻卡操作 * STC12C5A60S2通过UART与PN532相连 * 通过中断实现接收UART数据,并通过定时判断PN532的响应是否超时 ********************************************************************************/ #include "reg52.h" #include <intrins.h> #define ERR_NO 0 #define ERR_TIMEOUT 1 #define ERR_SENDDATA 2 #define ERR_RECVACK 3 #define ERR_RECVDATA 4 //-----------------------------UART1部分使用的全局变量--------------------------- xdata unsigned char gPn532Data[100]; //13.56M RF数据缓存 xdata unsigned char *gpPn532RxBuf, gPn532RxLen; //用于中断函数处理接收buf xdata unsigned char gi; //用于接收数据与接收ack之间进行区别 //------------------------------------------------------------------------------- unsigned char gTimeMult; unsigned char gTimeOutFlag; unsigned char gUart1RecvFlag; sbit p25 = P2^5; void C51InitIo(void) { P2M0 |= 0x20; P2M1 |= 0x00;//配置P2.5为强上拉输出 } //定时时间=num*25ms void C51InitTimer(unsigned char num) { //AUXR |= 0xC0;//bit7->T0x12:0->12T,1->1T;bit6->T1x12:0->12T,1->1T,默认情况下是传统8051速度 TMOD |= 0x01; TH0 = 0x4C; TL0 = 0x00;//0x4C00=19456,(65536-19456)*12/22118400=0.025s=25ms gTimeMult = num;//25*40=1000ms=1s ET0 = 1; TR0 = 1; } void C51StopTimer() { TR0 = 0; } /************************************************** Function: init_uart(); Description: set uart working mode, 使用独立波特率发生器作为波特率发生器 **************************************************/ void C51InitUart(void) { AUXR |= 0x18; //BRTR=1,启动独立波特率发生器,S2SMOD=1,串口2波特率*2,S1BRS=1,串口1使用独立波特率发生器作为波特率发生器,S1BRS=0,串口1使用定时器1作为波特率发生器 SCON |= 0x50; //UART1工作于模式1(8位uart,加上起始位与停止位共10位),可变速率f=((2^SMOD)/32)*BRT,ren==1->允许串行接收 PCON |= 0x80; //smod=1, TMOD |= 0x20; //定时器工作与方式2,由TR1控制定时器的开启与关闭 TH1 = 0xFF; //22.1184MHz:0xF4->9600, 0xFA->19200, 0xFD->38400, 0xFE->57600, 0xFF->115200 TL1 = 0xFF; TR1 = 1; //启动定时器1 ES = 1; //允许串口1中断 S2CON |= 0x50; //UART2工作于模式1(8位uart,加上起始位与停止位共10位),可变速率f=((2^S2SMOD)/32)*BRT,ren==1->允许串行接收 BRT = 0xF4; //BRTx12=0;0xFF->115200,0xF4->9600,0xA0->1200 IE2 |= 0x01; //允许串口2中断 } //串口1发送一个字节函数 void C51Uart1SendByte(unsigned char num) { ES = 0; TI = 0; SBUF = num; while (0==TI); TI = 0; ES = 1; } //---------串口2发送与接收一个字节函数---------- void C51Uart2SendByte(unsigned char num) { IE2 &= 0xFE; //允许串口2中断,需要增加关闭、打开中断语句,不然串口2工作不正常 S2CON = S2CON&0xFD;//清除发送中断标志 S2BUF = num; while (0==(S2CON&0x02));//等于1说明发送完成 S2CON = S2CON&0xFD;//清除发送中断标志 IE2 |= 0x01; //允许串口2中断 } //延时n*1us函数 void C51Delay1us(unsigned short n) { while (--n) { _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); } } /***************************************************************** * 函数名: PN532SendData * 函数功能:主控器向PN532发送数据 * 输入参数: pBuf:需要发送给PN532的帧数据 len: pBuf的长度 * 输出参数: 返回是否成功标志 成功:SUCCESS 失败:相应的错误代码 ********************************************************************/ unsigned char PN532SendData(unsigned char *pBuf, unsigned char len) { unsigned char i; WDT_CONTR = 0x3F; for (i=0; i<len; i++) { C51Uart1SendByte(pBuf); } return ERR_NO; } /*************************************************** * 函数名: PN532RecvData * 函数功能:主控器从PN532接收数据 * 输入参数: 无 * 输出参数: pBuf: 接收帧缓存 返回是否成功标志 成功:SUCCESS 失败:相应的错误代码 ***************************************************/ unsigned char PN532RecvData(unsigned char *pBuf) { gTimeOutFlag = 0; gUart1RecvFlag = 0; C51InitTimer(4); gpPn532RxBuf = pBuf; //Start of RX buffer gPn532RxLen = 6; // Load RX byte counter gi = 0; while (!(gTimeOutFlag||gUart1RecvFlag));//只要有一个为1则退出循环 C51StopTimer(); if (1==gUart1RecvFlag) { return ERR_NO; } else { return ERR_TIMEOUT; } } /**************************************** * 函数名: PN532SendAck * 函数功能:主控器向PN532发送ACK帧 * 输入参数: 无 * 输出参数: 返回是否成功标志 成功:SUCCESS 失败:相应的错误代码 *****************************************/ unsigned char PN532SendAck() { unsigned char pAckBuf[6] = {0x00,0x00,0xFF,0x00,0xFF,0x00}; unsigned char i; for (i=0; i<6; i++) { C51Uart1SendByte(pAckBuf); } return ERR_NO; } /*********************************************** * 函数名: PN532RecvAck * 函数功能:主控器从PN532接收ACK帧 * 输入参数: 无 * 输出参数: pBuf: 接收ACK帧缓存 返回是否成功标志 成功:SUCCESS 失败:相应的错误代码 *************************************************/ unsigned char PN532RecvAck(unsigned char *pBuf) { gTimeOutFlag = 0; gUart1RecvFlag = 0; C51InitTimer(1); gpPn532RxBuf = pBuf; //Start of RX buffer gPn532RxLen = 6; // Load RX byte counter gi = 0; while (!(gTimeOutFlag||gUart1RecvFlag));//只要有一个为1则退出循环 C51StopTimer(); if (1==gUart1RecvFlag) { return ERR_NO; } else { return ERR_TIMEOUT; } } /********************************************************************************************************* * 函数名: SAMConfiguration * 函数功能:设置PN532的内部参数 * 输入参数: mode: 0x01:normal mode 0x02:virtual mode 0x03:wired mode 0x04:dual mode timeout: 0x00:不使用timeout 0x01-0xFF:超时值 irq: 0x00:不使用P70_IRQ 0x01:使用P70_IRQ * 输出参数: 成功:ERR_NO 失败:ERR_RECVACK,ERR_RECVDATA * 输入输出参数: pRfBuf:输入,用于存放输入参数的缓存,从外部传入,用于解决在函数内部定义过大的数组问题 输出,存放从PN532接收的结果 **********************************************************************************************************/ unsigned char SAMConfiguration(unsigned char *pRfBuf, unsigned char mode, unsigned char timeout, unsigned char irq) { unsigned char temp; unsigned char s; pRfBuf[0] = 0x00; //前导码 pRfBuf[1] = 0x00; //包开始标志2个字节 pRfBuf[2] = 0xFF; pRfBuf[3] = 3 + 1 + 1;//len + 1字节的PD0 + 1字节的TFI pRfBuf[4] = 0x100-pRfBuf[3]; pRfBuf[5] = 0xD4; //方向标示 temp = pRfBuf[5]; pRfBuf[6] = 0x14; //命令码 temp += pRfBuf[6]; pRfBuf[7] = mode; temp += pRfBuf[7]; pRfBuf[8] = timeout; temp += pRfBuf[8]; pRfBuf[9] = irq; temp += pRfBuf[9]; pRfBuf[10] = 0x100 - temp; //DCS pRfBuf[11] = 0x00; //底层发送函数 s = PN532SendData(pRfBuf,12); if (s!=ERR_NO) { return ERR_SENDDATA; } s = PN532RecvAck(pRfBuf); if (s!=ERR_NO) { return ERR_RECVACK; } s = PN532RecvData(pRfBuf); if (s!=ERR_NO) { return ERR_RECVDATA; } return ERR_NO; } /**************************************************************************************** * 函数名: InListPassiveTarget * 函数功能:PN532检测卡 * 输入参数: maxTag: PN532最大初始化卡的个数,PN532一次只能同时处理2张卡 brty: 0x00 : 106 kbps type A (ISO/IEC14443 Type A), 0x01 : 212 kbps (FeliCa polling), 0x02 : 424 kbps (FeliCa polling), 0x03 : 106 kbps type B (ISO/IEC14443-3B), 0x04 : 106 kbps Innovision Jewel tag. pData: * 输出参数: 成功:ERR_NO 失败:ERR_RECVACK,ERR_RECVDATA * 输入输出参数: pRfBuf:输入,用于存放输入参数的缓存,从外部传入,用于解决在函数内部定义过大的数组问题 输出,存放从PN532接收的结果 *****************************************************************************************/ unsigned char InListPassiveTarget(unsigned char *pRfBuf, unsigned char maxTag, unsigned char brty, unsigned char *pData, unsigned char len) { unsigned char i,temp; unsigned char s; pRfBuf[0] = 0x00; //前导码 pRfBuf[1] = 0x00; //包开始标志2个字节 pRfBuf[2] = 0xFF; pRfBuf[3] = len + 1 + 1 + 1 + 1;//len + 1字节的maxTag + 1字节的brty + 1字节的PD0 + 1字节的TFI pRfBuf[4] = 0x100-pRfBuf[3]; pRfBuf[5] = 0xD4; //方向标示 temp = pRfBuf[5]; pRfBuf[6] = 0x4A; //命令码 temp += pRfBuf[6]; pRfBuf[7] = maxTag; temp += pRfBuf[7]; pRfBuf[8] = brty; temp += pRfBuf[8]; for (i=0; i<len; i++) { pRfBuf[9+i] = pData; temp += pData; } pRfBuf[9+i] = 0x100 - temp; //DCS pRfBuf[9+i+1] = 0x00; //底层发送函数 s = PN532SendData(pRfBuf,9+i+1+1); if (s!=ERR_NO) { return ERR_SENDDATA; } s = PN532RecvAck(pRfBuf); if (s!=ERR_NO) { return ERR_RECVACK; } s = PN532RecvData(pRfBuf); if (s!=ERR_NO) { return ERR_RECVDATA; } return ERR_NO; } void main() { unsigned char i,s; C51InitIo(); C51InitUart(); WDT_CONTR = 0x3F;//使能看门狗、清看门狗标志、空闲模式计数、分频系数(scale:bit2-bit0),溢出时间=(12*scale*32768)/Fosc EA = 1; //cpu中断总允许 p25 = 0; C51Delay1us(60000); C51Delay1us(60000); C51Delay1us(60000); C51Delay1us(60000); C51Delay1us(60000); p25 = 1; gTimeOutFlag = 0; gUart1RecvFlag = 0; //--------------唤醒PN532---------------- C51Uart1SendByte(0x55); C51Uart1SendByte(0x55); C51Uart1SendByte(0x00); C51Uart1SendByte(0x00); C51Uart1SendByte(0x00); SAMConfiguration(gPn532Data,1,0,1); for (i=0; i<gPn532Data[3]+7; i++) { C51Uart2SendByte(gPn532Data); } //--------------------------------------- while(1) { WDT_CONTR = 0x3F; s = InListPassiveTarget(gPn532Data,1,0,0,0); if (ERR_NO==s) { for (i=0; i<gPn532Data[3]+7; i++) { C51Uart2SendByte(gPn532Data); } p25 = 0; C51Delay1us(60000); C51Delay1us(60000); C51Delay1us(60000); C51Delay1us(60000); C51Delay1us(60000); p25 = 1; } } } //串口中断服务程序 void Uart1IsrHandler(void) interrupt 4 { if (RI) { RI = 0; gPn532RxLen--; if (gPn532RxLen) { *gpPn532RxBuf = SBUF; gi++; if (gi==4) { if (0x00==*gpPn532RxBuf)//由于ACK帧与普通帧有一定的区别,所以要区别对待 { gPn532RxLen = *gpPn532RxBuf + 2; //接收ACK } else { gPn532RxLen = *gpPn532RxBuf + 3; //包长度 + 1字节的包长度校验 + 1字节的数据校验 + 1字节的后导码 } } gpPn532RxBuf++; } else { *gpPn532RxBuf = SBUF; gUart1RecvFlag = 1; } } if (TI) { TI = 0; } } void Timer0IsrHandler(void) interrupt 1 { TH0 = 0x4C; TL0 = 0x00; if (--gTimeMult) return; gTimeOutFlag = 1; }
|