2019-05-08 11:47 PM
I'm using i2c to connect MPU6050 in asynchronous mode (means interrupt driven).
I've implemented dfa for that. Everything works fine, but there is strange interrupt right after Re-Start.
SR1 == 0.
Right after second read of SR1 there is right value (SB flag set).
If I don't read SR1 second time and just ignore this interrupt - everything works fine.
Just strange behavior.
I can provide source if it's necessary.
2019-05-09 05:01 AM
You don't say which stm32 you're using. There are differences between the I2C modules in different families.
A lot of people don't use repeated-start (I suppose it's only necessary in multi-master systems) and I think it isn't well supported in the documentation or the libraries.
For stm32f405, I found that I would get an early interrupt on sending the repeated-start.
And I found that reading I2Cn->DR in the interrupt handler immediately prior to setting I2C_CR1_ACK | I2C_CR1_START seemed to solve the problem.
But stm32f767 didn't have this problem.
Hope this helps,
Danish
2019-05-09 05:33 AM
Oh, sorry.
It's stm32f100rbt6. I'm using re-start condition because mpu6050 requires it (I read 14 bytes from it) .
What is "early interrupt" ?
Thank you for reply :)
uint8_t DFASignal(I2C_TypeDef *i2c) {
#define ERR_MASK (I2C_SR1_BERR | I2C_SR1_ARLO | I2C_SR1_OVR | I2C_SR1_PECERR | I2C_SR1_TIMEOUT | I2C_SR1_SMBALERT | I2C_SR1_AF)
volatile uint16_t sr1, sr2 = 0;
sr1 = i2c->SR1;
if (sr1 & I2C_SR1_SB)
return I2CEV_StartBitSent;
if (sr1 & I2C_SR1_ADDR) {
sr2 = i2c->SR2; //clear addr register if set
return I2CEV_AddresSent;
}
if (sr1 & I2C_SR1_BTF)
return I2CEV_DataByteTransferFinished;
if (sr1 & I2C_SR1_RXNE)
return I2CEV_ReceiveBufferNotEmpty;
if (sr1 & I2C_SR1_TXE)
return I2CEV_TransmitBufferEmpty;
if (sr1 & ERR_MASK)
return I2CER_ErrClass;
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//we here because there is no known interrupt flag set.
//actually sr1 == 0 here.
//after re-reading of I2C1->SR1 - SB flag is set. strange behavior
//only after repeat start condition.
//as I understand - some interrupt is happened, flag isn't set and
//isn't cleared after end of interrupt.
//so next time interrupt happened we read sr1 = i2c->SR1
//and now SB flag is set.
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
return 0xff;
}
2019-05-09 02:24 PM
What I meant by an "early" interrupt was that the interrupt-service-routine was being called with nothing to do because I2Cn->SR1 didn't have any of the expected bits set.
stm32f100 is afaik even older than stm32f4xx. So I'd think it even less likely to support repeated-start.
I'd be surprised if mpu6050 needs the repeated start. I would expect it to work just as well if you do a write to set up the register address, followed by a read.
(I know the data sheet doesn't mention this, but then you get the same with memory devices like EEPROMs, and then the official ST example does a separate write then read).
The downside to separate write followed by read is that in a multi-master I2C system, a second master might get hold of the bus between your write and your read, and it might change the register address before you get a chance to do your read!
Danish
2019-05-09 09:37 PM
Thank you. :)