Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 09:15 16 Jul 2025 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : rc522 RFID code

Author Message
drkl

Senior Member

Joined: 18/10/2015
Location: Hungary
Posts: 102
Posted: 09:13am 23 Feb 2016
Copy link to clipboard 
Print this post

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:
PRINT
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: Hungary
Posts: 102
Posted: 09:23am 23 Feb 2016
Copy link to clipboard 
Print this post

Sorry, the cited link is wrong.

The good one:

ebay-link

drkl
 
Grogster

Admin Group

Joined: 31/12/2012
Location: New Zealand
Posts: 9593
Posted: 09:39am 23 Feb 2016
Copy link to clipboard 
Print this post

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: Hungary
Posts: 102
Posted: 11:24pm 23 Feb 2016
Copy link to clipboard 
Print this post

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 States
Posts: 925
Posted: 10:00am 24 Feb 2016
Copy link to clipboard 
Print this post

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!!!
 
Print this page


To reply to this topic, you need to log in.

The Back Shed's forum code is written, and hosted, in Australia.
© JAQ Software 2025