|
|
View previous topic :: View next topic |
Author |
Message |
Mario_KA
Joined: 16 Nov 2017 Posts: 22
|
Using MFRC522 RFID Reader with PIC16F877 |
Posted: Thu Nov 30, 2017 6:51 am |
|
|
I managed to implement the MFRC522. The headerfile is based on https://github.com/ljos/MFRC522
main.c
Code: | #include <main.h>
#include <lcd16216.c>
#define CS PIN_A5
#use rs232( baud=9600, parity=N, xmit=PIN_C6, rcv=PIN_C7, bits=8, ERRORS)
//spi modes
#define SPI_MODE_0 (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_1 (SPI_L_TO_H)
#define SPI_MODE_2 (SPI_H_TO_L)
#define SPI_MODE_3 (SPI_H_TO_L | SPI_XMIT_L_TO_H)
byte FoundTag; // Variable used to check if Tag was found
byte ReadTag; // Variable used to store anti-collision value to read Tag information
byte TagData[16]; // Variable used to store Full Tag Data
byte GoodTagSerialNumber[4] = {0x9E, 0x80, 0xB1, 0x59}; // The Tag Serial number we are looking for
int i=0;
char buffer[20],buffer2[20],text[20];
byte version;
int GoodTag=0; // Variable used to confirm good Tag Detected
#include <mario_rfid.h>
void checktag()
{
if (GoodTag == 1)
{
printf("Access granted\r\n");
GoodTag=0;
delay_ms(500);
}
else
{
printf("Access Denied\r\n");
GoodTag=0;
delay_ms(500);
}
}
void readRFID()
{
// Get anti-collision value to properly read information from the Tag
ReadTag = antiCollision(TagData);
printf("Tag detected.\r\n");
printf("Serial Number: \r\n");
text = "Tag Serial";
for(i=0;i<=2;i++)
{
sprintf(buffer2,"%2X",(TagData[i])); //display version in hexadecimal
delay_ms(20);
printf(buffer2);
printf(", ");
}
sprintf(buffer2,"%2X",(TagData[i])); //display version in hexadecimal
delay_ms(20);
printf(buffer2);
printf("\r\nCheck Validity \r\n");
for(int i=0; i <= 3; i++)
{
if (GoodTagSerialNumber[i] != TagData[i])
{
GoodTag=0;
break; // if not equal, then break out of the "for" loop
}
}
if (TagData[3]==GoodTagSerialNumber[3])
{
// if we made it to 4 loops then the Tag Serial numbers are matching
GoodTag=1;
}
}
void print(){
version = readFromRegister(VersionReg);
if(!version)
{
text = "NO DEVICE";
lcd_gotoxy(1, 1);//go to position 1,1 on lcd
lcd_print(text);
}
if(version)
{
text = "DEVICE found";
lcd_gotoxy(1, 1);//go to position 1,1 on lcd
lcd_print(text);//print on lcd
sprintf(buffer,"%2X",(version)); //display version in hexadecimal
lcd_gotoxy(1, 2); //go to second line of lcd
lcd_print(buffer);
}
}
void main()
{
setup_oscillator(OSC_8MHZ, 3); //Adjust Oscillator for proper Serial Communication
setup_spi(SPI_MASTER|SPI_MODE_0|SPI_CLK_DIV_16);
lcd_init();
lcd_clear();
delay_ms(50);
begin(); //initialize MFRC522
print(); //print Firmwareverion on LCD
while(TRUE)
{
// Check to see if a Tag was detected
// If yes, then the variable FoundTag will contain "MI_OK"
FoundTag = requestTag(MF1_REQIDL, TagData);
printf("Checking for Tag \r\n");
delay_ms(2000);
if (FoundTag == MI_OK)
{
readRFID();
checktag();
delay_ms(500);
}
else printf("No Tag found");
}
}
|
RFID.h
Code: | #define MAX_LEN 16 // Maximum length of an array. CHECK IF IT IS MAXIMUM LENGTH/SIZE OF FIFO!!!!!!!!!!!
//MF522 MFRC522 error codes.
#define MI_OK 0 // Everything A-OK.
#define MI_NOTAGERR 1 // No tag error
#define MI_ERR 2 // General error
//MF522 Command word
#define MFRC522_IDLE 0x00 // NO action; Cancel the current command
#define MFRC522_MEM 0x01 // Store 25 byte into the internal buffer.
#define MFRC522_GENID 0x02 // Generates a 10 byte random ID number.
#define MFRC522_CALCCRC 0x03 // CRC Calculate or selftest.
#define MFRC522_TRANSMIT 0x04 // Transmit data
#define MFRC522_NOCMDCH 0x07 // No command change.
#define MFRC522_RECEIVE 0x08 // Receive Data
#define MFRC522_TRANSCEIVE 0x0C // Transmit and receive data,
#define MFRC522_AUTHENT 0x0E // Authentication Key
#define MFRC522_SOFTRESET 0x0F // Reset
//Mifare_One tag command word
#define MF1_REQIDL 0x26 // find the antenna area does not enter hibernation
#define MF1_REQALL 0x52 // find all the tags antenna area
#define MF1_ANTICOLL 0x93 // anti-collision
#define MF1_SELECTTAG 0x93 // election tag
#define MF1_AUTHENT1A 0x60 // authentication key A
#define MF1_AUTHENT1B 0x61 // authentication key B
#define MF1_READ 0x30 // Read Block
#define MF1_WRITE 0xA0 // write block
#define MF1_DECREMENT 0xC0 // debit
#define MF1_INCREMENT 0xC1 // recharge
#define MF1_RESTORE 0xC2 // transfer block data to the buffer
#define MF1_TRANSFER 0xB0 // save the data in the buffer
#define MF1_HALT 0x50 // Sleep
//------------------ MFRC522 registers---------------
//Page 0:Command and Status
#define Reserved00 0x00
#define CommandReg 0x01
#define CommIEnReg 0x02
#define DivIEnReg 0x03
#define CommIrqReg 0x04
#define DivIrqReg 0x05
#define ErrorReg 0x06
#define Status1Reg 0x07
#define Status2Reg 0x08
#define FIFODataReg 0x09
#define FIFOLevelReg 0x0A
#define WaterLevelReg 0x0B
#define ControlReg 0x0C
#define BitFramingReg 0x0D
#define CollReg 0x0E
#define Reserved01 0x0F
//Page 1:Command
#define Reserved10 0x10
#define ModeReg 0x11
#define TxModeReg 0x12
#define RxModeReg 0x13
#define TxControlReg 0x14
#define TxAutoReg 0x15
#define TxSelReg 0x16
#define RxSelReg 0x17
#define RxThresholdReg 0x18
#define DemodReg 0x19
#define Reserved11 0x1A
#define Reserved12 0x1B
#define MifareReg 0x1C
#define Reserved13 0x1D
#define Reserved14 0x1E
#define SerialSpeedReg 0x1F
//Page 2:CFG
#define Reserved20 0x20
#define CRCResultRegM 0x21
#define CRCResultRegL 0x22
#define Reserved21 0x23
#define ModWidthReg 0x24
#define Reserved22 0x25
#define RFCfgReg 0x26
#define GsNReg 0x27
#define CWGsPReg 0x28
#define ModGsPReg 0x29
#define TModeReg 0x2A
#define TPrescalerReg 0x2B
#define TReloadRegH 0x2C
#define TReloadRegL 0x2D
#define TCounterValueRegH 0x2E
#define TCounterValueRegL 0x2F
//Page 3:TestRegister
#define Reserved30 0x30
#define TestSel1Reg 0x31
#define TestSel2Reg 0x32
#define TestPinEnReg 0x33
#define TestPinValueReg 0x34
#define TestBusReg 0x35
#define AutoTestReg 0x36
#define VersionReg 0x37
#define AnalogTestReg 0x38
#define TestDAC1Reg 0x39
#define TestDAC2Reg 0x3A
#define TestADCReg 0x3B
#define Reserved31 0x3C
#define Reserved32 0x3D
#define Reserved33 0x3E
#define Reserved34 0x3F
//-----------------------------------------------
//Reads the value at a register.
byte readFromRegister(byte addr) {
byte val;
output_low(CS);
spi_write(((addr<<1)&0x7E) | 0x80);
val =spi_read(0x00);
output_high(CS);
return val;
}
//writes Values to specified registers.
void writeToRegister(byte addr, byte val) {
output_low(CS);
//Address format: 0XXXXXX0
spi_write((addr<<1)&0x7E);
spi_write(val);
output_high(CS);
}
//Mask to update registers
void setBitMask(byte addr, byte mask) {
byte current;
current = readFromRegister(addr);
writeToRegister(addr, current | mask);
}
//remove bitmask maybe not necessary
void clearBitMask(byte addr, byte mask) {
byte current;
current = readFromRegister(addr);
writeToRegister(addr, current & (~mask));
}
//Initialize RFID Reader
//Does the setup for the MFRC522.
void reset() {
writeToRegister(CommandReg, MFRC522_SOFTRESET);
}
void begin() {
output_high(CS);
reset();
//Timer: TPrescaler*TreloadVal/6.78MHz = 24ms
writeToRegister(TModeReg, 0x8D);
delay_ms(20);// Tauto=1; f(Timer) = 6.78MHz/TPreScaler
writeToRegister(TPrescalerReg, 0x3E); // TModeReg[3..0] + TPrescalerReg
delay_ms(20);
writeToRegister(TReloadRegL, 30);
delay_ms(20);
writeToRegister(TReloadRegH, 0);
delay_ms(20);
writeToRegister(TxAutoReg, 0x40); // 100%ASK
delay_ms(20);
writeToRegister(ModeReg, 0x3D); // CRC initial value 0x6363
delay_ms(20);
//writeToRegister(TxControlReg, 0x82);
delay_ms(20);
setBitMask(TxControlReg, 0x03); // Turn antenna on.
}
//Checking MFRC522 Firmwareversion
byte getFirmwareVersion() {
byte response;
response = readFromRegister(VersionReg);
return response;
}
/**************************************************************************/
/*!
@brief Sends a command to a tag.
@param cmd The command to the MFRC522 to send a command to the tag.
@param data The data that is needed to complete the command.
@param dlen The length of the data.
@param result The result returned by the tag.
@param rlen The number of valid bits in the resulting value.
@returns Returns the status of the calculation.
MI_ERR if something went wrong,
MI_NOTAGERR if there was no tag to send the command to.
MI_OK if everything went OK.
*/
/**************************************************************************/
int commandTag(byte cmd, byte *data, int dlen, byte *result, int *rlen) {
int status = MI_ERR;
byte irqEn = 0x00;
byte waitIRq = 0x00;
byte lastBits, n;
int i;
switch (cmd) {
case MFRC522_AUTHENT:
irqEn = 0x12;
waitIRq = 0x10;
break;
case MFRC522_TRANSCEIVE:
irqEn = 0x77;
waitIRq = 0x30;
break;
default:
break;
}
writeToRegister(CommIEnReg, irqEn|0x80); // interrupt request
clearBitMask(CommIrqReg, 0x80); // Clear all interrupt requests bits.
setBitMask(FIFOLevelReg, 0x80); // FlushBuffer=1, FIFO initialization.
writeToRegister(CommandReg, MFRC522_IDLE); // No action, cancel the current command.
// Write to FIFO
for (i=0; i < dlen; i++) {
writeToRegister(FIFODataReg, data[i]);
}
// Execute the command.
writeToRegister(CommandReg, cmd);
if (cmd == MFRC522_TRANSCEIVE) {
setBitMask(BitFramingReg, 0x80); // StartSend=1, transmission of data starts
}
// Waiting for the command to complete so we can receive data.
i = 25; // Max wait time is 25ms.
do {
delay_ms(1);
// CommIRqReg[7..0]
// Set1 TxIRq RxIRq IdleIRq HiAlerIRq LoAlertIRq ErrIRq TimerIRq
n = readFromRegister(CommIrqReg);
i--;
} while ((i!=0) && !(n&0x01) && !(n&waitIRq));
clearBitMask(BitFramingReg, 0x80); // StartSend=0
if (i != 0) { // Request did not time out.
if(!(readFromRegister(ErrorReg) & 0x1D)) { // BufferOvfl Collerr CRCErr ProtocolErr
status = MI_OK;
if (n & irqEn & 0x01) {
status = MI_NOTAGERR;
}
if (cmd == MFRC522_TRANSCEIVE) {
n = readFromRegister(FIFOLevelReg);
lastBits = readFromRegister(ControlReg) & 0x07;
if (lastBits) {
*rlen = (n-1)*8 + lastBits;
} else {
*rlen = n*8;
}
if (n == 0) {
n = 1;
}
if (n > MAX_LEN) {
n = MAX_LEN;
}
// Reading the recieved data from FIFO.
for (i=0; i<n; i++) {
result[i] = readFromRegister(FIFODataReg);
}
}
} else {
status = MI_ERR;
}
}
return status;
}
/**************************************************************************/
/*
@brief Checks to see if there is a tag in the vicinity.
@param mode The mode we are requsting in.
@param type If we find a tag, this will be the type of that tag.
0x4400 = Mifare_UltraLight
0x0400 = Mifare_One(S50)
0x0200 = Mifare_One(S70)
0x0800 = Mifare_Pro(X)
0x4403 = Mifare_DESFire
@returns Returns the status of the request.
MI_ERR if something went wrong,
MI_NOTAGERR if there was no tag to send the command to.
MI_OK if everything went OK.
*/
/**************************************************************************/
int requestTag(byte mode, byte *data) {
int status, len;
writeToRegister(BitFramingReg, 0x07); // TxLastBists = BitFramingReg[2..0]
data[0] = mode;
status = commandTag(MFRC522_TRANSCEIVE, data, 1, data, &len);
if ((status != MI_OK) || (len != 0x10)) {
status = MI_ERR;
}
return status;
}
/**************************************************************************/
/*!
@brief Handles collisions that might occur if there are multiple
tags available.
@param serial The serial nb of the tag.
@returns Returns the status of the collision detection.
MI_ERR if something went wrong,
MI_NOTAGERR if there was no tag to send the command to.
MI_OK if everything went OK.
*/
/**************************************************************************/
int antiCollision(byte *serial) {
int status, i, len;
byte check = 0x00;
writeToRegister(BitFramingReg, 0x00); // TxLastBits = BitFramingReg[2..0]
serial[0] = MF1_ANTICOLL;
serial[1] = 0x20;
status = commandTag(MFRC522_TRANSCEIVE, serial, 2, serial, &len);
len = len / 8; // len is in bits, and we want each byte.
if (status == MI_OK) {
// The checksum of the tag is the ^ of all the values.
for (i = 0; i < len-1; i++) {
check ^= serial[i];
}
// The checksum should be the same as the one provided from the
// tag (serial[4]).
if (check != serial[i]) {
status = MI_ERR;
}
}
return status;
}
/**************************************************************************/
/*!
@brief Calculates the CRC value for some data that should be sent to
a tag.
@param data The data to calculate the value for.
@param len The length of the data.
@param result The result of the CRC calculation.
*/
/**************************************************************************/
void calculateCRC(byte *data, int len, byte *result) {
int i;
byte n;
clearBitMask(DivIrqReg, 0x04); // CRCIrq = 0
setBitMask(FIFOLevelReg, 0x80); // Clear the FIFO pointer
//Writing data to the FIFO.
for (i = 0; i < len; i++) {
writeToRegister(FIFODataReg, data[i]);
}
writeToRegister(CommandReg, MFRC522_CALCCRC);
// Wait for the CRC calculation to complete.
i = 0xFF;
do {
n = readFromRegister(DivIrqReg);
i--;
} while ((i != 0) && !(n & 0x04)); //CRCIrq = 1
// Read the result from the CRC calculation.
result[0] = readFromRegister(CRCResultRegL);
result[1] = readFromRegister(CRCResultRegM);
} |
The Code is ready to use. You can just read RFID Tags/Serialnumbers.
To write Tags you have to edit/add some more functions from LJOS Library. |
|
|
merhuman
Joined: 10 Dec 2017 Posts: 2
|
|
Posted: Thu Dec 21, 2017 1:18 pm |
|
|
Hi Mario_KA, Im currently doing a project similar to yours. However, i use pic16f877a and feed it with 5v power source and crystal is 8Mhz. Yes, i also use lm1117 3.3v to down the voltage from 5v to 3.3v for supplying the mfrc522. I connect my pic and mfrc522 like this:
PIN_C5 (pin 24) -- MOSI
PIN_C4 (pin 25) -- MISO
PIN_C3 (pin 18) -- SCK
PIN_E2 (pin 10) -- SS
PIN_E0 (pin 8) -- RST
I tried to port the arduino code to c file too, but i didnt work. I also tried your code but the result still the same. The SPI communication between pic and mfrc522 is fine, but when it comes to transfer data to PICC tag the result is not so good.
Also im using ccs c 5.015. Really need some help about this. Thanks |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Dec 21, 2017 7:14 pm |
|
|
Are you using the PDIP-40 package for the 16F877A ? Probably.
You have MISO connected to the wrong pin on the PIC. MISO should
connect to pin RC4/SDI/SDA, which is on pin 23 of the PDIP-40 package
as shown below:
merhuman wrote: |
I connect my pic and mfrc522 like this:
PIN_C5 (pin 24) -- MOSI
PIN_C4 (pin 25) -- MISO <-- Should be pin 23 on the PIC
PIN_C3 (pin 18) -- SCK
PIN_E2 (pin 10) -- SS
PIN_E0 (pin 8) -- RST
|
|
|
|
merhuman
Joined: 10 Dec 2017 Posts: 2
|
|
Posted: Fri Dec 22, 2017 1:20 am |
|
|
Hi PCM programmer. Yes, you are right. I mistyped the number 25. It's pin 23 on my hardware tho . Sorry, i was exhausted.
But as i mentioned before, the write and read work fine. Here is the code i use
main.h
Code: |
#include <16F877A.h>
#device ADC=16
#include <stdlib.h>
#FUSES NOWDT //No Watch Dog Timer
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#use delay(crystal = 8000000)
#use spi(MASTER, SPI1, BAUD = 9600, MODE=0, BITS=8, STREAM=XFER)
#use standard_io(B)
#use standard_io(C)
#use standard_io(D)
#use standard_io(E)
//*******************header of RFID********************
#define SSLOW (output_low(PIN_E2))
#define SSHIGH (output_high(PIN_E2))
#define RSTLOW (output_low(PIN_E0))
#define RSTHIGH (output_high(PIN_E0))
//PCD_Register
//Page 0: Command and status
#define CommandReg 0x01 // starts and stops command execution
#define ComIEnReg 0x02 // enable and disable interrupt request control bits
#define DivIEnReg 0x03 // enable and disable interrupt request control bits
#define ComIrqReg 0x04 // interrupt request bits
#define DivIrqReg 0x05 // interrupt request bits
#define ErrorReg 0x06 // error bits showing the error status of the last command executed
#define Status1Reg 0x07 // communication status bits
#define Status2Reg 0x08 // receiver and transmitter status bits
#define FIFODataReg 0x09 // input and output of 64 byte FIFO buffer
#define FIFOLevelReg 0x0a // number of bytes stored in the FIFO buffer
#define WaterLevelReg 0x0b // level for FIFO underflow and overflow warning
#define ControlReg 0x0c // miscellaneous control registers
#define BitFramingReg 0x0d // adjustments for bit-oriented frames
#define CollReg 0x0e // bit position of the first bit-collision detected on the RF interface
//Page 1: Command
#define ModeReg 0x11 // defines general modes for transmitting and receiving
#define TxModeReg 0x12 // defines transmission data rate and framing
#define RxModeReg 0x13 // defines reception data rate and framing
#define TxControlReg 0x14 // controls the logical behavior of the antenna driver pins TX1 and TX2
#define TxASKReg 0x15 // controls the setting of the transmission modulation
#define TxSelReg 0x16 // selects the internal sources for the antenna driver
#define RxSelReg 0x17 // selects internal receiver settings
#define RxThresholdReg 0x18 // selects thresholds for the bit decoder
#define DemodReg 0x19 // defines demodulator settings
#define MfTxReg 0x1c // controls some MIFARE communication transmit parameters
#define MfRxReg 0x1d // controls some MIFARE communication receive parameters
#define SerialSpeedReg 0x1f // selects the speed of the serial UART interface
//Page 2: Configuration
#define CRCResultRegH 0x21 // shows the MSB and LSB values of the CRC calculation
#define CRCResultRegL 0x22
#define ModWidthReg 0x24 // controls the ModWidth setting?
#define RFCfgReg 0x26 // configures the receiver gain
#define GsNReg 0x27 // selects the conductance of the antenna driver pins TX1 and TX2 for modulation
#define CWGsPReg 0x28 // defines the conductance of the p-driver output during periods of no modulation
#define ModeGsPReg 0x29 // defines the conductance of the p-driver output during periods of modulation
#define TModeReg 0x2a // defines settings for the internal timer
#define TPrescalerReg 0x2b // the lower 8 bits of the TPrescaler value. The 4 high bits are in TModeReg.
#define TReloadRegH 0x2c // defines the 16-bit timer reload value
#define TReloadRegL 0x2d
#define TCounterValueRegH 0x2e // shows the 16-bit timer value
#define TCounterValueRegL 0x2f
//Commands
#define PCD_Idle 0x00 // no action, cancels current command execution
#define PCD_Mem 0x01 // stores 25 bytes into the internal buffer
#define PCD_GenerateRandomID 0x02 // generates a 10-byte random ID number
#define PCD_CalcCRC 0x03 // activates the CRC coprocessor or performs a self-test
#define PCD_Transmit 0x04 // transmits data from the FIFO buffer
#define PCD_NoCmdChange 0x07 // no command change, can be used to modify the CommandReg register bits without affecting the command, for example, the PowerDown bit
#define PCD_Receive 0x08 // activates the receiver circuits
#define PCD_Transceive 0x0c // transmits data from FIFO buffer to antenna and automatically activates the receiver after transmission
#define PCD_MFAuthent 0x0e // performs the MIFARE standard authentication as a reader
#define PCD_SoftReset 0x0f // resets the MFRC522
///Mifare_One tag command word
#define MF1_REQIDL 0x26 // find the antenna area does not enter hibernation
#define MF1_REQALL 0x52 // find all the tags antenna area
#define MF1_ANTICOLL 0x93 // anti-collision
#define MF1_SELECTTAG 0x93 // election tag
#define MF1_AUTHENT1A 0x60 // authentication key A
#define MF1_AUTHENT1B 0x61 // authentication key B
#define MF1_READ 0x30 // Read Block
#define MF1_WRITE 0xA0 // write block
#define MF1_DECREMENT 0xC0 // debit
#define MF1_INCREMENT 0xC1 // recharge
#define MF1_RESTORE 0xC2 // transfer block data to the buffer
#define MF1_TRANSFER 0xB0 // save the data in the buffer
#define MF1_HALT 0x50 // Sleep
//Status code
#define MI_OK 0
#define MI_NOTAGERR 1
#define MI_ERR 2
#define MAX_LEN 16
|
and here is the main.c
Code: |
void main()
{
spi_init(XFER, TRUE);
delay_ms(100);
LCD_Init();
LCD_PutCmd(0x01);
LCD_PutCmd(0x80);
RSTHIGH; // set rst pin of mfrc522 high
PCD_Init();
infoVersion();
while(TRUE)
{
//TODO: User Code
FoundTag = requestTag(MF1_REQIDL, TagData);
LCD_PutCmd(0x01);
LCD_PutCmd(0x80);
delay_ms(2000);
if(FoundTag == MI_OK)
{
LCD_PutChar("tag found");
}
else
{
LCD_PutChar("no tag found");
}
}
}
//******** RFID function ***********
//Read from register
unsigned int8 PCD_RdReg(unsigned int8 reg)
{
unsigned int8 address;
unsigned int8 value = 0;
SSLOW;
delay_us(20);
address = ((reg << 1) & 0x7e) | 0x80;
spi_xfer(XFER, address);
value = spi_xfer(XFER, 0x00);
delay_us(20);
SSHIGH;
return value;
}
//Write to register
void PCD_WrReg(unsigned int8 reg, unsigned int8 value)
{
unsigned int8 address;
SSLOW;
delay_us(20);
address = ((reg << 1) & 0x7e);
spi_xfer(XFER, address);
spi_xfer(XFER, value);
delay_us(20);
SSHIGH;
}
//Initialize the mfrc522 chip
void PCD_Init(void)
{
PCD_HReset();
delay_ms(50);
PCD_Reset();
//PCD_WrReg(TxModeReg, 0x00);
//PCD_WrReg(RxModeReg, 0x00);
//PCD_WrReg(ModWidthReg, 0x26);
PCD_WrReg(TModeReg, 0x8D);
PCD_WrReg(TPrescalerReg, 0x3e);
PCD_WrReg(TReloadRegH, 0x00);
PCD_WrReg(TReloadRegL, 0x30);
PCD_WrReg(TxASKReg, 0x40);
PCD_WrReg(ModeReg, 0x3d);
PCD_AntennaOn();
}
unsigned int8 getFirmwareVersion(void)
{
unsigned int8 response = PCD_RdReg(VersionReg);
return response;
}
int commandTag(byte cmd, byte *data, int dlen, byte *result, int *rlen)
{
int status = MI_ERR;
byte irqEn = 0x00;
byte waitIRq = 0x00;
byte lastBits, n;
int j;
switch (cmd)
{
case PCD_MFAuthent:
irqEn = 0x12;
waitIRq = 0x10;
break;
case PCD_Transceive:
irqEn = 0x77;
waitIRq = 0x30;
break;
default:
break;
}
PCD_WrReg(ComIEnReg, irqEn|0x80); // interrupt request
PCD_ClrBitMsk(ComIrqReg, 0x80); // Clear all interrupt requests bits.
PCD_SetBitMsk(FIFOLevelReg, 0x80); // FlushBuffer=1, FIFO initialization.
PCD_WrReg(CommandReg, PCD_Idle); // No action, cancel the current command.
// Write to FIFO
for (j=0; j < dlen; j++)
{
PCD_WrReg(FIFODataReg, data[j]);
}
// Execute the command.
PCD_WrReg(CommandReg, cmd);
if (cmd == PCD_Transceive)
{
PCD_SetBitMsk(BitFramingReg, 0x80); // StartSend=1, transmission of data starts
}
// Waiting for the command to complete so we can receive data.
j = 25; // Max wait time is 25ms.
do {
delay_ms(1);
// CommIRqReg[7..0]
// Set1 TxIRq RxIRq IdleIRq HiAlerIRq LoAlertIRq ErrIRq TimerIRq
n = PCD_RdReg(ComIrqReg);
j--;
} while ((j!=0) && !(n&0x01) && !(n&waitIRq));
PCD_ClrBitMsk(BitFramingReg, 0x80); // StartSend=0
if (j != 0)
{ // Request did not time out.
if(!(PCD_RdReg(ErrorReg) & 0x1D))
{ // BufferOvfl Collerr CRCErr ProtocolErr
status = MI_OK;
if (n & irqEn & 0x01)
{
status = MI_NOTAGERR;
}
if (cmd == PCD_Transceive)
{
n = PCD_RdReg(FIFOLevelReg);
lastBits = PCD_RdReg(ControlReg) & 0x07;
if (lastBits)
{
*rlen = (n-1)*8 + lastBits;
}
else
{
*rlen = n*8;
}
if (n == 0)
{
n = 1;
}
if (n > MAX_LEN)
{
n = MAX_LEN;
}
// Reading the recieved data from FIFO.
for (j=0; j<n; j++)
{
result[j] = PCD_RdReg(FIFODataReg);
}
}
}
else
{
status = MI_ERR;
}
}
return status;
}
int requestTag(byte mode, byte *data)
{
int status, len;
PCD_WrReg(BitFramingReg, 0x07);
data[0] = mode;
status = commandTag(PCD_Transceive, data, 1, data, &len);
if((status != MI_OK) || (len != 0x10))
{
status = MI_ERR;
}
return status;
}
int antiCollision(byte *serial)
{
int status, i, len;
byte check = 0x00;
PCD_WrReg(BitFramingReg, 0x00);
serial[0] = MF1_ANTICOLL;
serial[1] = 0x20;
status = commandTag(PCD_Transceive, serial, 2, serial, &len);
len = len / 8;
if (status == MI_OK)
{
for(i = 0; i < len-1; i++)
{
check ^= serial[i];
}
if(check != serial[i])
{
status = MI_ERR;
}
}
return status;
}
void calculateCRC(byte *data, int len, byte *result)
{
int i;
byte n;
PCD_ClrBitMsk(DivIrqReg, 0x04);
PCD_SetBitMsk(FIFOLevelReg, 0x80);
for(i = 0; i < len; i++)
{
PCD_WrReg(FIFODataReg, data[i]);
}
PCD_WrReg(CommandReg, PCD_CalcCRC);
i = 0xff;
do{
n = PCD_RdReg(DivIrqReg);
i--;
}while((i != 0) && !(n & 0x04));
result[0] = PCD_RdReg(CRCResultRegL);
result[1] = PCD_RdReg(CRCResultRegH);
}
////////////////////////////////////
void PCD_ClrBitMsk(char reg, char mask)
{
unsigned int8 tmp = 0x00;
tmp = PCD_RdReg(reg);
PCD_WrReg(reg, tmp&(~mask));
}
///////////////////////////////////
void PCD_SetBitMsk(char reg, char mask)
{
unsigned int8 tmp = 0x00;
PCD_WrReg(reg, tmp|mask);
}
//Soft Reset
void PCD_Reset(void)
{
PCD_WrReg(CommandReg,PCD_SoftReset);
delay_ms(50);
while(PCD_RdReg(CommandReg) & (1<<4));
}
//Hard Reset
void PCD_HReset(void)
{
RSTHIGH;
delay_us(1);
RSTLOW;
delay_us(1);
RSTHIGH;
delay_us(1);
}
//Turn the antenna on
void PCD_AntennaOn(void)
{
unsigned int8 value = PCD_RdReg(TxControlReg);
if((value & 0x03) != 0x03)
{
PCD_WrReg(TxControlReg, value | 0x03);
}
}
//Turn the antenna off
void PCD_AntennaOff(void)
{
PCD_ClrBitMsk(TxControlReg, 0x03);
}
void infoVersion(void)
{
version = PCD_RdReg(VersionReg);
if(!version)
{
LCD_PutChar("no device");
}
else
{
LCD_PutChar("device found");
LCD_PutCmd(0xc0);
LCD_Check(version);
}
}
|
Most of the code is similar to Mario_KA's code. Just the name of the registers and commands are a little bit different because of the ported code from arduino i have made from last month.
I stuck at requestTag(), it just return MI_ERR all the time. Is it because of the transmission time? I'm trying to figure it out by reading the references:
an10833 https://www.nxp.com/docs/en/application-note/AN10833.pdf
an10834https://www.nxp.com/docs/en/application-note/AN10834.pdf
an10927https://www.nxp.com/docs/en/application-note/AN10927.pdf
But still haven't figure it out. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Dec 22, 2017 2:36 am |
|
|
I suggest that you post your problem in the main forum so everyone can
look at it. Most things don't get solved in the Code Library. They may
get solved in the main forum:
http://www.ccsinfo.com/forum/viewforum.php?f=1
Also, I suggest that you read this 4-page thread. Mario_KA's questions
start on page 2.
http://www.ccsinfo.com/forum/viewtopic.php?t=51393
merhuman wrote: |
I use pic16f877a and feed it with 5v power source and crystal is
8Mhz. Yes, i also use lm1117 3.3v to down the voltage from 5v to 3.3v
for supplying the mfrc522. |
They are not going to like it when they find out you are running the
MFRC522 at 3.3v and the PIC at 5v. Read the thread in the link above,
starting at page 1. They discuss this issue. |
|
|
mohammad3d
Joined: 28 Mar 2009 Posts: 17
|
MFRC522 module |
Posted: Sun Oct 07, 2018 2:54 am |
|
|
Hi Every one,
I worked on Mario_KA program and apply some little change on his program.
Now, I tested with 2 different mfrc522 module and my program work great.
Please note that connect MFRC522 RST pin directly to +3.3V power.
All another pin connect directly to +5v PIC micro without any level converter.
main.c
Code: |
//main.c File
#include <16F887.h>
#FUSES NOWDT //No Watch Dog Timer
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage programing, B3(PIC16) or B5(PIC18) used for I/O
#FUSES XT
#use delay(crystal=4000000)//Set frequency at 4Mhz
#include <C_LCD.h>//2x16 Character LCD driver
//Note:Connect MFRC522 module to 5v PIC without any Level converter .It'll work fine.
//Note:mfrc522 work in SPI slave mode(PIC is MASTER)
//mfrc522 connection PIN
#define CS PIN_A1//mfrc 522 chip select pin(SS) to PIC pin3
//MFRC522 module RST pin to +3.3v
//MFRC522 module MOSI pin to PIC16f877 pin 24(RC5/SDO)
//MFRC522 module MISO pin to PIC16f877 pin 23(RC4/SDI)
//MFRC522 module SCK pin to PIC16f877 pin 18(RC3/SCK)
#include <MFRC522_driver.h>//mfrc 522 Driver
//spi modes
#define SPI_MODE_0 (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_1 (SPI_L_TO_H)
#define SPI_MODE_2 (SPI_H_TO_L)
#define SPI_MODE_3 (SPI_H_TO_L | SPI_XMIT_L_TO_H)
byte FoundTag; // Variable used to check if Tag was found
byte ReadTag; // Variable used to store anti-collision value to read Tag information
byte TagData[16]; // Variable used to store Full Tag Data
byte GoodTagSerialNumber[4] = {0x3D, 0xCA, 0x2B, 0x62}; // The Tag Serial number we are looking for
int i=0;
byte version;
int GoodTag=0; // Variable used to confirm good Tag Detected
void Get_UID()
{
// Get Tag UID
ReadTag = antiCollision(TagData);
lcd_gotoxy(1,1);
/// display Tag UID in hexadecimal
for(i=0;i<=2;i++)printf(lcd_putc,"%2X,",TagData[i]);
printf(lcd_putc,"%2X",(TagData[i]));
}
void Search_for_matching_Tag()
{
GoodTag=0;
for(int i=0; i <= 3; i++)
{
if (GoodTagSerialNumber[i] != TagData[i])
{
GoodTag=0;
break; // if not equal, then break out of the "for" loop
}
}
if (TagData[3]==GoodTagSerialNumber[3])
{
// if we made it to 4 loops then the Tag Serial numbers are matching
GoodTag=1;
}
lcd_gotoxy(1,2);
if (GoodTag == 1)
{
printf(lcd_putc,"Access granted ");
}
else
{
printf(lcd_putc,"Access Denied ");
GoodTag=0;
}
}
void Get_Chip_Version(){
while(True)
{
version = readFromRegister(VersionReg);
if(!version)
{
lcd_gotoxy(1,1);
printf(lcd_putc,"NO DEVICE");
}
if(version)
{
lcd_gotoxy(1,1);
printf(lcd_putc,"DEVICE found");
lcd_gotoxy(1, 2);
printf(lcd_putc,"ver %2X",version);
break;
}
}
}
void main()
{
setup_spi(SPI_MASTER|SPI_MODE_0|SPI_CLK_DIV_64);
lcd_init();
lcd_putc('\f');
delay_ms(50);
MFRC_522_init(); //initialize MFRC522
Get_Chip_Version(); //print Firmwareverion on LCD
delay_ms(2000);
lcd_putc('\f');
while(TRUE)
{
// Check to see if a Tag was detected
// If yes, then the variable FoundTag will contain "MI_OK"
FoundTag = requestTag(MF1_REQIDL, TagData);
lcd_gotoxy(1,1);
printf(lcd_putc,"Checking for Tag \r\n");
if (FoundTag == MI_OK)
{
lcd_gotoxy(1,2);
printf(lcd_putc,"Tag found ");
delay_ms(1000);
lcd_putc('\f');
Get_UID();
Search_for_matching_Tag();
delay_ms(1000);
}
else
{
lcd_gotoxy(1,2);
printf(lcd_putc,"No Tag found ");
}
}
}
|
C_LCD.h file
Code: |
//C_LCD.h file
#define _lcd_h_
#include <math.h>
void lcd_init(void);
byte lcd_read_byte(void);
byte lcd_read_nibble(void);
void lcd_send_byte(byte address, byte n);
void lcd_send_nibble(byte n);
void lcd_gotoxy(byte x, byte y);
char lcd_getc(byte x, byte y);
void lcd_putc(char c);
//Define LCD connection Pins
#define LCD_RS_PIN PIN_D1
#define LCD_RW_PIN PIN_D2
#define LCD_ENABLE_PIN PIN_D3
#define LCD_DATA4 PIN_D4
#define LCD_DATA5 PIN_D5
#define LCD_DATA6 PIN_D6
#define LCD_DATA7 PIN_D7
#define lcd_output_enable(x) output_bit(LCD_ENABLE_PIN, x)
#define lcd_enable_tris() output_drive(LCD_ENABLE_PIN)
#define lcd_output_rs(x) output_bit(LCD_RS_PIN, x)
#define lcd_rs_tris() output_drive(LCD_RS_PIN)
#define lcd_output_rw(x) output_bit(LCD_RW_PIN, x)
#define lcd_rw_tris() output_drive(LCD_RW_PIN)
#define lcd_line_one 0x00
#define lcd_line_two 0x40
#define lcd_line_three 0x14
#define lcd_line_four 0x54
#define LCD_TYPE 0x02
byte const LCD_INIT_STRING[4] = {0x28 | (LCD_TYPE << 2), 0x0C, 0x01, 0x06};
void lcd_init(void)
{
byte i;
output_drive(LCD_DATA4);
output_drive(LCD_DATA5);
output_drive(LCD_DATA6);
output_drive(LCD_DATA7);
lcd_enable_tris();
lcd_rs_tris();
lcd_rw_tris();
lcd_output_rs(0);
lcd_output_rw(0);
lcd_output_enable(0);
delay_ms(15);
for(i=1;i<=3;i++)
{
lcd_send_nibble(0x03);
delay_ms(5);
}
lcd_send_nibble(0x02);
for(i=0;i<=3;i++)
lcd_send_byte(0,LCD_INIT_STRING[i]);
}
// ***************************************************
byte lcd_read_byte(void)
{
byte low,high;
output_float(LCD_DATA4);
output_float(LCD_DATA5);
output_float(LCD_DATA6);
output_float(LCD_DATA7);
lcd_output_rw(1);
delay_cycles(1);
lcd_output_enable(1);
delay_cycles(1);
high = lcd_read_nibble();
lcd_output_enable(0);
delay_cycles(1);
lcd_output_enable(1);
delay_cycles(1);
low = lcd_read_nibble();
lcd_output_enable(0);
output_drive(LCD_DATA4);
output_drive(LCD_DATA5);
output_drive(LCD_DATA6);
output_drive(LCD_DATA7);
return((high<<4) | low);
}
// ***************************************************
byte lcd_read_nibble(void)
{
byte n = 0x00;
n |= input(LCD_DATA4);
n |= input(LCD_DATA5) << 1;
n |= input(LCD_DATA6) << 2;
n |= input(LCD_DATA7) << 3;
return(n);
}
// ***************************************************
void lcd_send_byte(byte address, byte n)
{
lcd_output_rs(0);
while(bit_test(lcd_read_byte(),7));
lcd_output_rs(address);
delay_cycles(1);
lcd_output_rw(0);
delay_cycles(1);
lcd_output_enable(0);
lcd_send_nibble(n >> 4);
lcd_send_nibble(n & 0x0F);
}
// ***************************************************
void lcd_send_nibble(byte n)
{
output_bit(LCD_DATA4, bit_test(n, 0));
output_bit(LCD_DATA5, bit_test(n, 1));
output_bit(LCD_DATA6, bit_test(n, 2));
output_bit(LCD_DATA7, bit_test(n, 3));
delay_cycles(1);
lcd_output_enable(1);
delay_us(2);
lcd_output_enable(0);
}
// ***************************************************
void lcd_gotoxy(byte x, byte y)
{
byte address;
if(y==1)
address=lcd_line_one;
else if(y==2)
address=lcd_line_two;
else if(y==3)
address=lcd_line_three;
else if(y==4)
address=lcd_line_four;
address+=x-1;
lcd_send_byte(0,0x80|address);
}
// ***************************************************
char lcd_getc(byte x, byte y)
{
char value;
lcd_gotoxy(x,y);
while(bit_test(lcd_read_byte(),7));
lcd_output_rs(1);
value = lcd_read_byte();
lcd_output_rs(0);
return(value);
}
// ***************************************************
void lcd_putc(char c)
{
switch (c)
{
case '\f':
lcd_send_byte(0,0x01);
delay_ms(2);
break;
case '\n':
lcd_gotoxy(1,0x02);
break;
case '\b':
lcd_send_byte(0,0x10);
break;
default:
lcd_send_byte(1,c);
break;
}
}
// ***************************************************
|
MFRC522_Driver.h file
Code: |
// MFRC522_Driver.h file
#define MAX_LEN 16 // Maximum length of an array. CHECK IF IT IS MAXIMUM LENGTH/SIZE OF FIFO!!!!!!!!!!!
//MF522 MFRC522 error codes.
#define MI_OK 0 // Everything A-OK.
#define MI_NOTAGERR 1 // No tag error
#define MI_ERR 2 // General error
//MF522 Command word
#define MFRC522_IDLE 0x00 // NO action; Cancel the current command
#define MFRC522_MEM 0x01 // Store 25 byte into the internal buffer.
#define MFRC522_GENID 0x02 // Generates a 10 byte random ID number.
#define MFRC522_CALCCRC 0x03 // CRC Calculate or selftest.
#define MFRC522_TRANSMIT 0x04 // Transmit data
#define MFRC522_NOCMDCH 0x07 // No command change.
#define MFRC522_RECEIVE 0x08 // Receive Data
#define MFRC522_TRANSCEIVE 0x0C // Transmit and receive data,
#define MFRC522_AUTHENT 0x0E // Authentication Key
#define MFRC522_SOFTRESET 0x0F // Reset
//Mifare_One tag command word
#define MF1_REQIDL 0x26 // find the antenna area does not enter hibernation
#define MF1_REQALL 0x52 // find all the tags antenna area
#define MF1_ANTICOLL 0x93 // anti-collision
#define MF1_SELECTTAG 0x93 // election tag
#define MF1_AUTHENT1A 0x60 // authentication key A
#define MF1_AUTHENT1B 0x61 // authentication key B
#define MF1_READ 0x30 // Read Block
#define MF1_WRITE 0xA0 // write block
#define MF1_DECREMENT 0xC0 // debit
#define MF1_INCREMENT 0xC1 // recharge
#define MF1_RESTORE 0xC2 // transfer block data to the buffer
#define MF1_TRANSFER 0xB0 // save the data in the buffer
#define MF1_HALT 0x50 // Sleep
//------------------ MFRC522 registers---------------
//Page 0:Command and Status
#define Reserved00 0x00
#define CommandReg 0x01
#define CommIEnReg 0x02
#define DivIEnReg 0x03
#define CommIrqReg 0x04
#define DivIrqReg 0x05
#define ErrorReg 0x06
#define Status1Reg 0x07
#define Status2Reg 0x08
#define FIFODataReg 0x09
#define FIFOLevelReg 0x0A
#define WaterLevelReg 0x0B
#define ControlReg 0x0C
#define BitFramingReg 0x0D
#define CollReg 0x0E
#define Reserved01 0x0F
//Page 1:Command
#define Reserved10 0x10
#define ModeReg 0x11
#define TxModeReg 0x12
#define RxModeReg 0x13
#define TxControlReg 0x14
#define TxAutoReg 0x15
#define TxSelReg 0x16
#define RxSelReg 0x17
#define RxThresholdReg 0x18
#define DemodReg 0x19
#define Reserved11 0x1A
#define Reserved12 0x1B
#define MifareReg 0x1C
#define Reserved13 0x1D
#define Reserved14 0x1E
#define SerialSpeedReg 0x1F
//Page 2:CFG
#define Reserved20 0x20
#define CRCResultRegM 0x21
#define CRCResultRegL 0x22
#define Reserved21 0x23
#define ModWidthReg 0x24
#define Reserved22 0x25
#define RFCfgReg 0x26
#define GsNReg 0x27
#define CWGsPReg 0x28
#define ModGsPReg 0x29
#define TModeReg 0x2A
#define TPrescalerReg 0x2B
#define TReloadRegH 0x2C
#define TReloadRegL 0x2D
#define TCounterValueRegH 0x2E
#define TCounterValueRegL 0x2F
//Page 3:TestRegister
#define Reserved30 0x30
#define TestSel1Reg 0x31
#define TestSel2Reg 0x32
#define TestPinEnReg 0x33
#define TestPinValueReg 0x34
#define TestBusReg 0x35
#define AutoTestReg 0x36
#define VersionReg 0x37
#define AnalogTestReg 0x38
#define TestDAC1Reg 0x39
#define TestDAC2Reg 0x3A
#define TestADCReg 0x3B
#define Reserved31 0x3C
#define Reserved32 0x3D
#define Reserved33 0x3E
#define Reserved34 0x3F
//-----------------------------------------------
//Reads the value at a register.
byte readFromRegister(byte addr) {
byte val;
output_low(CS);
delay_us(10);
spi_write(((addr<<1)&0x7E) | 0x80);
delay_us(100);
val =spi_read(0x00);
output_high(CS);
return val;
}
//writes Values to specified registers.
void writeToRegister(byte addr, byte val) {
output_low(CS);
delay_us(10);
//Address format: 0XXXXXX0
spi_write((addr<<1)&0x7E);
delay_us(10);
spi_write(val);
output_high(CS);
}
//Mask to update registers
void setBitMask(byte addr, byte mask) {
byte current;
current = readFromRegister(addr);
writeToRegister(addr, current | mask);
}
//remove bitmask maybe not necessary
void clearBitMask(byte addr, byte mask) {
byte current;
current = readFromRegister(addr);
writeToRegister(addr, current & (~mask));
}
//Initialize RFID Reader
//Does the setup for the MFRC522.
void reset() {
writeToRegister(CommandReg, MFRC522_SOFTRESET);
}
void MFRC_522_init() {
output_high(CS);
//software reset
reset();
//Timer: TPrescaler*TreloadVal/6.78MHz = 24ms
writeToRegister(TModeReg, 0x8D);
delay_ms(20);// Tauto=1; f(Timer) = 6.78MHz/TPreScaler
writeToRegister(TPrescalerReg, 0x3E); // TModeReg[3..0] + TPrescalerReg
delay_ms(20);
writeToRegister(TReloadRegL, 30);
delay_ms(20);
writeToRegister(TReloadRegH, 0);
delay_ms(20);
writeToRegister(TxAutoReg, 0x40); // 100%ASK
delay_ms(20);
writeToRegister(ModeReg, 0x3D); // CRC initial value 0x6363
delay_ms(20);
//writeToRegister(TxControlReg, 0x82);
delay_ms(20);
setBitMask(TxControlReg, 0x03); // Turn antenna on.
}
//Checking MFRC522 Firmwareversion
byte getFirmwareVersion() {
byte response;
response = readFromRegister(VersionReg);
return response;
}
/**************************************************************************/
/*!
@brief Sends a command to a tag.
@param cmd The command to the MFRC522 to send a command to the tag.
@param data The data that is needed to complete the command.
@param dlen The length of the data.
@param result The result returned by the tag.
@param rlen The number of valid bits in the resulting value.
@returns Returns the status of the calculation.
MI_ERR if something went wrong,
MI_NOTAGERR if there was no tag to send the command to.
MI_OK if everything went OK.
*/
/**************************************************************************/
int commandTag(byte cmd, byte *data, int dlen, byte *result, int *rlen) {
int status = MI_ERR;
byte irqEn = 0x00;
byte waitIRq = 0x00;
byte lastBits, n;
int i;
switch (cmd) {
case MFRC522_AUTHENT:
irqEn = 0x12;
waitIRq = 0x10;
break;
case MFRC522_TRANSCEIVE:
irqEn = 0x77;
waitIRq = 0x30;
break;
default:
break;
}
writeToRegister(CommIEnReg, irqEn|0x80); // interrupt request
clearBitMask(CommIrqReg, 0x80); // Clear all interrupt requests bits.
setBitMask(FIFOLevelReg, 0x80); // FlushBuffer=1, FIFO initialization.
writeToRegister(CommandReg, MFRC522_IDLE); // No action, cancel the current command.
// Write to FIFO
for (i=0; i < dlen; i++) {
writeToRegister(FIFODataReg, data[i]);
}
// Execute the command.
writeToRegister(CommandReg, cmd);
if (cmd == MFRC522_TRANSCEIVE) {
setBitMask(BitFramingReg, 0x80); // StartSend=1, transmission of data starts
}
// Waiting for the command to complete so we can receive data.
i = 25; // Max wait time is 25ms.
do {
delay_ms(1);
// CommIRqReg[7..0]
// Set1 TxIRq RxIRq IdleIRq HiAlerIRq LoAlertIRq ErrIRq TimerIRq
n = readFromRegister(CommIrqReg);
i--;
} while ((i!=0) && !(n&0x01) && !(n&waitIRq));
clearBitMask(BitFramingReg, 0x80); // StartSend=0
if (i != 0) { // Request did not time out.
if(!(readFromRegister(ErrorReg) & 0x1D)) { // BufferOvfl Collerr CRCErr ProtocolErr
status = MI_OK;
if (n & irqEn & 0x01) {
status = MI_NOTAGERR;
}
if (cmd == MFRC522_TRANSCEIVE) {
n = readFromRegister(FIFOLevelReg);
lastBits = readFromRegister(ControlReg) & 0x07;
if (lastBits) {
*rlen = (n-1)*8 + lastBits;
} else {
*rlen = n*8;
}
if (n == 0) {
n = 1;
}
if (n > MAX_LEN) {
n = MAX_LEN;
}
// Reading the recieved data from FIFO.
for (i=0; i<n; i++) {
result[i] = readFromRegister(FIFODataReg);
}
}
} else {
status = MI_ERR;
}
}
return status;
}
/**************************************************************************/
/*
@brief Checks to see if there is a tag in the vicinity.
@param mode The mode we are requsting in.
@param type If we find a tag, this will be the type of that tag.
0x4400 = Mifare_UltraLight
0x0400 = Mifare_One(S50)
0x0200 = Mifare_One(S70)
0x0800 = Mifare_Pro(X)
0x4403 = Mifare_DESFire
@returns Returns the status of the request.
MI_ERR if something went wrong,
MI_NOTAGERR if there was no tag to send the command to.
MI_OK if everything went OK.
*/
/**************************************************************************/
int requestTag(byte mode, byte *data) {
int status, len;
writeToRegister(BitFramingReg, 0x07); // TxLastBists = BitFramingReg[2..0]
data[0] = mode;
status = commandTag(MFRC522_TRANSCEIVE, data, 1, data, &len);
if ((status != MI_OK) || (len != 0x10)) {
status = MI_ERR;
}
return status;
}
/**************************************************************************/
/*!
@brief Handles collisions that might occur if there are multiple
tags available.
@param serial The serial nb of the tag.
@returns Returns the status of the collision detection.
MI_ERR if something went wrong,
MI_NOTAGERR if there was no tag to send the command to.
MI_OK if everything went OK.
*/
/**************************************************************************/
int antiCollision(byte *serial) {
int status, i, len;
byte check = 0x00;
writeToRegister(BitFramingReg, 0x00); // TxLastBits = BitFramingReg[2..0]
serial[0] = MF1_ANTICOLL;
serial[1] = 0x20;
status = commandTag(MFRC522_TRANSCEIVE, serial, 2, serial, &len);
len = len / 8; // len is in bits, and we want each byte.
if (status == MI_OK) {
// The checksum of the tag is the ^ of all the values.
for (i = 0; i < len-1; i++) {
check ^= serial[i];
}
// The checksum should be the same as the one provided from the
// tag (serial[4]).
if (check != serial[i]) {
status = MI_ERR;
}
}
return status;
}
/**************************************************************************/
/*!
@brief Calculates the CRC value for some data that should be sent to
a tag.
@param data The data to calculate the value for.
@param len The length of the data.
@param result The result of the CRC calculation.
*/
/**************************************************************************/
void calculateCRC(byte *data, int len, byte *result) {
int i;
byte n;
clearBitMask(DivIrqReg, 0x04); // CRCIrq = 0
setBitMask(FIFOLevelReg, 0x80); // Clear the FIFO pointer
//Writing data to the FIFO.
for (i = 0; i < len; i++) {
writeToRegister(FIFODataReg, data[i]);
}
writeToRegister(CommandReg, MFRC522_CALCCRC);
// Wait for the CRC calculation to complete.
i = 0xFF;
do {
n = readFromRegister(DivIrqReg);
i--;
} while ((i != 0) && !(n & 0x04)); //CRCIrq = 1
// Read the result from the CRC calculation.
result[0] = readFromRegister(CRCResultRegL);
result[1] = readFromRegister(CRCResultRegM);
}
|
This program fully tested and work Great.
Enjoy, |
|
|
bharath0209
Joined: 23 Jul 2019 Posts: 7
|
Re: MFRC522 module |
Posted: Tue Jul 23, 2019 3:40 am |
|
|
Hey Mohammad3d,
Thanks a lot for the code.
I have used it after modifying to be compatible with xc8 compiler and was successful until detecting the version of the RFID module.
After which it always returns MI_ERR when i checked the error using LCD.
It is stuck at RequestTag function.
It doesn't give right values from next steps.
If you have similar issues, it would be a great help f you could revert.
Would be happy to post the code if required.
Thanks
|
|
|
bharath0209
Joined: 23 Jul 2019 Posts: 7
|
Facing Same issue! Help. |
Posted: Tue Jul 23, 2019 3:47 am |
|
|
Hey merhuman,
I'm facing same issue after almost two years of your post !
This is one of the few good resources available for interfacing pic16f877a with rfid.
None other seems to work. This program worked for me at least to read data from versionreg.
It is stuck after similar to you.
I would be grateful if you could help me out with this in case you've managed to solve it and remembered it.
Thanks. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
Re: MFRC522 module |
Posted: Tue Jul 23, 2019 6:25 am |
|
|
bharath0209 wrote: | Hey Mohammad3d,
I have used it after modifying to be compatible with xc8 compiler
|
In CCS an 'int' is an unsigned 8-bit value. But in XC8 it's a signed 16-bit
value. So you need to use 'unsigned char' in XC8 anytime you see 'int'
in CCS. (This is true for the PCB, PCM, and PCH CCS compilers).
Also, if you got the SPI mode wrong, don't expect the program to work. |
|
|
bharath0209
Joined: 23 Jul 2019 Posts: 7
|
Re: MFRC522 module |
Posted: Tue Jul 23, 2019 6:32 am |
|
|
Thanks for the reply.
Yeah, I used unsigned char and also the spi mode works well as I tested it between two pic16f877a controllers.
In this, I'm able to read the versionReg. Only after that, the program keeps returning MI_ERR
Is there anything else I can check ? |
|
|
bharath0209
Joined: 23 Jul 2019 Posts: 7
|
Re: MFRC522 module |
Posted: Tue Jul 23, 2019 6:36 am |
|
|
Here's my code..
Main function
Code: |
#include <xc.h>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define _XTAL_FREQ 16000000
#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = ON // Power-up Timer Enable bit (PWRT enabled)
#pragma config BOREN = ON // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
//Note:Connect MFRC522 module to 5v PIC without any Level converter .It'll work fine.
//Note:mfrc522 work in SPI slave mode(PIC is MASTER)
//mfrc522 connection PIN
#define CS RB2//mfrc 522 chip select pin(SS) to PIC pin3
//MFRC522 module RST pin to +3.3v
//MFRC522 module MOSI pin to PIC16f877 pin 24(RC5/SDO)
//MFRC522 module MISO pin to PIC16f877 pin 23(RC4/SDI)
//MFRC522 module SCK pin to PIC16f877 pin 18(RC3/SCK)
#include "MFRC522_driver.h"//mfrc 522 Driver
//spi modes
#define SPI_MODE_0 (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_1 (SPI_L_TO_H)
#define SPI_MODE_2 (SPI_H_TO_L)
#define SPI_MODE_3 (SPI_H_TO_L | SPI_XMIT_L_TO_H)
byte FoundTag; // Variable used to check if Tag was found
byte ReadTag; // Variable used to store anti-collision value to read Tag information
byte TagData[16]; // Variable used to store Full Tag Data
byte GoodTagSerialNumber[4] = {0x3D, 0xCA, 0x2B, 0x62}; // The Tag Serial number we are looking for
int i=0;
byte version;
int GoodTag=0; // Variable used to confirm good Tag Detected
void Get_UID()
{
// Get Tag UID
ReadTag = antiCollision(TagData);
Lcd_Clear();
Lcd_Set_Cursor(1,1);
char uid1[10];
char uid2[10];
for(i=0;i<=2;i++)/// display Tag UID in hexadecimal
{ sprintf(uid1,"%2X",TagData[i]);
Lcd_Print_String(uid1);}
sprintf(uid2,"%2X",TagData[i]);
Lcd_Print_String(uid2);
__delay_ms(500);
}
void Search_for_matching_Tag()
{
GoodTag=0;
for(int i=0; i <= 3; i++)
{
if (GoodTagSerialNumber[i] != TagData[i])
{
GoodTag=0;
break; // if not equal, then break out of the "for" loop
}
}
if (TagData[3]==GoodTagSerialNumber[3])
{
// if we made it to 4 loops then the Tag Serial numbers are matching
GoodTag=1;
}
Lcd_Set_Cursor(2,1);
if (GoodTag == 1)
{
Lcd_Print_String("Access Granted!");
__delay_ms(1500);
}
else
{
Lcd_Print_String("Access Denied!");
__delay_ms(1500);
GoodTag=0;
}
}
void Get_Chip_Version(){
while(1)
{
version = readFromRegister(VersionReg);
if(!version)
{
Lcd_Clear();
Lcd_Set_Cursor(1,1);
Lcd_Print_String("No Device");
__delay_ms(500);
}
if(version)
{
Lcd_Clear();
Lcd_Set_Cursor(1,1);
Lcd_Print_String("Device Found");
Lcd_Set_Cursor(2, 1);
char ver[10];
sprintf(ver,"ver:%2X",version);
Lcd_Print_String(ver);
__delay_ms(2500);
if(version==0x92|version==0x91)
{
Lcd_Clear();
Lcd_Set_Cursor(1,1);
Lcd_Print_String("Device : MFRC522");
Lcd_Set_Cursor(2,3);
Lcd_Print_String("V1.0 or V2.0");
__delay_ms(2000);
break;
}
}
}
}
void main()
{
TRISB=0;
TRISD=0;
//setup_spi(SPI_MASTER|SPI_MODE_0|SPI_CLK_DIV_64);
Lcd_Start();
Lcd_Clear();
__delay_ms(50);
MFRC_522_init(); //initialize SPI and MFRC522
Get_Chip_Version(); //print Firmwareverion on LCD
__delay_ms(2000);
while(1)
{
// Check to see if a Tag was detected
// If yes, then the variable FoundTag will contain "MI_OK"
Lcd_Clear();
Lcd_Set_Cursor(1,1);
Lcd_Print_String("Checking for Tag");
__delay_ms(1000);
FoundTag = requestTag(MF1_REQIDL, TagData);
if (FoundTag == MI_OK)
{
Lcd_Set_Cursor(2,1);
Lcd_Print_String("Tag Found");
__delay_ms(500);
Get_UID();
Search_for_matching_Tag();
__delay_ms(100);
}
else
{
Lcd_Set_Cursor(2,1);
Lcd_Print_String("No Tag Found E:");
Lcd_Print_Char(FoundTag+'0');
__delay_ms(500);
}
}
}
|
Library and Lcd Functions
Code: |
#include<xc.h>
#define _XTAL_FREQ 16000000
// MFRC522_Driver.h file
#define MAX_LEN 16 // Maximum length of an array. CHECK IF IT IS MAXIMUM LENGTH/SIZE OF FIFO!!!!!!!!!!!
//MF522 MFRC522 error codes.
#define MI_OK 0 // Everything A-OK.
#define MI_NOTAGERR 1 // No tag error
#define MI_ERR 2 // General error
//MF522 Command word
#define MFRC522_IDLE 0x00 // NO action; Cancel the current command
#define MFRC522_MEM 0x01 // Store 25 byte into the internal buffer.
#define MFRC522_GENID 0x02 // Generates a 10 byte random ID number.
#define MFRC522_CALCCRC 0x03 // CRC Calculate or selftest.
#define MFRC522_TRANSMIT 0x04 // Transmit data
#define MFRC522_NOCMDCH 0x07 // No command change.
#define MFRC522_RECEIVE 0x08 // Receive Data
#define MFRC522_TRANSCEIVE 0x0C // Transmit and receive data,
#define MFRC522_AUTHENT 0x0E // Authentication Key
#define MFRC522_SOFTRESET 0x0F // Reset
//Mifare_One tag command word
#define MF1_REQIDL 0x26 // find the antenna area does not enter hibernation
#define MF1_REQALL 0x52 // find all the tags antenna area
#define MF1_ANTICOLL 0x93 // anti-collision
#define MF1_SELECTTAG 0x93 // election tag
#define MF1_AUTHENT1A 0x60 // authentication key A
#define MF1_AUTHENT1B 0x61 // authentication key B
#define MF1_READ 0x30 // Read Block
#define MF1_WRITE 0xA0 // write block
#define MF1_DECREMENT 0xC0 // debit
#define MF1_INCREMENT 0xC1 // recharge
#define MF1_RESTORE 0xC2 // transfer block data to the buffer
#define MF1_TRANSFER 0xB0 // save the data in the buffer
#define MF1_HALT 0x50 // Sleep
//------------------ MFRC522 registers---------------
//Page 0:Command and Status
#define Reserved00 0x00
#define CommandReg 0x01
#define CommIEnReg 0x02
#define DivIEnReg 0x03
#define CommIrqReg 0x04
#define DivIrqReg 0x05
#define ErrorReg 0x06
#define Status1Reg 0x07
#define Status2Reg 0x08
#define FIFODataReg 0x09
#define FIFOLevelReg 0x0A
#define WaterLevelReg 0x0B
#define ControlReg 0x0C
#define BitFramingReg 0x0D
#define CollReg 0x0E
#define Reserved01 0x0F
//Page 1:Command
#define Reserved10 0x10
#define ModeReg 0x11
#define TxModeReg 0x12
#define RxModeReg 0x13
#define TxControlReg 0x14
#define TxAutoReg 0x15
#define TxSelReg 0x16
#define RxSelReg 0x17
#define RxThresholdReg 0x18
#define DemodReg 0x19
#define Reserved11 0x1A
#define Reserved12 0x1B
#define MifareReg 0x1C
#define Reserved13 0x1D
#define Reserved14 0x1E
#define SerialSpeedReg 0x1F
//Page 2:CFG
#define Reserved20 0x20
#define CRCResultRegM 0x21
#define CRCResultRegL 0x22
#define Reserved21 0x23
#define ModWidthReg 0x24
#define Reserved22 0x25
#define RFCfgReg 0x26
#define GsNReg 0x27
#define CWGsPReg 0x28
#define ModGsPReg 0x29
#define TModeReg 0x2A
#define TPrescalerReg 0x2B
#define TReloadRegH 0x2C
#define TReloadRegL 0x2D
#define TCounterValueRegH 0x2E
#define TCounterValueRegL 0x2F
//Page 3:TestRegister
#define Reserved30 0x30
#define TestSel1Reg 0x31
#define TestSel2Reg 0x32
#define TestPinEnReg 0x33
#define TestPinValueReg 0x34
#define TestBusReg 0x35
#define AutoTestReg 0x36
#define VersionReg 0x37
#define AnalogTestReg 0x38
#define TestDAC1Reg 0x39
#define TestDAC2Reg 0x3A
#define TestADCReg 0x3B
#define Reserved31 0x3C
#define Reserved32 0x3D
#define Reserved33 0x3E
#define Reserved34 0x3F
//-----------------------------------------------
#define byte unsigned char
#define RS RD2 //Reset pin of LCD
#define EN RD3 //Enable pin of LCD
#define D4 RD4 //Data bit 0 of LCD
#define D5 RD5 //Data bit 1 of LCD
#define D6 RD6 //Data bit 2 of LCD
#define D7 RD7 //Data bit 3 of LCD
// LCD Settings
void Lcd_SetBit(char data_bit) //Based on the Hex value Set the Bits of the Data Lines
{
if (data_bit & 1)
D4 = 1;
else
D4 = 0;
if (data_bit & 2)
D5 = 1;
else
D5 = 0;
if (data_bit & 4)
D6 = 1;
else
D6 = 0;
if (data_bit & 8)
D7 = 1;
else
D7 = 0;
}
void Lcd_Cmd(char a) {
RS = 0;
Lcd_SetBit(a); //Incoming Hex value
EN = 1;
__delay_ms(4);
EN = 0;
}
void Lcd_Clear() {
Lcd_Cmd(0); //Clear the LCD
Lcd_Cmd(1); //Move the cursor to first position
}
void Lcd_Set_Cursor(char a, char b) {
char temp, z, y;
if (a == 1) {
temp = 0x80 + b - 1; //80H is used to move the cursor
z = temp >> 4; //Lower 8-bits
y = temp & 0x0F; //Upper 8-bits
Lcd_Cmd(z); //Set Row
Lcd_Cmd(y); //Set Column
} else if (a == 2) {
temp = 0xC0 + b - 1;
z = temp >> 4; //Lower 8-bits
y = temp & 0x0F; //Upper 8-bits
Lcd_Cmd(z); //Set Row
Lcd_Cmd(y); //Set Column
}
}
void Lcd_Start() {
Lcd_SetBit(0x00);
// for(int i=1065244; i<=0; i--) NOP();
Lcd_Cmd(0x03);
__delay_ms(5);
Lcd_Cmd(0x03);
__delay_ms(50); //changed from 11
Lcd_Cmd(0x03);
Lcd_Cmd(0x02); //02H is used for Return home -> Clears the RAM and initializes the LCD
Lcd_Cmd(0x02); //02H is used for Return home -> Clears the RAM and initializes the LCD
Lcd_Cmd(0x08); //Select Row 1
Lcd_Cmd(0x00); //Clear Row 1 Display
Lcd_Cmd(0x0C); //Select Row 2
Lcd_Cmd(0x00); //Clear Row 2 Display
Lcd_Cmd(0x06);
}
void Lcd_Print_Char(char data) //Send 8-bits through 4-bit mode
{
char Lower_Nibble, Upper_Nibble;
Lower_Nibble = data & 0x0F;
Upper_Nibble = data & 0xF0;
RS = 1; // => RS = 1
Lcd_SetBit(Upper_Nibble >> 4); //Send upper half by shifting by 4
EN = 1;
//for(int i=2130483; i<=0; i--) NOP();
EN = 0;
Lcd_SetBit(Lower_Nibble); //Send Lower half
EN = 1;
// for(int i=2130483; i<=0; i--) NOP();
EN = 0;
}
void Lcd_Print_String(char *a) {
int i;
for (i = 0; a[i] != '\0'; i++)
Lcd_Print_Char(a[i]); //Split the string using pointers and call the Char function
}
/*
void spi_write(byte value )
{
SSPBUF = dat;
}
byte spiRead() //REad the received data
{
while ( !SSPSTATbits.BF ); // Wait for Data Receive complete
return(SSPBUF); // read the received data from the buffer
}
*/
/**
Section: Macro Declarations
*/
/**
Section: Module APIs
*/
void SPI_Initialize(void) {
TRISC5 = 0;
TRISC4=1;
SSPSTAT =0b00000000; //| 0b00000000;// sDataSample | sTransmitEdge;
TRISC3 = 0;
SSPCON = 0b00110001; //| 0b00010010;//sType | sClockIdle,fosc/64;
}
byte SPI_Exchange8bit(byte data) {
// Clear the Write Collision flag, to allow writing
SSPCONbits.WCOL = 0;
SSPBUF = data;
while (SSPSTATbits.BF == 0) {
}
return (SSPBUF);
}
byte SPI_Exchange8bitBuffer(byte *dataIn, byte bufLen, byte *dataOut) {
int bytesWritten = 0;
if (bufLen != 0) {
if (dataIn != NULL) {
while (bytesWritten < bufLen) {
if (dataOut == NULL) {
SPI_Exchange8bit(dataIn[bytesWritten]);
} else {
dataOut[bytesWritten] = SPI_Exchange8bit(dataIn[bytesWritten]);
}
bytesWritten++;
}
} else {
if (dataOut != NULL) {
while (bytesWritten < bufLen) {
dataOut[bytesWritten] = SPI_Exchange8bit(0x00);
bytesWritten++;
}
}
}
}
return bytesWritten;
}
//Reads the value at a register.
byte readFromRegister(byte addr) {
byte val;
//output_low(CS);
CS=0;
__delay_us(10);
//spi_write(((addr<<1)&0x7E) | 0x80);
byte temp = SPI_Exchange8bit(((addr<<1)&0x7E) | 0x80);
__delay_us(100);
//val =spi_read(0x00);
val= SPI_Exchange8bit(0x00);
//output_high(CS);
CS=1;
return val;
}
//writes Values to specified registers.
void writeToRegister(byte addr, byte val) {
//output_low(CS);
CS=0;
__delay_us(10);
//Address format: 0XXXXXX0
//spi_write((addr<<1)&0x7E);
byte temp = SPI_Exchange8bit(((addr<<1)&0x7E) | 0x80);
__delay_us(10);
// spi_write(val);
byte temp2 = SPI_Exchange8bit(val);
CS=1;
//output_high(CS);
}
//Mask to update registers
void setBitMask(byte addr, byte mask) {
byte current;
current = readFromRegister(addr);
writeToRegister(addr, current | mask);
}
//remove bitmask maybe not necessary
void clearBitMask(byte addr, byte mask) {
byte current;
current = readFromRegister(addr);
writeToRegister(addr, current & (~mask));
}
//Initialize RFID Reader
//Does the setup for the MFRC522.
void reset() {
writeToRegister(CommandReg, MFRC522_SOFTRESET);
}
void MFRC_522_init() {
//output_high(CS);
SPI_Initialize();
CS=1;
//software reset
reset();
//Timer: TPrescaler*TreloadVal/6.78MHz = 24ms
writeToRegister(TModeReg, 0x8D);
__delay_ms(20);// Tauto=1; f(Timer) = 6.78MHz/TPreScaler
writeToRegister(TPrescalerReg, 0x3E); // TModeReg[3..0] + TPrescalerReg
__delay_ms(20);
writeToRegister(TReloadRegL, 30);
__delay_ms(20);
writeToRegister(TReloadRegH, 0);
__delay_ms(20);
writeToRegister(TxAutoReg, 0x40); // 100%ASK
__delay_ms(20);
writeToRegister(ModeReg, 0x3D); // CRC initial value 0x6363
__delay_ms(20);
//writeToRegister(TxControlReg, 0x82);
__delay_ms(20);
byte temp0 = readFromRegister(TxControlReg);
if (!(temp0 & 0x03))
{
setBitMask(TxControlReg, 0x03);
}
Lcd_Clear();
Lcd_Set_Cursor(1,3);
Lcd_Print_String("Init Done...");
__delay_ms(1500);
//setBitMask(TxControlReg, 0x03); // Turn antenna on.
}
//Checking MFRC522 Firmwareversion
byte getFirmwareVersion() {
byte response;
response = readFromRegister(VersionReg);
return response;
}
/**************************************************************************/
/*!
@brief Sends a command to a tag.
@param cmd The command to the MFRC522 to send a command to the tag.
@param data The data that is needed to complete the command.
@param dlen The length of the data.
@param result The result returned by the tag.
@param rlen The number of valid bits in the resulting value.
@returns Returns the status of the calculation.
MI_ERR if something went wrong,
MI_NOTAGERR if there was no tag to send the command to.
MI_OK if everything went OK.
*/
/**************************************************************************/
int commandTag(byte cmd, byte *data, int dlen, byte *result, int *rlen) {
int status = MI_ERR;
byte irqEn = 0x00;
byte waitIRq = 0x00;
byte lastBits, n;
int i;
switch (cmd) {
case MFRC522_AUTHENT:
irqEn = 0x12;
waitIRq = 0x10;
break;
case MFRC522_TRANSCEIVE:
irqEn = 0x77;
waitIRq = 0x30;
break;
default:
break;
}
writeToRegister(CommIEnReg, irqEn|0x80); // interrupt request
clearBitMask(CommIrqReg, 0x80); // Clear all interrupt requests bits.
setBitMask(FIFOLevelReg, 0x80); // FlushBuffer=1, FIFO initialization.
writeToRegister(CommandReg, MFRC522_IDLE); // No action, cancel the current command.
// Write to FIFO
for (i=0; i < dlen; i++) {
writeToRegister(FIFODataReg, data[i]);
}
// Execute the command.
writeToRegister(CommandReg, cmd);
if (cmd == MFRC522_TRANSCEIVE) {
setBitMask(BitFramingReg, 0x80); // StartSend=1, transmission of data starts
}
// Waiting for the command to complete so we can receive data.
i = 25; // Max wait time is 25ms.
do {
__delay_ms(1);
// CommIRqReg[7..0]
// Set1 TxIRq RxIRq IdleIRq HiAlerIRq LoAlertIRq ErrIRq TimerIRq
n = readFromRegister(CommIrqReg);
i--;
} while ((i!=0) && !(n&0x01) && !(n&waitIRq));
clearBitMask(BitFramingReg, 0x80); // StartSend=0
if (i != 0) { // Request did not time out.
if(!(readFromRegister(ErrorReg) & 0x1D)) { // BufferOvfl Collerr CRCErr ProtocolErr
status = MI_OK;
if (n & irqEn & 0x01) {
status = MI_NOTAGERR;
}
if (cmd == MFRC522_TRANSCEIVE) {
n = readFromRegister(FIFOLevelReg);
lastBits = readFromRegister(ControlReg) & 0x07;
if (lastBits) {
*rlen = (n-1)*8 + lastBits;
} else {
*rlen = n*8;
}
if (n == 0) {
n = 1;
}
if (n > MAX_LEN) {
n = MAX_LEN;
}
// Reading the recieved data from FIFO.
for (i=0; i<n; i++) {
result[i] = readFromRegister(FIFODataReg);
}
}
} else {
status = MI_ERR;
}
}
return status;
}
/**************************************************************************/
/*
@brief Checks to see if there is a tag in the vicinity.
@param mode The mode we are requsting in.
@param type If we find a tag, this will be the type of that tag.
0x4400 = Mifare_UltraLight
0x0400 = Mifare_One(S50)
0x0200 = Mifare_One(S70)
0x0800 = Mifare_Pro(X)
0x4403 = Mifare_DESFire
@returns Returns the status of the request.
MI_ERR if something went wrong,
MI_NOTAGERR if there was no tag to send the command to.
MI_OK if everything went OK.
*/
/**************************************************************************/
int requestTag(byte mode, byte *data) {
int status, len;
writeToRegister(BitFramingReg, 0x07); // TxLastBists = BitFramingReg[2..0]
data[0] = mode;
status = commandTag(MFRC522_TRANSCEIVE, data, 1, data, &len);
if ((status != MI_OK) || (len != 0x10)) {
status = MI_ERR;
}
return status;
}
/**************************************************************************/
/*!
@brief Handles collisions that might occur if there are multiple
tags available.
@param serial The serial nb of the tag.
@returns Returns the status of the collision detection.
MI_ERR if something went wrong,
MI_NOTAGERR if there was no tag to send the command to.
MI_OK if everything went OK.
*/
/**************************************************************************/
int antiCollision(byte *serial) {
int status, i, len;
byte check = 0x00;
writeToRegister(BitFramingReg, 0x00); // TxLastBits = BitFramingReg[2..0]
serial[0] = MF1_ANTICOLL;
serial[1] = 0x20;
status = commandTag(MFRC522_TRANSCEIVE, serial, 2, serial, &len);
len = len / 8; // len is in bits, and we want each byte.
if (status == MI_OK) {
// The checksum of the tag is the ^ of all the values.
for (i = 0; i < len-1; i++) {
check ^= serial[i];
}
// The checksum should be the same as the one provided from the
// tag (serial[4]).
if (check != serial[i]) {
status = MI_ERR;
}
}
return status;
}
/**************************************************************************/
/*!
@brief Calculates the CRC value for some data that should be sent to
a tag.
@param data The data to calculate the value for.
@param len The length of the data.
@param result The result of the CRC calculation.
*/
/**************************************************************************/
void calculateCRC(byte *data, int len, byte *result) {
int i;
byte n;
clearBitMask(DivIrqReg, 0x04); // CRCIrq = 0
setBitMask(FIFOLevelReg, 0x80); // Clear the FIFO pointer
//Writing data to the FIFO.
for (i = 0; i < len; i++) {
writeToRegister(FIFODataReg, data[i]);
}
writeToRegister(CommandReg, MFRC522_CALCCRC);
// Wait for the CRC calculation to complete.
i = 0xFF;
do {
n = readFromRegister(DivIrqReg);
i--;
} while ((i != 0) && !(n & 0x04)); //CRCIrq = 1
// Read the result from the CRC calculation.
result[0] = readFromRegister(CRCResultRegL);
result[1] = readFromRegister(CRCResultRegM);
} |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Jul 23, 2019 7:20 pm |
|
|
The code library post shows the spi setup should be like this for CCS:
Code: | setup_spi(SPI_MASTER|SPI_MODE_0|SPI_CLK_DIV_16);
|
You have this spi setup:
Quote: | void SPI_Initialize(void) {
TRISC5 = 0;
TRISC4 = 1;
SSPSTAT =0b00000000; // 0x00
TRISC3 = 0;
SSPCON = 0b00110001; // 0x31
} |
Here are the Spi register values for each mode, for clock divisor 16:
Code: |
SPI Mode SSPCON SSPSTAT
0 0x21 0x40
1 0x21 0x00
2 0x31 0x40
3 0x31 0x00
|
From the table above, we can see that you have set it up for SPI mode 3.
But the original post in the Code Library uses spi mode 0. Based on the
MFRC522 data sheet, I think it might work with Mode 3, but that's not
what the original post has. You should try to duplicate the original post
as closely as possible. |
|
|
bharath0209
Joined: 23 Jul 2019 Posts: 7
|
|
Posted: Tue Jul 23, 2019 10:18 pm |
|
|
Yeah. I'm sorry I didn't mention this.
But I have tried all the modes changing the SSPCON and SSPSTAT registers.
This is just the last one I've tried. |
|
|
bharath0209
Joined: 23 Jul 2019 Posts: 7
|
|
Posted: Wed Jul 24, 2019 6:05 am |
|
|
UPDATE
Found the error in Register write function where I forgot to remove "| 0x80" which is only to read.
After that, it is working in mode 3 of spi and not in mode 1.
Now, it detects the tags and again had some trouble in reading the UID of tags.
It is giving MI_NOTAGERROR as a result with Anticollision function which is called only after it detects tag.
Tried with many different tags, but shows same error.
I really appreciate your time in looking into the code earlier.
If you didn't point out the mode, I may take even more time to find the bug. |
|
|
bharath0209
Joined: 23 Jul 2019 Posts: 7
|
|
Posted: Thu Jul 25, 2019 5:44 am |
|
|
New UPDATE
I finally got it to work with different tags.
I had to change the Receiver gain to 38db and increase the supply voltage to 3.7 volts for it to work perfectly.
-Thanks. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|