I am fairly new to I2C so please excuse my lack of knowledge. I am trying to read Data from an PAC1710 sensor using an Stm32H743ZI MCU with the HAL-Library and the cubemx code generator.
I can send the first part of my message but I don't get an acknowledge after sending the address. I am using a 2700 Ohm resistor to ground on the ADDR_SEL Pin, ALERT goes to ground over an 10 kOhm resistor.
As for my code, this is my intializiation:
void MX_I2C2_Init(void)
{
hi2c2.Instance = I2C2;
hi2c2.Init.Timing = 0x307075B1;
hi2c2.Init.OwnAddress1 = 0;
hi2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c2.Init.OwnAddress2 = 0;
hi2c2.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c2) != HAL_OK) {
Error_Handler();
}
/** Configure Analogue filter */
if (HAL_I2CEx_ConfigAnalogFilter(&hi2c2, I2C_ANALOGFILTER_ENABLE) != HAL_OK) {
Error_Handler();
}
/** Configure Digital filter */
if (HAL_I2CEx_ConfigDigitalFilter(&hi2c2, 0) != HAL_OK) {
Error_Handler();
}
}
void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if (i2cHandle->Instance == I2C2) {
/* USER CODE BEGIN I2C2_MspInit 0 */
/* USER CODE END I2C2_MspInit 0 */
__HAL_RCC_GPIOF_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/**I2C2 GPIO Configuration
PB11 ------> I2C2_SDA
PF1 ------> I2C2_SCL
*/
GPIO_InitStruct.Pin = GPIO_PIN_1;
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_I2C2;
HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_11;
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_I2C2;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* I2C2 clock enable */
__HAL_RCC_I2C2_CLK_ENABLE();
}
}
My implementation is very simplistic:
uint8_t i2cbuffer[8];
uint16_t val = 0;
HAL_StatusTypeDef ret;
and in the main loop I have the following code:
i2cbuffer[0] = 254;
ret = HAL_I2C_Master_Transmit(&hi2c2, PAC1710Address << 1, i2cbuffer, 1, HAL_MAX_DELAY);
if (ret == HAL_OK) {
ret = HAL_I2C_Master_Receive(&hi2c2, PAC1710Address << 1 , i2cbuffer, 2, HAL_MAX_DELAY);
if (ret == HAL_OK) {
val = i2cbuffer[0];
}
}
HAL_Delay(500);
I chose 254 because I though the slave should be able to answer to that regardless of his measurement. However I don't even get as far as sending the register, after looking into it with an oscilloscope I send the address and get a NACK.
Is there anything obvious I am missing?
After some comments, there was more useful info, biggest part being that oscilloscope showed Start 1010100 0 1 Stop
. While 1010100
is the 0x54 address, the W
bit needs to be counted as well, so the 8-bit data was actually 10101000
, instead of the expected 01010100
. Address should not have been shifted left, as it was already correct.
This is a somewhat common mistake with I2C. Attention needs to be paid to the exact address and R/!W
bits, as in some documents and APIs they're shifted left, in some they aren't.
A very helpful bit of info here was the oscilloscope trace, that really helped show what exactly is going on.