RC522.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. // Mifare RC522 RFID Card reader 13.56 MHz
  2. // MFRC522 STM32F103 DESCRIPTION
  3. // CS (SDA) PB0 SPI1_NSS Chip select for SPI
  4. // SCK PA5 SPI1_SCK Serial Clock for SPI
  5. // MOSI PA7 SPI1_MOSI Master In Slave Out for SPI
  6. // MISO PA6 SPI1_MISO Master Out Slave In for SPI
  7. // IRQ - Irq
  8. // GND GND Ground
  9. // RST 3.3V Reset pin (3.3V)
  10. // VCC 3.3V 3.3V power
  11. #include "RC522.h"
  12. /******template******/
  13. // 0-255数字转换为字符 0xFF--"FF"
  14. void char_to_hex(uint8_t data, uint8_t *retStr) {
  15. uint8_t digits[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
  16. if (data < 16) {
  17. retStr[0] = '0';
  18. retStr[1] = digits[data];
  19. } else {
  20. retStr[0] = digits[(data & 0xF0)>>4];
  21. retStr[1] = digits[(data & 0x0F)];
  22. }
  23. }
  24. /**
  25. * @brief 扫描RFID卡
  26. * @param cardID 四字节数组
  27. * @retval 0扫描到RFID卡
  28. */
  29. uint8_t RC522_cardScan(uint8_t *cardID)
  30. {
  31. if(!MFRC522_Request(PICC_REQIDL, cardID)) {
  32. if(!MFRC522_Anticoll(cardID)) {
  33. #ifdef DEBUG_printf
  34. uint8_t cardIDString[8] = {0};
  35. for(uint8_t i = 0; i < 4; i++) {
  36. char_to_hex(cardID[i], cardIDString+i*2);
  37. }
  38. printf("card id:%s\n", cardIDString);
  39. #endif
  40. return 0;
  41. }
  42. }
  43. return 1;
  44. }
  45. /********************/
  46. void SPI1_WriteReg(uint8_t address, uint8_t value) {
  47. cs_reset();
  48. SPISendByte(address);
  49. SPISendByte(value);
  50. cs_set();
  51. }
  52. uint8_t SPI1_ReadReg(uint8_t address) {
  53. uint8_t val;
  54. cs_reset();
  55. SPISendByte(address);
  56. val = SPISendByte(0x00);
  57. cs_set();
  58. return val;
  59. }
  60. void MFRC522_WriteRegister(uint8_t addr, uint8_t val) {
  61. addr = (addr << 1) & 0x7E; // Address format: 0XXXXXX0
  62. SPI1_WriteReg(addr, val);
  63. }
  64. uint8_t MFRC522_ReadRegister(uint8_t addr) {
  65. uint8_t val;
  66. addr = ((addr << 1) & 0x7E) | 0x80;
  67. val = SPI1_ReadReg(addr);
  68. return val;
  69. }
  70. uint8_t MFRC522_Check(uint8_t* id) {
  71. uint8_t status;
  72. status = MFRC522_Request(PICC_REQIDL, id); // Find cards, return card type
  73. if (status == MI_OK) status = MFRC522_Anticoll(id); // Card detected. Anti-collision, return card serial number 4 bytes
  74. MFRC522_Halt(); // Command card into hibernation
  75. return status;
  76. }
  77. uint8_t MFRC522_Compare(uint8_t* CardID, uint8_t* CompareID) {
  78. uint8_t i;
  79. for (i = 0; i < 5; i++) {
  80. if (CardID[i] != CompareID[i]) return MI_ERR;
  81. }
  82. return MI_OK;
  83. }
  84. void MFRC522_SetBitMask(uint8_t reg, uint8_t mask) {
  85. MFRC522_WriteRegister(reg, MFRC522_ReadRegister(reg) | mask);
  86. }
  87. void MFRC522_ClearBitMask(uint8_t reg, uint8_t mask){
  88. MFRC522_WriteRegister(reg, MFRC522_ReadRegister(reg) & (~mask));
  89. }
  90. uint8_t MFRC522_Request(uint8_t reqMode, uint8_t* TagType) {
  91. uint8_t status;
  92. uint16_t backBits; // The received data bits
  93. MFRC522_WriteRegister(MFRC522_REG_BIT_FRAMING, 0x07); // TxLastBists = BitFramingReg[2..0]
  94. TagType[0] = reqMode;
  95. status = MFRC522_ToCard(PCD_TRANSCEIVE, TagType, 1, TagType, &backBits);
  96. if ((status != MI_OK) || (backBits != 0x10)) status = MI_ERR;
  97. return status;
  98. }
  99. uint8_t MFRC522_ToCard(uint8_t command, uint8_t* sendData, uint8_t sendLen, uint8_t* backData, uint16_t* backLen) {
  100. uint8_t status = MI_ERR;
  101. uint8_t irqEn = 0x00;
  102. uint8_t waitIRq = 0x00;
  103. uint8_t lastBits;
  104. uint8_t n;
  105. uint16_t i;
  106. switch (command) {
  107. case PCD_AUTHENT: {
  108. irqEn = 0x12;
  109. waitIRq = 0x10;
  110. break;
  111. }
  112. case PCD_TRANSCEIVE: {
  113. irqEn = 0x77;
  114. waitIRq = 0x30;
  115. break;
  116. }
  117. default:
  118. break;
  119. }
  120. MFRC522_WriteRegister(MFRC522_REG_COMM_IE_N, irqEn | 0x80);
  121. MFRC522_ClearBitMask(MFRC522_REG_COMM_IRQ, 0x80);
  122. MFRC522_SetBitMask(MFRC522_REG_FIFO_LEVEL, 0x80);
  123. MFRC522_WriteRegister(MFRC522_REG_COMMAND, PCD_IDLE);
  124. // Writing data to the FIFO
  125. for (i = 0; i < sendLen; i++) MFRC522_WriteRegister(MFRC522_REG_FIFO_DATA, sendData[i]);
  126. // Execute the command
  127. MFRC522_WriteRegister(MFRC522_REG_COMMAND, command);
  128. if (command == PCD_TRANSCEIVE) MFRC522_SetBitMask(MFRC522_REG_BIT_FRAMING, 0x80); // StartSend=1,transmission of data starts
  129. // Waiting to receive data to complete
  130. i = 2000; // i according to the clock frequency adjustment, the operator M1 card maximum waiting time 25ms
  131. do {
  132. // CommIrqReg[7..0]
  133. // Set1 TxIRq RxIRq IdleIRq HiAlerIRq LoAlertIRq ErrIRq TimerIRq
  134. n = MFRC522_ReadRegister(MFRC522_REG_COMM_IRQ);
  135. i--;
  136. } while ((i!=0) && !(n&0x01) && !(n&waitIRq));
  137. MFRC522_ClearBitMask(MFRC522_REG_BIT_FRAMING, 0x80); // StartSend=0
  138. if (i != 0) {
  139. if (!(MFRC522_ReadRegister(MFRC522_REG_ERROR) & 0x1B)) {
  140. status = MI_OK;
  141. if (n & irqEn & 0x01) status = MI_NOTAGERR;
  142. if (command == PCD_TRANSCEIVE) {
  143. n = MFRC522_ReadRegister(MFRC522_REG_FIFO_LEVEL);
  144. lastBits = MFRC522_ReadRegister(MFRC522_REG_CONTROL) & 0x07;
  145. if (lastBits) *backLen = (n-1)*8+lastBits; else *backLen = n*8;
  146. if (n == 0) n = 1;
  147. if (n > MFRC522_MAX_LEN) n = MFRC522_MAX_LEN;
  148. for (i = 0; i < n; i++) backData[i] = MFRC522_ReadRegister(MFRC522_REG_FIFO_DATA); // Reading the received data in FIFO
  149. }
  150. } else status = MI_ERR;
  151. }
  152. return status;
  153. }
  154. uint8_t MFRC522_Anticoll(uint8_t* serNum) {
  155. uint8_t status;
  156. uint8_t i;
  157. uint8_t serNumCheck = 0;
  158. uint16_t unLen;
  159. MFRC522_WriteRegister(MFRC522_REG_BIT_FRAMING, 0x00); // TxLastBists = BitFramingReg[2..0]
  160. serNum[0] = PICC_ANTICOLL;
  161. serNum[1] = 0x20;
  162. status = MFRC522_ToCard(PCD_TRANSCEIVE, serNum, 2, serNum, &unLen);
  163. if (status == MI_OK) {
  164. // Check card serial number
  165. for (i = 0; i < 4; i++) serNumCheck ^= serNum[i];
  166. if (serNumCheck != serNum[i]) status = MI_ERR;
  167. }
  168. return status;
  169. }
  170. void MFRC522_CalculateCRC(uint8_t* pIndata, uint8_t len, uint8_t* pOutData) {
  171. uint8_t i, n;
  172. MFRC522_ClearBitMask(MFRC522_REG_DIV_IRQ, 0x04); // CRCIrq = 0
  173. MFRC522_SetBitMask(MFRC522_REG_FIFO_LEVEL, 0x80); // Clear the FIFO pointer
  174. // Write_MFRC522(CommandReg, PCD_IDLE);
  175. // Writing data to the FIFO
  176. for (i = 0; i < len; i++) MFRC522_WriteRegister(MFRC522_REG_FIFO_DATA, *(pIndata+i));
  177. MFRC522_WriteRegister(MFRC522_REG_COMMAND, PCD_CALCCRC);
  178. // Wait CRC calculation is complete
  179. i = 0xFF;
  180. do {
  181. n = MFRC522_ReadRegister(MFRC522_REG_DIV_IRQ);
  182. i--;
  183. } while ((i!=0) && !(n&0x04)); // CRCIrq = 1
  184. // Read CRC calculation result
  185. pOutData[0] = MFRC522_ReadRegister(MFRC522_REG_CRC_RESULT_L);
  186. pOutData[1] = MFRC522_ReadRegister(MFRC522_REG_CRC_RESULT_M);
  187. }
  188. uint8_t MFRC522_SelectTag(uint8_t* serNum) {
  189. uint8_t i;
  190. uint8_t status;
  191. uint8_t size;
  192. uint16_t recvBits;
  193. uint8_t buffer[9];
  194. buffer[0] = PICC_SElECTTAG;
  195. buffer[1] = 0x70;
  196. for (i = 0; i < 5; i++) buffer[i+2] = *(serNum+i);
  197. MFRC522_CalculateCRC(buffer, 7, &buffer[7]); //??
  198. status = MFRC522_ToCard(PCD_TRANSCEIVE, buffer, 9, buffer, &recvBits);
  199. if ((status == MI_OK) && (recvBits == 0x18)) size = buffer[0]; else size = 0;
  200. return size;
  201. }
  202. uint8_t MFRC522_Auth(uint8_t authMode, uint8_t BlockAddr, uint8_t* Sectorkey, uint8_t* serNum) {
  203. uint8_t status;
  204. uint16_t recvBits;
  205. uint8_t i;
  206. uint8_t buff[12];
  207. // Verify the command block address + sector + password + card serial number
  208. buff[0] = authMode;
  209. buff[1] = BlockAddr;
  210. for (i = 0; i < 6; i++) buff[i+2] = *(Sectorkey+i);
  211. for (i=0; i<4; i++) buff[i+8] = *(serNum+i);
  212. status = MFRC522_ToCard(PCD_AUTHENT, buff, 12, buff, &recvBits);
  213. if ((status != MI_OK) || (!(MFRC522_ReadRegister(MFRC522_REG_STATUS2) & 0x08))) status = MI_ERR;
  214. return status;
  215. }
  216. uint8_t MFRC522_Read(uint8_t blockAddr, uint8_t* recvData) {
  217. uint8_t status;
  218. uint16_t unLen;
  219. recvData[0] = PICC_READ;
  220. recvData[1] = blockAddr;
  221. MFRC522_CalculateCRC(recvData,2, &recvData[2]);
  222. status = MFRC522_ToCard(PCD_TRANSCEIVE, recvData, 4, recvData, &unLen);
  223. if ((status != MI_OK) || (unLen != 0x90)) status = MI_ERR;
  224. return status;
  225. }
  226. uint8_t MFRC522_Write(uint8_t blockAddr, uint8_t* writeData) {
  227. uint8_t status;
  228. uint16_t recvBits;
  229. uint8_t i;
  230. uint8_t buff[18];
  231. buff[0] = PICC_WRITE;
  232. buff[1] = blockAddr;
  233. MFRC522_CalculateCRC(buff, 2, &buff[2]);
  234. status = MFRC522_ToCard(PCD_TRANSCEIVE, buff, 4, buff, &recvBits);
  235. if ((status != MI_OK) || (recvBits != 4) || ((buff[0] & 0x0F) != 0x0A)) status = MI_ERR;
  236. if (status == MI_OK) {
  237. // Data to the FIFO write 16Byte
  238. for (i = 0; i < 16; i++) buff[i] = *(writeData+i);
  239. MFRC522_CalculateCRC(buff, 16, &buff[16]);
  240. status = MFRC522_ToCard(PCD_TRANSCEIVE, buff, 18, buff, &recvBits);
  241. if ((status != MI_OK) || (recvBits != 4) || ((buff[0] & 0x0F) != 0x0A)) status = MI_ERR;
  242. }
  243. return status;
  244. }
  245. void MFRC522_Init(void) {
  246. MFRC522_Reset();
  247. MFRC522_WriteRegister(MFRC522_REG_T_MODE, 0x8D);
  248. MFRC522_WriteRegister(MFRC522_REG_T_PRESCALER, 0x3E);
  249. MFRC522_WriteRegister(MFRC522_REG_T_RELOAD_L, 30);
  250. MFRC522_WriteRegister(MFRC522_REG_T_RELOAD_H, 0);
  251. MFRC522_WriteRegister(MFRC522_REG_RF_CFG, 0x70); // 48dB gain
  252. MFRC522_WriteRegister(MFRC522_REG_TX_AUTO, 0x40);
  253. MFRC522_WriteRegister(MFRC522_REG_MODE, 0x3D);
  254. MFRC522_AntennaOn(); // Open the antenna
  255. }
  256. void MFRC522_Reset(void) {
  257. MFRC522_WriteRegister(MFRC522_REG_COMMAND, PCD_RESETPHASE);
  258. }
  259. void MFRC522_AntennaOn(void) {
  260. uint8_t temp;
  261. temp = MFRC522_ReadRegister(MFRC522_REG_TX_CONTROL);
  262. if (!(temp & 0x03)) MFRC522_SetBitMask(MFRC522_REG_TX_CONTROL, 0x03);
  263. }
  264. void MFRC522_AntennaOff(void) {
  265. MFRC522_ClearBitMask(MFRC522_REG_TX_CONTROL, 0x03);
  266. }
  267. void MFRC522_Halt(void) {
  268. uint16_t unLen;
  269. uint8_t buff[4];
  270. buff[0] = PICC_HALT;
  271. buff[1] = 0;
  272. MFRC522_CalculateCRC(buff, 2, &buff[2]);
  273. MFRC522_ToCard(PCD_TRANSCEIVE, buff, 4, buff, &unLen);
  274. }