AN3291 oddity (problems with I2C device on QG8)

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

AN3291 oddity (problems with I2C device on QG8)

9,501 Views
jarin
Contributor I
Hi all,
I'm trying to connect 24FC512 EEPROM to QG8 device. I downloaded AN3291 and copied routines to read/write from EEPROM with I2C module in HCS08 devices into my project, after a slight changes (like converting IIC1S to IICS and so on) I downloaded code to FLASH and the routines behaved somehow strange. Write routine followed with read routine worked, but reading byte back stopped at waiting for ACK signal after third transmitted byte (first is device address, second and third are memory address bytes). I searched for problem in read routine, but when I placed two write routines subsequently, the second one stopped at the same place, indicating the is something wrong with the write routine. Putting AN in contrast with datasheet showed that IICIF flag should be cleared (by writing 1) after writing data byte into EEPROM.
This is how routine looked originally:

void I2C_write_byte (word addr,byte data)
{
EE_Addr = addr; // address input;
temp = (EE_Addr_H & 0x07) 1;
IIC1C_TX = 1; // Set transmit mode;
//-------start of transmit first byte to IIC bus-----
IIC1C_MST = 1; // Start transfer - Master bit = 1;
IIC1D = sl_addr | temp; // send "Write" + high address;
while (!(IIC1S_IIC1IF));
IIC1S_IIC1IF = 1;
while (IIC1S_RXAK); // wait for ACK from slave;
//-----Slave ACK occurred------------
IIC1D = EE_Addr_L; // send low address byte;
while (!(IIC1S_IIC1IF)); // wait till data transferred;
IIC1S_IIC1IF = 1;
while (IIC1S_RXAK); // wait for ACK from slave;
//-----Slave ACK occurred------------
IIC1D = data; // write data byte into EEPROM;
while (!(IIC1S_IIC1IF)); // wait till data transferred;
while (IIC1S_RXAK); // wait for ACK from slave;
IIC1C_MST = 0; // STOP bit;
}

and this is how the routine works for me:

void I2C_write_byte (word addr,byte data)
{
EE_Addr = addr; // address input;
temp = (EE_Addr_H & 0x07) 1;
IIC1C_TX = 1; // Set transmit mode;
//-------start of transmit first byte to IIC bus-----
IIC1C_MST = 1; // Start transfer - Master bit = 1;
IIC1D = sl_addr | temp; // send "Write" + high address;
while (!(IIC1S_IIC1IF));
IIC1S_IIC1IF = 1;
while (IIC1S_RXAK); // wait for ACK from slave;
//-----Slave ACK occurred------------
IIC1D = EE_Addr_L; // send low address byte;
while (!(IIC1S_IIC1IF)); // wait till data transferred;
IIC1S_IIC1IF = 1;
while (IIC1S_RXAK); // wait for ACK from slave;
//-----Slave ACK occurred------------
IIC1D = data; // write data byte into EEPROM;
while (!(IIC1S_IIC1IF)); // wait till data transferred;
//*****************************here is flag clearing*************************
IIC1S_IIC1IF = 1; //!!!!!!!!!!!ADDED LINE!!!!!!!!!!!!
//***************************************************************************
while (IIC1S_RXAK); // wait for ACK from slave;
IIC1C_MST = 0; // STOP bit;
}

I think it is quite logical to clear flag after it was set. This is also mentioned in datasheet for QG8 device (figure 11-3) - there is difference, described as interrupt routine, but it can be easily converted into polled routines, IICIF flag is cleared after EVERY entry to interrupt routine, it means everytime when IICIF flag is set.
After adding line routines work like expected - I'm able to write/read from external EEPROM.

Is the missed line mistake in document or I have got another problem?


By the way, interesting fact is that the write/read sequence worked well when doing single steps through routine code AND with Data window opened. With Data windows closed, routine hanged on the same place as before. It is probably because I2C module registers were showed in Data window and thus read by BDM POD.
Labels (1)
0 Kudos
33 Replies

1,373 Views
er_nikhil
Contributor I

Hi all,

 I am trying to use I2C module of S08PT series.I need to communicate with two same kind of S08PT MCUs.But somes times communication breaks.I am using PTB6,PTB7 pins as SDA and SCL.No external pullup resistor provided and connected two boards using 30cm long rmc connector.Please help to rectify this problem.

My code for Master and Slave is as shown below.

Master

void IIC_Init(void)
{
SYS_SOPT1_IICPS = 1; // IIC SCL and SDA are mapped on PTB7 and PTB6
I2C_C1_IICEN = 1; // Enable I2C;
I2C_C1_TXAK = 1; // not generate ACK by master after transfer;
I2C_C1_MST = 0; // Slave mode actually;
I2C_F = 0x47; // Set speed to 100kbps    Bus = 8MHz; 
I2C_S_SRW = 0; // R/W bit = 0;

}

0 Kudos

1,373 Views
er_nikhil
Contributor I

Hi all,

 I am trying to use I2C module of S08PT series.I need to communicate with two same kind of S08PT MCUs.But somes times communication breaks.I am using PTB6,PTB7 pins as SDA and SCL.No external pullup resistor provided and connected two boards using 30cm long rmc connector.Please help to rectify this problem.

 

My code for Master and Slave is as shown below.

Master

void IIC_Init(void)
{
SYS_SOPT1_IICPS = 1; // IIC SCL and SDA are mapped on PTB7 and PTB6
I2C_C1_IICEN = 1; // Enable I2C;
I2C_C1_TXAK = 1; // not generate ACK by master after transfer;
I2C_C1_MST = 0; // Slave mode actually;
I2C_F = 0x47; // Set speed to 100kbps    Bus = 8MHz; 
I2C_S_SRW = 0; // R/W bit = 0;

}

void IIC_Start(void)
{
I2C_C1 |= I2C_C1_TX_MASK;
I2C_C1 |= I2C_C1_MST_MASK;
}

void IIC_Stop(void)
{
I2C_C1_MST = 0; // generate stop signal
}

0 Kudos

1,377 Views
Stano
NXP Employee
NXP Employee

Hi Irob,

 

sorry I answer a bit later, but I was very busy. A long time ago I write the routine for 1-byte address IIC communication between S08GB60 and PCF8574 GPIO extender. This application works very well - without debug interface of course. I use it as the standard GPIO port for buttons input or LED drive output. The SW routines are in follow:

 

//------------------------------------------------------------
void I2C_write_byte (byte data)
{
     IIC1C_IICEN = 1;
     IIC1C_TX = 1;
        //-------start of transmit first byte to IIC bus-----
     IIC1C_MST = 1;            // Start transfer - Master bit = 1;
     IIC1D = sl_addr;
     while (!(IIC1S_IICIF));
     IIC1S_IICIF = 1;        
     while (IIC1S_RXAK);       // wait for ACK from slave;
       //-----Slave ACK occured------------
     IIC1D = data;             // write data byte into EEPROM;
     while (!(IIC1S_TCF));     // wait till data transfered;
     while (IIC1S_RXAK);       // wait for ACK from slave;
     while (!(IIC1S_TCF));     // wait till data transfered;
     IIC1C_MST = 0;            // STOP bit;
     IIC1C_IICEN = 0;
}
//------------------------------------------------------------
byte I2C_read_byte (void)
{
     IIC1C_TX = 1;             // Set transmit mode;
        //-------start of transmit first byte to IIC bus-----
     IIC1C_MST = 1;            // Start transfer - Master bit = 1;
     IIC1D = (sl_addr | 1);
     while (!(IIC1S_IICIF));
     IIC1S_IICIF = 1;        
     while (IIC1S_RXAK);       // wait for ACK from slave;
       //-----Slave ACK occured------------
     IIC1C_TX = 0;             // Set receive mode;
     rd_data = IIC1D;          // read IIC data
     while (!(IIC1S_IICIF));
     IIC1S_IICIF = 1;
     IIC1C_MST = 0;            // STOP bit;
     return rd_data;
}

 

The important think is that the IIC bus can freeze when the salve device can't answer properly. Slave device must receive right amount of SCL clock impulses to send whole answer to master. When this state (IIC freeze) arrives, master must make the IIC bus reset - this means send 9 SCL impulses while SDA = 0. Then the communication can start. For this "reset" switch off the IIC internal module, go to GPIO mode and emulate IIC reset by the same pins but in GPIO mode. Then activate internal IIC module and use it. The best way to recognize that the byte transfer is complete is use the IICIF flag - you can use it in interrupt routine or not - see example above.

I don't know what kind of IC you use for 1-byte address communication, but this code could be good example. The best way for IIC debug is use the scope, because it is not possible debug it step-by-step.

 

I hope it hels you.

 

Bye,

Stano.

0 Kudos

1,377 Views
irob
Contributor V

Thanks again, Stano, for your help!  I'm confused about when exactly we must check the I2C interrupt flag.  In your most recent example, you have that...

 

while (!(IIC1S_IICIF)

 

 ...happening every time you write to or read from the I2C data channel.  And now you are also checking the TOF bit:

 

 

while (!(IIC1S_TCF))

 

 ...though you weren't above in your original code.  Seems inconsistent to me.

 

 

0 Kudos

1,377 Views
Stano
NXP Employee
NXP Employee

Hi irob,

 

sorry for confusion. I made test of these routines once again and the final result is - use the IICIF flag instead TCF flag. The TCF flag is valid only short time - durring or immediately after byte transfer. The IICIF flag is set and you need clear it by software - write "1" to this bit. So you have reliable information about transfered data to/from IIC module.

 

So the final code for communication between S08 MCU and PCF8574 GPIO port extender is in follow:

 

//-------------------------------------------------------------------------------
void I2C_write_byte (byte data)
{
     IIC1C_IICEN = 1;
        //-------start of transmit first byte to IIC bus-----
     IIC1C_MST = 1;              // Start transfer - Master bit = 1;
     IIC1C_TX = 1;                // Set transmit mode;
     IIC1D = sl_addr;
     while (!(IIC1S_IICIF));
     IIC1S_IICIF = 1;             // clear the flag;        
     while (IIC1S_RXAK);        // wait for ACK from slave;
       //-----Slave ACK occured------------
     IIC1D = data;                 // write data byte into EEPROM;
     while (IIC1S_RXAK);        // wait for ACK from slave;
     while (!(IIC1S_IICIF));     // wait till data transfered;
     IIC1S_IICIF = 1;             // clear the flag;
     IIC1C_MST = 0;              // STOP bit;
     IIC1C_IICEN = 0;            // deactivate IIC module;
}
//-------------------------------------------------------------------------------
byte I2C_read_byte (void)
{
     IIC1C_IICEN = 1;
        //-------start of transmit first byte to IIC bus-----
     IIC1C_MST = 1;              // Start transfer - Master bit = 1;
     IIC1C_TX = 1;                // Set transmit mode;
     IIC1D = (sl_addr | 1);      // "read" command;
     while (!(IIC1S_IICIF));     // wait till data transfered;
     IIC1S_IICIF = 1;             // clear the flag;        
     while (IIC1S_RXAK);        // wait for ACK from slave;
       //-----Slave ACK occured------------
     IIC1C_TX = 0;               // Set receive mode;
     temp = IIC1D;               // send SCL impulses to read slave;
     while (!(IIC1S_IICIF));    // wait till data transfered;
     IIC1S_IICIF = 1;            // clear the flag;
     IIC1C_MST = 0;             // STOP bit;
     rd_data = IIC1D;           // save received data from slave;
     IIC1C_IICEN = 0;           // deactivate IIC module;
     return rd_data;             
}
//-------------------------------------------------------------------------------

 

So you can use it for one-byte transfer as example.

 

I hope it helps you;

 

Bye,

Stano.

0 Kudos

1,373 Views
irob
Contributor V

From your code above, Stano, you are enabling/disabling the module inside the I2C_write_byte and I2C_read_byte functions:

:

 

//-------------------------------------------------------------------------------
void I2C_write_byte (byte data)
{
     IIC1C_IICEN = 1;
        //-------start of transmit first byte to IIC bus-----
     IIC1C_MST = 1;              // Start transfer - Master bit = 1;
     IIC1C_TX = 1;                // Set transmit mode;
     IIC1D = sl_addr;
     while (!(IIC1S_IICIF));
     IIC1S_IICIF = 1;             // clear the flag;       
     while (IIC1S_RXAK);        // wait for ACK from slave;
       //-----Slave ACK occured------------
     IIC1D = data;                 // write data byte into EEPROM;
     while (IIC1S_RXAK);        // wait for ACK from slave;
     while (!(IIC1S_IICIF));     // wait till data transfered;
     IIC1S_IICIF = 1;             // clear the flag;
     IIC1C_MST = 0;              // STOP bit;
     IIC1C_IICEN = 0;            // deactivate IIC module;
}
//-------------------------------------------------------------------------------
byte I2C_read_byte (void)
{
     IIC1C_IICEN = 1;
        //-------start of transmit first byte to IIC bus-----
     IIC1C_MST = 1;              // Start transfer - Master bit = 1;
     IIC1C_TX = 1;                // Set transmit mode;
     IIC1D = (sl_addr | 1);      // "read" command;
     while (!(IIC1S_IICIF));     // wait till data transfered;
     IIC1S_IICIF = 1;             // clear the flag;       
     while (IIC1S_RXAK);        // wait for ACK from slave;
       //-----Slave ACK occured------------
     IIC1C_TX = 0;               // Set receive mode;
     temp = IIC1D;               // send SCL impulses to read slave;
     while (!(IIC1S_IICIF));    // wait till data transfered;
     IIC1S_IICIF = 1;            // clear the flag;
     IIC1C_MST = 0;             // STOP bit;
     rd_data = IIC1D;           // save received data from slave;
     IIC1C_IICEN = 0;           // deactivate IIC module;
     return rd_data;            
}
//-------------------------------------------------------------------------------

 

 

 

0 Kudos

1,377 Views
Richly
Contributor III

Hi, Stano.

 

I'm trying to figure out the IIC drivers.  I note that your routines here in the forum either

Case 1: start with

        IICS_IICIF = 1;

or

Case 2: start with

         IIC1C_IICEN = 1;

    and then end with

         IIC1C_IICEN = 0;

 

Neither of these cases occurs in the latest version of AN3291.pdf (Rev. 2, 04/2007).  Are they necessary? What problem does Case 1 solve?  It seems excessive to disable the IIC module after each transfer and then enable it again for the next transfer (Case 2).  Is it another way to solve the same problem as Case 1?

 

Would it be reasonable to have code that uses a counter to limit the amount of time to wait for the IIC device to respond instead of hanging in an infinite loop until a COP interrupt occurs (if it happens to be enabled)?  Would this solve any of the issues the code above addresses?

 

Furthermore, the IIC_write_byte() routine in AN3291 has a line that is not in your forum code:

        IICS_IICIF=1;          // Clear the flag

just before its last line

        IICC_MST = 0;          // Generate STOP

 

I cannot figure out why this is needed, since the flag was already cleared immediately following the wait for the Interrupt flag and before waiting for the AK.

 

Actually, the situation is more confusing than that: your final forum  I2C_write_byte() routine waits for an AK from the slave before it waits for the Interrupt flag to be set, indicating that the data finished transferring.  All other drivers I've seen reverse this order, first waiting for the Interrupt flag and then the AK.  Can you explain?

 

In short, there seem to be several different versions of IIC code on Freescale sites.  They differ in just a few -- to me mysterious --  particulars.  But these particulars seem to be related to serious issues that various posts have raised about failed IIC communications.

 

Can someone provide "gold standard" versions of IIC transfer code with comments especially for "gotcha" situations?  It'd be nice if there were both single- and multiple-byte transfer routines, both with and without interrupts.  Links to these "gold standards" should be prominently placed near all the older drivers, so people looking for help don't get bogged down with code that almost works.

 

Thanks,

    Richly


 

0 Kudos

1,377 Views
irob
Contributor V

I've been beating my head against a wall all day on this, trying to get the IIC module to work.  No offense to the author, but with the many versions of sample code posted, it's difficult to suss out the right "flavor" to get simple master IIC transactions working with a registered slave.

 

The best results I can achieve, using verbatim the code(s) posted by Stano, are passing write and read transactions in BDM mode only.  In other words, I can only write a byte to my I2C slave chip and read it back successfully if I step through code in the debugger on my HCS908QG8.  If I let the chip run, it always hangs in the slave acknowledge while.

 

Something that hasn't been discussed at all either here or in the app note, is the QG8's SDA hold time and SCL divider values.  There's a fairly involved formula/chart on the matter in the datasheet on pages 162-163.  I've tried both the values in the datasheet's example, and my own set, neither of which made a difference for me.

 

Anyone else make heads or tails of this mess?

0 Kudos

1,377 Views
Stano
NXP Employee
NXP Employee

Hello,

 

I want to help you with this issue, so send me please the source code as a zipped attachmend and the type of the slave used.

 

Thanks,

Stano.

0 Kudos

1,377 Views
irob
Contributor V

Thanks, Stano.  I will PM you the code. 

 

Before I left for a long weekend, I did make a breakthrough.  I had noticed one key difference between your code example and mine.  I had written an I2C init routine that I only called once to turn channels on, timing settings, etc.  In your examples, you turn on and off the I2C module every time you call a Write or Read function.  I believe on of the readers on this board questioned that.

 

I can indeed now get I2C functioning stand-alone outside of the debugger, but only if I do as you do -- turn on the module before use, turn back off after completed.

 

It's not clear to me why this is the case.  Is this a shortcoming of the module only in QG8s?  All S08s?  Perhaps an errata is in order.

0 Kudos

1,377 Views
Richly
Contributor III

I'm using a MC9S08SH16 and experiencing the same problems, e.g., works, if at all, only when single stepping.  So it doesn't appear to be just the QG8.

 

I'm glad to see activity on this thread again and would love to receive answers to the series of questions I raised in my message of 2009-11-29 07:34 PM.

 

Thanks,

    Richly

0 Kudos

1,377 Views
irob
Contributor V

Richly, have you tried enabling the I2C module in your I2C write/read functions first, then disabling after complete?  These steps got it working for me outside of the debugger.

0 Kudos

1,377 Views
Richly
Contributor III

Thanks.  Yes, I tried the enabling/disabling; it didn't help.  I even tried clearing all the status flags each time the write or read routine starts.

 

Using the debugger and adding some code that sets status values in global variables, I've figured out that when the IIC unit runs at speed, the ARBL bit is being set while the MC9S08SH16 is waiting for the AK after the dummy read that initiates a real read.  Since the only components on the buss at present are the microprocessor, which is set as the master, and an FRAM, which can behave only as a slave, this makes no sense: there is nothing else that can generate a START.

 

I may have fixed the problem by slowing down the SCL frequency from ~100 kHz to ~50 kHz.  This shouldn't be necessary, since the part is rated to 1000 kHz.  I've got to do more checking to convince myself that this is a reliable solution.

 

The easiest way I've found to figure out what the SCL frequency will be is to use the Device Initialization offered by the CodeWarrior IDE.  Once you've set the CPU's clock options (don't forget to click OK after you've done this!), then setting the IIC's Multiplier Factor and Clock rate options displays the resultant SCL frequency and SDA Hold.  I let the IDE generate initialization code that I can cut and paste elsewhere if needed.

 

0 Kudos

1,373 Views
jiri_naprstek
Contributor I

Hi, I'd like to point out few things which could potentially help to your issue when the code works when traced in debugger only (few other concerns to follow :smileywink: ):

 

IMO switching off the IIC interface (IICEN=0) immediately after leaving the master master mode (MST=0) could cause troubles, because MST=0 starts the STOP indication sequence (pulling SDA high whn SCK is high) but this may not be a immediate operation, especially if it is issued right after the TCF (or Interrupt) is raised.

 

Therefore, if you trace it in debugger, there is plenty of time to finish the operation, but if the code runs at full speed, the MCU is obviously "a bit" faster and:

1) can cut the closing operation

2) subsequent operation may overlap because no one actually checks, if the STOP sequence is finished.

0 Kudos

1,373 Views
jiri_naprstek
Contributor I

Chaps,

 

just to build up the question pile:

 

I've managed to convince the IIC interface to work *mostly* the way I'd like it to work. So far the code needs a lot of polishing, but it works. Almost. (if anyone is interested in the code, just let me know, it is interrupt driven master)

 

I'd like to ask the audience and/or contemporary freescalers if anyone tried to disturb the I2C bus operation by noise? All examples I found around the e-globe deal with 100% reliable links only being not prepared for errors at all. I went to a tricky situation, when e.g. the SCL line is pulled low (as an error on the bus), the IIC is asked to masterify and send data (code snippet follows) and the SCL is released after MST=1 happens.

 

while( IICS_BUSY );

IICC1_TX = 1;
IICC1_MST = 1;
IICD = ( addr<<1 );

....

 

Having the interrupts enabled, this should generate the interrupt once either the data is sent, or an arbitration error happens. But, nothing. The only cure I know is to cycle the EN bit (a reset probably happens). Also, I've got no idea, how to realize that such situation happend without implementing some external timeout function.

 

Many thanks for any ideas.

 

Rgrds, Jiri

0 Kudos

1,373 Views
MICROAR
Contributor I

AN3291 do not works. I don´t know why.

 

 

void Init_I2C_c (void)
{
//IIC1C_IIC1EN = 1; // Enable I2C;
IIC1C_IICEN = 1;
IIC1C_TXAK = 1; // not generate ACK by master after transfer;
IIC1C_MST = 0; // Slave mode actually;
IIC1F = 0x59; // Set speed to 50kHz for Bus = 18.8743MHz;
// 12.5k->0x39; 50k->0x99; 100k->0x59;
IIC1S_SRW = 0; // R/W bit = 0;
}
void IIC_write_byte_c(byte data, word addr)
{
Address = addr; // load address;
temp = (Addr_H & 0x07) << 1;
IIC1C_TXAK = 0; // RX/TX = 1; MS/SL = 1; TXAK = 0;
IIC1C |= 0x30; // And generate START condition;
//-------start of transmit first byte to IIC bus-----
IIC1D = IIC_SLAVE | temp; // Address the slave and set up for master transmit;
while (!IIC1S_IICIF); // wait until IBIF;
IIC1S_IICIF=1; // clear the interrupt event flag;
while(IIC1S_RXAK); // check for RXAK;
//-----Slave ACK occurred------------
IIC1D = Addr_L; // Send low byte of the word address;
while (!IIC1S_IICIF); // wait until IBIF;
IIC1S_IICIF=1; // clear the interrupt event flag;
while(IIC1S_RXAK); // check for RXAK;
//-----Slave ACK occurred------------
IIC1D = data;
while (!IIC1S_IICIF); // wait until IBIF;
IIC1S_IICIF=1; // clear the interrupt event flag;
while(IIC1S_RXAK); // check for RXAK;
//-----Slave ACK occurred------------
IIC1S_IICIF=1; // clear the interrupt event flag;
IIC1C_MST = 0; // generate STOP condition;
}
byte IIC_read_byte_c(word addr)
{
Address = addr;
temp = (Addr_H & 0x07) << 1;
IIC1C_TXAK = 0; // RX/TX = 1; MS/SL = 1; TXAK = 0;
IIC1C |= 0x30; // And generate START condition;
IIC1D = IIC_SLAVE | temp; // Address the slave and set up for master transmit;
while (!IIC1S_IICIF); // wait until IBIF;
IIC1S_IICIF=1; // clear the interrupt event flag;
while(IIC1S_RXAK); // check for RXAK;
//-----Slave ACK occurred------------
IIC1D = Addr_L; // Send low byte of word address;
while (!IIC1S_IICIF); // wait until IBIF;
IIC1S_IICIF=1; // clear the interrupt event flag;
while(IIC1S_RXAK); // check for RXAK;
//-----Slave ACK occurred------------
IIC1C_RSTA = 1; // set up repeated start;
IIC1D = IIC_SLAVE | temp | 1; // (slave_address) | (RW = 1);
while (!IIC1S_IICIF); // wait until IBIF;
  IIC1S_IICIF=1; // clear the interrupt event flag;
while (IIC1S_RXAK); // check for RXAK;
//-----Slave ACK occurred------------
IIC1C_TX = 0; // set up to receive;
IIC1C_TXAK = 1; // acknowledge disable;
RD_data = IIC1D; // dummy read;
while (!IIC1S_IICIF); // wait until IBIF;
IIC1S_IICIF=1; // clear the interrupt event flag;
IIC1C_MST = 0; // generate stop signal;
RD_data = IIC1D; // read right data;
return RD_data;
}

 

 

void main( void )

{

  /* Init MCU internal peripherals */

byte dato = 10;

byte index = 0;

MCU_Init();

 

RPMRatio=2500000;

 

//Delay( 100 );

//Delay( 100 );

 

Band.stop=1;

Estado=SAVE;

 

InitSCI();

 

 

 SendChar('O') ;

 SendChar('K') ;

 SendChar(CR) ;

 SendChar(LF) ;

 

 

Addr_H = 0;

Addr_L = 0;

Init_I2C_c();

 

 

/*IIC_write_byte('2',2);

 

 SendChar('W') ;

 SendChar('R') ;

 SendChar(CR) ;

 SendChar(LF) ;       */

 

 

for(index = 0;index < 16;index++) {

 

  DBUF[index] = 'a' + index;

 

}

 

IIC_write_byte_c('s',0); 

 

 for(index = 0;index < 16;index++) {

 

  DBUF[index] = 0;

 

}

 

dato = IIC_read_byte_c(0)  ;

 

SendChar(dato);

 

for(index  =0;index < 16;index++) {

 

  SendChar(DBUF[index] + 0x30);

 

}

 

 

 SendChar('R') ;

 SendChar('D') ;

 SendChar(CR) ;

 SendChar(LF) ;

 

asm cli

//****************************************

for(;:smileywink: {

 

 

 

 

}

}

 

0 Kudos

1,373 Views
Coffi
Contributor I

What's the value for IIC_SLAVE on AN3291???

0 Kudos

1,373 Views
Stano
NXP Employee
NXP Employee

Hello,

 

the IIC_SLAVE in this example is the IIC address of the slave device used. For example the serial EEPROM has the IIC address 0xA0.

 

Best Regards,

Stano.

0 Kudos

1,373 Views
Coffi
Contributor I

I'm having a similar problem. I write a value to the memory, and after I try to transmit this value by wireless communication several times reading the value. The first time I read the value and transmit, it works. But after, no way. If I toggle the bit IIC1C_IICEN after the writing and after reading, will it work? What's is the easiest way to fix this bug?

0 Kudos

1,373 Views
Coffi
Contributor I

Here is the code for i2c:

 

#define EEPROM_ID   0xA0

//unsigned int eeprom_address;
//char eeprom_data, operation;

word eeprom_address;

typedef union
{
word EE_Address;
struct
{
byte Address_H;
byte Address_L;
}Bytes;
}tAddr;
tAddr ADDR;
#define Address ADDR.EE_Address
#define Addr_L ADDR.Bytes.Address_L
#define Addr_H ADDR.Bytes.Address_H

// MCU initialization
void i2c_init(void)
{
IIC1C_IICEN = 1; // Enable I2C;
IIC1C_TXAK = 1; // not generate ACK by master after transfer;
IIC1C_MST = 0; // Slave mode actually;
IIC1F = 0x59; // Set speed to 50kHz for Bus = 18.8743MHz;
// 12.5k->0x39; 50k->0x99; 100k->0x59;
IIC1S_SRW = 0; // R/W bit = 0;
}


// This is the I2C EEPROM byte writing function
void eeprom_bytewrite(word addr, byte data)
{
word temp;
//IIC1C_IICEN = 1;
IIC1S_IICIF = 1;
Address = addr; // load address;
temp = (Addr_H & 0x07) << 1;
IIC1C_TX = 1; // RX/TX = 1; MS/SL = 1; TXAK = 0;
IIC1C_MST = 1; // And generate START condition;
//-------start of transmit first byte to IIC bus-----
IIC1D = EEPROM_ID | temp; // Address the slave and set up for master transmit;
while (!IIC1S_IICIF); // wait until IBIF;
IIC1S_IICIF=1; // clear the interrupt event flag;
while(IIC1S_RXAK); // check for RXAK;
//-----Slave ACK occurred------------
IIC1D = Addr_L; // Send low byte of the word address;
while (!IIC1S_IICIF); // wait until IBIF;
IIC1S_IICIF=1; // clear the interrupt event flag;
while(IIC1S_RXAK); // check for RXAK;
//-----Slave ACK occurred------------
IIC1D = data;
while (!IIC1S_IICIF); // wait until IBIF;
IIC1S_IICIF=1; // clear the interrupt event flag;
while(IIC1S_RXAK); // check for RXAK;
//-----Slave ACK occurred------------
//IIC1S_IICIF=1; // clear the interrupt event flag;
IIC1C_MST = 0; // generate STOP condition;
//IIC1C_IICEN = 0; 
}

// This is the I2C EEPROM byte reading function
byte eeprom_byteread(word addr)
{
word temp;
byte RD_data;
IIC1S_IICIF = 1;
Address = addr;
temp = (Addr_H & 0x07) << 1;
IIC1C_TX = 1; // RX/TX = 1; MS/SL = 1; TXAK = 0;
IIC1C_MST = 1; // And generate START condition;
IIC1D = EEPROM_ID | temp; // Address the slave and set up for master transmit;
while (!(IIC1S_IICIF)); // wait until IBIF;
IIC1S_IICIF=1; // clear the interrupt event flag;
while(IIC1S_RXAK); // check for RXAK;
//-----Slave ACK occurred------------
IIC1D = Addr_L; // Send low byte of word address;
while (!(IIC1S_IICIF)); // wait until IBIF;
IIC1S_IICIF=1; // clear the interrupt event flag;
while(IIC1S_RXAK); // check for RXAK;
//-----Slave ACK occurred------------
IIC1C_RSTA = 1; // set up repeated start;
IIC1D = EEPROM_ID | temp | 1; // (slave_address) | (RW = 1);
while (!(IIC1S_IICIF)); // wait until IBIF;
IIC1S_IICIF=1; // clear the interrupt event flag;
while (IIC1S_RXAK); // check for RXAK;
//-----Slave ACK occurred------------
IIC1C_TX = 0; // set up to receive;
IIC1C_TXAK = 1; // acknowledge disable;
temp = IIC1D; // dummy read;
while (!(IIC1S_IICIF)); // wait until IBIF;
IIC1S_IICIF=1; // clear the interrupt event flag;
IIC1C_MST = 0; // generate stop signal;
RD_data = IIC1D; // read right data;
return RD_data;
}



And here the call of functions:

 

  i2c_init();                     // initialize the MCU
 
  eeprom_address = 5;
 
  eeprom_bytewrite(eeprom_address, vd);

 

  eeprom_address = 5;  
 
    templida = eeprom_byteread(eeprom_address);

 

WHAT'S HAPPENING? ALWAYS THE READING GIVES AS RESULT 255, ALWAYS. What's wrong?

0 Kudos