|
|
View previous topic :: View next topic |
Author |
Message |
ariahope
Joined: 05 Jun 2014 Posts: 7
|
13MHz RFID |
Posted: Thu Jun 05, 2014 2:39 pm |
|
|
Hi,
I work with RFID reader and writer 13MHz, MFRC522 from NXP.
At first I read and write internal register of it with SPI protocol without any problem it work very good.
As mentioned in "AN10833 MIFARE Type Identification Procedure" now I want to send "Request Command, TypeA" (REQA) and pickup "Answer to Request" from RFID TAG 1k, but I didn't read anything.
Code: | #include <18F26K20.h>
#device adc=10
#FUSES NOWDT //No Watch Dog Timer
#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOXINST //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES HS
#use delay(clock=20000000)
#use FIXED_IO( B_outputs=PIN_B0 )
#define CS PIN_B0
//
#use FIXED_IO( A_outputs=PIN_A5 )
#define LED PIN_A5
//
//UART SETUP
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
//
//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)
//
void main()
{
port_b_pullups(TRUE);
//adc
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
//end of adc
//watchdog
setup_wdt(WDT_OFF);
//
//SPI
setup_spi(SPI_MASTER|SPI_MODE_0|SPI_CLK_DIV_4);//ya 1 ya 2
//end of SPI
int8 value[2];
int t,j=1;
delay_ms(1000);
printf("hello MFRC522\r\n");
while(j<=3)
{
if(j<4)
{
j++;
output_low(LED);
}
//**1.PERFORM A SOFT RESET**\\
output_low(CS);
spi_write(0x02);//WRITE ON CONFIGREG
delay_ms(10);
Spi_write(0x2F);//WRITE VALUE ON CONFIGREG
delay_ms(10);
output_high(CS);
delay_ms(100);
//**END OF SOFT RESET**\\
//**read operation only**\\
output_low(CS);
spi_write(0xA9);//0xa9 TxControlReg// 0x94 for FIFO levelReg// 0xEC for AutoTest REG//8c error//0x82setup Status1Reg0x8E for reading
delay_ms(10);
value[0]=spi_read(0);// reading from Status1Reg
delay_ms(10);
printf("TxControlReg0=%X\r\n",value[0]);
output_high(CS);
delay_ms(300);
//**end of read operation only**\\
//**turn on the antenna by enabling PINs TX1 and TX2. After a reset these pins disabled**\
output_low(CS);
spi_write(0x29);//WRITE ON TxControlReg
delay_ms(10);
Spi_write(0x83);//WRITE VALUE ON TxControlReg
delay_ms(10);
output_high(CS);
delay_ms(100);
//**End of turn on the antenna by enabling PINs TX1 and TX2 **\\
//**read operation only**\\
output_low(CS);
spi_write(0xA9);//0xa9 TxControlReg// 0x94 for FIFO levelReg// 0xEC for AutoTest REG//8c error//0x82setup Status1Reg0x8E for reading
delay_ms(10);
value[0]=spi_read(0);// reading from Status1Reg
delay_ms(10);
printf("TxControlReg1=%X\r\n",value[0]);
output_high(CS);
delay_ms(300);
//**end of read operation only**\\
//**Write 26h to the FIFO buffer**\
output_low(CS);
spi_write(0x12);//WRITE ON FIFODATAREG
delay_ms(10);
Spi_write(0x26);
delay_ms(10);
output_high(CS);
delay_ms(100);
//**End of Write 26h to the FIFO buffer**\\
//**read FIFOlevelREG
output_low(CS);
spi_write(0x94);//0x94 for FIFO levelReg// 0xEC for AutoTest REG//8c error//0x82setup Status1Reg0x8E for reading
delay_ms(10);
value[0]=spi_read(0);// reading from FIFOlevelREG
delay_ms(10);
printf("FIFOlevelReg0=%X\r\n",value[0]);
output_high(CS);
delay_ms(300);
//**end of reading FIFOlevelREG
//**Enable Transceive Mode**\\
output_low(CS);
spi_write(0x02);//WRITE ON CONFIGREG
delay_ms(10);
Spi_write(0x2C);//WRITE VALUE ON CONFIGREG
delay_ms(10);
output_high(CS);
delay_ms(100);
//**End of Transceive Mode**\\
//**read FIFOlevelREG
output_low(CS);
spi_write(0x94);//0x94 for FIFO levelReg// 0xEC for AutoTest REG//8c error//0x82setup Status1Reg0x8E for reading
delay_ms(10);
value[0]=spi_read(0);// reading from FIFOlevelREG
delay_ms(10);
printf("FIFOlevelReg2=%X\r\n",value[0]);
output_high(CS);
delay_ms(300);
//**end of reading FIFOlevelREG
//**send data by set BitframingReg**\
output_low(CS);
spi_write(0x1A);//WRITE ON BitframingReg
delay_ms(10);
Spi_write(0x80);//WRITE VALUE ON BitframingReg
delay_ms(10);
output_high(CS);
delay_ms(100);
//**end of send data setting**\
output_low(CS);
spi_write(0x94);//0x94 for FIFO levelReg// 0xEC for AutoTest REG//8c error//0x82setup Status1Reg0x8E for reading
delay_ms(10);
value[0]=spi_read(0);// reading from Status1Reg
delay_ms(10);
printf("FIFOlevelReg1=%X\r\n",value[0]);
output_high(CS);
delay_ms(300);
//**read operation only**\\
//**read 2byte from FIFO Buffer**\
for(t=1;t<=2;++t)
{
output_low(CS);
spi_write(0x92);//setup Status1Reg0x8E for reading
delay_ms(10);
value[1]=spi_read(0);// reading from Status1Reg
delay_ms(10);
printf("FIFO[%d]=%X\r\n",t,value[1]);
output_high(CS);
}
//**read 2byte from FIFO Buffer**\
output_low(CS);
spi_write(0x91);//0x91 Status2Reg//0xa9 TxControlReg// 0x94 for FIFO levelReg// 0xEC for AutoTest REG//8c error//0x82setup Status1Reg0x8E for reading
delay_ms(10);
value[0]=spi_read(0);// reading from Status1Reg
delay_ms(10);
printf("Status2Reg=%X\r\n",value[0]);
output_high(CS);
delay_ms(300);
//**end of read operation only**\\
}
} |
any help would be greatly appreciated |
|
|
ariahope
Joined: 05 Jun 2014 Posts: 7
|
|
Posted: Fri Jun 06, 2014 4:21 am |
|
|
ANY Idea Ttelmah , PCM Programmer and ... ? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Fri Jun 06, 2014 8:44 am |
|
|
Seriously I stopped looking when I saw you repeating code, rather than using routines to do the jobs. I suspect many others did the same. |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Fri Jun 06, 2014 9:11 am |
|
|
Reduce your code to 10 lines or so, then we may be tempted to have a look at it.
I, for one, will not bother to scroll down several screens full.
Mike
PS.
Your code must also be complete and compilable, otherwise you are wasting time. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Fri Jun 06, 2014 9:16 am |
|
|
I had the same problem. The program is difficult to understand because it is one large blob of code.
I suggest to Ariahope to split the program in multiple functions. For starters, a function to write to the external chip and another function for reading.
One golden rule is that a function should never be more than 40 lines of code, this is what normal people can keep track of in memory. This means that when your program get larger you will have to split it up into more functions. |
|
|
ariahope
Joined: 05 Jun 2014 Posts: 7
|
|
Posted: Fri Jun 06, 2014 2:27 pm |
|
|
Hi I am sorry for long code, i summarize my code and explain it below:
this is my steps;
in summary at first I reset MFRC522 then I turn on antenna in step3,4 and 5 I send REQuest command, Type A (0x26) to Mifare CARD and then in step 6 I wait for Answer To reQuest, Type A
//**1.PERFORM A SOFT RESET**\\
//**2.turn on the antenna by enabling PINs TX1 and TX2. After a reset these pins disabled**\
//**3.Write 26h to the FIFO buffer**\
//**4.Enable Transceive Mode**\\
//**5.send data by set BitframingReg**\
//**6.read from FIFO Buffer**\ |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Sat Jun 07, 2014 1:44 am |
|
|
You are missing the point.
It's to do with program structure.
Have two simple routines. One to write a byte/bytes to a numbered register. One to read a byte/bytes from a numbered register.
Then your main code just becomes half a dozen lines calling these routines.
So routines like:
Code: |
#include <18F26K20.h>
#device adc=10
#FUSES NOWDT //No Watch Dog Timer
#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOXINST //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES HS
#use delay(clock=20000000)
#define CS PIN_B0
#define LED PIN_A5
//UART SETUP
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
//
//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)
//
#define READFLAG 0x80 //bits for direction control on SPI commands
#define WRITEFLAG 0
//routine to read 'numbytes' bytes, from registers starting at 'address'
void read_block(int8 address, int8* data, int8 numbytes)
{
int8 icount;
int8 itemp;
output_low(CS); //select chip
for (icount=0;icount<=numbytes;icount++) //one more transfer than bytes
{
itemp=spi_read(address++*2 | READFLAG); //top bit set for a read
if (icount!=0)
{
*data++=itemp;
}
}
output_low(CS);
}
//routine to write 'numbytes' bytes to registers starting at 'address'
void write_block(int8 address, int8* data, int8 numbytes)
{
int8 icount;
int8 itemp;
output_low(CS); //select chip
for (icount=0;icount<=numbytes;icount++) //one more transfer than bytes
{
if (icount==0)
itemp=spi_read(address++*2|WRITEFLAG);
else
itemp=spi_read(*data++);
}
output_low(CS);
}
void main()
{
int8 block[8]; //Keep to C. Declare variables at the start of code blocks
port_b_pullups(TRUE);
//adc
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
//end of adc
//watchdog
setup_wdt(WDT_OFF);
//
//SPI
setup_spi(SPI_MASTER|SPI_MODE_0|SPI_CLK_DIV_4);//ya 1 ya 2
//end of SPI
delay_ms(1000);
printf("hello MFRC522\r\n");
output_low(LED); //counter seems pointless
//Then you just setup the array for output with the data required
//and access the registers.....
//I'd #define the register names you want to use - reduces errors.
|
Now there are major problems with your code beyond this.
The very first thing you do, you say 'write on CONFIGREG'. You send '2', which is register address '1' (register numbers are doubled went sent to the chip). You then send '2F' to this. So you are sending 00101111. If you look at the command register bit description, this turns off the analog part of the receiver....
Also on these commands you should wait till the chip says it is ready. You do this by reading the register after writing it, and waiting for bit 4 to go low. Your long delays probably avoid the need for this, but it's better to use the signal the chip gives you.
So:
Code: |
#define COMMANDREG 1
block[0]=0x2F; //if this is right.....
write_block(COMMANDREG,block,1); //write one byte chip
do
{
read_block(COMMANDREG,block,1); //read register
} while (bit_test(block[0],4)==1); //wait for 'power down' to go off
|
Then there are problems later. All 'address bytes' sent to the chip end with '0' (since they are multiplied by 2). Yet you have 29, and A9, as addresses being sent. Not possible. |
|
|
ariahope
Joined: 05 Jun 2014 Posts: 7
|
|
Posted: Sun Jun 08, 2014 12:59 pm |
|
|
Hi Ttelmah like every time thank you alot,
I have some simple question
Quote: | //routine to read 'numbytes' bytes, from registers starting at 'address'
void read_block(int8 address, int8* data, int8 numbytes)
{
int8 icount;
int8 itemp;
output_low(CS); //select chip
for (icount=0;icount<=numbytes;icount++) //one more transfer than bytes
{
itemp=spi_read(address++*2 | READFLAG); //top bit set for a read
if (icount!=0)
{
*data++=itemp;
}
}
output_low(CS);
} |
what does the difference between int8 and int8*?
and also what does *data mean?
why you don't use spi_write function?
excuse me for my simple question, I am beginner,
best regards. |
|
|
ariahope
Joined: 05 Jun 2014 Posts: 7
|
|
Posted: Sun Jun 08, 2014 2:46 pm |
|
|
Hi, I hope I got what you said, I changed my code. because I just want to read Card Answer and nothing to do with it in this first phase I do all setup in a true while, this is my new code:
Code: | #include <18F26K20.h>
#device adc=10
#FUSES NOWDT //No Watch Dog Timer
#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOXINST //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES HS
#use delay(clock=20000000)
#use FIXED_IO( B_outputs=PIN_B0 )
#define CS PIN_B0
//
#use FIXED_IO( A_outputs=PIN_A5 )
#define LED PIN_A5
//
//UART SETUP
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
//
//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)
//
#define CommandReg 0x01
#define status1Reg 0x07
#define status2Reg 0x08
#define FIFODataReg 0x09
#define FIFOLevelReg 0x0A
#define TxControlReg 0x14
#define BitframingReg 0x0D
//write register Function
void write_reg(int8 address,int8 value)
{
output_low(CS);
spi_write((address*2));
delay_ms(10);
spi_write(value);
delay_ms(10);
output_high(CS);
}
//end of write register
//read register Function and aslso printf it's value
void read_reg(int8 address,int8 numbyte)
{
int8 read_data;
int8 counter;
for(counter=1;counter<=numbyte;++counter)
{
output_low(CS);
spi_write((address*2)+0x80);
delay_ms(10);
read_data=spi_read(0);// reading from reg
delay_ms(10);
printf("address%X byte[%d]=%X\r\n",address,counter,read_data);
output_high(CS);
}
}
//end of read register and printf it's value
void main()
{
port_b_pullups(TRUE);
//adc
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
//end of adc
//watchdog
setup_wdt(WDT_OFF);
//
//SPI
setup_spi(SPI_MASTER|SPI_MODE_0|SPI_CLK_DIV_4);//ya 1 ya 2
//end of SPI
int8 t=1;
delay_ms(1000);
//**.PERFORM A SOFT RESET**\\
write_reg(CommandReg,0x2F);
//**END OF SOFT RESET**\\
//Clear the internal buffer by writing 64 bytes of 00h and implement the Config command
for(t=1;t<=64;t++)
{
write_reg(FIFODataReg,0x00);
}
while(true)
{
delay_ms(2000);
printf("************\r\n");
printf("Start\r\n");
printf("************\r\n");
output_toggle(PIN_A5);
//**.PERFORM A SOFT RESET**\\
write_reg(CommandReg,0x2F);
//**END OF SOFT RESET**\\
//**turn on the antenna by enabling PINs TX1 and TX2. After a reset these pins disabled**\
write_reg(TxControlReg,0x83);
//**End of turn on the antenna by enabling PINs TX1 and TX2 **\\
//send request command to FIFO
write_reg(FIFODataReg,0x26);
//end
//**Enable Transceive Mode**\\
write_reg(CommandReg,0x2C);
//**End of Transceive Mode**\\
//**send data by set BitframingReg**\
write_reg(BitframingReg,0x80);
//**end of send data setting**\
read_reg(FIFODataReg,2);
printf("************\r\n");
printf("End\r\n");
printf("************\r\n");
}
} |
also here is Arduino library and example but it is very complicated for me.
https://github.com/miguelbalboa/rfid
all the best,
Ariahope
Last edited by ariahope on Sun Jun 08, 2014 11:35 pm; edited 1 time in total |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jun 08, 2014 4:03 pm |
|
|
In your first code, you use 0x83 to turn on the antenna:
Quote: | //**turn on the antenna by enabling PINs TX1 and TX2. After a reset these pins disabled**\
output_low(CS);
spi_write(0x29);//WRITE ON TxControlReg
delay_ms(10);
Spi_write(0x83);//WRITE VALUE ON TxControlReg
delay_ms(10);
output_high(CS);
delay_ms(100); |
In your latest code you have dropped the 0x and changed it to 83 decimal.
Quote: |
//**turn on the antenna by enabling PINs TX1 and TX2. After a reset these pins disabled**\
write_reg(TxControlReg,83);
//**End of turn on the antenna by enabling PINs TX1 and TX2 **\\ |
These are not the same number. Attention to detail is important.
You can't write successful code without it. |
|
|
ariahope
Joined: 05 Jun 2014 Posts: 7
|
|
Posted: Sun Jun 08, 2014 11:38 pm |
|
|
Quote: | In your first code, you use 0x83 to turn on the antenna.
In your latest code you have dropped the 0x and changed it to 83 decimal. |
Hi PCM Programmer it was my fault I corrected it. but it doesn't work yet. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Mon Jun 09, 2014 12:15 am |
|
|
Basic C here. int8, is an int8
int8 *, is the _address_ of an int8. A pointer.
This really is basic C. You need to go through a C primer, before trying to program.
*data is the byte _addressed by_ the address 'data'.
This is one of the standard ways to allow you to access data in a 'calling' function from a 'called' function. Hand the address of a byte or in this case an array of bytes (in C there is a 'shortcut', that the name of an array _is_ it's address), and then just take data from or put data back into the array.
I use spi_read, rather than spi_write, since spi_read writes the byte, and returns the byte clocked out. Doing this ensures you are writing the byte and getting the byte back. For the 'write' operations not much difference, but using the read function, ensures there is not a byte 'left' in the register.
As I have already pointed out 'register addresses' as sent, always end in with a zero bit.
0x29, does not.
The format is
R/W address 0
Where R/W is 0/1 for read/write, and the address is a six bit address.
The TX control register is register 0x14. Doubling this gives 0x28 that needs to be sent, not 0x29.....
I was being 'generic', since I can see you needing to send more than one byte, but for the simple code as posted, just reading and writing one byte, use:
Code: |
#define READFLAG 0x80
//routine to write one byte to a register
void write_reg(int8 address, int8 data)
{
int8 itemp;
output_low(CS); //select chip
itemp=spi_read(address*2);
itemp=spi_read(data);
output_low(CS);
}
//routine to read one byte from a register
int8 read_reg(int8 address)
{
int8 itemp;
output_low(CS); //select chip
itemp=spi_read((address*2) | READFLAG); //top bit set for a read
itemp=spi_read(0);
}
output_low(CS);
return(itemp);
}
|
As a general comment, get rid of the fixed_io and tris commands. For 99% of use, the compiler handles the tris better than you.
The start of your main then goes:
Code: |
#define CONFIGREG 1
#define TXCONTROL 0x14
//etc.
void main()
{
int8 value[2];
int t,j=1;
port_b_pullups(TRUE);
//adc
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
//end of adc
//watchdog
setup_wdt(WDT_OFF);
//
//SPI
setup_spi(SPI_MASTER|SPI_MODE_0|SPI_CLK_DIV_4);//ya 1 ya 2
//end of SPI
output_high(CS); //you need to ensure this starts high
delay_ms(1000);
printf("hello MFRC522\r\n");
output_low(LED);
//**1.PERFORM A SOFT RESET**\\
write_reg(CONFIGREG, 0x2F);
while (bit_test(read_reg(CONFIGREG),4)==1)) //test bit four
;
//wait for chip to go ready
//etc.....
|
If you perform an spi_write, and then follow this with an spi_read, the read will return the value clocked 'back' during the write. spi_read(val), does both operations in one command, performing a write and a read.
It makes read the easier and safer command to use for all spi operations, just throw away the dummy byte returned during the first read.
Only real change functionally is using the data returned to actually see the chip is ready.
Key thing though is that several of your values are wrong.
Use #defines as I show, and let the compiler do the *2. Much safer!. |
|
|
ariahope
Joined: 05 Jun 2014 Posts: 7
|
|
Posted: Tue Jun 10, 2014 2:33 am |
|
|
Hi Ttelmah,
your advises was great, really thanks.
in my second code I changed my basic problem did you see it? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Tue Jun 10, 2014 9:00 am |
|
|
Note the way I wait for the chip to wake. Most commands don't need this, but the wake up does.
You have a sort of 'half multi byte' read, where you are specifying a number of bytes to read, but loop reading the same byte. |
|
|
|
|
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
|