LPC810 I2C: master write one byte to subaddress

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

LPC810 I2C: master write one byte to subaddress

2,208 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by bremans on Sun Jan 04 14:14:52 MST 2015
Hi,

I'm a newbie trying out with the LPC810.

I'm trying to use the I2C to turn on an oled display (no specific reason, just a learning experience). After going through the datasheet several times.. I hope somebody can tell me what's missing in my code.

It should write 0xAF to subaddress 0x00, the address of the display is 0x3C. My code is based on the code example from the datasheet.


#include "LPC8xx.h"

#define I2C_CFG_MSTEN (0x1)
#define I2C_STAT_MSTPENDING (0x1)
#define I2C_STAT_MSTSTATE (0xe)
#define I2C_STAT_MSTST_IDLE (0x0)
#define I2C_STAT_MSTST_RX (0x2)
#define I2C_STAT_MSTST_TX (0x4)
#define I2C_MSTCTL_MSTCONTINUE (0x1)
#define I2C_MSTCTL_MSTSTART (0x2)
#define I2C_WSTCTL_MSTSTOP (0x4)

int main ()
{
        //Set clock for SWM
        LPC_SYSCON->SYSAHBCLKCTRL |= 1<<7;

        //Disable special functions
        LPC_SWM->PINENABLE0 |= 0xFF0FFFFFFUL;

        //Set pins for i2c
        LPC_SWM->PINASSIGN7 |= 0x03FFFFFFUL;
        LPC_SWM->PINASSIGN8 |= 0xFFFFFF04UL;
 
        //Set clock for IOCON
        LPC_SYSCON->SYSAHBCLKCTRL |= 1<<18;

        //Disable Pullups for PIO0_2 and PIO0_3
        LPC_IOCON->PIO0_2 = 0x80;
        LPC_IOCON->PIO0_3 = 0x80;
 
       //Set clock for i2c
        LPC_SYSCON->SYSAHBCLKCTRL |= 1<<5;

        //Set preset for i2c
        LPC_SYSCON->PRESETCTRL &= ~1<<6;
        LPC_SYSCON->PRESETCTRL |= 1<<6;

        //NVIC enable
        NVIC_EnableIRQ(I2C_IRQn);

        //Set i2c clock DIV
        LPC_I2C->DIV = 0x1;

        //Enable i2c master
        LPC_I2C->CFG = I2C_CFG_MSTEN;

        while(!(LPC_I2C->STAT & I2C_STAT_MSTPENDING));
        if((LPC_I2C->STAT & I2C_STAT_MSTSTATE) == I2C_STAT_MSTST_IDLE){
                //Set address
                LPC_I2C->MSTDAT = (0x3C << 1) | 0;
                //Send startbit
                LPC_I2C->MSTCTL = 0x2;
        }

        while(!(LPC_I2C->STAT & I2C_STAT_MSTPENDING));
        if((LPC_I2C->STAT & I2C_STAT_MSTSTATE) == I2C_STAT_MSTST_TX){
                //Send subaddress
                LPC_I2C->MSTDAT = 0x00;
                //Send continue
                LPC_I2C->MSTCTL = 0x1;
        }

        while(!(LPC_I2C->STAT & I2C_STAT_MSTPENDING));
        if((LPC_I2C->STAT & I2C_STAT_MSTSTATE) == I2C_STAT_MSTST_TX){
                //Send value
                LPC_I2C->MSTDAT = 0xAF;
                //Send continue
                LPC_I2C->MSTCTL = 0x1;
        }

        while(!(LPC_I2C->STAT & I2C_STAT_MSTPENDING));
        if((LPC_I2C->STAT & I2C_STAT_MSTSTATE) == I2C_STAT_MSTST_TX){
                //Send stopbit
                LPC_I2C->MSTCTL = 0x4;
        }

        while(!(LPC_I2C->STAT & I2C_STAT_MSTPENDING));
        if((LPC_I2C->STAT & I2C_STAT_MSTSTATE) == I2C_STAT_MSTST_IDLE);
}

Labels (1)
0 Kudos
Reply
4 Replies

1,986 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by HammingBird on Wed Mar 16 10:39:43 MST 2016

Hallo bremans,
you used "PIO0_3" and "PIO0_4" for SDA & SCL . And  you wrote:

//Disable Pullups for PIO0_2 and PIO0_3
        LPC_IOCON->PIO0_2 = 0x80;
        LPC_IOCON->PIO0_3 = 0x80;


So,  you are using pullups for  "PIO0_2" and "PIO0_3".
why ?  Because, you are using  "PIO0_3" and "PIO0_4"   for  SWM.

So,the pull up registors should be for both   "PIO0_3" and "PIO0_4" isn't it ? And the address is not 0x80  But 0x90.

Am I right ?

Thanks  :)
0 Kudos
Reply

1,986 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by larryvc on Mon Jan 05 19:52:40 MST 2015

Quote: bremans
Is this an error?

Most definitely!    The only way the code is working is because the left shift, by virtue of how it works, is leaving the lsb (bit 0) cleared.
0x23 = 0b00100011  << 1 = 0x46 = 0b01000110  


The example code was made using sloppy cut and paste without verification.  I'll report it.
0 Kudos
Reply

1,986 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by bremans on Mon Jan 05 11:59:52 MST 2015
Hi Larry,

Thx for the advice! I'm gonna study those bitwise operations!

But all the code examples (p. 340) are mentioning this:
LPC_I2C->MSTDAT = (0x23 << 1) | 0; // address and 0 for RWn bit in order to write
// subaddress


Is this an error?

Kind regards,

Bart
0 Kudos
Reply

1,986 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by larryvc on Mon Jan 05 01:22:53 MST 2015
I'm not sure what is causing the problem with your program, but I am wondering what you think this line of code will do.  Do you know that when you bitwise inclusive OR some value with 0 that nothing happens, the value remains unchanged?
    //Set address
    LPC_I2C->MSTDAT = (0x3C << 1) | 0;
Try these two code snippets and note the difference: (hovering over the | or & while in the debugger will show the value of the operation)
    int i;
    i = 0xFF | 0; // The value assigned to i is 0xFF, bitwise inclusive ORing with 0 did nothing to the value 0xFF
In order to clear a bit you need to use the bitwise AND of the ones complement of (1 shifted to the bit position of the bit you want to clear):
    int i;
    i = 0xFF & ~(1<<0); // The value assigned to i is 0xFE, bitwise ANDing with ~(1<<0) cleared bit 0

Knowledge of Boolean algebra and C Bit Operators is extremely important for working with microcontrollers, I suggest that you study up on them.
0 Kudos
Reply