cancel
Showing results for 
Search instead for 
Did you mean: 

Does anyone have a quick and dirty i2c example?

paulcowper
Associate II
Posted on November 22, 2011 at 00:18

Hi all,

I am very new to the STM32, currently using the STM32L..

As I am new to developing on this platform (Never touched anything ARM before), I am overwhelmed by the amount of documentation although trying to dig out the bits that are useful is a little confusing to me right now. While there is lots of information about i2c, it is very application specific (EEPROM etc). Some times I think simple is best.

I am wondering if anyone would be able to take the time to help me? I am using the standard lib and using TrueStudio.

I would like to see if anyone could create or already has an example of the following:

Setting up i2c, Setting the micro as the master, checking the presense of the device at address 0x40 and verifying the ACK and sending data to it, and maybe as a brucie bonus being able to do the same for a second device on the same bus. The actual slave is an IO extender device that I am using to test i2c.

Now I could go and read through the documentation again lots of times and try and get the bits I need. I have tried and failed to break bits out of the ST help files.

Your efforts are most apreciated :)

Many Thanks

Paul
14 REPLIES 14
infoinfo989
Associate III
Posted on November 22, 2011 at 01:39

Take a look at the ST supplied ''standard peripherals library''. It contains simple code examples for talking to the I2C port.

paulcowper
Associate II
Posted on November 22, 2011 at 09:57

That is what I have been using, but the provided examples are overly bloated and very application specific. All I need to do right now is to check if a provided address is on the bus but the documentation is obfuscating how I can find that out and the source code comments are not helping me much either.

paulcowper
Associate II
Posted on November 22, 2011 at 23:46

Well I have now created some code that I think looks ok from both the examples and things I have found around the internet. How ever I am always hitting the timeouts, either when checking I2C_EVENT_MASTER_MODE_SELECT or if I comment that part out, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED. I am watching these with breakpoints in Keil and they always hit.

I also can not see any activity on PB6 and PB7 (I realy should get a bus pirate)

I am hoping that it is something realy simple and that I am just not doing something that would be clear to someone with more experience. I am currently developing on the STM32L-Discovery.

Here is my current code...

#define I2C_SPEED 100000

#define I2C1_SLAVE_ADDRESS7 0x040

#define I2C_TIMEOUT 100000

GPIO_InitTypeDef GPIO_InitStructure;

I2C_InitTypeDef I2C_InitStructure;

/* PRIVATE */

int main(void)

{

    GPIO_InitTypeDef GPIO_InitStructure;

    I2C_InitTypeDef I2C_InitStructure;

    int TimeOut;

    

    /*!< I2C Periph clock enable */

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);

    

    /*!< SDA GPIO clock enable */

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);

    

    /*!< SCL GPIO clock enable */

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);

    

    /* Connect PXx to I2C_SCL */

    GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1);

    /* Connect PXx to I2C_SDA */

    GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_I2C1);

    

    

    /*!< Configure I2C SCL pin */

    GPIO_InitStructure.GPIO_Pin = GPIO_PinSource6;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz;

    GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;

    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;

    GPIO_Init(GPIOB, &GPIO_InitStructure);

    

     /*!< Configure I2C SDA pin */

    GPIO_InitStructure.GPIO_Pin = GPIO_PinSource7;

    GPIO_Init(GPIOB, &GPIO_InitStructure);

                                                                                      

    I2C_DeInit(I2C1);

    

    I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;

    I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;

    I2C_InitStructure.I2C_OwnAddress1 = 0x020;

    I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;

    I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;

    I2C_InitStructure.I2C_ClockSpeed = I2C_SPEED;

    I2C_Init(I2C1, &I2C_InitStructure);

    

    /*ENABLE*/

    I2C_Cmd(I2C1, ENABLE);

    I2C_GenerateSTART(I2C1, ENABLE);

    

    /* Check we can be master */

    TimeOut = I2C_TIMEOUT;

    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT))

    {

        TimeOut--;

        if (TimeOut == 0)

        {

            return 1;

        }

    } 

    

    I2C_SendData(I2C1, 0x03); /*Set pin states*/

                                              

    I2C_Send7bitAddress(I2C1, I2C1_SLAVE_ADDRESS7, I2C_Direction_Transmitter);

    

    TimeOut = I2C_TIMEOUT;

    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))

    {

        TimeOut--;

        if (TimeOut == 0)

        {

            I2C_GenerateSTOP(I2C1, ENABLE);

            return 2;

        }

    }

    return 1;

}

Any further help would be greatly apreciated.

camille
Associate II
Posted on November 23, 2011 at 10:17

Hello.

It seems you forgotted to enable the alternate function pin clock :

RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

you also should check the following event after sending the device 7bit adress :

I2C_CheckEvent(EE_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);

good luck.

paulcowper
Associate II
Posted on November 23, 2011 at 14:50

Thank you very much, I shall try that out when I get home. What a learning curve this is, but I am always up for a challenge :)

Posted on November 23, 2011 at 14:53

It seems you forgotted to enable the alternate function pin clock :

 

RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

The STM32L1xx series does not have this, there is now a SYSCFG unit. The L1, F2 and F4 series have the muxing under the individual GPIOx units.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
paulcowper
Associate II
Posted on November 23, 2011 at 15:10

In that case I shall have a look into using the SYSCFG unit.

Cheers  :)

Paul

paulcowper
Associate II
Posted on November 23, 2011 at 21:58

I have added

RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);

and still no luck, it also seems that some of the demos manage to omit this, but I guess it would be set up elsewhere in that case.

Looking at what I have, it seems pretty spot on to what works for others, But maybe I am missing something realy silly.

And just to verify I am externaly pulling up both SCL and SDA with 4k7 resistors.

camille
Associate II
Posted on November 24, 2011 at 13:46

Hi Paul.

Try the following :

Connect Pins to I2C_SCL/SDA after Configuring GPIO pins (''GPIO_PinAFConfig(...)'' after ''GPIO_Init(...)'' )

Enable I2C before configuring it (''I2C_Cmd(I2C1, ENABLE)'' before ''I2C_Init(I2C, &I2C_InitStructure)'')

Hope it will help.

Regards.