Skip to main content
hbhim
Associate II
December 28, 2018
Question

Read/Write specific register value on I2C

Hi,

I am using STM32L031K6 MCU and SW4STM32 IDE for development. I want to read/write specific register value of i2c slave device from MCU(i2c master)

Below is a code I am using.

#include "main.h"
 
#define I2C_ADDRESS 0x3c
#define MASTER_BOARD
#define I2C_TIMING 0x00B1112E 
 
I2C_HandleTypeDef I2cHandle;
 
uint8_t aTxBuffer[] = "ff";
uint8_t aRxBuffer[4];
 
void SystemClock_Config(void);
static uint16_t Buffercmp(uint8_t* pBuffer1, uint8_t* pBuffer2, uint16_t BufferLength);
static void Error_Handler(void);
 
int main(void)
{
 GPIO_InitTypeDef GPIO_InitStruct;
 HAL_Init();
 SystemClock_Config();
 BSP_LED_Init(LED3);
 
 I2cHandle.Instance = I2Cx;
 I2cHandle.Init.Timing = I2C_TIMING;
 I2cHandle.Init.OwnAddress1 = I2C_ADDRESS;
 I2cHandle.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
 I2cHandle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
 I2cHandle.Init.OwnAddress2 = 0xFF;
 I2cHandle.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
 I2cHandle.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
 I2cHandle.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; 
 
 if(HAL_I2C_Init(&I2cHandle) == HAL_ERROR)
 {
 Error_Handler();
 }
 
 
 HAL_I2CEx_ConfigAnalogFilter(&I2cHandle,I2C_ANALOGFILTER_ENABLE);
 do
 {
 if(HAL_I2C_Mem_Read(&I2cHandle, (uint16_t)I2C_ADDRESS, (uint16_t)0x00, I2C_MEMADD_SIZE_8BIT, (uint8_t *)aRxBuffer, 1, 10) != HAL_OK)
 {
 Error_Handler();
 }
 while (HAL_I2C_GetState(&I2cHandle) != HAL_I2C_STATE_READY)
 {
 }
 }
 while(HAL_I2C_GetError(&I2cHandle) == HAL_I2C_ERROR_AF);
 
 HAL_Delay(1000);
 while (1)
 {
 }
}
 
void SystemClock_Config(void)
{
 RCC_ClkInitTypeDef RCC_ClkInitStruct ={0};
 RCC_OscInitTypeDef RCC_OscInitStruct = {0};
 
 __HAL_RCC_PWR_CLK_ENABLE();
 
 __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
 
 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
 RCC_OscInitStruct.HSIState = RCC_HSI_ON;
 RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
 RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
 RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL4;
 RCC_OscInitStruct.PLL.PLLDIV = RCC_PLL_DIV2;
 if (HAL_RCC_OscConfig(&RCC_OscInitStruct)!= HAL_OK)
 {
 /* Initialization Error */
 while(1); 
 }
 
 RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | 
 RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | 
 RCC_CLOCKTYPE_PCLK2);
 RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
 RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
 RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; 
 RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; 
 if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1)!= HAL_OK)
 {
 /* Initialization Error */
 while(1); 
 }
}
 
void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *I2cHandle)
{
 BSP_LED_Toggle(LED3);
}
 
void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *I2cHandle)
{
 BSP_LED_Toggle(LED3);
}
 
void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *I2cHandle)
{
 if (HAL_I2C_GetError(I2cHandle) != HAL_I2C_ERROR_AF)
 {
 Error_Handler();
 }
}
 
static void Error_Handler(void)
{
 while(1)
 {
 BSP_LED_Toggle(LED3);
 HAL_Delay(1000);
 }
}

HAL_I2C_Mem_Read is not returning HAL_OK and starts blinking LED3 from Error_Handler().

Please advice, thank you!

This topic has been closed for replies.

11 replies

S.Ma
Principal
December 28, 2018

Not clear. Is the STM32 a master or a slave? If master talking to a mems, the mcu own address should be unique from other devices. If master, start with gpio sw bit bang i2c emulation to validate the hw and system, then activate the Hw I2c peripheral. If the Mcu should behave as slave, no comments.

hbhim
hbhimAuthor
Associate II
December 28, 2018

MCU is a master device. There is only once slave connected on i2c bus.

S.Ma
Principal
December 28, 2018

I2cHandle.Init.OwnAddress1 = I2C_ADDRESS;

replace by

I2cHandle.Init.OwnAddress1 = 0xAA; // an unused address

And check if this makes a difference

Mon2
Senior III
December 29, 2018

Try,

// Actual I2C address to use is 0x3c = 0011 1100 << 1 = 0111 1000
I2cHandle.Init.OwnAddress1 = 0x78; 

I2cHandle.Init.OwnAddress1 = 0x78; // that is your I2C address of 0x3c = 0011 1100 << 1 = 0111 1000

also,

 if(HAL_I2C_Mem_Read(&I2cHandle, (uint16_t)I2C_ADDRESS, (uint16_t)0x00, I2C_MEMADD_SIZE_8BIT, (uint8_t *)aRxBuffer, 1, 10) != HAL_OK)

The 0x00 is the register address you will be R/W from I2C slave.

hbhim
hbhimAuthor
Associate II
December 31, 2018

Thank you for the answer. Tried with 0x78 I2C address, but no luck. Found same behaviour.

Mon2
Senior III
December 31, 2018

Hi. Meant to say to use:

#define I2C_ADDRESS 0x78

Is that what you tested?

Q1: Did you apply the required pull-up resistors onto your I2C port pins? Confirm this as they are mandatory. The value is not critical but often the values are 2k2 to 10k for the pull-up on SCL and SDA port pins to +3v3. This is because I2C is an open drain architecture, meaning that there is a logic low definition but no logic high. So the pull-up resistors are required else will not work correctly.

Q2: What is the I2C widget you are using? What does the datasheet report as the I2C address?

Q3: In your code, where is the error being raised? Comment out line 44 and see if you still get the error handler being called. That is, perhaps the error being raised is somewhere else.