LPC11Uxx I2C repeated start issue

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

LPC11Uxx I2C repeated start issue

3,420 Views
diggitallr
Contributor I

LPC11UXX I2C repeated start and sequental read

 

I have trouble getting the repeated start to work.

I'm trying to write a easy code for reading values from MMA8452 accelerometer.

 

Code i'm an working on:

 

int debug = 0;

while(debug < 5){    //get_data looppi

 

 

  LPC_I2C->CONSET |= (1<<5);            

  do{                                   

  status = LPC_I2C->STAT & 0xF8;    

  }

  while(status != 0x08);               

  //START bit + accelerometer adress + writebit

  LPC_I2C->DAT        = 0x38;            //Device adress + W

  LPC_I2C->CONCLR     = 0x28;           

 

  //Transmit 1:st registry adress to start read from

  while(LPC_I2C->STAT != 0x18);          

  LPC_I2C->DAT        = 0x01;           

  LPC_I2C->CONCLR     = (1<<3);          

 

//start bit + accelerometer adress + readbit

  while(LPC_I2C->STAT != 0x28);

  LPC_I2C->CONSET |= (1<<5);

  LPC_I2C->DAT        = 0x39;           //Device adress + R

  LPC_I2C->CONCLR     = 0x28;         

 

_delay_ms(100);

  debug ++;

}

return 0 ;

 

I've learned from the LPC11U14 manual, that by setting the CONSET registry flag for (bit:5) START to 1, the next datawrite operation should come with repeated start.

It doesn't work.

 

Accelorometer replies with ACK, the communication works. I just can't get the repeated start to work.

 

Code is based on https://eewiki.net/display/microcontroller/Getting+Started+with+NXP

The LPCXpresso provided examples for LPC11Uxx are quite complicated with several headerfiles and extensive implementation of features.

 

What am i doing wrong?

 

Oscari

 

Attached image of datatransmission.

Labels (1)
0 Kudos
Reply
6 Replies

2,702 Views
diggitallr
Contributor I

As a reply to my original question about the different states and catching the right statecode for next account.
I found an way where the code waits for SIC-bit, instead of explicit states.

            LPC_I2C->CONSET       = (1<<5);

            while(!(LPC_I2C->CONSET & (1<<3)));   //Wait for interupt to be set

            LPC_I2C->DAT               = 0x38;             //Device adress + W

             LPC_I2C->CONCLR     = (1<<5); // Reset STA

             LPC_I2C->CONCLR     = (1<<3); //Reset interupt

             //Transmit 1:st registry adress to start read from

             //while(LPC_I2C->STAT != 0x18);

             while(!(LPC_I2C->CONSET & (1<<3)));

             LPC_I2C->DAT              = 0x01;

             LPC_I2C->CONCLR     = (1<<3);

             //start bit + accelerometer adress + readbit

             while(!(LPC_I2C->CONSET & (1<<3)));

             LPC_I2C->CONCLR     = (1<<3);

             LPC_I2C->CONSET     = (1<<5);               //Set Startbit

             //Adress + readbit with repeated start

             while(!(LPC_I2C->CONSET & (1<<3)));

             LPC_I2C->CONCLR     = (1<<3);

             LPC_I2C->DAT              = 0x39;           //Device adress + R

             //wait for last i2c operation to execute

             //while(!(LPC_I2C->CONSET & (1<<3)));

             LPC_I2C->CONCLR     = (1<<5);          //Clear Startbit

             LPC_I2C->CONCLR     = (1<<3);

             // Read X MSB

             while(!(LPC_I2C->CONSET & (1<<3)));

             Rbuf[0] = LPC_I2C->DAT;           

             LPC_I2C->CONSET = (1<<2);          // ACK first byte

             LPC_I2C->CONCLR     = (1<<3);

             // Read X LSB

             while(!(LPC_I2C->CONSET & (1<<3)));

             Rbuf[1] = LPC_I2C->DAT;

             LPC_I2C->CONCLR = (1<<2);          //NACK Second byte

             LPC_I2C->CONCLR     = (1<<3);

             while(!(LPC_I2C->CONSET & (1<<3)));

               LPC_I2C->CONCLR     = (1<<5);   //cleat STA

               LPC_I2C->CONSET     = (1<<4);   

               LPC_I2C->CONCLR     = (1<<3);         

The code works as intended. I got enough playing around with states. I got the sending states to work, but when it came to dealing with repeated start, write/read and ack/nack in same transmission, use of states came overwhelming.

I've attaached an image about the above transmission.

TX-RX_succes.png

0 Kudos
Reply

2,699 Views
diggitallr
Contributor I

Thank you for response. I've tested the code with added delay.

while(debug < 1){    //get_data looppi

status = 0;

//START bit + accelerometer adress + writebit

LPC_I2C->CONSET  = (1<<5);

do{                                    //wait for start condition to be sent

    status = LPC_I2C->STAT & 0xF8;    //store current state (sec 15.7.2)

  }

while(status != 0x08);

  LPC_I2C->DAT        = 0x38;            //Device adress + W

LPC_I2C->CONCLR    = (1<<3); //Reset SI

LPC_I2C->CONCLR = (1<<5); // Reset STA

//Transmit 1:st registry adress to start read from

while(LPC_I2C->STAT != 0x18);

  LPC_I2C->DAT        = 0x01;

LPC_I2C->CONCLR    = (1<<3);

//start bit + accelerometer adress + readbit

while(LPC_I2C->STAT != 0x28);

  _delay_ms(1);

LPC_I2C->CONSET    |= (1<<5);

_delay_ms(1);

//while(LPC_I2C->STAT != 0x10)

LPC_I2C->DAT        = 0x39;          //Device adress + R

LPC_I2C->CONCLR = (1<<3);

_delay_ms(100);

debug = 2;

}

The delay didn' do the trick.

I have been reading the LPC11Uxx manual, the I2C section really closely to be precise.

The MMA8452 needs the following data sequence illustrated in the attached image. The initialization code works well and data transmission is correct.

I can't get an hold on about how the I2C bus actually works. I think i should change the operation mode to MASTER-RECEIVE from MASTER-TRANSMIT that is udes in the initialization of the accelerometer. The initialization is a set of binary instructions write to the various setup registry, that works and the accelerometer answers with ACK.

If I uncomment the STAT  != 0x10 condition, code stops running at that point. Clearly there is a problem with repeated start with my code.

The documentation gave me an expression that the status registry as instructive register, I've got that expression that the status flags must be correct for repeated start to occur. The communication must be controller with the status registry.

I can't understand how the communication should be done.

Loop start{

CONSET bit to 1

Status = 0x08

send DAT, device adress + writebit (8bit)   -> master transmit, status changes to 0x18

send DAT, registry adress (7bit)  -> master transmit, status changes to 0x28

CONSET bit to 1 for repeated start.

send DAT, device adress + readbit (8bit) -> mode should be in master receive, status changes to 0x40

(of course the necessary SI and STA CONCLR bits are set between commands)

the 0x40 status for reading data expects the previous state to be 0x08 or 0x10. How can i write data without changing the state to 0x28.

The 0x28 sends automaticly STOP-flag if no data is sent after.

The more I try to understand, the more questions I've got.

I can't be to far away from working code, any further advice would be highly appreciated.

Oscari

0 Kudos
Reply

2,699 Views
rolfmeeser
NXP Employee
NXP Employee

Make sure to never use read-modify-write with the CONSET Register. There are CONSET|= statements which should be plain assignments (CONSET=) instead.

Clearing SI bit must be the last action in each state. It's wrong to clear SI and clear STA afterwards. Change the order in which you clear the bits, or clear them simultaneously (CONCLR=SIC|STAC)

In state 0x28 you are almost there: CONSET=STA, CONCLR=SIC (missing...). This will bring you to state 0x10.

Once there, don't forget to clear both SI and STA after writing the read address to DAT.

2,699 Views
diggitallr
Contributor I

Thank you.
I didn't realise that the order of clearing flags had such a big impact.

I got the code working after tweaking with the SIC clear bit.

0 Kudos
Reply

2,697 Views
diggitallr
Contributor I

I've made an illustrative diagram to explain the data transmission.

I have been working with I2C devices bvefore, i'm new to LPC11U14 and LPCXpresso development environment. I can't get an hold on how the transmission syntax should be setup in programming code.
I don't need an working example of code, an example or pseudocode about how the STAT-register and order of commands would be helpfull.

Oscari

0 Kudos
Reply

2,697 Views
kerryzhou
NXP TechSupport
NXP TechSupport

Hi Oscari,

  Because I don't have the MMA8452 accelerometer on my side, then I can't test it.

  But I think you can try to add a little delay follow 0X01+ACK

int debug = 0;

while(debug < 5){    //get_data looppi

  LPC_I2C->CONSET |= (1<<5);           

  do{                                   

  status = LPC_I2C->STAT & 0xF8;   

  }

  while(status != 0x08);               

  //START bit + accelerometer adress + writebit

  LPC_I2C->DAT        = 0x38;            //Device adress + W

  LPC_I2C->CONCLR    = 0x28;           

  //Transmit 1:st registry adress to start read from

  while(LPC_I2C->STAT != 0x18);         

  LPC_I2C->DAT        = 0x01;           

  LPC_I2C->CONCLR    = (1<<3);         

//start bit + accelerometer adress + readbit

  while(LPC_I2C->STAT != 0x28);

_delay_ms(5);

  LPC_I2C->CONSET |= (1<<5);

  LPC_I2C->DAT        = 0x39;          //Device adress + R

  LPC_I2C->CONCLR    = 0x28;         

_delay_ms(100);

  debug ++;

}

return 0 ;

I have check your wave, it seems the I2C data signal didn't pullup in time, so please add the delay(5) check it again, whether the I2C_DAT can be pullup?

74.jpg

After add the delay, please give me your test wave, I need to analysis it.


Have a great day,
Jingjing

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos
Reply