Skip to main content
paulcowper
Associate II
November 21, 2011
Question

Does anyone have a quick and dirty i2c example?

  • November 21, 2011
  • 14 replies
  • 2864 views
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
    This topic has been closed for replies.

    14 replies

    infoinfo989
    Associate III
    November 22, 2011
    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
    November 22, 2011
    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
    November 22, 2011
    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
    November 23, 2011
    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
    November 23, 2011
    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 :)

    Tesla DeLorean
    Guru
    November 23, 2011
    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 (See Profile) Up vote any posts that you find helpful, it shows what's working..
    paulcowper
    Associate II
    November 23, 2011
    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
    November 23, 2011
    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
    November 24, 2011
    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.

    paulcowper
    Associate II
    November 24, 2011
    Posted on November 24, 2011 at 15:32

    Hi Robin,

    Thank you for that, I shall try moving those about.

    Many Thanks

    Paul