CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

RFID using I2C

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
mirno



Joined: 16 Jan 2015
Posts: 6

View user's profile Send private message

RFID using I2C
PostPosted: Fri Jan 16, 2015 9:12 am     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Jan 16, 2015 10:54 am     Reply with quote

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

View user's profile Send private message

PostPosted: Sat Jan 17, 2015 7:43 am     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Jan 19, 2015 4:43 am     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Jan 19, 2015 11:11 am     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Jan 20, 2015 3:27 am     Reply with quote

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: 9174
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Tue Jan 20, 2015 6:31 am     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Jan 20, 2015 7:41 am     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Jan 20, 2015 12:05 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Jan 21, 2015 3:36 am     Reply with quote

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
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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