Skip to main content
Pilous Droip
Senior
March 7, 2018
Question

Read from I2C - STM32F767

  • March 7, 2018
  • 3 replies
  • 4062 views
Posted on March 07, 2018 at 11:52

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.

0690X00000609yOQAQ.png

I receive:

   S-Address-W-A-Command-A-

P

-S-Address-R-A-Data-nA-P

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_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 ltc

In position 6 I have stop bit. It is wrong.

0690X00000609vgQAA.png

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-f767zi
This topic has been closed for replies.

3 replies

David Littell
Senior II
March 7, 2018
Posted on March 07, 2018 at 14:37

I'd suggest you become more familiar with what the LL_...() functions are actually doing, particularly

LL_I2C_EnableAutoEndMode

().
Pilous Droip
Senior
March 7, 2018
Posted on March 07, 2018 at 14:42

I tried everything. But this code works best.

Pilous Droip
Senior
March 7, 2018
Posted on March 07, 2018 at 15:01

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;

}

0690X00000609mnQAA.png
Pilous Droip
Senior
March 8, 2018
Posted on March 08, 2018 at 08:02

Hello friends.

This code working fine only for reading two byte.

0690X00000609udQAA.png

But when I read 3 bytes I have big problem. I don't send stop bit:

0690X00000609vBQAQ.png

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??

Pilous Droip
Senior
March 8, 2018
Posted on March 08, 2018 at 08:40

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:

0690X0000060A0jQAE.png

READ 3 bytes is bad:

0690X0000060A1IQAU.png
waclawek.jan
Super User
March 8, 2018
Posted on March 08, 2018 at 11:14

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

Pilous Droip
Senior
March 8, 2018
Posted on March 08, 2018 at 13:09

Yes of course. Problem is in HW.