cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F407VG I2C HAL_I2C_ERROR_AF Error but not in SPL?

Jeremy Vance_2
Associate III
Posted on January 13, 2016 at 18:53

So, I'm trying to take the plunge into HAL with my STM32F407VG to be more ''future-proof'' but HAL seems to fight me at every avenue. Today's headache: I2C. Something that is usually pretty trivial to do has turned into just frustration. I have dumbed this down to a newly created project in STM32CubeMX with I2C1 being used.

I'm trying to write to device 0x94, address 0x2, value 0x1. So I try to use the following:

1.
uint8_t data[2] = { 2, 1 };
2.
HAL_I2C_Master_Transmit(&hi2c1, 0x94, &data[0], 2, 100);

Here are the cube's generated files for I2C:


/* I2C1 init function */

void
MX_I2C1_Init(
void
)

{


hi2c1.Instance = I2C1;

hi2c1.Init.ClockSpeed = 400000;

hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;

hi2c1.Init.OwnAddress1 = 0;

hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;

hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLED;

hi2c1.Init.OwnAddress2 = 0;

hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLED;

hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLED;

HAL_I2C_Init(&hi2c1);


}

and low level initialization:


void
HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c)

{


GPIO_InitTypeDef GPIO_InitStruct;

if
(hi2c->Instance==I2C1)

{

/* USER CODE BEGIN I2C1_MspInit 0 */


/* USER CODE END I2C1_MspInit 0 */


/**I2C1 GPIO Configuration 

PB8 ------> I2C1_SCL

PB9 ------> I2C1_SDA 

*/

GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;

GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;

GPIO_InitStruct.Pull = GPIO_PULLUP;

GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;

GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;

HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);


/* Peripheral clock enable */

__I2C1_CLK_ENABLE();

/* USER CODE BEGIN I2C1_MspInit 1 */


/* USER CODE END I2C1_MspInit 1 */

}

}

Here is the code from my std periph lib program using direct register changing:


// Configure I2C SCL and SDA pins.

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9; 

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;

GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

GPIO_Init(GPIOB, &GPIO_InitStructure);


GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_I2C1);

GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_I2C1);


// Configure I2C.

uint32_t pclk1 = 42000000;


I2C1 ->CR2 = pclk1 / 1000000; 
// Configure frequency and disable interrupts and DMA.

I2C1 ->OAR1 = I2C_OAR1_ADDMODE | 0x33;


// Configure I2C speed in standard mode.

const
uint32_t i2c_speed = 100000;

int
ccrspeed = pclk1 / (i2c_speed * 2);

if
(ccrspeed < 4) {

ccrspeed = 4;

}

I2C1 ->CCR = ccrspeed;

I2C1 ->TRISE = pclk1 / 1000000 + 1;


I2C1 ->CR1 = I2C_CR1_ACK | I2C_CR1_PE; 
// Enable and configure the I2C peripheral.

And here is the write function for the same command:


while
(I2C1 ->SR2 & I2C_SR2_BUSY );

I2C1 ->CR1 |= I2C_CR1_START; 
// Start the transfer sequence.

while
(!(I2C1 ->SR1 & I2C_SR1_SB )); 
// Wait for start bit.

I2C1 ->DR = 0x94;

while
(!(I2C1 ->SR1 & I2C_SR1_ADDR )); 
// Wait for master transmitter mode.

I2C1 ->SR2;

I2C1 ->DR = 0x02; 
// Transmit the address to write to.

while
(!(I2C1 ->SR1 & I2C_SR1_TXE )); 
// Wait for byte to move to shift register.

I2C1 ->DR = 0x01; 
// Transmit the value.

while
(!(I2C1 ->SR1 & I2C_SR1_BTF )); 
// Wait for all bytes to finish.

I2C1 ->CR1 |= I2C_CR1_STOP; 
// End the transfer sequence.

The std periph works great everytime. The HAL library fails with the same error after the device address is sent HAL_I2C_ERROR_AF everytime. Can someone tell me what I'm doing wrong here? I have put the same device on the logic analyzer and I get 0x94+NAK on the HAL and 0x94+ACK, 0x2, 0x1 on the Std Periph. Thanks for any help! #i2c #stm32f407vg #fixed
7 REPLIES 7
Jeremy Vance_2
Associate III
Posted on January 14, 2016 at 01:40

I posted the HAL code with 400kHz as the speed but that was just from me trying something.  I have tried in both 100kHz and 400kHz modes.  On the logic analyzer both waveforms are identical up to the NAK on the HAL side and measure at 100kHz.

Jeremy Vance_2
Associate III
Posted on January 14, 2016 at 03:03

(No Text)... Post from my phone.  Apparently, it doesn't work well.

Jeremy Vance_2
Associate III
Posted on January 14, 2016 at 17:24

Does anyone have any ideas?  Surely, someone has used i2C with HAL?

Amel NASRI
ST Employee
Posted on January 15, 2016 at 17:28

Hi vance.jeremy,

If you increase the timeout value (Ex: use 10000 instead of 100), do you get the same error?

-Mayla-

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Jeremy Vance_2
Associate III
Posted on January 16, 2016 at 00:59

Mayla,

   Thanks for getting back to me on this.  I tried changing the timeout to 10000 and I still get the same error for each and every try.  No ACK from the CS43L22.  I have also tried this on the F407 Discovery board and am getting the exact same results.

Jeremy Vance_2
Associate III
Posted on January 18, 2016 at 18:32

Argh, found the issue.  I had a bug in the initialization of the CS43L22 DAC.  The reset line was being kept low for an active low reset line.  Problem fixed and I2C on HAL is working.

Amel NASRI
ST Employee
Posted on January 20, 2016 at 08:39

Great to know that you fixed your issue. Thanks for update.

-Mayla-

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.