2011-11-21 03:18 PM
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 Paul2011-11-21 04:39 PM
Take a look at the ST supplied ''standard peripherals library''. It contains simple code examples for talking to the I2C port.
2011-11-22 12:57 AM
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.
2011-11-22 02:46 PM
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.2011-11-23 01:17 AM
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.2011-11-23 05:50 AM
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 :)
2011-11-23 05:53 AM
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.
2011-11-23 06:10 AM
In that case I shall have a look into using the SYSCFG unit.
Cheers :) Paul2011-11-23 12:58 PM
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.2011-11-24 04:46 AM
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.