2021-01-27 05:37 PM
Hello,
I have troubles using I2C with the STM32F103C8T6 "Blue Pill" board. I set up the code in CubeMX, using LL Libraries.
After initializing the I2C periphery I try to send the address, but the ADDR bit in I2C1_SR1 register remains 0. AF bit remains 0, too. I checked it by debugging and observing the registers. At the moment right before the function call "LL_I2C_TransmitData8(...)", in SR1, everything is 0 except SB, and in SR2 everything is 0 except BUSY and MSL. After this function call, SB becomes 0. After that, ADDR remains 0 and the program stucks in the while loop.
I could not find any solution to this problem neither on the internet, nor in the errata sheets.
I tested the I2C-LCD with an AVR Atmega328PB, works perfectly there. It's a 16x02 LCD with a PCF8574T 8-bit-to-i2c expander.
I am sure everything is connected properly: GND to GND, VCC to 5V, SDA to PB9, SCL to PB8. Also tested the contact with a multimeter.
Unfortunately, I don't have an oscilloscope or logic analyzer.
Here is my setup in CubeMX:
Here is the code:
#include "main.h"
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_I2C1_Init(void);
void errata_2_14_7_workaround(void)
{
LL_I2C_Disable(I2C1);
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = LL_GPIO_PIN_8|LL_GPIO_PIN_9; //PIN_8 = SCL, PIN_9 = SDA
GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;
LL_GPIO_Init(GPIOB, &GPIO_InitStruct);
LL_GPIO_SetOutputPin(GPIOB, LL_GPIO_PIN_8);
LL_GPIO_SetOutputPin(GPIOB, LL_GPIO_PIN_9);
while(!LL_GPIO_IsOutputPinSet(GPIOB, LL_GPIO_PIN_8) || !LL_GPIO_IsOutputPinSet(GPIOB, LL_GPIO_PIN_9)){}
LL_GPIO_ResetOutputPin(GPIOB, LL_GPIO_PIN_9);
while(LL_GPIO_IsOutputPinSet(GPIOB, LL_GPIO_PIN_9)){}
LL_GPIO_ResetOutputPin(GPIOB, LL_GPIO_PIN_8);
while(LL_GPIO_IsOutputPinSet(GPIOB, LL_GPIO_PIN_8)){}
LL_GPIO_SetOutputPin(GPIOB, LL_GPIO_PIN_8);
while(!LL_GPIO_IsOutputPinSet(GPIOB, LL_GPIO_PIN_8)){}
LL_GPIO_SetOutputPin(GPIOB, LL_GPIO_PIN_9);
while(!LL_GPIO_IsOutputPinSet(GPIOB, LL_GPIO_PIN_9)){}
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;
LL_GPIO_Init(GPIOB, &GPIO_InitStruct);
LL_I2C_EnableReset(I2C1);
LL_I2C_DisableReset(I2C1);
LL_I2C_Enable(I2C1);
}
int main(void)
{
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_AFIO);
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR);
NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
LL_GPIO_AF_Remap_SWJ_NOJTAG();
SystemClock_Config();
MX_GPIO_Init();
MX_I2C1_Init();
LL_GPIO_SetOutputPin(GPIOC, LL_GPIO_PIN_13); //LED off
errata_2_14_7_workaround();
LL_I2C_DisableBitPOS(I2C1);
LL_I2C_AcknowledgeNextData(I2C1, LL_I2C_ACK);
LL_I2C_GenerateStartCondition(I2C1);
while(!LL_I2C_IsActiveFlag_SB(I2C1)){};
(void) I2C1->SR1;
LL_I2C_TransmitData8(I2C1, (0x27 << 1)); //0x27 is the address of the Slave
while(!LL_I2C_IsActiveFlag_ADDR(I2C1) && !LL_I2C_IsActiveFlag_AF(I2C1)){}; //the program hangs here
LL_I2C_ClearFlag_ADDR(I2C1);
LL_I2C_GenerateStopCondition(I2C1);
while (1)
{
LL_mDelay(250);
LL_GPIO_TogglePin(GPIOC, LL_GPIO_PIN_13); //LED blinking
}
}
void SystemClock_Config(void)
{
LL_FLASH_SetLatency(LL_FLASH_LATENCY_2);
while(LL_FLASH_GetLatency()!= LL_FLASH_LATENCY_2)
{
}
LL_RCC_HSE_Enable();
/* Wait till HSE is ready */
while(LL_RCC_HSE_IsReady() != 1)
{
}
LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSE_DIV_1, LL_RCC_PLL_MUL_9);
LL_RCC_PLL_Enable();
/* Wait till PLL is ready */
while(LL_RCC_PLL_IsReady() != 1)
{
}
LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1);
LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_2);
LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1);
LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL);
/* Wait till System clock is ready */
while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL)
{
}
LL_Init1msTick(72000000);
LL_SetSystemCoreClock(72000000);
}
static void MX_I2C1_Init(void)
{
/* USER CODE BEGIN I2C1_Init 0 */
/* USER CODE END I2C1_Init 0 */
LL_I2C_InitTypeDef I2C_InitStruct = {0};
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOB);
/**I2C1 GPIO Configuration
PB8 ------> I2C1_SCL
PB9 ------> I2C1_SDA
*/
GPIO_InitStruct.Pin = LL_GPIO_PIN_8|LL_GPIO_PIN_9;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;
LL_GPIO_Init(GPIOB, &GPIO_InitStruct);
LL_GPIO_AF_EnableRemap_I2C1();
/* Peripheral clock enable */
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C1);
/* USER CODE BEGIN I2C1_Init 1 */
/* USER CODE END I2C1_Init 1 */
/** I2C Initialization
*/
LL_I2C_DisableOwnAddress2(I2C1);
LL_I2C_DisableGeneralCall(I2C1);
LL_I2C_EnableClockStretching(I2C1);
I2C_InitStruct.PeripheralMode = LL_I2C_MODE_I2C;
I2C_InitStruct.ClockSpeed = 100000;
I2C_InitStruct.DutyCycle = LL_I2C_DUTYCYCLE_2;
I2C_InitStruct.OwnAddress1 = 0;
I2C_InitStruct.TypeAcknowledge = LL_I2C_ACK;
I2C_InitStruct.OwnAddrSize = LL_I2C_OWNADDRESS1_7BIT;
LL_I2C_Init(I2C1, &I2C_InitStruct);
LL_I2C_SetOwnAddress2(I2C1, 0);
/* USER CODE BEGIN I2C1_Init 2 */
/* USER CODE END I2C1_Init 2 */
}
static void MX_GPIO_Init(void)
{
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOC);
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOD);
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOA);
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOB);
/**/
LL_GPIO_ResetOutputPin(GPIOC, LL_GPIO_PIN_13);
/**/
GPIO_InitStruct.Pin = LL_GPIO_PIN_13;
GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
LL_GPIO_Init(GPIOC, &GPIO_InitStruct);
}
void Error_Handler(void)
{
}