STM32 + RC522(SPI2 和 模拟SPI)
一. STM32 + RC522(SPI2 模式)
1. 头文件: rc522.h
1 #include "stm32f10x.h" 2 ///////////////////////////////////////////////////////////////////// 3 //MF522命令字 4 ///////////////////////////////////////////////////////////////////// 5 #define PCD_IDLE 0x00 //取消当前命令 6 #define PCD_AUTHENT 0x0E //验证密钥 7 #define PCD_RECEIVE 0x08 //接收数据 8 #define PCD_TRANSMIT 0x04 //发送数据 9 #define PCD_TRANSCEIVE 0x0C //发送并接收数据 10 #define PCD_RESETPHASE 0x0F //复位 11 #define PCD_CALCCRC 0x03 //CRC计算 12 13 ///////////////////////////////////////////////////////////////////// 14 //Mifare_One卡片命令字 15 ///////////////////////////////////////////////////////////////////// 16 #define PICC_REQIDL 0x26 //寻天线区内未进入休眠状态 17 #define PICC_REQALL 0x52 //寻天线区内全部卡 18 #define PICC_ANTICOLL1 0x93 //防冲撞 19 #define PICC_ANTICOLL2 0x95 //防冲撞 20 #define PICC_AUTHENT1A 0x60 //验证A密钥 21 #define PICC_AUTHENT1B 0x61 //验证B密钥 22 #define PICC_READ 0x30 //读块 23 #define PICC_WRITE 0xA0 //写块 24 #define PICC_DECREMENT 0xC0 //扣款 25 #define PICC_INCREMENT 0xC1 //充值 26 #define PICC_RESTORE 0xC2 //调块数据到缓冲区 27 #define PICC_TRANSFER 0xB0 //保存缓冲区中数据 28 #define PICC_HALT 0x50 //休眠 29 30 ///////////////////////////////////////////////////////////////////// 31 //MF522 FIFO长度定义 32 ///////////////////////////////////////////////////////////////////// 33 #define DEF_FIFO_LENGTH 64 //FIFO size=64byte 34 #define MAXRLEN 18 35 36 ///////////////////////////////////////////////////////////////////// 37 //MF522寄存器定义 38 ///////////////////////////////////////////////////////////////////// 39 // PAGE 0 40 #define RFU00 0x00 41 #define CommandReg 0x01 42 #define ComIEnReg 0x02 43 #define DivlEnReg 0x03 44 #define ComIrqReg 0x04 45 #define DivIrqReg 0x05 46 #define ErrorReg 0x06 47 #define Status1Reg 0x07 48 #define Status2Reg 0x08 49 #define FIFODataReg 0x09 50 #define FIFOLevelReg 0x0A 51 #define WaterLevelReg 0x0B 52 #define ControlReg 0x0C 53 #define BitFramingReg 0x0D 54 #define CollReg 0x0E 55 #define RFU0F 0x0F 56 // PAGE 1 57 #define RFU10 0x10 58 #define ModeReg 0x11 59 #define TxModeReg 0x12 60 #define RxModeReg 0x13 61 #define TxControlReg 0x14 62 #define TxAutoReg 0x15 63 #define TxSelReg 0x16 64 #define RxSelReg 0x17 65 #define RxThresholdReg 0x18 66 #define DemodReg 0x19 67 #define RFU1A 0x1A 68 #define RFU1B 0x1B 69 #define MifareReg 0x1C 70 #define RFU1D 0x1D 71 #define RFU1E 0x1E 72 #define SerialSpeedReg 0x1F 73 // PAGE 2 74 #define RFU20 0x20 75 #define CRCResultRegM 0x21 76 #define CRCResultRegL 0x22 77 #define RFU23 0x23 78 #define ModWidthReg 0x24 79 #define RFU25 0x25 80 #define RFCfgReg 0x26 81 #define GsNReg 0x27 82 #define CWGsCfgReg 0x28 83 #define ModGsCfgReg 0x29 84 #define TModeReg 0x2A 85 #define TPrescalerReg 0x2B 86 #define TReloadRegH 0x2C 87 #define TReloadRegL 0x2D 88 #define TCounterValueRegH 0x2E 89 #define TCounterValueRegL 0x2F 90 // PAGE 3 91 #define RFU30 0x30 92 #define TestSel1Reg 0x31 93 #define TestSel2Reg 0x32 94 #define TestPinEnReg 0x33 95 #define TestPinValueReg 0x34 96 #define TestBusReg 0x35 97 #define AutoTestReg 0x36 98 #define VersionReg 0x37 99 #define AnalogTestReg 0x38 100 #define TestDAC1Reg 0x39 101 #define TestDAC2Reg 0x3A 102 #define TestADCReg 0x3B 103 #define RFU3C 0x3C 104 #define RFU3D 0x3D 105 #define RFU3E 0x3E 106 #define RFU3F 0x3F 107 108 ///////////////////////////////////////////////////////////////////// 109 //和MF522通讯时返回的错误代码 110 ///////////////////////////////////////////////////////////////////// 111 #define MI_OK 0 112 #define MI_NOTAGERR (1) 113 #define MI_ERR (2) 114 115 #define SHAQU1 0X01 116 #define KUAI4 0X04 117 #define KUAI7 0X07 118 #define REGCARD 0xa1 119 #define CONSUME 0xa2 120 #define READCARD 0xa3 121 #define ADDMONEY 0xa4 122 123 // 124 //#define spi_cs 1; 125 //sbit spi_ck=P0^6; 126 //sbit spi_mosi=P0^7; 127 //sbit spi_miso=P4^1; 128 //sbit spi_rst=P2^7; 129 #define SPIReadByte() SPIWriteByte(0) 130 u8 SPIWriteByte(u8 byte); 131 void SPI2_Init(void); 132 133 #define SET_SPI_CS (GPIOF->BSRR=0X01) 134 #define CLR_SPI_CS (GPIOF->BRR=0X01) 135 136 137 138 #define SET_RC522RST GPIOF->BSRR=0X02 139 #define CLR_RC522RST GPIOF->BRR=0X02 140 void InitRc522(void); 141 void ClearBitMask(u8 reg,u8 mask); 142 void WriteRawRC(u8 Address, u8 value); 143 void SetBitMask(u8 reg,u8 mask); 144 char PcdComMF522(u8 Command, 145 u8 *pIn , 146 u8 InLenByte, 147 u8 *pOut , 148 u8 *pOutLenBit); 149 void CalulateCRC(u8 *pIn ,u8 len,u8 *pOut ); 150 u8 ReadRawRC(u8 Address); 151 void PcdAntennaOn(void); 152 153 char PcdReset(void); 154 char PcdRequest(unsigned char req_code,unsigned char *pTagType); 155 void PcdAntennaOn(void); 156 void PcdAntennaOff(void); 157 char M500PcdConfigISOType(unsigned char type); 158 char PcdAnticoll(unsigned char *pSnr); 159 char PcdSelect(unsigned char *pSnr); 160 char PcdAuthState(unsigned char auth_mode,unsigned char addr,unsigned char *pKey,unsigned char *pSnr); 161 char PcdWrite(unsigned char addr,unsigned char *pData); 162 char PcdRead(unsigned char addr,unsigned char *pData); 163 char PcdHalt(void); 164 void Reset_RC522(void); 165 char PcdValue(u8 dd_mode,u8 addr,u8 *pValue); 166 char PcdBakValue(u8 sourceaddr, u8 goaladdr);
2. C文件:rc522.c
1 #include "sys.h" 2 #include "rc522.h" 3 #include "delay.h" 4 5 void delay_ns(u32 ns) 6 { 7 u32 i; 8 for(i=0;i<ns;i++) 9 { 10 __nop(); 11 __nop(); 12 __nop(); 13 } 14 } 15 16 u8 SPIWriteByte(u8 Byte) 17 { 18 while((SPI2->SR&0X02)==0); //等待发送区空 19 SPI2->DR=Byte; //发送一个byte 20 while((SPI2->SR&0X01)==0); //等待接收完一个byte 21 return SPI2->DR; //返回收到的数据 22 } 23 24 //SPIx 读写一个字节 25 //TxData:要写入的字节 26 //返回值:读取到的字节 27 u8 SPI2_ReadWriteByte(u8 TxData) 28 { 29 u8 retry=0; 30 while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET) //检查指定的SPI标志位设置与否:发送缓存空标志位 31 { 32 retry++; 33 if(retry>200)return 0; 34 } 35 SPI_I2S_SendData(SPI2, TxData); //通过外设SPIx发送一个数据 36 retry=0; 37 38 while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET) //检查指定的SPI标志位设置与否:接受缓存非空标志位 39 { 40 retry++; 41 if(retry>200)return 0; 42 } 43 return SPI_I2S_ReceiveData(SPI2); //返回通过SPIx最近接收的数据 44 } 45 46 47 //SPI 速度设置函数 48 //SpeedSet: 49 //SPI_BaudRatePrescaler_2 2分频 50 //SPI_BaudRatePrescaler_8 8分频 51 //SPI_BaudRatePrescaler_16 16分频 52 //SPI_BaudRatePrescaler_256 256分频 53 54 void SPI2_SetSpeed(u8 SPI_BaudRatePrescaler) 55 { 56 assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler)); 57 SPI2->CR1&=0XFFC7; 58 SPI2->CR1|=SPI_BaudRatePrescaler; //设置SPI2速度 59 SPI_Cmd(SPI2,ENABLE); 60 61 } 62 63 64 65 66 void SPI2_Init(void) 67 { 68 GPIO_InitTypeDef GPIO_InitStructure; 69 SPI_InitTypeDef SPI_InitStructure; 70 RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOF, ENABLE );//PORTB时钟使能 71 RCC_APB1PeriphClockCmd( RCC_APB1Periph_SPI2, ENABLE );//SPI2时钟使能 72 73 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1; //IO-->PF0、PF1 端口配置 74 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 75 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz 76 GPIO_Init(GPIOF, &GPIO_InitStructure); //根据设定参数初始化PF0、PF1 77 GPIO_ResetBits(GPIOF,GPIO_Pin_1); //PF1输出低 78 //GPIO_SetBits(GPIOF,GPIO_Pin_0); 79 80 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15; 81 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //PB13/14/15复用推挽输出 82 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 83 GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOB 84 85 GPIO_SetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15); //PB13/14/15上拉 86 87 SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工 88 SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //设置SPI工作模式:设置为主SPI 89 SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //设置SPI的数据大小:SPI发送接收8位帧结构 90 SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //串行同步时钟的空闲状态为低电平 91 SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //串行同步时钟的第一个跳变沿(上升或下降)数据被采样 92 SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制 93 SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; //定义波特率预分频的值:波特率预分频值为256 94 SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始 95 SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式 96 SPI_Init(SPI2, &SPI_InitStructure); //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器 97 98 SPI_Cmd(SPI2, ENABLE); //使能SPI外设 99 100 //SPI2_ReadWriteByte(0xff);//启动传输 101 } 102 103 void InitRc522(void) 104 { 105 SPI2_Init(); 106 PcdReset(); 107 PcdAntennaOff(); 108 delay_ms(2); 109 PcdAntennaOn(); 110 M500PcdConfigISOType( 'A' ); 111 } 112 void Reset_RC522(void) 113 { 114 PcdReset(); 115 PcdAntennaOff(); 116 delay_ms(2); 117 PcdAntennaOn(); 118 } 119 ///////////////////////////////////////////////////////////////////// 120 //功 能:寻卡 121 //参数说明: req_code[IN]:寻卡方式 122 // 0x52 = 寻感应区内所有符合14443A标准的卡 123 // 0x26 = 寻未进入休眠状态的卡 124 // pTagType[OUT]:卡片类型代码 125 // 0x4400 = Mifare_UltraLight 126 // 0x0400 = Mifare_One(S50) 127 // 0x0200 = Mifare_One(S70) 128 // 0x0800 = Mifare_Pro(X) 129 // 0x4403 = Mifare_DESFire 130 //返 回: 成功返回MI_OK 131 ///////////////////////////////////////////////////////////////////// 132 char PcdRequest(u8 req_code,u8 *pTagType) 133 { 134 char status; 135 u8 unLen; 136 u8 ucComMF522Buf[MAXRLEN]; 137 138 ClearBitMask(Status2Reg,0x08); 139 WriteRawRC(BitFramingReg,0x07); 140 SetBitMask(TxControlReg,0x03); 141 142 ucComMF522Buf[0] = req_code; 143 144 status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,1,ucComMF522Buf,&unLen); 145 146 if ((status == MI_OK) && (unLen == 0x10)) 147 { 148 *pTagType = ucComMF522Buf[0]; 149 *(pTagType+1) = ucComMF522Buf[1]; 150 } 151 else 152 { status = MI_ERR; } 153 154 return status; 155 } 156 157 ///////////////////////////////////////////////////////////////////// 158 //功 能:防冲撞 159 //参数说明: pSnr[OUT]:卡片序列号,4字节 160 //返 回: 成功返回MI_OK 161 ///////////////////////////////////////////////////////////////////// 162 char PcdAnticoll(u8 *pSnr) 163 { 164 char status; 165 u8 i,snr_check=0; 166 u8 unLen; 167 u8 ucComMF522Buf[MAXRLEN]; 168 169 170 ClearBitMask(Status2Reg,0x08); 171 WriteRawRC(BitFramingReg,0x00); 172 ClearBitMask(CollReg,0x80); 173 174 ucComMF522Buf[0] = PICC_ANTICOLL1; 175 ucComMF522Buf[1] = 0x20; 176 177 status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,2,ucComMF522Buf,&unLen); 178 179 if (status == MI_OK) 180 { 181 for (i=0; i<4; i++) 182 { 183 *(pSnr+i) = ucComMF522Buf[i]; 184 snr_check ^= ucComMF522Buf[i]; 185 } 186 if (snr_check != ucComMF522Buf[i]) 187 { status = MI_ERR; } 188 } 189 190 SetBitMask(CollReg,0x80); 191 return status; 192 } 193 194 ///////////////////////////////////////////////////////////////////// 195 //功 能:选定卡片 196 //参数说明: pSnr[IN]:卡片序列号,4字节 197 //返 回: 成功返回MI_OK 198 ///////////////////////////////////////////////////////////////////// 199 char PcdSelect(u8 *pSnr) 200 { 201 char status; 202 u8 i; 203 u8 unLen; 204 u8 ucComMF522Buf[MAXRLEN]; 205 206 ucComMF522Buf[0] = PICC_ANTICOLL1; 207 ucComMF522Buf[1] = 0x70; 208 ucComMF522Buf[6] = 0; 209 for (i=0; i<4; i++) 210 { 211 ucComMF522Buf[i+2] = *(pSnr+i); 212 ucComMF522Buf[6] ^= *(pSnr+i); 213 } 214 CalulateCRC(ucComMF522Buf,7,&ucComMF522Buf[7]); 215 216 ClearBitMask(Status2Reg,0x08); 217 218 status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,9,ucComMF522Buf,&unLen); 219 220 if ((status == MI_OK) && (unLen == 0x18)) 221 { status = MI_OK; } 222 else 223 { status = MI_ERR; } 224 225 return status; 226 } 227 228 ///////////////////////////////////////////////////////////////////// 229 //功 能:验证卡片密码 230 //参数说明: auth_mode[IN]: 密码验证模式 231 // 0x60 = 验证A密钥 232 // 0x61 = 验证B密钥 233 // addr[IN]:块地址 234 // pKey[IN]:密码 235 // pSnr[IN]:卡片序列号,4字节 236 //返 回: 成功返回MI_OK 237 ///////////////////////////////////////////////////////////////////// 238 char PcdAuthState(u8 auth_mode,u8 addr,u8 *pKey,u8 *pSnr) 239 { 240 char status; 241 u8 unLen; 242 u8 i,ucComMF522Buf[MAXRLEN]; 243 244 ucComMF522Buf[0] = auth_mode; 245 ucComMF522Buf[1] = addr; 246 // for (i=0; i<6; i++) 247 // { ucComMF522Buf[i+2] = *(pKey+i); } 248 // for (i=0; i<6; i++) 249 // { ucComMF522Buf[i+8] = *(pSnr+i); } 250 memcpy(&ucComMF522Buf[2], pKey, 6); 251 memcpy(&ucComMF522Buf[8], pSnr, 4); 252 253 status = PcdComMF522(PCD_AUTHENT,ucComMF522Buf,12,ucComMF522Buf,&unLen); 254 if ((status != MI_OK) || (!(ReadRawRC(Status2Reg) & 0x08))) 255 { status = MI_ERR; } 256 257 return status; 258 } 259 260 ///////////////////////////////////////////////////////////////////// 261 //功 能:读取M1卡一块数据 262 //参数说明: addr[IN]:块地址 263 // p [OUT]:读出的数据,16字节 264 //返 回: 成功返回MI_OK 265 ///////////////////////////////////////////////////////////////////// 266 char PcdRead(u8 addr,u8 *p ) 267 { 268 char status; 269 u8 unLen; 270 u8 i,ucComMF522Buf[MAXRLEN]; 271 272 ucComMF522Buf[0] = PICC_READ; 273 ucComMF522Buf[1] = addr; 274 CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]); 275 276 status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen); 277 if ((status == MI_OK) && (unLen == 0x90)) 278 // { memcpy(p , ucComMF522Buf, 16); } 279 { 280 for (i=0; i<16; i++) 281 { *(p +i) = ucComMF522Buf[i]; } 282 } 283 else 284 { status = MI_ERR; } 285 286 return status; 287 } 288 289 ///////////////////////////////////////////////////////////////////// 290 //功 能:写数据到M1卡一块 291 //参数说明: addr[IN]:块地址 292 // p [IN]:写入的数据,16字节 293 //返 回: 成功返回MI_OK 294 ///////////////////////////////////////////////////////////////////// 295 char PcdWrite(u8 addr,u8 *p ) 296 { 297 char status; 298 u8 unLen; 299 u8 i,ucComMF522Buf[MAXRLEN]; 300 301 ucComMF522Buf[0] = PICC_WRITE; 302 ucComMF522Buf[1] = addr; 303 CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]); 304 305 status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen); 306 307 if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A)) 308 { status = MI_ERR; } 309 310 if (status == MI_OK) 311 { 312 //memcpy(ucComMF522Buf, p , 16); 313 for (i=0; i<16; i++) 314 { 315 ucComMF522Buf[i] = *(p +i); 316 } 317 CalulateCRC(ucComMF522Buf,16,&ucComMF522Buf[16]); 318 319 status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,18,ucComMF522Buf,&unLen); 320 if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A)) 321 { status = MI_ERR; } 322 } 323 324 return status; 325 } 326 327 ///////////////////////////////////////////////////////////////////// 328 //功 能:命令卡片进入休眠状态 329 //返 回: 成功返回MI_OK 330 ///////////////////////////////////////////////////////////////////// 331 char PcdHalt(void) 332 { 333 u8 status; 334 u8 unLen; 335 u8 ucComMF522Buf[MAXRLEN]; 336 337 ucComMF522Buf[0] = PICC_HALT; 338 ucComMF522Buf[1] = 0; 339 CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]); 340 341 status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen); 342 343 return MI_OK; 344 } 345 346 ///////////////////////////////////////////////////////////////////// 347 //用MF522计算CRC16函数 348 ///////////////////////////////////////////////////////////////////// 349 void CalulateCRC(u8 *pIn ,u8 len,u8 *pOut ) 350 { 351 u8 i,n; 352 ClearBitMask(DivIrqReg,0x04); 353 WriteRawRC(CommandReg,PCD_IDLE); 354 SetBitMask(FIFOLevelReg,0x80); 355 for (i=0; i<len; i++) 356 { WriteRawRC(FIFODataReg, *(pIn +i)); } 357 WriteRawRC(CommandReg, PCD_CALCCRC); 358 i = 0xFF; 359 do 360 { 361 n = ReadRawRC(DivIrqReg); 362 i--; 363 } 364 while ((i!=0) && !(n&0x04)); 365 pOut [0] = ReadRawRC(CRCResultRegL); 366 pOut [1] = ReadRawRC(CRCResultRegM); 367 } 368 369 ///////////////////////////////////////////////////////////////////// 370 //功 能:复位RC522 371 //返 回: 成功返回MI_OK 372 ///////////////////////////////////////////////////////////////////// 373 char PcdReset(void) 374 { 375 //PORTD|=(1<<RC522RST); 376 SET_RC522RST; 377 delay_ns(10); 378 //PORTD&=~(1<<RC522RST); 379 CLR_RC522RST; 380 delay_ns(10); 381 //PORTD|=(1<<RC522RST); 382 SET_RC522RST; 383 delay_ns(10); 384 WriteRawRC(CommandReg,PCD_RESETPHASE); 385 WriteRawRC(CommandReg,PCD_RESETPHASE); 386 delay_ns(10); 387 388 WriteRawRC(ModeReg,0x3D); //和Mifare卡通讯,CRC初始值0x6363 389 WriteRawRC(TReloadRegL,30); 390 WriteRawRC(TReloadRegH,0); 391 WriteRawRC(TModeReg,0x8D); 392 WriteRawRC(TPrescalerReg,0x3E); 393 394 WriteRawRC(TxAutoReg,0x40);//必须要 395 396 return MI_OK; 397 } 398 ////////////////////////////////////////////////////////////////////// 399 //设置RC632的工作方式 400 ////////////////////////////////////////////////////////////////////// 401 char M500PcdConfigISOType(u8 type) 402 { 403 if (type == 'A') //ISO14443_A 404 { 405 ClearBitMask(Status2Reg,0x08); 406 WriteRawRC(ModeReg,0x3D);//3F 407 WriteRawRC(RxSelReg,0x86);//84 408 WriteRawRC(RFCfgReg,0x7F); //4F 409 WriteRawRC(TReloadRegL,30);//tmoLength);// TReloadVal = 'h6a =tmoLength(dec) 410 WriteRawRC(TReloadRegH,0); 411 WriteRawRC(TModeReg,0x8D); 412 WriteRawRC(TPrescalerReg,0x3E); 413 delay_ns(1000); 414 PcdAntennaOn(); 415 } 416 else{ return 1; } 417 418 return MI_OK; 419 } 420 ///////////////////////////////////////////////////////////////////// 421 //功 能:读RC632寄存器 422 //参数说明:Address[IN]:寄存器地址 423 //返 回:读出的值 424 ///////////////////////////////////////////////////////////////////// 425 u8 ReadRawRC(u8 Address) 426 { 427 u8 ucAddr; 428 u8 ucResult=0; 429 CLR_SPI_CS; 430 ucAddr = ((Address<<1)&0x7E)|0x80; 431 432 SPIWriteByte(ucAddr); 433 ucResult=SPIReadByte(); 434 SET_SPI_CS; 435 return ucResult; 436 } 437 438 ///////////////////////////////////////////////////////////////////// 439 //功 能:写RC632寄存器 440 //参数说明:Address[IN]:寄存器地址 441 // value[IN]:写入的值 442 ///////////////////////////////////////////////////////////////////// 443 void WriteRawRC(u8 Address, u8 value) 444 { 445 u8 ucAddr; 446 // u8 tmp; 447 448 CLR_SPI_CS; 449 ucAddr = ((Address<<1)&0x7E); 450 451 SPIWriteByte(ucAddr); 452 SPIWriteByte(value); 453 SET_SPI_CS; 454 455 // tmp=ReadRawRC(Address); 456 // 457 // if(value!=tmp) 458 // printf("wrong\n"); 459 } 460 ///////////////////////////////////////////////////////////////////// 461 //功 能:置RC522寄存器位 462 //参数说明:reg[IN]:寄存器地址 463 // mask[IN]:置位值 464 ///////////////////////////////////////////////////////////////////// 465 void SetBitMask(u8 reg,u8 mask) 466 { 467 char tmp = 0x0; 468 tmp = ReadRawRC(reg); 469 WriteRawRC(reg,tmp | mask); // set bit mask 470 } 471 472 ///////////////////////////////////////////////////////////////////// 473 //功 能:清RC522寄存器位 474 //参数说明:reg[IN]:寄存器地址 475 // mask[IN]:清位值 476 ///////////////////////////////////////////////////////////////////// 477 void ClearBitMask(u8 reg,u8 mask) 478 { 479 char tmp = 0x0; 480 tmp = ReadRawRC(reg); 481 WriteRawRC(reg, tmp & ~mask); // clear bit mask 482 } 483 484 ///////////////////////////////////////////////////////////////////// 485 //功 能:通过RC522和ISO14443卡通讯 486 //参数说明:Command[IN]:RC522命令字 487 // pIn [IN]:通过RC522发送到卡片的数据 488 // InLenByte[IN]:发送数据的字节长度 489 // pOut [OUT]:接收到的卡片返回数据 490 // *pOutLenBit[OUT]:返回数据的位长度 491 ///////////////////////////////////////////////////////////////////// 492 char PcdComMF522(u8 Command, 493 u8 *pIn , 494 u8 InLenByte, 495 u8 *pOut , 496 u8 *pOutLenBit) 497 { 498 char status = MI_ERR; 499 u8 irqEn = 0x00; 500 u8 waitFor = 0x00; 501 u8 lastBits; 502 u8 n; 503 u16 i; 504 switch (Command) 505 { 506 case PCD_AUTHENT: 507 irqEn = 0x12; 508 waitFor = 0x10; 509 break; 510 case PCD_TRANSCEIVE: 511 irqEn = 0x77; 512 waitFor = 0x30; 513 break; 514 default: 515 break; 516 } 517 518 WriteRawRC(ComIEnReg,irqEn|0x80); 519 ClearBitMask(ComIrqReg,0x80); //清所有中断位 520 WriteRawRC(CommandReg,PCD_IDLE); 521 SetBitMask(FIFOLevelReg,0x80); //清FIFO缓存 522 523 for (i=0; i<InLenByte; i++) 524 { WriteRawRC(FIFODataReg, pIn [i]); } 525 WriteRawRC(CommandReg, Command); 526 // n = ReadRawRC(CommandReg); 527 528 if (Command == PCD_TRANSCEIVE) 529 { SetBitMask(BitFramingReg,0x80); } //开始传送 530 531 //i = 600;//根据时钟频率调整,操作M1卡最大等待时间25ms 532 i = 2000; 533 do 534 { 535 n = ReadRawRC(ComIrqReg); 536 i--; 537 } 538 while ((i!=0) && !(n&0x01) && !(n&waitFor)); 539 ClearBitMask(BitFramingReg,0x80); 540 541 if (i!=0) 542 { 543 if(!(ReadRawRC(ErrorReg)&0x1B)) 544 { 545 status = MI_OK; 546 if (n & irqEn & 0x01) 547 { status = MI_NOTAGERR; } 548 if (Command == PCD_TRANSCEIVE) 549 { 550 n = ReadRawRC(FIFOLevelReg); 551 lastBits = ReadRawRC(ControlReg) & 0x07; 552 if (lastBits) 553 { *pOutLenBit = (n-1)*8 + lastBits; } 554 else 555 { *pOutLenBit = n*8; } 556 if (n == 0) 557 { n = 1; } 558 if (n > MAXRLEN) 559 { n = MAXRLEN; } 560 for (i=0; i<n; i++) 561 { pOut [i] = ReadRawRC(FIFODataReg); } 562 } 563 } 564 else 565 { status = MI_ERR; } 566 567 } 568 569 570 SetBitMask(ControlReg,0x80); // stop timer now 571 WriteRawRC(CommandReg,PCD_IDLE); 572 return status; 573 } 574 575 ///////////////////////////////////////////////////////////////////// 576 //开启天线 577 //每次启动或关闭天险发射之间应至少有1ms的间隔 578 ///////////////////////////////////////////////////////////////////// 579 void PcdAntennaOn(void) 580 { 581 u8 i; 582 i = ReadRawRC(TxControlReg); 583 if (!(i & 0x03)) 584 { 585 SetBitMask(TxControlReg, 0x03); 586 } 587 } 588 589 590 ///////////////////////////////////////////////////////////////////// 591 //关闭天线 592 ///////////////////////////////////////////////////////////////////// 593 void PcdAntennaOff(void) 594 { 595 ClearBitMask(TxControlReg, 0x03); 596 } 597 598 ///////////////////////////////////////////////////////////////////// 599 //功 能:扣款和充值 600 //参数说明: dd_mode[IN]:命令字 601 // 0xC0 = 扣款 602 // 0xC1 = 充值 603 // addr[IN]:钱包地址 604 // pValue[IN]:4字节增(减)值,低位在前 605 //返 回: 成功返回MI_OK 606 ///////////////////////////////////////////////////////////////////// 607 char PcdValue(u8 dd_mode,u8 addr,u8 *pValue) 608 { 609 char status; 610 u8 unLen; 611 u8 ucComMF522Buf[MAXRLEN]; 612 //u8 i; 613 614 ucComMF522Buf[0] = dd_mode; 615 ucComMF522Buf[1] = addr; 616 CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]); 617 618 status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen); 619 620 if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A)) 621 { status = MI_ERR; } 622 623 if (status == MI_OK) 624 { 625 memcpy(ucComMF522Buf, pValue, 4); 626 //for (i=0; i<16; i++) 627 //{ ucComMF522Buf[i] = *(pValue+i); } 628 CalulateCRC(ucComMF522Buf,4,&ucComMF522Buf[4]); 629 unLen = 0; 630 status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,6,ucComMF522Buf,&unLen); 631 if (status != MI_ERR) 632 { status = MI_OK; } 633 } 634 635 if (status == MI_OK) 636 { 637 ucComMF522Buf[0] = PICC_TRANSFER; 638 ucComMF522Buf[1] = addr; 639 CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]); 640 641 status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen); 642 643 if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A)) 644 { status = MI_ERR; } 645 } 646 return status; 647 } 648 649 ///////////////////////////////////////////////////////////////////// 650 //功 能:备份钱包 651 //参数说明: sourceaddr[IN]:源地址 652 // goaladdr[IN]:目标地址 653 //返 回: 成功返回MI_OK 654 ///////////////////////////////////////////////////////////////////// 655 char PcdBakValue(u8 sourceaddr, u8 goaladdr) 656 { 657 char status; 658 u8 unLen; 659 u8 ucComMF522Buf[MAXRLEN]; 660 661 ucComMF522Buf[0] = PICC_RESTORE; 662 ucComMF522Buf[1] = sourceaddr; 663 CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]); 664 665 status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen); 666 667 if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A)) 668 { status = MI_ERR; } 669 670 if (status == MI_OK) 671 { 672 ucComMF522Buf[0] = 0; 673 ucComMF522Buf[1] = 0; 674 ucComMF522Buf[2] = 0; 675 ucComMF522Buf[3] = 0; 676 CalulateCRC(ucComMF522Buf,4,&ucComMF522Buf[4]); 677 678 status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,6,ucComMF522Buf,&unLen); 679 if (status != MI_ERR) 680 { status = MI_OK; } 681 } 682 683 if (status != MI_OK) 684 { return MI_ERR; } 685 686 ucComMF522Buf[0] = PICC_TRANSFER; 687 ucComMF522Buf[1] = goaladdr; 688 689 CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]); 690 691 status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen); 692 693 if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A)) 694 { status = MI_ERR; } 695 696 return status; 697 }
一. STM32 + RC522(模拟SPI 模式)
1. 头文件: rc522.h
1 #ifndef _RC522_H 2 #define _RC522_H 3 #include "sys.h" 4 #include "delay.h" 5 6 7 ///////////////////////////////////////////////////////////////////// 8 //MF522命令字 9 ///////////////////////////////////////////////////////////////////// 10 #define PCD_IDLE 0x00 //取消当前命令 11 #define PCD_AUTHENT 0x0E //验证密钥 12 #define PCD_RECEIVE 0x08 //接收数据 13 #define PCD_TRANSMIT 0x04 //发送数据 14 #define PCD_TRANSCEIVE 0x0C //发送并接收数据 15 #define PCD_RESETPHASE 0x0F //复位 16 #define PCD_CALCCRC 0x03 //CRC计算 17 18 ///////////////////////////////////////////////////////////////////// 19 //Mifare_One卡片命令字 20 ///////////////////////////////////////////////////////////////////// 21 #define PICC_REQIDL 0x26 //寻天线区内未进入休眠状态 22 #define PICC_REQALL 0x52 //寻天线区内全部卡 23 #define PICC_ANTICOLL1 0x93 //防冲撞 24 #define PICC_ANTICOLL2 0x95 //防冲撞 25 #define PICC_AUTHENT1A 0x60 //验证A密钥 26 #define PICC_AUTHENT1B 0x61 //验证B密钥 27 #define PICC_READ 0x30 //读块 28 #define PICC_WRITE 0xA0 //写块 29 #define PICC_DECREMENT 0xC0 //扣款 30 #define PICC_INCREMENT 0xC1 //充值 31 #define PICC_RESTORE 0xC2 //调块数据到缓冲区 32 #define PICC_TRANSFER 0xB0 //保存缓冲区中数据 33 #define PICC_HALT 0x50 //休眠 34 35 ///////////////////////////////////////////////////////////////////// 36 //MF522 FIFO长度定义 37 ///////////////////////////////////////////////////////////////////// 38 #define DEF_FIFO_LENGTH 64 //FIFO size=64byte 39 40 ///////////////////////////////////////////////////////////////////// 41 //MF522寄存器定义 42 ///////////////////////////////////////////////////////////////////// 43 // PAGE 0 44 #define RFU00 0x00 45 #define CommandReg 0x01 46 #define ComIEnReg 0x02 47 #define DivlEnReg 0x03 48 #define ComIrqReg 0x04 49 #define DivIrqReg 0x05 50 #define ErrorReg 0x06 51 #define Status1Reg 0x07 52 #define Status2Reg 0x08 53 #define FIFODataReg 0x09 54 #define FIFOLevelReg 0x0A 55 #define WaterLevelReg 0x0B 56 #define ControlReg 0x0C 57 #define BitFramingReg 0x0D 58 #define CollReg 0x0E 59 #define RFU0F 0x0F 60 // PAGE 1 61 #define RFU10 0x10 62 #define ModeReg 0x11 63 #define TxModeReg 0x12 64 #define RxModeReg 0x13 65 #define TxControlReg 0x14 66 #define TxAutoReg 0x15 67 #define TxSelReg 0x16 68 #define RxSelReg 0x17 69 #define RxThresholdReg 0x18 70 #define DemodReg 0x19 71 #define RFU1A 0x1A 72 #define RFU1B 0x1B 73 #define MifareReg 0x1C 74 #define RFU1D 0x1D 75 #define RFU1E 0x1E 76 #define SerialSpeedReg 0x1F 77 // PAGE 2 78 #define RFU20 0x20 79 #define CRCResultRegM 0x21 80 #define CRCResultRegL 0x22 81 #define RFU23 0x23 82 #define ModWidthReg 0x24 83 #define RFU25 0x25 84 #define RFCfgReg 0x26 85 #define GsNReg 0x27 86 #define CWGsCfgReg 0x28 87 #define ModGsCfgReg 0x29 88 #define TModeReg 0x2A 89 #define TPrescalerReg 0x2B 90 #define TReloadRegH 0x2C 91 #define TReloadRegL 0x2D 92 #define TCounterValueRegH 0x2E 93 #define TCounterValueRegL 0x2F 94 // PAGE 3 95 #define RFU30 0x30 96 #define TestSel1Reg 0x31 97 #define TestSel2Reg 0x32 98 #define TestPinEnReg 0x33 99 #define TestPinValueReg 0x34 100 #define TestBusReg 0x35 101 #define AutoTestReg 0x36 102 #define VersionReg 0x37 103 #define AnalogTestReg 0x38 104 #define TestDAC1Reg 0x39 105 #define TestDAC2Reg 0x3A 106 #define TestADCReg 0x3B 107 #define RFU3C 0x3C 108 #define RFU3D 0x3D 109 #define RFU3E 0x3E 110 #define RFU3F 0x3F 111 112 ///////////////////////////////////////////////////////////////////// 113 //和MF522通讯时返回的错误代码 114 ///////////////////////////////////////////////////////////////////// 115 #define MI_OK 0 116 #define MI_NOTAGERR (-1) 117 #define MI_ERR (-2) 118 119 120 #define MF522_NSS PFout(0) //PF0 SDA 121 #define MF522_SCK PFout(1) //PF1 122 #define MF522_SI PFout(2) //PF2 123 #define MF522_SO PFin(3) //PF3 124 #define MF522_RST PFout(4) //PF4 125 126 127 ///////////////////////////////////////////////////////////////////// 128 //函数原型 129 ///////////////////////////////////////////////////////////////////// 130 char PcdReset(void); 131 void PcdAntennaOn(void); 132 void PcdAntennaOff(void); 133 char PcdRequest(unsigned char req_code,unsigned char *pTagType); 134 char PcdAnticoll(unsigned char *pSnr); 135 char PcdSelect(unsigned char *pSnr); 136 char PcdAuthState(unsigned char auth_mode,unsigned char addr,unsigned char *pKey,unsigned char *pSnr); 137 char PcdRead(unsigned char addr,unsigned char *pData); 138 char PcdWrite(unsigned char addr,unsigned char *pData); 139 char PcdValue(unsigned char dd_mode,unsigned char addr,unsigned char *pValue); 140 char PcdBakValue(unsigned char sourceaddr, unsigned char goaladdr); 141 char PcdHalt(void); 142 char PcdComMF522(unsigned char Command, 143 unsigned char *pInData, 144 unsigned char InLenByte, 145 unsigned char *pOutData, 146 unsigned int *pOutLenBit); 147 void CalulateCRC(unsigned char *pIndata,unsigned char len,unsigned char *pOutData); 148 void WriteRawRC(unsigned char Address,unsigned char value); 149 unsigned char ReadRawRC(unsigned char Address); 150 void SetBitMask(unsigned char reg,unsigned char mask); 151 void ClearBitMask(unsigned char reg,unsigned char mask); 152 void RC522_Init(void); 153 #endif
2. C文件:rc522.c
1 #include "RC522.h" 2 3 #define MAXRLEN 18 4 5 void RC522_Init(void) 6 { 7 GPIO_InitTypeDef GPIO_InitStructure; 8 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF, ENABLE); //使能PF端口时钟 9 10 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_0|GPIO_Pin_2|GPIO_Pin_4; 11 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 12 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz 13 GPIO_Init(GPIOF, &GPIO_InitStructure); 14 GPIO_SetBits(GPIOF,GPIO_Pin_1|GPIO_Pin_0|GPIO_Pin_2|GPIO_Pin_4); //拉高 15 16 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; 17 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入 18 GPIO_Init(GPIOF, &GPIO_InitStructure); 19 } 20 21 22 23 ///////////////////////////////////////////////////////////////////// 24 //功 能:寻卡 25 //参数说明: req_code[IN]:寻卡方式 26 // 0x52 = 寻感应区内所有符合14443A标准的卡 27 // 0x26 = 寻未进入休眠状态的卡 28 // pTagType[OUT]:卡片类型代码 29 // 0x4400 = Mifare_UltraLight 30 // 0x0400 = Mifare_One(S50) 31 // 0x0200 = Mifare_One(S70) 32 // 0x0800 = Mifare_Pro(X) 33 // 0x4403 = Mifare_DESFire 34 //返 回: 成功返回MI_OK 35 ///////////////////////////////////////////////////////////////////// 36 char PcdRequest(unsigned char req_code,unsigned char *pTagType) 37 { 38 char status; 39 unsigned int unLen; 40 unsigned char ucComMF522Buf[MAXRLEN]; 41 42 ClearBitMask(Status2Reg,0x08); 43 WriteRawRC(BitFramingReg,0x07); 44 SetBitMask(TxControlReg,0x03); 45 46 ucComMF522Buf[0] = req_code; 47 48 status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,1,ucComMF522Buf,&unLen); 49 50 if ((status == MI_OK) && (unLen == 0x10)) 51 { 52 *pTagType = ucComMF522Buf[0]; 53 *(pTagType+1) = ucComMF522Buf[1]; 54 } 55 else 56 { status = MI_ERR; 57 } 58 59 return status; 60 } 61 62 ///////////////////////////////////////////////////////////////////// 63 //功 能:防冲撞 64 //参数说明: pSnr[OUT]:卡片序列号,4字节 65 //返 回: 成功返回MI_OK 66 ///////////////////////////////////////////////////////////////////// 67 char PcdAnticoll(unsigned char *pSnr) 68 { 69 char status; 70 unsigned char i,snr_check=0; 71 unsigned int unLen; 72 unsigned char ucComMF522Buf[MAXRLEN]; 73 74 75 ClearBitMask(Status2Reg,0x08); 76 WriteRawRC(BitFramingReg,0x00); 77 ClearBitMask(CollReg,0x80); 78 79 ucComMF522Buf[0] = PICC_ANTICOLL1; 80 ucComMF522Buf[1] = 0x20; 81 82 status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,2,ucComMF522Buf,&unLen); 83 84 if (status == MI_OK) 85 { 86 for (i=0; i<4; i++) 87 { 88 *(pSnr+i) = ucComMF522Buf[i]; 89 snr_check ^= ucComMF522Buf[i]; 90 91 } 92 if (snr_check != ucComMF522Buf[i]) 93 { status = MI_ERR; } 94 } 95 96 SetBitMask(CollReg,0x80); 97 return status; 98 } 99 100 ///////////////////////////////////////////////////////////////////// 101 //功 能:选定卡片 102 //参数说明: pSnr[IN]:卡片序列号,4字节 103 //返 回: 成功返回MI_OK 104 ///////////////////////////////////////////////////////////////////// 105 char PcdSelect(unsigned char *pSnr) 106 { 107 char status; 108 unsigned char i; 109 unsigned int unLen; 110 unsigned char ucComMF522Buf[MAXRLEN]; 111 112 ucComMF522Buf[0] = PICC_ANTICOLL1; 113 ucComMF522Buf[1] = 0x70; 114 ucComMF522Buf[6] = 0; 115 for (i=0; i<4; i++) 116 { 117 ucComMF522Buf[i+2] = *(pSnr+i); 118 ucComMF522Buf[6] ^= *(pSnr+i); 119 } 120 CalulateCRC(ucComMF522Buf,7,&ucComMF522Buf[7]); 121 122 ClearBitMask(Status2Reg,0x08); 123 124 status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,9,ucComMF522Buf,&unLen); 125 126 if ((status == MI_OK) && (unLen == 0x18)) 127 { status = MI_OK; } 128 else 129 { status = MI_ERR; } 130 131 return status; 132 } 133 134 ///////////////////////////////////////////////////////////////////// 135 //功 能:验证卡片密码 136 //参数说明: auth_mode[IN]: 密码验证模式 137 // 0x60 = 验证A密钥 138 // 0x61 = 验证B密钥 139 // addr[IN]:块地址 140 // pKey[IN]:密码 141 // pSnr[IN]:卡片序列号,4字节 142 //返 回: 成功返回MI_OK 143 ///////////////////////////////////////////////////////////////////// 144 char PcdAuthState(unsigned char auth_mode,unsigned char addr,unsigned char *pKey,unsigned char *pSnr) 145 { 146 char status; 147 unsigned int unLen; 148 unsigned char i,ucComMF522Buf[MAXRLEN]; 149 150 ucComMF522Buf[0] = auth_mode; 151 ucComMF522Buf[1] = addr; 152 for (i=0; i<6; i++) 153 { ucComMF522Buf[i+2] = *(pKey+i); } 154 for (i=0; i<6; i++) 155 { ucComMF522Buf[i+8] = *(pSnr+i); } 156 // memcpy(&ucComMF522Buf[2], pKey, 6); 157 // memcpy(&ucComMF522Buf[8], pSnr, 4); 158 159 status = PcdComMF522(PCD_AUTHENT,ucComMF522Buf,12,ucComMF522Buf,&unLen); 160 if ((status != MI_OK) || (!(ReadRawRC(Status2Reg) & 0x08))) 161 { status = MI_ERR; } 162 163 return status; 164 } 165 166 ///////////////////////////////////////////////////////////////////// 167 //功 能:读取M1卡一块数据 168 //参数说明: addr[IN]:块地址 169 // pData[OUT]:读出的数据,16字节 170 //返 回: 成功返回MI_OK 171 ///////////////////////////////////////////////////////////////////// 172 char PcdRead(unsigned char addr,unsigned char *pData) 173 { 174 char status; 175 unsigned int unLen; 176 unsigned char i,ucComMF522Buf[MAXRLEN]; 177 178 ucComMF522Buf[0] = PICC_READ; 179 ucComMF522Buf[1] = addr; 180 CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]); 181 182 status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen); 183 if ((status == MI_OK) && (unLen == 0x90)) 184 // { memcpy(pData, ucComMF522Buf, 16); } 185 { 186 for (i=0; i<16; i++) 187 { *(pData+i) = ucComMF522Buf[i]; } 188 } 189 else 190 { status = MI_ERR; } 191 192 return status; 193 } 194 195 ///////////////////////////////////////////////////////////////////// 196 //功 能:写数据到M1卡一块 197 //参数说明: addr[IN]:块地址 198 // pData[IN]:写入的数据,16字节 199 //返 回: 成功返回MI_OK 200 ///////////////////////////////////////////////////////////////////// 201 char PcdWrite(unsigned char addr,unsigned char *pData) 202 { 203 char status; 204 unsigned int unLen; 205 unsigned char i,ucComMF522Buf[MAXRLEN]; 206 207 ucComMF522Buf[0] = PICC_WRITE; 208 ucComMF522Buf[1] = addr; 209 CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]); 210 211 status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen); 212 213 if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A)) 214 { status = MI_ERR; } 215 216 if (status == MI_OK) 217 { 218 //memcpy(ucComMF522Buf, pData, 16); 219 for (i=0; i<16; i++) 220 { ucComMF522Buf[i] = *(pData+i); } 221 CalulateCRC(ucComMF522Buf,16,&ucComMF522Buf[16]); 222 223 status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,18,ucComMF522Buf,&unLen); 224 if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A)) 225 { status = MI_ERR; } 226 } 227 228 return status; 229 } 230 231 ///////////////////////////////////////////////////////////////////// 232 //功 能:扣款和充值 233 //参数说明: dd_mode[IN]:命令字 234 // 0xC0 = 扣款 235 // 0xC1 = 充值 236 // addr[IN]:钱包地址 237 // pValue[IN]:4字节增(减)值,低位在前 238 //返 回: 成功返回MI_OK 239 ///////////////////////////////////////////////////////////////////// 240 char PcdValue(unsigned char dd_mode,unsigned char addr,unsigned char *pValue) 241 { 242 char status; 243 unsigned int unLen; 244 unsigned char i,ucComMF522Buf[MAXRLEN]; 245 246 ucComMF522Buf[0] = dd_mode; 247 ucComMF522Buf[1] = addr; 248 CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]); 249 250 status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen); 251 252 if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A)) 253 { status = MI_ERR; } 254 255 if (status == MI_OK) 256 { 257 // memcpy(ucComMF522Buf, pValue, 4); 258 for (i=0; i<16; i++) 259 { ucComMF522Buf[i] = *(pValue+i); } 260 CalulateCRC(ucComMF522Buf,4,&ucComMF522Buf[4]); 261 unLen = 0; 262 status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,6,ucComMF522Buf,&unLen); 263 if (status != MI_ERR) 264 { status = MI_OK; } 265 } 266 267 if (status == MI_OK) 268 { 269 ucComMF522Buf[0] = PICC_TRANSFER; 270 ucComMF522Buf[1] = addr; 271 CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]); 272 273 status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen); 274 275 if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A)) 276 { status = MI_ERR; } 277 } 278 return status; 279 } 280 281 ///////////////////////////////////////////////////////////////////// 282 //功 能:备份钱包 283 //参数说明: sourceaddr[IN]:源地址 284 // goaladdr[IN]:目标地址 285 //返 回: 成功返回MI_OK 286 ///////////////////////////////////////////////////////////////////// 287 char PcdBakValue(unsigned char sourceaddr, unsigned char goaladdr) 288 { 289 char status; 290 unsigned int unLen; 291 unsigned char ucComMF522Buf[MAXRLEN]; 292 293 ucComMF522Buf[0] = PICC_RESTORE; 294 ucComMF522Buf[1] = sourceaddr; 295 CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]); 296 297 status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen); 298 299 if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A)) 300 { status = MI_ERR; } 301 302 if (status == MI_OK) 303 { 304 ucComMF522Buf[0] = 0; 305 ucComMF522Buf[1] = 0; 306 ucComMF522Buf[2] = 0; 307 ucComMF522Buf[3] = 0; 308 CalulateCRC(ucComMF522Buf,4,&ucComMF522Buf[4]); 309 310 status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,6,ucComMF522Buf,&unLen); 311 if (status != MI_ERR) 312 { status = MI_OK; } 313 } 314 315 if (status != MI_OK) 316 { return MI_ERR; } 317 318 ucComMF522Buf[0] = PICC_TRANSFER; 319 ucComMF522Buf[1] = goaladdr; 320 321 CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]); 322 323 status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen); 324 325 if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A)) 326 { status = MI_ERR; } 327 328 return status; 329 } 330 331 332 ///////////////////////////////////////////////////////////////////// 333 //功 能:命令卡片进入休眠状态 334 //返 回: 成功返回MI_OK 335 ///////////////////////////////////////////////////////////////////// 336 char PcdHalt(void) 337 { 338 char status; 339 unsigned int unLen; 340 unsigned char ucComMF522Buf[MAXRLEN]; 341 342 ucComMF522Buf[0] = PICC_HALT; 343 ucComMF522Buf[1] = 0; 344 CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]); 345 346 status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen); 347 348 return MI_OK; 349 } 350 351 ///////////////////////////////////////////////////////////////////// 352 //用MF522计算CRC16函数 353 ///////////////////////////////////////////////////////////////////// 354 void CalulateCRC(unsigned char *pIndata,unsigned char len,unsigned char *pOutData) 355 { 356 unsigned char i,n; 357 ClearBitMask(DivIrqReg,0x04); 358 WriteRawRC(CommandReg,PCD_IDLE); 359 SetBitMask(FIFOLevelReg,0x80); 360 for (i=0; i<len; i++) 361 { WriteRawRC(FIFODataReg, *(pIndata+i)); } 362 WriteRawRC(CommandReg, PCD_CALCCRC); 363 i = 0xFF; 364 do 365 { 366 n = ReadRawRC(DivIrqReg); 367 i--; 368 } 369 while ((i!=0) && !(n&0x04)); 370 pOutData[0] = ReadRawRC(CRCResultRegL); 371 pOutData[1] = ReadRawRC(CRCResultRegM); 372 } 373 374 ///////////////////////////////////////////////////////////////////// 375 //功 能:复位RC522 376 //返 回: 成功返回MI_OK 377 ///////////////////////////////////////////////////////////////////// 378 char PcdReset(void) 379 { 380 //unsigned char i; 381 MF522_RST=1; 382 383 delay_us(10); 384 385 MF522_RST=0; 386 387 delay_us(10); 388 389 MF522_RST=1; 390 391 delay_us(10); 392 393 WriteRawRC(CommandReg,PCD_RESETPHASE); 394 395 delay_us(10); 396 397 398 WriteRawRC(ModeReg,0x3D); //和Mifare卡通讯,CRC初始值0x6363 399 WriteRawRC(TReloadRegL,30); 400 WriteRawRC(TReloadRegH,0); 401 WriteRawRC(TModeReg,0x8D); 402 WriteRawRC(TPrescalerReg,0x3E); 403 WriteRawRC(TxAutoReg,0x40); 404 return MI_OK; 405 } 406 407 ///////////////////////////////////////////////////////////////////// 408 //功 能:读RC632寄存器 409 //参数说明:Address[IN]:寄存器地址 410 //返 回:读出的值 411 ///////////////////////////////////////////////////////////////////// 412 unsigned char ReadRawRC(unsigned char Address) 413 { 414 unsigned char i, ucAddr; 415 unsigned char ucResult=0; 416 417 MF522_SCK = 0; 418 MF522_NSS = 0; 419 ucAddr = ((Address<<1)&0x7E)|0x80; 420 421 for(i=8;i>0;i--) 422 { 423 MF522_SI = ((ucAddr&0x80)==0x80); 424 MF522_SCK = 1; 425 ucAddr <<= 1; 426 MF522_SCK = 0; 427 delay_us(10); //STM32需要多加的延时时间。51的不需要加 428 } 429 430 for(i=8;i>0;i--) 431 { 432 MF522_SCK = 1; 433 ucResult <<= 1; 434 ucResult|=MF522_SO; 435 MF522_SCK = 0; 436 delay_us(10); //STM32需要多加的延时时间。51的不需要加 437 } 438 439 MF522_NSS = 1; 440 MF522_SCK = 1; 441 return ucResult; 442 } 443 444 ///////////////////////////////////////////////////////////////////// 445 //功 能:写RC632寄存器 446 //参数说明:Address[IN]:寄存器地址 447 // value[IN]:写入的值 448 ///////////////////////////////////////////////////////////////////// 449 void WriteRawRC(unsigned char Address, unsigned char value) 450 { 451 unsigned char i, ucAddr; 452 453 MF522_SCK = 0; 454 MF522_NSS = 0; 455 ucAddr = ((Address<<1)&0x7E); 456 457 for(i=8;i>0;i--) 458 { 459 MF522_SI = ((ucAddr&0x80)==0x80); 460 MF522_SCK = 1; 461 ucAddr <<= 1; 462 MF522_SCK = 0; 463 delay_us(10); //STM32需要多加的延时时间。51的不需要加 464 } 465 466 for(i=8;i>0;i--) 467 { 468 MF522_SI = ((value&0x80)==0x80); 469 MF522_SCK = 1; 470 value <<= 1; 471 MF522_SCK = 0; 472 delay_us(10); //STM32需要多加的延时时间。51的不需要加 473 } 474 MF522_NSS = 1; 475 MF522_SCK = 1; 476 } 477 478 ///////////////////////////////////////////////////////////////////// 479 //功 能:置RC522寄存器位 480 //参数说明:reg[IN]:寄存器地址 481 // mask[IN]:置位值 482 ///////////////////////////////////////////////////////////////////// 483 void SetBitMask(unsigned char reg,unsigned char mask) 484 { 485 char tmp = 0x0; 486 tmp = ReadRawRC(reg); 487 WriteRawRC(reg,tmp | mask); // set bit mask 488 } 489 490 ///////////////////////////////////////////////////////////////////// 491 //功 能:清RC522寄存器位 492 //参数说明:reg[IN]:寄存器地址 493 // mask[IN]:清位值 494 ///////////////////////////////////////////////////////////////////// 495 void ClearBitMask(unsigned char reg,unsigned char mask) 496 { 497 char tmp = 0x0; 498 tmp = ReadRawRC(reg); 499 WriteRawRC(reg, tmp & ~mask); // clear bit mask 500 } 501 502 ///////////////////////////////////////////////////////////////////// 503 //功 能:通过RC522和ISO14443卡通讯 504 //参数说明:Command[IN]:RC522命令字 505 // pInData[IN]:通过RC522发送到卡片的数据 506 // InLenByte[IN]:发送数据的字节长度 507 // pOutData[OUT]:接收到的卡片返回数据 508 // *pOutLenBit[OUT]:返回数据的位长度 509 ///////////////////////////////////////////////////////////////////// 510 char PcdComMF522(unsigned char Command, 511 unsigned char *pInData, 512 unsigned char InLenByte, 513 unsigned char *pOutData, 514 unsigned int *pOutLenBit) 515 { 516 char status = MI_ERR; 517 unsigned char irqEn = 0x00; 518 unsigned char waitFor = 0x00; 519 unsigned char lastBits; 520 unsigned char n; 521 unsigned int i; 522 switch (Command) 523 { 524 case PCD_AUTHENT: 525 irqEn = 0x12; 526 waitFor = 0x10; 527 break; 528 case PCD_TRANSCEIVE: 529 irqEn = 0x77; 530 waitFor = 0x30; 531 break; 532 default: 533 break; 534 } 535 536 WriteRawRC(ComIEnReg,irqEn|0x80); 537 ClearBitMask(ComIrqReg,0x80); 538 WriteRawRC(CommandReg,PCD_IDLE); 539 SetBitMask(FIFOLevelReg,0x80); 540 541 for (i=0; i<InLenByte; i++) 542 { WriteRawRC(FIFODataReg, pInData[i]); } 543 WriteRawRC(CommandReg, Command); 544 545 546 if (Command == PCD_TRANSCEIVE) 547 { SetBitMask(BitFramingReg,0x80); } 548 549 i = 600;//根据时钟频率调整,操作M1卡最大等待时间25ms 550 do 551 { 552 n = ReadRawRC(ComIrqReg); 553 i--; 554 } 555 while ((i!=0) && !(n&0x01) && !(n&waitFor)); 556 ClearBitMask(BitFramingReg,0x80); 557 558 if (i!=0) 559 { 560 if(!(ReadRawRC(ErrorReg)&0x1B)) 561 { 562 status = MI_OK; 563 if (n & irqEn & 0x01) 564 { status = MI_NOTAGERR; } 565 if (Command == PCD_TRANSCEIVE) 566 { 567 n = ReadRawRC(FIFOLevelReg); 568 lastBits = ReadRawRC(ControlReg) & 0x07; 569 if (lastBits) 570 { *pOutLenBit = (n-1)*8 + lastBits; } 571 else 572 { *pOutLenBit = n*8; } 573 if (n == 0) 574 { n = 1; } 575 if (n > MAXRLEN) 576 { n = MAXRLEN; } 577 for (i=0; i<n; i++) 578 { pOutData[i] = ReadRawRC(FIFODataReg); } 579 } 580 } 581 else 582 { status = MI_ERR; } 583 584 } 585 586 587 SetBitMask(ControlReg,0x80); // stop timer now 588 WriteRawRC(CommandReg,PCD_IDLE); 589 return status; 590 } 591 592 593 ///////////////////////////////////////////////////////////////////// 594 //开启天线 595 //每次启动或关闭天险发射之间应至少有1ms的间隔 596 ///////////////////////////////////////////////////////////////////// 597 void PcdAntennaOn() 598 { 599 unsigned char i; 600 i = ReadRawRC(TxControlReg); 601 if (!(i & 0x03)) 602 { 603 SetBitMask(TxControlReg, 0x03); 604 } 605 } 606 607 608 ///////////////////////////////////////////////////////////////////// 609 //关闭天线 610 ///////////////////////////////////////////////////////////////////// 611 void PcdAntennaOff() 612 { 613 ClearBitMask(TxControlReg, 0x03); 614 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 字符编码:从基础到乱码解决