2019-12-01 07:41 AM
Hi,
I found in my search there is a similar question that went unanswered. This may be a newb question, but I'm stuck on it.
What I have found is that when executing HAL_I2C_Master_Transmit(), the data transfer happens as expected. (I happen to have green LEDs hanging on GPIO). When I execute HAL_I2C_Master_Transmit_IT(), only the 7-bit address is sent, and the Master (this program) continues to hold the SCL line low.
If someone could explain what I am doing wrong with the HAL_I2C_Master_Transmit_IT() program, that would be much appreciated!
//Turn on the two green LEDs on the LTC4306's GPIO
data[0] = 0x01;
data[1] = 0b00001111;
status = HAL_I2C_Master_Transmit(&hi2c1, ltc4306_Address, data, 2, 1 );
//Turn off the two green LEDs on the LTC4306's GPIO
data[0] = 0x01;
data[1] = 0b00111111;
status = HAL_I2C_Master_Transmit(&hi2c1, ltc4306_Address, data, 2, 1 );
//Turn on the two green LEDs on the LTC4306's GPIO
data[0] = 0x01;
data[1] = 0b00001111;
status = HAL_I2C_Master_Transmit_IT(&hi2c1, ltc4306_Address, data, 2 ); //This returns HAL_OK... but the master (this program) is holding SCL low after having transmitted the 7-bit address.
HAL_I2C_MasterTxCpltCallback(&hi2c1); // SCL still being held low after execution of this line. Doesn't seem to help.
2019-12-01 08:37 AM
Executing this line after the HAL_I2C_Master_Transmit_IT() function results in an infinite loop. I thought this might be a problem stepping through the program.
while (HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY){};
2019-12-08 10:07 AM
Any help would be much appreciated!
2019-12-09 06:12 AM
Have you enabled the interrupt for I2C?
2019-12-10 06:35 AM
Hi Johnny,
I appreciate the reply. I think I have interrupts enabled, but perhaps not properly.
I found an example in the STM32Cube installed files for IT functions here (this is where they are on my computer at least):
C:\Users\SomeGuyInNH\STM32Cube\Repository\STM32Cube_FW_G0_V1.3.0\Projects\NUCLEO-G071RB\Examples\I2C\I2C_TwoBoards_ComIT\Src
What I saw there were two functions in the HAL_I2C_MspInit() function
/* I2C1 interrupt Init */
HAL_NVIC_SetPriority(I2C1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(I2C1_IRQn);
I don't seem to have a HAL_I2C_MSPInit() but I'm wondering if this MX_I2C1_Init() is where to stick these functions. This is where the above functions are now, but the I2C bus is still hanging. It seems like it should be going to an ISR, but something is missing (or wrong).
2019-12-13 02:09 PM
Hi,
Any help from the community on this would be greatly appreciated. I've been stuck on this for two weeks now. I'm at the point I'm going to ditch the STM32 and start with a different brand microcontroller.
I am trying to send a repeated start on I2C. It seems from the documentation that using the _IT functions to do this is the only way, but all code I have tried results in the STM32G071RB holding the SCL line low indefinitely after HAL_I2C_Master_Transmit_IT(). I simply do not understand why it is doing this.
If anyone that can point me towards example code, or explain why the SCL line just hangs, it would be much appreciated.
Thanks
2019-12-16 12:47 AM
I don't know an answer to your exact question because i never use HAL_I2C_Master_Transmit_x but instead HAL_I2C_Mem_Read_x to read something from an address or HAL_I2C_Mem_Write_x to write something to an address. If you don't want to do something very special, it should work easy with these functions.
For example:
// Read from a sensor
HAL_I2C_Mem_Read_DMA(&hi2c1, I2CADDRESS_AS5601, ReadAddress, I2C_MEMADD_SIZE_8BIT, data, size);
For your need maybe something like this:
register_address = 0x01;
size = 1;
data[0] = 0b00001111;
HAL_I2C_Mem_Write_IT(hi2c1, ltc4306_Address, register_address, I2C_MEMADD_SIZE_8BIT, data, size, 100);
2020-08-05 07:45 AM
@SomeGuyFromNH Did you find a solution? I seem to have a similar problem.
2020-08-05 08:10 AM
@SomeGuyFromNH (Community Member), maybe it has something to do with the IRQ priorities. I think the SysTick should have a higher priority than the I2C, because HAL uses it for the timeout handling. So you could try to lower the I2C IRQ priority under the SysTick IRQ priority.
2021-02-07 02:12 AM
I got similar infinite SCL low.
my situation:
STM32G070CB
multimaster I2C ( three CPU, every CPU sends as master, receives as slave)
if I set up addressed MCU to answer (to send packet as master) immediately after STOP interrupt (in the interrupt function) when it recieved and processed some packet as slave - it will hang forever with low SCL wire, cause no TXIS interrupt occurs.
(by the way, even the first byte, which was put into TXD register during send setup, was not sent out)
(I tried change I2C interrupt priority highest or lowest - no changes)
furthermore:
if i set up to answer in my general 1ms interrupt routine, it is ok unless it occurs in vicinity of next packet reception end - with very high probability,
about once per 100 packets (packets are ~2ms long, sent at random 2...20ms intervals).
my WORKAROUND:
first I tried after reception to reinit I2C by setting CR1=0 and then set it up from scratch - no success.
I did not try to reset I2C from RCC - may be could help.
========================================================================
for information:
chip marking:
STM32G070
CBT6
GQ267189R
CHN GQ 950
ST (e3) B
====================
I2C2 used.
init and set to receive (very long timing used while seeking for problem source - does not change anything):
I2C2->CR1 = 0;
NVIC_ClearPendingIRQ(BOOT_I2C_IRQn);
I2C2->CR1 = I2C_CR1_GCEN | I2C_CR1_STOPIE | I2C_CR1_ERRIE | I2C_CR1_TCIE | I2C_CR1_ADDRIE | (15UL << I2C_CR1_DNF_Pos);
I2C2->TIMINGR = (0x5 << I2C_TIMINGR_PRESC_Pos) | (0x7f << I2C_TIMINGR_SCLL_Pos) | (0x7f << I2C_TIMINGR_SCLH_Pos) | (0xf << I2C_TIMINGR_SCLDEL_Pos) | (0xf << I2C_TIMINGR_SDADEL_Pos);
I2C2->CR1 |= I2C_CR1_PE;
set to transmit:
__disable_irq();
I2C2->ICR = I2C_ICR_ARLOCF | I2C_ICR_BERRCF | I2C_ICR_STOPCF | I2C_ICR_NACKCF;
I2C2->CR1 |= I2C_CR1_TXIE;
I2C2->TXDR = buf[1];
I2C2->CR2 = I2C_CR2_AUTOEND | buf[0] | (bufLength << I2C_CR2_NBYTES_Pos); // buf[0] == destinationAddress
I2C2->CR2 |= I2C_CR2_START;
__enable_irq();