![]() |
Forum Index : Microcontroller and PC projects : rc522 RFID code
Author | Message | ||||
drkl![]() Senior Member ![]() Joined: 18/10/2015 Location: HungaryPosts: 102 |
Hello, I bought one of these: rc522-ebay As the modul operation is complex and ready MMBasic code is not found, so I looked around and found a solution in AVR-Basic. I wrote over and works great. I wrote a letter (Hkipnik@aol.com) for the author, and asked to publish the modified program, and to this he contributed mail. The program code: '46-RFID-RC522-SHORT.BAS ''******************************************************************************* 'Test Demo RC522 NFC Chip Card RFID Module 'This is the Radio Frequency Identification (RFID) 13.56 Mhz module 'Date 08.09.2014 'Email: Hkipnik@aol.com 'Copyright (c) 2013 Hkipnik. All rights reserved. 'Written by Hkipnik 'BSD license, check license.txt for more information 'All Text Above , And The Splash Screen Below Must Be Included In Any Redistribution. 'Version V1.12 'Read and Write Data - only Mifare Classic 1K (s50) tag ID -- 4Byte ID ISO14443A 'MODIFIED TO MICROMITE BASIC BY DRK 2016.02.23 'MMITE SPI PINS 'MM28MISO-14 MM28MOSI-3 MM28CLK-25 3.3V-28-13 GND-27-19-8 CS-10 RES-5 'MM44MISO-41 MM44MOSI-20 MM44CLK-14 'MM64MISO-45 MM64MOSI-8 MM64CLK-50 >SPI1 'MM64MISO-47 MM64MOSI-5 MM64CLK-4 >SPI2 'RFID-RC522 PINS: 'SDA SCK MOSI MISO IRQ GND RST 3.3V 'MM PINS: 'CS=10 SCK MOSI MISO X GND RFID_RES=5 3.3V '**************************************************************************** 'Read 7Byte Tag ID ISO14443A ' Mifare Desfire EV1 ' Mifare Ultralight X ' Topaz NFC ' Mifare Classic S70 '**************************************************************************** OPTION EXPLICIT CONST Read_write=0 ' 0= only Read TAG ID 1=Read and Write Data to Card DIM Rc522_buffer(18) AS INTEGER 'out Buffer DIM Rc522_inbuffer(18) AS INTEGER 'in Buffer DIM Tag_typ AS INTEGER 'WORD Tag Typ DIM Tag_typa(2) AS INTEGER 'BYTEAt Tag_typ Overlay DIM Sak,I AS INTEGER DIM Tag_id(4) AS INTEGER DIM Tag_crc AS INTEGER 'Byte5 CRC DIM Id_leng AS INTEGER DIM Tag_id7(7) AS INTEGER DIM Textbyte(16) AS INTEGER DIM TEXT AS STRING LENGTH 16 'At Textbyte(1) Overlay CONST Pcd_authent = &H0E CONST Pcd_transceive = &H0C CONST Bitframingreg = &H0D CONST Commienreg = &H02 CONST Commirqreg = &H04 CONST Fifolevelreg = &H0A CONST Controlreg = &H0C CONST Fifodatareg = &H09 CONST Commandreg = &H01 CONST Errorreg = &H06 CONST Picc_auth1a = &H60 'MadKeyA =FF, FF, FF, FF, FF, FF CONST Picc_auth1b = &H61 'MadKeyA =A0, A1, A2, A3, A4, A5 DIM Tag_fount AS INTEGER DIM Status AS INTEGER DIM Lastbits AS INTEGER DIM Backleng AS INTEGER DIM Error1 AS INTEGER DIM Crc_low AS INTEGER DIM Crc_high AS INTEGER '******************************************************************************* '******************************************************************************* '======RFID INIT======================================================= 'CONST RFID_CS =23:SETPIN RFID_CS,DOUT: PIN(RFID_CS)=1 'M44 CONST RFID_CS =10:SETPIN RFID_CS,DOUT: PIN(RFID_CS)=1 'M28 CONST RFID_RES=5: SETPIN RFID_RES,DOUT:PIN(RFID_RES)=1 ' SPI OPEN 5000000,3,8 Initrc522 '******************************************************************************* DO Is_card IF Tag_fount = 1 THEN Read_chipid 'Read Tag ID PRINT "Chip fount" PRINT "Tag Typ= " ; HEX$(tag_typa(2),2);HEX$(tag_typa(1),2) ; " SAK= " ; HEX$(sak)'SAK Level1 IF Id_leng = 4 THEN PRINT "Tag ID4= ";HEX$(tag_id(1));" ";HEX$(tag_id(2));" ";HEX$(tag_id(3));" ";HEX$(tag_id(4)) ELSEIF Id_leng = 7 THEN PRINT "Tag ID7= ";HEX$(tag_id7(1));" ";HEX$(tag_id7(2));" ";HEX$(tag_id7(3));" ";HEX$(tag_id7(4)); PRINT " ";HEX$(tag_id7(5));" ";HEX$(tag_id7(6));" " ;HEX$(tag_id7(7)) ENDIF '******************************************************************************* if Read_write = 1 THEN IF Id_leng = 4 THEN 'only Mifare Classic 1K (s50) Rc522_selecttag() IF Status = 1 THEN Rc522_auth(picc_auth1a , 8) 'Authentication to enable Sector 2 8/4=2 Sector Rc522_read(8) 'read Data Sector 2 0 Rc522_read(9) 'read Data Sector 2 +1 Rc522_read(10) 'read Data Sector 2 +2 'Write Data To Card TEXT = "Hello Bascom " FOR I=1 TO 16: Textbyte(I)=ASC(MID$(TEXT,I,1)): NEXT I Rc522_write(8) 'write Data Sector 2 0 TEXT = "NFC RC522 Demo " FOR I=1 TO 16: Textbyte(I)=ASC(MID$(TEXT,I,1)): NEXT I Rc522_write(9) 'write Data Sector 2 +1 TEXT = "by Hkipnik " FOR I=1 TO 16: Textbyte(I)=ASC(MID$(TEXT,I,1)): NEXT I Rc522_write(10) 'write Data Sector 2 +2 ENDIF ENDIF endif '******************************************************************************* Rc522_stop 'Stop Auth Mode Rc522_halt 'go to state Wait for new Card ELSE PRINT "No Chip fount" ENDIF ' Call Rc522_halt() PAUSE 100 'Wait 1 LOOP END '******************************************************************************* ' '******************************************************************************* ' Reed 4Byte UID or 7Byte UID '******************************************************************************* SUB Read_chipid Anticoll(&H93) 'Level 1 PICC_ANTICOLL_1 IF Tag_id(1) = &H88 THEN 'CT = Cascade Tag fount 7Byte UID Tag_id7(1) = Tag_id(2) 'Cascade Level 1 Tag_id7(2) = Tag_id(3) Tag_id7(3) = Tag_id(4) Rc522_selecttag Anticoll(&H95) 'Cascade Level 2 PICC_ANTICOLL_2 Tag_id7(4) = Tag_id(1) Tag_id7(5) = Tag_id(2) Tag_id7(6) = Tag_id(3) Tag_id7(7) = Tag_id(4) Id_leng = 7 '7Byte UID ELSE Id_leng = 4 '4Byte UID ENDIF END SUB '******************************************************************************* ' Anti- collision detection , reading selected card serial number card ' only MIFARE Classic Chips 4Byte ID '******************************************************************************* SUB Anticoll(Selecttag AS INTEGER) Write522(bitframingreg , &H00) 'BitFramingReg 0x0D Rc522_buffer(1) = Selecttag 'PICC_ANTICOLL h93 95 Rc522_buffer(2) = &H20 Rc522to_card(pcd_transceive , 2) IF Backleng = 40 THEN 'fount 5 Bytes Byte 5 is CRC Tag_id(1) = Rc522_inbuffer(1) Tag_id(2) = Rc522_inbuffer(2) Tag_id(3) = Rc522_inbuffer(3) Tag_id(4) = Rc522_inbuffer(4) Tag_crc = Rc522_inbuffer(5) 'use in Rc522_selecttag ENDIF END SUB '******************************************************************************* ' Writes a byte to the specified register in the MFRC522 chip '******************************************************************************* SUB Write522(Addrb AS INTEGER,Daten AS INTEGER) local Addr Addr=Addrb Addr=Addr<<1 'Shift Addr , LEFT , 1 Addr = Addr AND &H7E PIN(RFID_CS)=0 'Reset Cs_pin SPI WRITE 2,Addr,Daten PIN(RFID_CS)=1 'Set Cs_pn END SUB '******************************************************************************* ' Reads a byte from the specified register in the MFRC522 chip '******************************************************************************* FUNCTION Read522(Addreb AS INTEGER) Local Addre Addre=Addreb Addre=Addre<<1 'Shift Addre , LEFT , 1 Addre = Addre AND &H7E Addre = Addre OR &H80 PIN(RFID_CS)=0 ' Reset Cs_pin sPI WRITE 1,Addre 'Spiout Addre , 1 Read522=SPI(0) 'Spiin Read522 , 1 PIN(RFID_CS)=1 'Set Cs_pn END FUNCTION '******************************************************************************* ' Sets the bits given in mask in register reg '******************************************************************************* SUB Setbitmask(Reg AS INTEGER,Mask AS INTEGER) LOCAL Rxin AS INTEGER Rxin = Read522(reg) Rxin = Rxin OR Mask Write522(reg , Rxin) END SUB '******************************************************************************* ' Clears the bits given in mask from register reg '******************************************************************************* SUB Clearbitmask(Reg AS INTEGER, Mask AS INTEGER) LOCAL Inbyte AS INTEGER Inbyte = Read522(reg) Mask = Mask XOR &HFF Inbyte = Inbyte AND Mask Write522(reg , Inbyte) END SUB '******************************************************************************* ' Soft Reset RC522 '******************************************************************************* SUB Rc522_reset Write522(commandreg , &H0F) 'PCD_RESETPHASE 0x0F END SUB '******************************************************************************* ' Init RC522 '******************************************************************************* SUB Initrc522 PIN(RFID_RES)=0 'Reset Rst522 Pause 100 PIN(RFID_RES)=1 'Set Rst522 pause 1 Rc522_reset Pause 500 Write522(&H2a , &H8D) 'TModeReg 8d Write522(&H2b , &H3E) 'TPrescalerReg a9 3e Write522(&H2d , &H03) 'TReloadRegL 25ms before timeout. Write522(&H2c , &HE8) 'TReloadRegH Write522(&H15 , &H40) 'TxAutoReg Write522(&H11 , &H3D) 'ModeReg 'antene On Setbitmask(&H14,&H03) 'TxControlReg END SUB '******************************************************************************* ' RC522 and ISO14443 card communication '******************************************************************************* SUB Rc522to_card(Command AS INTEGER , Sendlen AS INTEGER) LOCAL Irqen,Waitirq,Timeout AS INTEGER LOCAL Temps,N,Dum AS INTEGER SELECT CASE Command CASE Pcd_authent Irqen = &H12 Waitirq = &H14 CASE Pcd_transceive Irqen = &H77 Waitirq = &H64 END SELECT Dum = Irqen OR &H80 Write522(commienreg ,Dum) 'CommIEnReg CommIEnReg 0x02 Clearbitmask(commirqreg , &H80) 'CommIrqReg 0x04 Setbitmask(fifolevelreg , &H80) ' Fifolevelreg 0x0a Write522(commandreg , &H00) 'CommandReg 01, PCD_IDLE 00 FOR Dum = 1 TO Sendlen Write522(fifodatareg ,Rc522_buffer(Dum)) 'FIFODataReg 0x09 NEXT Dum Write522(commandreg,Command) IF Command = Pcd_transceive THEN Setbitmask(bitframingreg,&H80) 'BitFramingReg 0x0D ENDIF Timeout = 250 DO Dum = Read522(commirqreg) Timeout=Timeout-1 IF Dum = Waitirq THEN EXIT DO 'Waitirq LOOP UNTIL Timeout = 0 Clearbitmask(bitframingreg,&H80) 'BitFramingReg 0x0D IF Timeout > 0 THEN Temps=Read522(errorreg) 'ErrorReg Temps=Temps AND &H1B IF Temps = 0 THEN 'todo Error1 = 0 ELSE Error1 = 1 PRINT "Error" ENDIF IF Command = Pcd_transceive THEN 'Read Back Data Dum = Read522(fifolevelreg) 'FIFOLevelReg = 0x0A N = Dum Lastbits = Read522(controlreg) '.ControlReg)0C & 0x07 Lastbits = Lastbits AND &H07 IF Lastbits > 0 THEN Dum=Dum-1 Dum = Dum * 8 Backleng = Dum + Lastbits ELSE Backleng = Dum * 8 ENDIF IF N = 0 THEN N = 1 FOR Dum = 1 TO N Rc522_inbuffer(dum) = Read522(fifodatareg) 'FIFODataReg=0x09 NEXT Dum ENDIF ENDIF END SUB '******************************************************************************* ' Find cards , read the card type number ' H4400 = Mifare_UltraLight ' H0400 = Mifare_one(s50) ' H0200 = Mifare_one(s70) ' H0800 = Mifare_pro(x) ' H4403 = Mifare_desfire ' H000C = Topaz NFC '******************************************************************************* SUB Is_card Write522(bitframingreg,&H07) 'BitFramingReg = 0x0D Rc522_buffer(1) = &H26 Rc522to_card(pcd_transceive,1) IF Backleng = 16 THEN Tag_fount = 1 'Chip fount Tag_typa(2) = Rc522_inbuffer(1) 'Little Endian Tag_typa(1) = Rc522_inbuffer(2) ELSE Tag_fount = 0 ENDIF END SUB '******************************************************************************* 'Use the CRC coprocessor in the MFRC522 to calculate a CRC '******************************************************************************* SUB Calculate_crc(Leng AS integer) LOCAL Zbv1,Timeou AS integer Clearbitmask(&H05 , &H04) ' DivIrqReg 0x05 Setbitmask(fifolevelreg , &H80) 'FIFOLevelReg 0x0A FOR Zbv1 = 1 TO Leng Write522(fifodatareg,Rc522_buffer(zbv1)) 'FIFODataReg 0x09 NEXT Zbv1 Write522(commandreg , &H03) 'CommandReg 0x01 Timeou = 2000 DO Zbv1=Read522(&H05) 'DivIrqReg 0x05 Timeou=Timeou-1 LOOP UNTIL Timeou = 0 OR Zbv1 = &H04 '04 Crc_low = Read522(&H22) 'Crcresultregl 0x22 Crc_high = Read522(&H21) 'Crcresultregm 0x21 END SUB '******************************************************************************* 'Instructs a Chip in state ACTIVE(*) to go to state HALT. '******************************************************************************* SUB Rc522_halt Rc522_buffer(1) = &H50 'PICC_HALT 0x50 Rc522_buffer(2) = &H00 Calculate_crc(2) Rc522_buffer(3) = Crc_low Rc522_buffer(4) = Crc_high Rc522to_card(pcd_transceive , 4) END SUB '******************************************************************************* 'Select card,and read Card storage volume '******************************************************************************* SUB Rc522_selecttag Rc522_buffer(1) = &H93 'PICC_SElECTTAG 0x93 Rc522_buffer(2) = &H70 Rc522_buffer(3) = Tag_id(1) Rc522_buffer(4) = Tag_id(2) Rc522_buffer(5) = Tag_id(3) Rc522_buffer(6) = Tag_id(4) Rc522_buffer(7) = Tag_crc Calculate_crc(7) Rc522_buffer(8) = Crc_low Rc522_buffer(9) = Crc_high Rc522to_card(pcd_transceive,9) IF Backleng = &H18 THEN '24Bit Status = 1 Sak = Rc522_inbuffer(1) ' Print "Storage Volume KByte " ; Rc522_inbuffer(1) 'read card storage volume /8 ELSE Status = 0 END IF END SUB '******************************************************************************* ' authMode--password verify mode ' Block Sector 0 - 4 - 8 - 12 - 16 - 20 - 24 - 28 - 32 - 36 - 40 - 44 - 48 - 52 - 56 - 60 ' per Sector read and write 4Byte ' Byte4 Config Data only write sector trailer when you know what you're doing '******************************************************************************* SUB Rc522_auth(Authmode AS INTEGER,Blockaddr AS INTEGER) Rc522_buffer(1) = Authmode Rc522_buffer(2) = Blockaddr Rc522_buffer(3) = &HFF 'Defalt buffer A Password Rc522_buffer(4) = &HFF Rc522_buffer(5) = &HFF Rc522_buffer(6) = &HFF Rc522_buffer(7) = &HFF Rc522_buffer(8) = &HFF Rc522_buffer(9) = Tag_id(1) Rc522_buffer(10) = Tag_id(2) Rc522_buffer(11) = Tag_id(3) Rc522_buffer(12) = Tag_id(4) Rc522to_card(pcd_authent , 12) END SUB '******************************************************************************* ' Read data ' Block = Blockaddr or Blockaddr +1 or Blockaddr +2 ' Blockaddr + 3 is Config Data from the Card '******************************************************************************* SUB Rc522_read(Block AS INTEGER) LOCAL Temp2 AS INTEGER Rc522_buffer(1) = &H30 'PICC_READ = 0x30 Rc522_buffer(2) = Block Calculate_crc(2) Rc522_buffer(3) = Crc_low Rc522_buffer(4) = Crc_high Rc522to_card(pcd_transceive , 4) IF Backleng = 144 THEN '144Bit 18Byte PRINT "Read 16Byte-- " ; 'Dump 16Byte Buffer FOR Temp2 = 1 TO 16 PRINT CHR$(rc522_inbuffer(temp2)) ; NEXT END IF END SUB '******************************************************************************* ' Write data ' Block = Blockaddr or Blockaddr +1 or Blockaddr +2 ' Blockaddr + 3 is Config Data from the - Card Warning: ' only write sector trailer when you know what you're doing '******************************************************************************* SUB Rc522_write(Block AS INTEGER) LOCAL Zbv AS INTEGER PRINT "Write Data" Rc522_buffer(1) = &HA0 'PICC_WRITE=0xA0 PICC_CMD_UL_WRITE = 0xA2 Rc522_buffer(2) = Block Calculate_crc(2) Rc522_buffer(3) = Crc_low Rc522_buffer(4) = Crc_high Rc522to_card(pcd_transceive , 4) FOR Zbv = 1 TO 16 Rc522_buffer(zbv) = Textbyte(zbv) 'Copy Text Data to RC522 Buffer NEXT Calculate_crc(16) Rc522_buffer(17) = Crc_low Rc522_buffer(18) = Crc_high Rc522to_card(pcd_transceive , 18) ' 18 END SUB '******************************************************************************* 'Stop Auth Mode '******************************************************************************* SUB Rc522_stop Clearbitmask(&H08 , &H08) 'Status2Reg 0x08 END SUB '======[RC522 REGISTERS READ-WRITE TEST-WRITTEN BY DRKL]======================== 'ONLY FOR DEBUGGING SUB REGRW LOCAL ADR$,ERT$,M$ UJRA: INPUT "FORMAT: R OR W + TWO HEX DIGIT ADDRESS: ",ADR$ ADR$=UCASE$(ADR$): M$=LEFT$(ADR$,1) IF (M$<>"R" AND M$<>"W") THEN PRINT "ERROR!!!" GOTO UJRA ENDIF ADR$="&H"+RIGHT$(ADR$,2) OLV: IF M$="R" THEN PRINT "READ >> ADDR: ",ADR$," HEX VALUE: ","&H"+HEX$(READ522(VAL(ADR$)),2)," &B"+BIN$(READ522(VAL(ADR$)),8) GOTO UJRA ENDIF IF M$="W" THEN INPUT "HEX VALUE: ",ERT$: ERT$="&H"+ERT$:WRITE522 VAL(ADR$),VAL(ERT$) PRINT "WRITE>> ADDR: ",ADR$," HEX VALUE: ",ERT$," &B"+BIN$((VAL(ERT$)),8) M$="R":GOTO OLV ENDIF goto UJRA END SUB END I hope this program is useful to someone drkl |
||||
drkl![]() Senior Member ![]() Joined: 18/10/2015 Location: HungaryPosts: 102 |
Sorry, the cited link is wrong. The good one: ebay-link drkl |
||||
Grogster![]() Admin Group ![]() Joined: 31/12/2012 Location: New ZealandPosts: 9593 |
Now you can see why I elected to go with the RDM6300 reader instead. ![]() I do have a couple of these RC522 modules, but as you now know, the code to make them work is a rather major thing, whereas the other module, you can read the tag or card ID from the MM serial port buffer with one single line of MMBASIC code. However, the modules I am using can't write to tags or cards, but in my case, all I wanted was read ability anyway. Nice work, but looks like it was a lot of work. ![]() Smoke makes things work. When the smoke gets out, it stops! |
||||
drkl![]() Senior Member ![]() Joined: 18/10/2015 Location: HungaryPosts: 102 |
Hello Grogster, In part you are right, but twice the price, and the size (due to the antenna loop) is larger. The eternal problem: what should be the HW/SW ratio? If you use only for read-only ID, code size can be reduced. Because there are some rc522 piece, if necessary, it will be used. ![]() drkl |
||||
viscomjim Guru ![]() Joined: 08/01/2014 Location: United StatesPosts: 925 |
NICE ONE drkl!!! Now I HAVE to get some of these. My room is getting smaller and smaller, but oh well... Thanks for your effort. Another nice piece of code for the library!!! |
||||
![]() |
![]() |
The Back Shed's forum code is written, and hosted, in Australia. | © JAQ Software 2025 |