Recently I've been trying to get the I2C bus working on the STM32F030F4P6 MCU, but with little luck.
I'm using an STM32F0 module and have found plenty of resources for the STM32F1 module I2C initialization, but nothing specific about the STM32F0 initialization/transfer process.
Here's my initialization code:
void i2c_init(uint8_t ownAddress)
{
GPIO_InitTypeDef GPIO_InitStructure;
I2C_InitTypeDef I2C_InitStructure;
// Enable GPIOA clocks
RCC_APB2PeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
// Configure I2C1 clock and GPIO
GPIO_StructInit(&GPIO_InitStructure);
/* I2C1 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
/* I2C1 SDA and SCL configuration */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* I2C1 Reset */
RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, ENABLE);
RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, DISABLE);
/* Configure I2C1 */
I2C_InitStructure.I2C_AnalogFilter = I2C_AnalogFilter_Enable;
I2C_StructInit(&I2C_InitStructure);
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
//I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = ownAddress;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
//I2C_InitStructure.I2C_ClockSpeed = ClockSpeed;
I2C_Init(I2C1, &I2C_InitStructure);
I2C_Cmd(I2C1, ENABLE);
}
In order to test to see if my setup was correct I designed some I2C transmission code that would transfer data in a never ending loop. Here's the code for that:
while(1)
{
I2C_SlaveAddressConfig(I2C1, RegName);
I2C_GenerateSTART(I2C1, ENABLE);
I2C_NumberOfBytesConfig(I2C1, 8);
I2C_SendData(I2C1,0b00000000);
I2C_GenerateSTOP(I2C1, ENABLE);
}
Where:
RegName = 0x75
SDA = GPIO_PIN_10 on GPIOA
SCL = GPIO_PIN_9 on GPIOA
I2C = I2C1
ownAdrress = 0x68
When I scope the I2C lines after I start this code I get a floating voltage around 160mV. When I step through the code every one of the I2C function calls happen and complete, so that's why I was thinking that it had something more so to do with my initialization of the pins themselves.
My problem is very similar to this thread, but was never answered:
Edit 1: Here's my latest code; still not working (Edit 2: Updated to what I currently have; moved things into more correct locations):
void i2c_init(uint8_t ownAddress)
{
/* TypeDefs for GPIOA and I2C1 */
GPIO_InitTypeDef GPIO_InitStructure;
I2C_InitTypeDef I2C_InitStructure;
/* Enable GPIOA clocks and I2C1 clock enable */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
/* Configure I2C1 clock and GPIO */
GPIO_StructInit(&GPIO_InitStructure);
/* I2C1 SDA and SCL configuration */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; //UP
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
/* GPIO AF Configuration -> GPIO_AF_1: USART2, CEC, Tim3, USART1, USART2,EVENTOUT, I2C1, I2C2, TIM15 */
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1);
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* I2C1 Reset */
RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, ENABLE);
RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, DISABLE);
//I2C_DeInit(I2C1);
/* Configure I2C1 */
I2C_StructInit(&I2C_InitStructure);
I2C_InitStructure.I2C_AnalogFilter = I2C_AnalogFilter_Enable;
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_OwnAddress1 = ownAddress;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_Init(I2C1, &I2C_InitStructure);
I2C_Cmd(I2C1, ENABLE);
//I2C_AcknowledgeConfig(I2C1, ENABLE);
}
As you can see I added the two lines GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1);
and GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1);
where I found that GPIO_AF_1 had the alternate function of I2C1 from the STM32F0 Standard Peripheral bibliotheek.
Any other ideas? I've been playing around with the clocks to see if that changed anything and have been adding snippets of other people's code just to see if that has any effect on the output of my device.
Edit 3: I have tried pulling both the SDA and SCL lines up to VCC with a 1kohm resistor as instructed by this guide: https://electronics.stackexchange.com/questions/57121/i2c-pullup-resistor-calculations
->(3.3V-0.4)/3mA ~= 1kohm
Edit 4: After going through my code line by line I tried outputting various flag bit registers. Specifically these registers: isr = I2C1->ISR;
, cr1 = I2C1->CR1;
, and cr2 = I2C1->CR2;
The flag I get after initiating the I2C transfer handling with I2C_TransferHandling(I2C1, 0x02, 1, I2C_AutoEnd_Mode, I2C_Generate_Start_Write);
was 0x8001
which can be deciphered down to two errors:
#define I2C_ISR_BUSY ((uint32_t)0x00008000) /*!< Bus busy */
and
#define I2C_ISR_TXE ((uint32_t)0x00000001) /*!< Transmit data register empty */
I've found some work arounds at this link here (remove the space after https: to go to the link -> stack overflow won't let me post more than 1 link for some reason): https: //my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=%2Fpublic%2FSTe2ecommunities%2Fmcu%2FLists%2Fcortex_mx_stm32%2FSTM32L151RB%20I2C%20Busy%20flag%20always%20set&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B¤tviews=690 that I'm looking to implement and will report back as soon as I try them out.