STM32 I2C Lecture 35- Exercise: Coding Part 2

  • Post author:
  • Post category:Blog

 

Exercise: Coding Part 2

 

  1. Compile the code in Figure 1.
Figure 1. Compiling the code.

 

2. Download the code into the board, as shown in Figure 2.

Figure 2. Downloading the code into board.

 

3.Reset both the Arduino and STM board.

4. Open the logic analyzer (Figure 3).

Figure 3. Logic analyzer.

 

5. Capture the result by pressing the start button.

Figure 4. Result in the logic analyzer.

Look at Figure 4. It looks like the application is not working properly.

  • There is a start condition.
  • After the start condition, there is an I2C write transaction.
  • Performing address phase: Master writes a slave address 0x68, as shown in Figure 5.
Figure 5. Performing address phase.

 

  • Then the master sends the command code 0x51.
  • The master terminates the I2C transaction by generating the stop condition.

There is no problem with the first transaction.

  • To read the data master triggers the read transaction.
  • Figure 6 shows the generation of the read transaction. There is no reply from the slave for this transaction, and it looks like the SCL line is pulled to high. 
Figure 6. Generation of read transaction.

 

The stop is generated abruptly, as shown in Figure 7, because there is some problem with the driver. This problem may be because of our code.

Figure 7. Stop is generated abruptly.

 

Now let’s make some changes to the code:

  • Observe the master receive data API in Figure 8. In the section where length is equal to 1 when the ADDR is 1, the ACK is set to 0, and the STOP bit is set to 1. This is actually wrong. 
  • Instead, make ACK=0 and then clear the ADDR flag. Wait for the RXNE=1. When RXNE becomes 1, set the STOP bit. Then you read the data.
  • Since we are making STOP=1, the moment you clear the ADDR flag, the stop is generated. This method is also mentioned in the transfer sequence diagram section of the reference manual shown in Figure 9.
Figure 8. master receive data API

 

Figure 9. Transfer sequence diagram for master receiver.

Look at the transfer sequence diagram for a master receiver in Figure 9. Here they are telling us to set the stop bit after clearing the ADDR flag. 

Now let’s make the changes to the driver code, as shown in Figure 10.

Figure 10. Changes made to the code of master receive data API.

 

Steps to be followed to check whether the changed code works or not:

  • Compile the code.
  • Program the board.
  • Reset both the boards.
  • Capture the result by pressing the start button (Figure 11).
Figure 11. Result of logic analyzer after making changes to the code.

 

  • Observe Figure 11. In the write phase, the master sends the command code 0x51.
  • After that master generates the read transaction, and for that transaction, the slave is replied. 27 is the reply from the slave, which you can see in Figure 11.
  • After receiving 27, the master sent NACK.
  • Since we are interested in only one byte, the stop is generated after receiving one byte.
  • Next, the master again generated the write phase, and you can see in Figure 12 that now the master sent command code 0x52. Then the master generated the stop condition.
Figure 12. Result of logic analyzer for write transaction.

 

  • After that, the master again generated the read transaction, as shown in Figure 13.
  • After the start condition generation, the master starts receiving the byte from the slave, and the master receives 1-byte that is T, as shown in Figure 13.
  • After receiving 1-byte, the master sent NACK, which is wrong because we should receive 27 bytes.
Figure 13. Result of logic analyzer for second read transaction.

 

  • Here the master didn’t ACK the slave. It only received T. Because, in the Arduino sketch, the data which is being sent is the string shown in Figure 14.
Figure 14. String data being sent from the slave.

 

  • The slave sent the first character T, but the problem is the master didn’t send the ACK for the received byte.
  • Now you have to debug the code to determine why the master code is not sending the ACK.
  • To debug the code, go to the debug perspective and make sure that current debugging is off. Click on the terminate button to make the debugging off.
  • Then go to breakpoints, and if any breakpoints, then remove all the breakpoints as shown in Figure 15. 
Exercise: Coding Part 2
Figure 15. Removing the break points.

 

  • When you have set many breakpoints, the IDE will crash for some time. So, it is better to remove all breakpoints. Then go to the C and C++ perspective and after that, right-click and go to debug as (Figure 16).
Exercise: Coding Part 2
Figure 16. Debugging the code.

 

  • Launch the debugger by clicking on yes, as shown in Figure 17.
Exercise: Coding Part 2
Figure 17. Launching the debugger.

 

Now the problem is the master is not sending the ACK. That means the troubleshooting point would be checking whether the ACK bit is enabled or not in the master.

In the I2C init function, the ACK is enabled (Figure 18), but we should understand whether it is really affecting the control register or not. That means in the control register, you have to check whether the ACK is really enabled or not.

Exercise: Coding Part 2
Figure 18. I2C init function.

 

  • Figure 19 shows the code for enabling the ACK in the CR1 register. Let’s keep the breakpoint here as in Figure 19.
Exercise: Coding Part 2
Figure 19. Code for enabling the ACK in the CR1 register.

 

  • Hit the run. The control has reached the breakpoint, then let’s do a single step and analyze the tempreg value. Now the tempreg value or the 10th bit is set, as shown in Figure 20.
Exercise: Coding Part 2
Figure 20. tempreg value analysis.

 

  • Check whether the CR1 will get affected or not: Go to the I/O registers, select I2C, then open I2C1. In Figure 21, you can see that the CR1 is currently 00.
Exercise: Coding Part 2
Figure 21. CR1 register.

 

If everything is fine, then in the CR1 register, the ACK field must be one after executing line 199. Let’s do a step over. Then update the CR1 register by double-tapping it.

In Figure 22, you can see that the ACK bit is not set. That’s why the master is sending NACK.

Exercise: Coding Part 2
Figure 22. Updated values of CR1 register.

 

Now why this is happening even though the 10th bit of tempreg is indeed set to 1. To resolve this problem, you have to understand the ACK bit in the control register completely.

Observe Figure 23. Here the ACK bit explanation says that ACK bit is set and cleared by the software and cleared by the hardware when PE=0.

Look at Figure 24. In our application, the PE=0. It is impossible to make ACK=1 when PE=0. The ACK bit will become one only when you set the PE bit.

Exercise: Coding Part 2
Figure 23. I2C_CR1 register.

 

Exercise: Coding Part 2
Figure 24. Value of PE bit of CR1 register.

 

Go back to the project and make the necessary changes to the code as follows:

  • Enable the ACK bit after PE=1, as shown in Figure 25.
Exercise: Coding Part 2
Figure 25. Code to enable the ACK bit after PE=1.

 

  • Make sure that you have re-enabled (Figure 26) the ACK bit before leaving the master receive data API.
Exercise: Coding Part 2
Figure 26. Code to re-enable the ACK bit in the MasterReceiveData API.

 

  • There is a return statement at the end of the MasterReceiveData API, which makes the program control to return before re-enabling the ACK. Therefore, remove the return statement shown in Figure 27.
Exercise: Coding Part 2
Figure 27. Return statement in the MasterReceiveData API.

 

  • Now compile the code.
  • Program the board.
  • Reset both the boards.
  • Capture the logic analyzer results by pressing the user button. In Figure 28, you can observe all the bytes which are being received from the slave. The last two characters are \r and \n (Figure 29), which is there in the string sent by the Arduino sketch shown in Figure 14.
Exercise: Coding Part 2
Figure 28. Trace of I2C read transaction to read 27 bytes from the slave.

 

Exercise: Coding Part 2
Figure 29. Last two bytes of I2C read transaction trace.
  • The stop is generated, and both the lines are released, as shown in Figure 29.

Let’s continue in the following article. Click Here.

 

FastBit Embedded Brain Academy Courses,

Click here: https://fastbitlab.com/course1

FastBitLab

The FastBit Embedded Brain Academy uses the power of internet to bring the online courses related to the field of embedded system programming, Real time operating system, Embedded Linux systems, etc at your finger tip with very low cost. Backed with strong experience of industry, we have produced lots of courses with the customer enrolment over 3000+ across 100+ countries.