2019-02-05 05:01 AM
I have a problem with the operation of the I2C interface on stm32f103. Hangs waiting for ADDR bit(while(!(I2C1->SR1 & I2C_SR1_ADDR))) in the master transmit mode.
In the Internet, many people have this problem, but is no solution. Who was the problem and who solved it?
RCC->APB2ENR |= RCC_APB2ENR_AFIOEN; //enable AF
RCC->APB2ENR |= RCC_APB2ENR_IOPBEN; /enable clock port b
AFIO->MAPR &= ~AFIO_MAPR_I2C1_REMAP;
GPIOB->CRL |= GPIO_CRL_CNF6; //Alternate function open drain
GPIOB->CRL |= GPIO_CRL_CNF7; //Alternate function open drain
GPIOB->CRL |= GPIO_CRL_MODE6; // Output mode, max speed 50 MHz.
GPIOB->CRL |= GPIO_CRL_MODE7; // Output mode, max speed 50 MHz.
/*********** Init I2C *******************************/
RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; //Enable clock I2C1
I2C1->CR1 |= I2C_CR1_SWRST; //reset i2c
I2C1->CR1 &= ~I2C_CR1_SWRST;
I2C1->CR1 &= ~I2C_CR1_PE;
I2C1->CR2 |= 36; //set FREQ = APB1= 36MHz
I2C1->CCR |= 180;
I2C1->TRISE = 0x00;
I2C1->TRISE |= 37; //TRISE = 36MHz APB1 bus + 1
I2C1->CR1 |= I2C_CR1_PE; // I2C_CR1 register to enable the peripheral
/*********************send data***************************/
//Start
I2C1->CR1 |= I2C_CR1_START;
while(!(I2C1->SR1 & I2C_SR1_SB)){}; ///Here is normal
(void) I2C1->SR1;
//send addres unit
I2C1->DR = adr_unit;
while(!(I2C1->SR1 & I2C_SR1_ADDR)){}; //// Here is loop!
(void) I2C1->SR1;
(void) I2C1->SR2;
//send addres reg
I2C1->DR = reg_addr;
while(!(I2C1->SR1 & I2C_SR1_TXE)){};
//write data
I2C1->DR = data;
while(!(I2C1->SR1 & I2C_SR1_BTF)){};
I2C1->CR1 |= I2C_CR1_STOP;
Solved! Go to Solution.
2019-02-05 05:26 AM
It means the master isn't receiving the ACK bit for some reason. Check the connectivity between master and slave, check the pull-ups, check the slave address. Use a logic analyzer or an oscilloscope to check whether the ACK is coming from the slave.
In real-world application you would want to add timeout mechanisms to all those infinite loops so your firmware doesn't hang indefinitely.
2019-02-05 05:26 AM
It means the master isn't receiving the ACK bit for some reason. Check the connectivity between master and slave, check the pull-ups, check the slave address. Use a logic analyzer or an oscilloscope to check whether the ACK is coming from the slave.
In real-world application you would want to add timeout mechanisms to all those infinite loops so your firmware doesn't hang indefinitely.
2019-02-05 07:49 AM
Thank you very much friend, the address of the device is 7 bits, so need shift to the left by 1 bit to the address was correct.:thumbs_up:
In real-world application you would want to add timeout mechanisms to all those infinite loops so your firmware doesn't hang indefinitely.
Agreed. I seen many implementations, which one do you use?
2019-02-05 11:44 PM
> I seen many implementations, which one do you use?
One based on SysTick's counter (I assume it is configured to tick every millisecond). I make my polling functions return int 0 for good result, negative values for bad results (like timeout), and positive values when it must return something useful (like number of characters read). Part of your code in such a function would become something like this (... for omitted parts):
#define I2C_TIMEOUT_MS (1000U)
...
...
...
int i2c_read_sensor(void)
{
uint32_t timeout;
...
...
I2C1->CR1 |= I2C_CR1_START;
timeout = I2C_TIMEOUT_MS;
while (!(I2C1->SR1 & I2C_SR1_SB)) {
if (SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) {
if (timeout-- == 0) {
ERR("I2C_SR1_SB timeout\n");
return -4;
}
}
}
(void) I2C1->SR1;
...
...
I2C1->DR = adr_unit;
timeout = I2C_TIMEOUT_MS;
while (!(I2C1->SR1 & I2C_SR1_ADDR)) {
if (SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) {
if (timeout-- == 0) {
ERR("I2C_SR1_ADDR timeout\n");
return -5;
}
}
}
(void) I2C1->SR1;
(void) I2C1->SR2;
...
...
return 0;
}