Problem configuring I2C on CMWX1ZZABZ (that is to say STM32L072CZ) for accelerometer MMA8652.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2018-10-30 6:21 AM
Hi there! I am actually fighting again i2c communication on the B-L072Z-LRWAN1 evaluation board (STM32L072CZ). Basically I would like to interface a NXP MMA8652 accelerometer over the I2C bus. I was able to do that (get the "who am I" register, get x/y/z acceleration values) with an Arduino board but could not get it properly run on the ST. I can actually see the 100kHz SCL/SDA on the scope but the accelerometer only answers 0xff to all requests.
I used CubeMX to set the board, (I2C base freq is 2,048MHz), and based my code on the "I2C_TwoBoards_AdvComIT" example from ST.
The code is pretty simple, IT based.
Init:
hi2c1.Instance = I2C1;
hi2c1.Init.Timing = 0x00000708;
hi2c1.Init.OwnAddress1 = 0;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
Read:
uint8_t MMA8652_read(uint8_t address)
{
uint8_t aTransferRequest[2];
// Ask
// ##-5- Master sends read request for slave ##############################
do
{
if(HAL_I2C_Master_Transmit_IT(&hi2c1, (uint16_t)I2C_ADDRESS, (uint8_t*)&address, 1)!= HAL_OK)
{
Error_Handler();
}
while (HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY)
{
}
}
while(HAL_I2C_GetError(&hi2c1) == HAL_I2C_ERROR_AF);
// Get
//##-7- Master receives aRxBuffer from slave #############################
do
{
if(HAL_I2C_Master_Receive_IT(&hi2c1, (uint16_t)I2C_ADDRESS, (uint8_t*)aTransferRequest, 1)!= HAL_OK)
{
Error_Handler();
}
while (HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY)
{
}
}
while(HAL_I2C_GetError(&hi2c1) == HAL_I2C_ERROR_AF);
return aTransferRequest[0];
}
Here is the "detect accelerometer" function: the MMA8652 (address 0x1D) has a "who_am_i" register (address 0x0D) that should contains 0x4A.
From Arduino:
From the ST:
Did I miss something?
Thanks!
Bezac
Solved! Go to Solution.
- Labels:
-
I2C
Accepted Solutions
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2019-04-24 12:59 AM
Ouch! I cannot believe how lot I let this unsolved!
Long story short: the device (slave) actually has multiple byte read capability. It uses repeated start condition (generally "SR") and thus requires the *sequential* transmit function :
do
{
if(HAL_I2C_Master_Sequential_Transmit_IT(&Handle, (uint16_t)I2C_ADDRESS, (uint8_t*)aTxBuffer, 2, I2C_FIRST_FRAME)!= HAL_OK)
Error_Handler();
while (HAL_I2C_GetState(&Handle) != HAL_I2C_STATE_READY)
;
}
while(HAL_I2C_GetError(&Handle) == HAL_I2C_ERROR_AF);
That's all folk!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2018-10-30 8:50 AM
Just to add that PB8/9 are used (so alternate function 4):
/**I2C1 GPIO Configuration
PB9 ------> I2C1_SDA
PB8 ------> I2C1_SCL
*/
GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_8;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2018-10-30 2:05 PM
Got an I2C 128x64 OLED running off the LRWAN1-DISCO here, not using the IT variety.
From the scope it looks like the address has been shifted correctly on the ST implementation, ie I2C_ADDR =(0x1D << 1)
Up vote any posts that you find helpful, it shows what's working..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2018-10-31 1:51 AM
Thanks for the input Clive, the I2C address is indeed configured as you mentioned: (0x1D << 1). The data are not acknowledged when it is different, that actually shows that my i2C device is alive! Good to know.
It's now quite sure that the way to communicate, i.e. the way i2c is configured on the ST side, is to be ajusted.
Just in case, I gave a try with polling function (avoiding IT) and the result is (of course) similar. It is slightly faster though, which is hard to understand.
I am quite surprise of this long delay between pointing the register (in the previous scope-view: Write_1D, register 0D) and the request (Read_1D, Get_FF). This should actually be as fast as with the Arduino... I switched compiler options to size optimisation and no debug, the "delay" is shorter but still >200us. What's wrong here?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2019-04-24 12:59 AM
Ouch! I cannot believe how lot I let this unsolved!
Long story short: the device (slave) actually has multiple byte read capability. It uses repeated start condition (generally "SR") and thus requires the *sequential* transmit function :
do
{
if(HAL_I2C_Master_Sequential_Transmit_IT(&Handle, (uint16_t)I2C_ADDRESS, (uint8_t*)aTxBuffer, 2, I2C_FIRST_FRAME)!= HAL_OK)
Error_Handler();
while (HAL_I2C_GetState(&Handle) != HAL_I2C_STATE_READY)
;
}
while(HAL_I2C_GetError(&Handle) == HAL_I2C_ERROR_AF);
That's all folk!
