|
|
View previous topic :: View next topic |
Author |
Message |
mirno
Joined: 16 Jan 2015 Posts: 6
|
RFID using I2C |
Posted: Fri Jan 16, 2015 9:12 am |
|
|
Hello,
I am trying to make my RFID M24LR16E chip working, but it won't.
I already tries a lot of things, and i can't find out what the problem is. This is the latest program:
Code: |
#include <16F887.h>
#use delay(clock=8000000)
#fuses HS,WDT,INTRC_IO,PUT, NOLVP
//set up i2c peripheral and use hardware SSP
#use i2c(Master,sda=PIN_C4,scl=PIN_C3,RESTART_WDT)
//#use i2c(Master,sda=PIN_C4,scl=PIN_C3,RESTART_WDT) //aangepast 1-12-2014
//int array[1] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
//#int_SSP
#include "flex_lcd.c"
#define SLAVE_ADDRESS 0x6A
/*SSP_isr()
{ //communicate every 50 ms
i2c_start(); //set i2c to start condition
i2c_write(0x04); //send address
i2c_write(0x55); //send master data from port B bits
i2c_start(); //restart to change data direction
i2c_write(0x05); //address with direction bit changed
// lcd_init();
// lcd_putc(~i2c_read(0));
output_d(~i2c_read(0)); //get slave data and display
i2c_stop(); //stop i2c activity
}*/
void main()
{
int data[5];
int verdieping = 0;
unsigned char rx_byte;
//#BYTE OSCCON = 0b0111111;
setup_adc_ports(NO_ANALOGS);
// CM2CON0 &= 0x1111111;
setup_comparator(NC_NC_NC_NC);
setup_counters(RTCC_INTERNAL,WDT_1152MS);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
port_b_pullups(FALSE); //pull ups for input pins
//enable_interrupts(INT_SSP);
//enable_interrupts(global);
lcd_init();
lcd_putc("\fHello World\n");
while(1)
{
i2c_start();
delay_ms(50);
~i2c_write (SLAVE_ADDRESS); /* Device Address */
delay_ms(50);
// ~i2c_write(0x05);
delay_ms(50);
// i2c_write(12);
delay_ms(100);
i2c_start(); // restart condition
~i2c_write(SLAVE_ADDRESS + 1);
rx_byte = ~i2c_read(0);
if (rx_byte > 0x00 )
{
lcd_init();
lcd_putc("Bigger than 0x00 \n");
// printf ("rx_byte = 0x%2.2X\r\n", rx_byte);
}
else
{
lcd_init();
lcd_putc("0x00 \n");
}
i2c_stop();
}
}
|
We still get as return 0xFF, And now 0x00 because we inverted it, as a try.
Here is the datasheet: http://www.st.com/web/en/resource/technical/document/datasheet/DM00031737.pdf
I can't really find out what the slave address is, i think it is 0x6A because i read it in some forums. Maybe the RFID chip is locked or something?
If anyone can give me a little help with this one, for getting started i will really appreciate it.
Greeting,
Mirno |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Jan 16, 2015 10:54 am |
|
|
Quote: |
I can't really find out what the slave address is, i think it is 0x6A because i
read it in some forums. |
Use this i2c bus scanner program to see if it detects the M24LR16E:
http://www.ccsinfo.com/forum/viewtopic.php?t=49713
If it detects the chip, it will tell you the address it found. |
|
|
mirno
Joined: 16 Jan 2015 Posts: 6
|
|
Posted: Sat Jan 17, 2015 7:43 am |
|
|
PCM programmer wrote: | Quote: |
I can't really find out what the slave address is, i think it is 0x6A because i
read it in some forums. |
Use this i2c bus scanner program to see if it detects the M24LR16E:
http://www.ccsinfo.com/forum/viewtopic.php?t=49713
If it detects the chip, it will tell you the address it found. |
That is Great!
I will try it,
But instead of the printf command i will use something for the LCD_unit. I think that's also possible.
Because i can't connect it to te PC, only on the 16f887 chip we use for it.
Greetings,
Mirno |
|
|
mirno
Joined: 16 Jan 2015 Posts: 6
|
|
Posted: Mon Jan 19, 2015 4:43 am |
|
|
I have read the adresses from the program, it works great! I put the output on our LCD screen in the elevator.
Code: | #include <16F887.h>
#fuses INTRC_IO,NOWDT,NOPROTECT,PUT,NOLVP,NOBROWNOUT
#use delay(clock=4M)
#use i2c(Master, sda=PIN_C4, scl=PIN_C3)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#include "flex_lcd.c"
// This function writes the slave address to the i2c bus.
// If a slave chip is at that address, it should respond to
// this with an "ACK". This function returns TRUE if an
// ACK was found. Otherwise it returns FALSE.
int8 get_ack_status(int8 address)
{
int8 status;
i2c_start();
status = i2c_write(address); // Status = 0 if got an ACK
i2c_stop();
if(status == 0)
return(TRUE);
else
return(FALSE);
}
//=================================
void main()
{
int8 i;
int8 status;
int8 count = 0;
lcd_init();
printf(lcd_putc, "\n\rStart:\n\r");
delay_ms(1000);
// Try all slave addresses from 0x10 to 0xEF.
// See if we get a response from any slaves
// that may be on the i2c bus.
for(i=0x04; i < 0xF0; i+=2)
{
status = get_ack_status(i);
if(status == TRUE)
{
lcd_init();
printf(lcd_putc, "ACK addr: %X\n\r", i);
count++;
delay_ms(2000);
}
}
if(count == 0)
{
lcd_init();
printf(lcd_putc, "\n\rNothing Found");
}
else
{
lcd_init();
printf(lcd_putc, "\n\rNumbers : %u", count);
}
while(1);
} |
But there is another problem.
The RFID chip has two addresses: 0xA6 and 0xAE . Why would he have two addresses? I already tried a lot with the 0xA6 wich I got from a forum, but no response.
Anyone any idea's ?
Greetings, Mirno |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Jan 19, 2015 11:11 am |
|
|
Quote: |
The RFID chip has two addresses: 0xA6 and 0xAE . Why would he have
two addresses ?
|
Read the M24LR16E-R data sheet:
http://www.st.com/web/en/resource/technical/document/datasheet/DM00031737.pdf
The device uses two i2c addresses, selected by the "E2" bit in the slave
address, as shown in this table on page 18 of the data sheet:
Quote: | Table 2. Device select code |
Address 0xA6:
- To access the user memory, the device select code used for any I2C
command must have the E2 Chip Enable address at 0.
Address: 0xAE:
- To access the Sector security status byte area, the device select code
used for any I2C command must have the E2 Chip Enable address at 1.
- To access the I2C_Write_Lock bit area, the device select code used for
any I2C command must have the E2 Chip Enable address at 1.
- To access the Configuration byte, the device select code used for any
I²C command must have the E2 Chip enable address at 1.
- To access the Control register, the device select code used for any I²C
command must have the E2 Chip enable address at 1.
- And the ISO 15693 system parameters sector (E2 = 1). |
|
|
mirno
Joined: 16 Jan 2015 Posts: 6
|
|
Posted: Tue Jan 20, 2015 3:27 am |
|
|
PCM programmer wrote: | Quote: |
The RFID chip has two addresses: 0xA6 and 0xAE . Why would he have
two addresses ?
|
Read the M24LR16E-R data sheet:
http://www.st.com/web/en/resource/technical/document/datasheet/DM00031737.pdf
The device uses two i2c addresses, selected by the "E2" bit in the slave
address, as shown in this table on page 18 of the data sheet:
Quote: | Table 2. Device select code |
Address 0xA6:
- To access the user memory, the device select code used for any I2C
command must have the E2 Chip Enable address at 0.
Address: 0xAE:
- To access the Sector security status byte area, the device select code
used for any I2C command must have the E2 Chip Enable address at 1.
- To access the I2C_Write_Lock bit area, the device select code used for
any I2C command must have the E2 Chip Enable address at 1.
- To access the Configuration byte, the device select code used for any
I²C command must have the E2 Chip enable address at 1.
- To access the Control register, the device select code used for any I²C
command must have the E2 Chip enable address at 1.
- And the ISO 15693 system parameters sector (E2 = 1). |
Thank you for the information, i see what you mean.
However I am really new to this techniques, both for I²C as for RFID. So these things are still quite difficult for me.
I don't know exactly how to configure all these settings in a program.
I need to put the E2 to 0 with the 0xA6 address,
and with the 0xAE address I should afterwards be able to read from the slave, and notice the difference between when the RFID is used on the chip or not. I used a While loop, but nothings changes on the screen when i put the RFID chip on.
This is my current program:
Code: | #include <16F887.h>
#use delay(clock=8000000)
#fuses HS,WDT,INTRC_IO,PUT, NOLVP
//set up i2c peripheral and use hardware SSP
#use i2c(Master,sda=PIN_C4,scl=PIN_C3,RESTART_WDT)
//#use i2c(Master,sda=PIN_C4,scl=PIN_C3,RESTART_WDT) //aangepast 1-12-2014
//int array[1] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
//#int_SSP
#include "flex_lcd.c"
#define SLAVE_ADDRESS 0xAE
/*SSP_isr()
{ //communicate every 50 ms
i2c_start(); //set i2c to start condition
i2c_write(0x04); //send address
i2c_write(0x55); //send master data from port B bits
i2c_start(); //restart to change data direction
i2c_write(0x05); //address with direction bit changed
// lcd_init();
// lcd_putc(~i2c_read(0));
output_d(~i2c_read(0)); //get slave data and display
i2c_stop(); //stop i2c activity
}*/
void main()
{
int data[8];
int verdieping = 0;
int c;
// unsigned char rx_byte;
//#BYTE OSCCON = 0b0111111;
setup_adc_ports(NO_ANALOGS);
// CM2CON0 &= 0x1111111;
setup_comparator(NC_NC_NC_NC);
setup_counters(RTCC_INTERNAL,WDT_1152MS);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
port_b_pullups(FALSE); //pull ups for input pins
//enable_interrupts(INT_SSP);
//enable_interrupts(global);
lcd_init();
lcd_putc("\fHello World\n");
while(1)
{
i2c_start();
delay_ms(50);
i2c_write (0xA6); /* E2 = 0? */
delay_ms(50);
E2 = 1
i2c_start(); // restart condition
i2c_write(0xAE);
data[0] = i2c_read(0) ;
data[1] = i2c_read(0) ;
data[2] = i2c_read(0) ;
data[3] = i2c_read(0) ;
data[4] = i2c_read(0) ;
data[5] = i2c_read(0) ;
data[6] = i2c_read(0) ;
data[7] = i2c_read(0) ;
lcd_init();
for(c = 0; c < 8; c++)
{
printf(lcd_putc, data[c]);
}
/*if(data[0] == 0xA6)
{
lcd_init();
lcd_putc("A6 \n");
// printf ("rx_byte = 0x%2.2X\r\n", rx_byte);
}
else if(data[0] == 0xAE)
{
lcd_init();
lcd_putc("AE \n");
}
else if (data[0] == 0xFF)
{
lcd_init();
lcd_putc("0xFF \n");
}
else
{
lcd_init();
lcd_putc("Anders \n");
}*/
i2c_stop();
}
} |
The things i see on the LCD are:
"ääääääää"
Also tried something like this:
Code: | #include <16F887.h>
#use delay(clock=8000000)
#fuses HS,WDT,INTRC_IO,PUT, NOLVP
//set up i2c peripheral and use hardware SSP
#use i2c(Master,sda=PIN_C4,scl=PIN_C3,RESTART_WDT)
//#use i2c(Master,sda=PIN_C4,scl=PIN_C3,RESTART_WDT) //aangepast 1-12-2014
//int array[1] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
//#int_SSP
#include "flex_lcd.c"
#define SLAVE_ADDRESS 0xAE
/*SSP_isr()
{ //communicate every 50 ms
i2c_start(); //set i2c to start condition
i2c_write(0x04); //send address
i2c_write(0x55); //send master data from port B bits
i2c_start(); //restart to change data direction
i2c_write(0x05); //address with direction bit changed
// lcd_init();
// lcd_putc(~i2c_read(0));
output_d(~i2c_read(0)); //get slave data and display
i2c_stop(); //stop i2c activity
}*/
void main()
{
int data[8];
int verdieping = 0;
int c;
int E2_waarde[1];
// unsigned char rx_byte;
//#BYTE OSCCON = 0b0111111;
setup_adc_ports(NO_ANALOGS);
// CM2CON0 &= 0x1111111;
setup_comparator(NC_NC_NC_NC);
setup_counters(RTCC_INTERNAL,WDT_1152MS);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
port_b_pullups(FALSE); //pull ups for input pins
//enable_interrupts(INT_SSP);
//enable_interrupts(global);
lcd_init();
lcd_putc("\fHello World\n");
while(1)
{
i2c_start();
delay_ms(50);
i2c_write (0xA6); /* E2 = 0? */
delay_ms(50);
//E2_waarde[0] = 0b10100111;
//E2_waarde[0] = i2c_read(0);
//i2c_start(); // restart condition
i2c_write(0b10100111);
delay_ms(50);
// i2c_start();
// i2c_write(0xAE);
// i2c_write(0b10101111);
//i2c_write(0xAF);
data[0] = i2c_read(0) ;
data[1] = i2c_read(0) ;
data[2] = i2c_read(0) ;
data[3] = i2c_read(0) ;
data[4] = i2c_read(0) ;
data[5] = i2c_read(0) ;
data[6] = i2c_read(0) ;
data[7] = i2c_read(0) ;
lcd_init();
for(c = 0; c < 8; c++)
{
printf(lcd_putc, E2_waarde[0]);
}
/*if(data[0] == 0xA6)
{
lcd_init();
lcd_putc("A6 \n");
// printf ("rx_byte = 0x%2.2X\r\n", rx_byte);
}
else if(data[0] == 0xAE)
{
lcd_init();
lcd_putc("AE \n");
}
else if (data[0] == 0xFF)
{
lcd_init();
lcd_putc("0xFF \n");
}
else
{
lcd_init();
lcd_putc("Anders \n");
}*/
i2c_stop();
}
} |
Now it started spacing really hard with appearing all random tokens.
Any idea's? |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9225 Location: Greensville,Ontario
|
|
Posted: Tue Jan 20, 2015 6:31 am |
|
|
query. Is your LCD module properly working? Normally you only need to do the LCD_init() call once in a program however it must be preceded by a delay_ms(500);.
This delay is to allow the LCD module to 'powerup and get organized' before the PIC actually accesses it.
ie:
main () {
...
...
...
delay_ms(500);//delay for LCD powerup
lcd_init();// access lcd,change to 4bit mode,rtc.
...
...
... rest of program
...
Also be sure you've got a good 5 volt supply to the PIC and LCD BUT is the RFID device 5 volt or 3 volt? Most these days are 3 volt! Best to check the datasheet!!
jay |
|
|
mirno
Joined: 16 Jan 2015 Posts: 6
|
|
Posted: Tue Jan 20, 2015 7:41 am |
|
|
temtronic wrote: | query. Is your LCD module properly working? Normally you only need to do the LCD_init() call once in a program however it must be preceded by a delay_ms(500);.
This delay is to allow the LCD module to 'powerup and get organized' before the PIC actually accesses it.
ie:
main () {
...
...
...
delay_ms(500);//delay for LCD powerup
lcd_init();// access lcd,change to 4bit mode,rtc.
...
...
... rest of program
...
Also be sure you've got a good 5 volt supply to the PIC and LCD BUT is the RFID device 5 volt or 3 volt? Most these days are 3 volt! Best to check the datasheet!!
jay |
Yes it is properly working, we are also using it for the elevator, to show text from the stages etc. works fine!
It's a little sloppy programming i guess.
Single supply voltage:
– 1.8 V to 5.5 V
We are using 5V. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Jan 20, 2015 12:05 pm |
|
|
Quote: | i2c_start();
delay_ms(50);
i2c_write (0xA6); /* E2 = 0? */
delay_ms(50);
//E2_waarde[0] = 0b10100111;
//E2_waarde[0] = i2c_read(0);
//i2c_start(); // restart condition
i2c_write(0b10100111);
delay_ms(50);
// i2c_start();
// i2c_write(0xAE);
// i2c_write(0b10101111);
//i2c_write(0xAF);
data[0] = i2c_read(0) ;
data[1] = i2c_read(0) ;
data[2] = i2c_read(0) ;
data[3] = i2c_read(0) ;
data[4] = i2c_read(0) ;
data[5] = i2c_read(0) ;
data[6] = i2c_read(0) ;
data[7] = i2c_read(0) ; |
Figure 11 on page 38 of the M24LR16E-R data sheet shows what you
need to do, to perform a Sequential Random Read. You are not doing
this. The comment in the data sheet about doing a delay after a write
operation does not apply to i2c_write(). They are talking about the
internal time required for the write to eeprom to finish. You are not
writing to eeprom in the code above. You are doing a read operation.
The delay_ms(50) statements are not required.
You are also not sending the two address bytes. You're not doing the
re-start operation. You're sending NACK on all bytes read, instead of
just the last one. You have no i2c_stop() line at the end of the reads.
Basically you need to start over and carefully follow the data sheet.
And get rid of all those commented out lines. They just cause confusion. |
|
|
mirno
Joined: 16 Jan 2015 Posts: 6
|
|
Posted: Wed Jan 21, 2015 3:36 am |
|
|
PCM programmer wrote: | Quote: | i2c_start();
delay_ms(50);
i2c_write (0xA6); /* E2 = 0? */
delay_ms(50);
//E2_waarde[0] = 0b10100111;
//E2_waarde[0] = i2c_read(0);
//i2c_start(); // restart condition
i2c_write(0b10100111);
delay_ms(50);
// i2c_start();
// i2c_write(0xAE);
// i2c_write(0b10101111);
//i2c_write(0xAF);
data[0] = i2c_read(0) ;
data[1] = i2c_read(0) ;
data[2] = i2c_read(0) ;
data[3] = i2c_read(0) ;
data[4] = i2c_read(0) ;
data[5] = i2c_read(0) ;
data[6] = i2c_read(0) ;
data[7] = i2c_read(0) ; |
Figure 11 on page 38 of the M24LR16E-R data sheet shows what you
need to do, to perform a Sequential Random Read. You are not doing
this. The comment in the data sheet about doing a delay after a write
operation does not apply to i2c_write(). They are talking about the
internal time required for the write to eeprom to finish. You are not
writing to eeprom in the code above. You are doing a read operation.
The delay_ms(50) statements are not required.
You are also not sending the two address bytes. You're not doing the
re-start operation. You're sending NACK on all bytes read, instead of
just the last one. You have no i2c_stop() line at the end of the reads.
Basically you need to start over and carefully follow the data sheet.
And get rid of all those commented out lines. They just cause confusion. |
Hmm this is quite difficult, i still have no idea how to program this, this is my first experience with this btw. I never had an example or something before.
I now have this as program:
Code: | #include <16F887.h>
#use delay(clock=8000000)
#fuses HS,WDT,INTRC_IO,PUT, NOLVP
#use i2c(Master,sda=PIN_C4,scl=PIN_C3,RESTART_WDT)
#include "flex_lcd.c"
void main()
{
int data[8];
int verdieping = 0;
setup_adc_ports(NO_ANALOGS);
setup_comparator(NC_NC_NC_NC);
setup_counters(RTCC_INTERNAL,WDT_1152MS);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
port_b_pullups(FALSE);
lcd_init();
lcd_putc("\fHello World\n");
while(1) // According to page 38, figure 11.
{
i2c_start(); // Start
i2c_write(0b10100110); //E2 set to 1 and ~R/w (Device 0xA6 selected? )
//Byte address (automatic addresses with tag anf without tag?
i2c_start();// start again
i2c_write(0b10101111); //E2 set to 0 and ~R/w (Device 0xAE selected? )
data[0] = i2c_read(0) ; //Data out?_Reading
data[1] = i2c_read(0) ;
data[2] = i2c_read(0) ;
data[3] = i2c_read(0) ;
data[4] = i2c_read(0) ;
data[5] = i2c_read(0) ;
data[6] = i2c_read(0) ;
data[7] = i2c_read(0) ;
lcd_init();
for(c = 0; c < 8; c++)
{
printf(lcd_putc, E2_waarde[0]); //print on LCD
}
i2c_stop(); // stop
}
} |
Behind the things i do i referred to figure 11 on page 38. I know I'm still doing something wrong, but no idea what's wrong exactly.
Maybe i just buy another RFID chip, if I can't start this one.
Greetings, Mirno |
|
|
|
|
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
|