2018-03-07 02:52 AM
Helo friends.
Problem with write on I2C bus I solved.
If anyone wanted to, I would provide a solution
.Now I have problem with reading.
I have got 1 stop bit more.
Here is good communication packet.
I receive:
S-Address-W-A-Command-A-
P
-S-Address-R-A-Data-nA-Puint8_t I2C_read_brekeke(I2C_TypeDef *I2Cx, unsigned char Address, uint8_t reg, int nBytes, unsigned char *data)
{
LL_I2C_SetSlaveAddr(I2Cx, (Address<<1)); /* Prepare Address to send */
LL_I2C_SetMasterAddressingMode(I2Cx, LL_I2C_ADDRSLAVE_7BIT);
LL_I2C_SetTransferRequest(I2Cx, LL_I2C_REQUEST_WRITE); /* Reguest write */
LL_I2C_EnableAutoEndMode(I2Cx); /* Enable autoend mode*/
LL_I2C_SetTransferSize(I2Cx, 1); /* Set transfer size register */
while(LL_I2C_IsActiveFlag_BUSY(I2Cx)){} /* check I2C bussy */
LL_I2C_GenerateStartCondition(I2Cx); /* generate I2C Start address and send address*/
while(!LL_I2C_IsActiveFlag_STOP(I2Cx)) /* check STOP bit */
{
if(LL_I2C_IsActiveFlag_TXE(I2Cx))
{
LL_I2C_TransmitData8(I2Cx, reg); /* send data out */
}
}
LL_I2C_ClearFlag_STOP(I2Cx); /* Clear STOP flag */
LL_I2C_ClearFlag_TXE(I2Cx); /* Clear Transmit data register empty flag */
LL_I2C_SetSlaveAddr(I2Cx, (Address<<1)); /* Prepare Address to send */
LL_I2C_SetMasterAddressingMode(I2Cx, LL_I2C_ADDRSLAVE_7BIT);
LL_I2C_SetTransferRequest(I2Cx, LL_I2C_REQUEST_READ); /* Reguest write */
LL_I2C_EnableAutoEndMode(I2Cx); /* Enable autoend mode*/
LL_I2C_SetTransferSize(I2Cx, nBytes); /* Set transfer size register */
while(LL_I2C_IsActiveFlag_BUSY(I2Cx)){} /* check I2C bussy */
LL_I2C_GenerateStartCondition(I2Cx); /* generate I2C Start address and send address*/
while(!LL_I2C_IsActiveFlag_STOP(I2Cx)) /* check STOP bit */
{
if(LL_I2C_IsActiveFlag_RXNE(I2Cx))
{
*data++ = LL_I2C_ReceiveData8(I2Cx); /* send data out */
}
}
return 0;
}
My call function:
uint8_t ltc[] = {0, 0, 0, 0};
I2C_read_brekeke(I2C4, 0x6F, 0x14, 2, ltc); //address 0x6F; Reg 0x14, receive to ltcIn position 6 I have stop bit. It is wrong.
Any idea, what is wrong?
=================================================================
I found this function: LL_I2C_EnableAuto10BitRead()
Where is wrote:
/**
* @brief Enable automatic RESTART Read request condition for 10bit address header (master mode). * @note The master sends the complete 10bit slave address read sequence : * Start + 2 bytes 10bit address in Write direction + Restart + first 7 bits of 10bit address in Read direction. * @rmtoll CR2 HEAD10R LL_I2C_EnableAuto10BitRead * @param I2Cx I2C Instance. * @retval None */And I try use it, but it doesn't work.
#stm32f767 #read-i2c #nucleo-f767zi2018-03-07 05:37 AM
I'd suggest you become more familiar with what the LL_...() functions are actually doing, particularly
LL_I2C_EnableAutoEndMode
().2018-03-07 06:01 AM
Here is function solution.....
uint8_t I2C_read_brekeke(I2C_TypeDef *I2Cx, unsigned char Address, uint8_t reg, int nBytes, unsigned char *data)
{
LL_I2C_SetSlaveAddr(I2Cx, (Address<<1)); /* Prepare Address to send */
LL_I2C_SetMasterAddressingMode(I2Cx, LL_I2C_ADDRSLAVE_7BIT);
LL_I2C_SetTransferRequest(I2Cx, LL_I2C_REQUEST_WRITE); /* Reguest write */
LL_I2C_DisableAutoEndMode(I2Cx); /* Disable automatic STOP condition generation */
LL_I2C_SetTransferSize(I2Cx, 1); /* Set transfer size register */
while(LL_I2C_IsActiveFlag_BUSY(I2Cx)){} /* check I2C bussy */
LL_I2C_GenerateStartCondition(I2Cx); /* generate I2C Start address and send address*/
while(!LL_I2C_IsActiveFlag_TC(I2Cx)) /* check STOP bit */
{
if(LL_I2C_IsActiveFlag_TXE(I2Cx))
{
LL_I2C_TransmitData8(I2Cx, reg); /* send data out */
}
}
LL_I2C_SetSlaveAddr(I2Cx, (Address<<1)); /* Prepare Address to send */
LL_I2C_SetMasterAddressingMode(I2Cx, LL_I2C_ADDRSLAVE_7BIT);
LL_I2C_SetTransferRequest(I2Cx, LL_I2C_REQUEST_READ); /* Reguest write */
LL_I2C_DisableAutoEndMode(I2Cx); /* Enable autoend mode*/
LL_I2C_SetTransferSize(I2Cx, nBytes); /* Set transfer size register */
/*while(LL_I2C_IsActiveFlag_BUSY(I2Cx)){} check I2C bussy */
LL_I2C_GenerateStartCondition(I2Cx); /* generate I2C Start address and send address*/
while(!LL_I2C_IsActiveFlag_TC(I2Cx)) /* check STOP bit */
{
if(LL_I2C_IsActiveFlag_RXNE(I2Cx))
{
*data++ = LL_I2C_ReceiveData8(I2Cx); /* send data out */
}
}
LL_I2C_GenerateStopCondition(I2Cx);
return 0;
}
2018-03-07 06:42 AM
I tried everything. But this code works best.
2018-03-08 12:02 AM
Hello friends.
This code working fine only for reading two byte.
But when I read 3 bytes I have big problem. I don't send stop bit:
uint8_t I2C_read_from_device(I2C_TypeDef *I2Cx, unsigned char Address, uint8_t reg, uint8_t nBytes, unsigned char *data)
{
LL_I2C_SetSlaveAddr(I2Cx, (Address<<1)); /* Prepare Address to send */
LL_I2C_SetMasterAddressingMode(I2Cx, LL_I2C_ADDRSLAVE_7BIT);
LL_I2C_SetTransferRequest(I2Cx, LL_I2C_REQUEST_WRITE); /* Reguest write */
LL_I2C_DisableAutoEndMode(I2Cx); /* Disable automatic STOP condition generation */
LL_I2C_SetTransferSize(I2Cx, 1); /* Set transfer size register */
while(LL_I2C_IsActiveFlag_BUSY(I2Cx)){} /* check I2C bussy */
LL_I2C_GenerateStartCondition(I2Cx); /* generate I2C Start address and send address*/
while(!LL_I2C_IsActiveFlag_TC(I2Cx)) /* check STOP bit */
{
if(LL_I2C_IsActiveFlag_TXE(I2Cx))
{
LL_I2C_TransmitData8(I2Cx, reg); /* send data out */
}
}
LL_I2C_SetSlaveAddr(I2Cx, (Address<<1)); /* Prepare Address to send */
LL_I2C_SetMasterAddressingMode(I2Cx, LL_I2C_ADDRSLAVE_7BIT);
LL_I2C_SetTransferRequest(I2Cx, LL_I2C_REQUEST_READ); /* Reguest write */
LL_I2C_DisableAutoEndMode(I2Cx); /* Enable autoend mode*/
LL_I2C_SetTransferSize(I2Cx, nBytes); /* Set transfer size register */
/*while(LL_I2C_IsActiveFlag_BUSY(I2Cx)){} check I2C bussy */
LL_I2C_GenerateStartCondition(I2Cx); /* generate I2C Start address and send address*/
while(nBytes--)
{
while(!LL_I2C_IsActiveFlag_RXNE(I2Cx)){};
*data++ = LL_I2C_ReceiveData8(I2Cx); /* send data out */
}
LL_I2C_GenerateStopCondition(I2Cx);
LL_I2C_ClearFlag_TXE(I2Cx);
LL_I2C_ClearFlag_STOP(I2Cx);
return 0;
}
Any idea, what is wrong??
2018-03-08 12:40 AM
And now I try modificate the function, but the result is the same
uint8_t I2C_read_from_device(I2C_TypeDef *I2Cx, unsigned char Address, uint8_t reg, uint8_t nBytes, unsigned char *data)
{ LL_I2C_SetSlaveAddr(I2Cx, (Address<<1)); /* Prepare Address to send */ LL_I2C_SetMasterAddressingMode(I2Cx, LL_I2C_ADDRSLAVE_7BIT); LL_I2C_SetTransferRequest(I2Cx, LL_I2C_REQUEST_WRITE); /* Reguest write */ LL_I2C_DisableAutoEndMode(I2Cx); /* Disable automatic STOP condition generation */ LL_I2C_SetTransferSize(I2Cx, 1); /* Set transfer size register */while(LL_I2C_IsActiveFlag_BUSY(I2Cx)){} /* check I2C bussy */
LL_I2C_GenerateStartCondition(I2Cx); /* generate I2C Start address and send address*/while(!LL_I2C_IsActiveFlag_TC(I2Cx)) /* check STOP bit */
{ if(LL_I2C_IsActiveFlag_TXE(I2Cx)) { LL_I2C_TransmitData8(I2Cx, reg); /* send data out */ } }LL_I2C_SetSlaveAddr(I2Cx, (Address<<1)); /* Prepare Address to send */
LL_I2C_SetMasterAddressingMode(I2Cx, LL_I2C_ADDRSLAVE_7BIT); LL_I2C_SetTransferRequest(I2Cx, LL_I2C_REQUEST_READ); /* Reguest write */ LL_I2C_DisableAutoEndMode(I2Cx); /* Enable autoend mode*/ LL_I2C_SetTransferSize(I2Cx, nBytes); /* Set transfer size register *//*while(LL_I2C_IsActiveFlag_BUSY(I2Cx)){} check I2C bussy */
LL_I2C_GenerateStartCondition(I2Cx); /* generate I2C Start address and send address*/ while(nBytes--) { if (!nBytes) { LL_I2C_AcknowledgeNextData(I2Cx, LL_I2C_NACK); LL_I2C_GenerateStopCondition(I2Cx); while (!LL_I2C_IsActiveFlag_RXNE(I2Cx)){}; *data++ = LL_I2C_ReceiveData8(I2Cx); } else { LL_I2C_AcknowledgeNextData(I2Cx, LL_I2C_ACK); while (!LL_I2C_IsActiveFlag_RXNE(I2Cx)){}; *data++ = LL_I2C_ReceiveData8(I2Cx); } } LL_I2C_ClearFlag_TXE(I2Cx); LL_I2C_ClearFlag_OVR(I2Cx); LL_I2C_ClearFlag_NACK(I2Cx); LL_I2C_ClearFlag_STOP(I2Cx);return 0;
}READ 2 bytes is good:
READ 3 bytes is bad:
2018-03-08 01:53 AM
I'm looking in the registers.
And:
When I receive 2 bytes (when all is good) register ISR is set:
ADDCODE - 0x00
ADDR - 0x00
ALERT - 0x00
ARLO - 0x00
BERR - 0x00
BUSY - 0x00
DIR - 0x00
OVR - 0x00
PECERR - 0x00
RXNE - 0x00
TC - 0x00
TCR - 0x00
TIMEOUT - 0x00
TXE - 0x00
TXIS - 0x00
When I receive 3 bytes (read is wrong) register ISR is set:
ADDCODE - 0x00
ADDR - 0x00
ALERT - 0x00
ARLO - 0x01
BERR - 0x00
BUSY - 0x01
DIR - 0x00
NACKF - 0x01
OVR - 0x00
PECERR - 0x00
RXNE - 0x00
STOPF - 0x00
TC - 0x00
TCR - 0x00
TIMEOUT - 0x00
TXE - 0x00
TXIS - 0x00
In datasheet is writing:
ARLO - This flag is set by hardware in case of arbitration loss. It is cleared by software by setting the ARLOCF bit.
BUSY - This flag indicates that a communication is in progress on the bus. It is set by hardware when a START bit is detected. It is cleared by PE=0 or when STOP bit is detected.
STOPF - Stop bit detection
2018-03-08 02:14 AM
Arbitration loss indicates that something is wrong with that last NAK (and the picture indecates the same).
Try decrease pullups on SDA, increase timing, and observe with oscilloscope.
JW
2018-03-08 02:44 AM
I try this function. It is working only, when I am going to receive 2 bytes.
When I am receiving 1, 3, 4 bytes it is not working.
uint8_t I2C_read_from_device(I2C_TypeDef *I2Cx, unsigned char Address, uint8_t reg, uint8_t nBytes, unsigned char *data)
{
LL_I2C_SetSlaveAddr(I2Cx, (Address<<1)); /* Prepare Address to send */ LL_I2C_SetMasterAddressingMode(I2Cx, LL_I2C_ADDRSLAVE_7BIT); LL_I2C_SetTransferRequest(I2Cx, LL_I2C_REQUEST_WRITE); /* Reguest write */ LL_I2C_DisableAutoEndMode(I2Cx); /* Disable automatic STOP condition generation */ LL_I2C_SetTransferSize(I2Cx, 1); /* Set transfer size register */while(LL_I2C_IsActiveFlag_BUSY(I2Cx)){} /* check I2C bussy */
LL_I2C_GenerateStartCondition(I2Cx); /* generate I2C Start address and send address*/while(!LL_I2C_IsActiveFlag_TC(I2Cx)) /* check STOP bit */
{ if(LL_I2C_IsActiveFlag_TXE(I2Cx)) { LL_I2C_TransmitData8(I2Cx, reg); /* send data out */ } }LL_I2C_SetSlaveAddr(I2Cx, (Address<<1)); /* Prepare Address to send */
LL_I2C_SetMasterAddressingMode(I2Cx, LL_I2C_ADDRSLAVE_7BIT); LL_I2C_SetTransferRequest(I2Cx, LL_I2C_REQUEST_READ); /* Reguest write */ LL_I2C_DisableAutoEndMode(I2Cx); /* Enable autoend mode*/ LL_I2C_SetTransferSize(I2Cx, nBytes); /* Set transfer size register *//*while(LL_I2C_IsActiveFlag_BUSY(I2Cx)){} check I2C bussy */
LL_I2C_GenerateStartCondition(I2Cx); /* generate I2C Start address and send address*/ while(nBytes--) { if (!nBytes) { LL_I2C_AcknowledgeNextData(I2Cx, LL_I2C_NACK); LL_I2C_GenerateStopCondition(I2Cx); while (!LL_I2C_IsActiveFlag_RXNE(I2Cx)){}; *data++ = LL_I2C_ReceiveData8(I2Cx); } else { LL_I2C_AcknowledgeNextData(I2Cx, LL_I2C_ACK); while (!LL_I2C_IsActiveFlag_RXNE(I2Cx)){}; *data++ = LL_I2C_ReceiveData8(I2Cx); } } LL_I2C_ClearFlag_TXE(I2Cx); LL_I2C_ClearFlag_OVR(I2Cx); LL_I2C_ClearFlag_NACK(I2Cx); LL_I2C_ClearFlag_STOP(I2Cx);return 0;
}2018-03-08 05:09 AM
Yes of course. Problem is in HW.