Skip to main content
Graduate
September 19, 2024
Solved

I2C HAL_BUSY NUCLEO-FR103RB Master

  • September 19, 2024
  • 3 replies
  • 1504 views

NUCLEO STM32 I2C

Hello, I'm trying to make a master NUCLEO-FR103RB send data to a slave device using fast mode (400 kHz). Slave to master is not essential at the moment. As slave I am using the Total Phase AARDVARK in slave mode simulating a LED driver which is going to be implemented later on.

  • I2C frequency = 400 kHz
  • 0x28 Slave address
  • VCC = 5V
  • RP = 3.9 kΩ (Not sure if optimal)

 

uint8_t TX_Buffer[] = "Hello Aardvark"; // Data to send
uint16_t I2C_ADDRESS = 0x28; // Aardvark I2C address (7-bit)
HAL_I2C_IsDeviceReady(&hi2c1, (uint16_t) (I2C_ADDRESS << 1), 3, HAL_MAX_DELAY);
HAL_I2C_Master_Transmit_IT(&hi2c1, I2C_ADDRESS, TX_Buffer, sizeof(TX_Buffer));
hi2c1.Instance = I2C1;
hi2c1.Init.ClockSpeed = 400000;
hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
hi2c1.Init.OwnAddress1 = 0;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;

 

The only issue is that whenever I try communicating with it the function returns HAL_BUSY every time (using both IT and normal modes).
I know there's already a lot of posts talking about the issue but I don't seem to be able to solve it. I am using a pullup resistor for each line and when "idling" both are logic level HIGH which it's correct if I'm not mistaken. When trying to send data from the MCU my oscilloscope doesn't pick up any signal. I connected the peripheriial to the morpho headers and of course in the code is I2C1.image_2024-09-19_131011655.png

 

I2C.drawio (1).png

 If I put the AARDVARK in master mode and try sending data from it I can clearly see the two lines on the oscilloscope display.

Does somebody happen to know any possible solution? It's also my first time using AARDVARK, but any random peripherial will do if that's the case. The goal of this is to get me started with I2C so I can build an application for when the LP5024EVM arrives.

Thank you very much in advance for any suggestion, :)

    This topic has been closed for replies.
    Best answer by xenon

    UPDATE:

    I can now successefully enstablish a connection and send master-to-slave data. I simply rewrote the code in a cleaner way and tried 100 kHz before stepping up to 400 kHz. Nothing really changed except that now the address's bit is shifted when declared instead of doing it in the function inputs.
    This the address initialization and buffer part:

    static const uint8_t I2C_ADDRESS = 0x28 << 1;
    uint8_t tx_buffer[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};

    Alive check function (sends 0x00 in the buffer):

    HAL_I2C_IsDeviceReady(&hi2c1, I2C_ADDRESS, 2, HAL_MAX_DELAY);

    Blocking function:

    HAL_I2C_Master_Transmit(&hi2c1, I2C_ADDRESS, tx_buffer, sizeof(tx_buffer), HAL_MAX_DELAY);

    Non-blocking (interrupt driven) function:

    HAL_I2C_Master_Transmit_IT(&hi2c1, I2C_ADDRESS, tx_buffer, sizeof(tx_buffer));

    Both of them have the same result:image_2024-09-20_101845595.png

    My next step will be slave-to-master communication. I can now mark this issue as solved. Thanks to @TDK  and @Peter BENSCH for taking your time to answer me. I also didn't know I couldn't apply 5V to GPIO pins when the VDD was unpowered.

    3 replies

    Super User
    September 19, 2024

    What exactly is returning HAL_BUSY?

    If HAL_I2C_IsDeviceReady returns HAL_BUSY, it means the BUSY bit is set, which means SDA or SCL is low. This indicates a hardware issue of some kind.

    TDK_0-1726750195352.png

     

    xenonAuthor
    Graduate
    September 19, 2024

    Both the transmit and IsDeviceReady returned busy, however the both the SDA and SCL were high.
    In the end I was able to send master to slave data with the blocking function. I moved the bit shifting phase at the declaration of the address since I also saw I was often forgetting it. If tomorrow I'll be able to implement the interrupts successefully I'll mark this thread as solved and make an update post showing what I did.
    Thank you very much for your reply though :)

    Technical Moderator
    September 19, 2024

    @xenon You also cannot connect a 5V I2C device directly to the STM32 without a level shifter.

    [corrected, see justification with reference to AN4899 below]

    xenonAuthor
    Graduate
    September 19, 2024

    Why not? All GPIO pins are designed to be 5V tolerant. I am also using the open drain configuration if that changes something.
    In the end I was able to successefully send master to slave data through 5V. Withouth interrupts though. As I said in an other reply I'll post an update tomorrow explaining everything better.
    Please let me know and thanks for replying

    Technical Moderator
    September 20, 2024

    Sorry, I had confused this with another application. Yes, you can communicate with a I2C at 5V, as discussed in AN4899, section 5.3.3.

    The only restriction: the 5V must not be applied when VDD of the STM32 is switched off, because this exceeds the absolute max ratings (max VDD+4.0V). This also applies to transients that can be intercepted with a TVS or Zener, as shown at the end of section 5.3.3.

    Regards
    /Peter

    xenonAuthorAnswer
    Graduate
    September 20, 2024

    UPDATE:

    I can now successefully enstablish a connection and send master-to-slave data. I simply rewrote the code in a cleaner way and tried 100 kHz before stepping up to 400 kHz. Nothing really changed except that now the address's bit is shifted when declared instead of doing it in the function inputs.
    This the address initialization and buffer part:

    static const uint8_t I2C_ADDRESS = 0x28 << 1;
    uint8_t tx_buffer[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};

    Alive check function (sends 0x00 in the buffer):

    HAL_I2C_IsDeviceReady(&hi2c1, I2C_ADDRESS, 2, HAL_MAX_DELAY);

    Blocking function:

    HAL_I2C_Master_Transmit(&hi2c1, I2C_ADDRESS, tx_buffer, sizeof(tx_buffer), HAL_MAX_DELAY);

    Non-blocking (interrupt driven) function:

    HAL_I2C_Master_Transmit_IT(&hi2c1, I2C_ADDRESS, tx_buffer, sizeof(tx_buffer));

    Both of them have the same result:image_2024-09-20_101845595.png

    My next step will be slave-to-master communication. I can now mark this issue as solved. Thanks to @TDK  and @Peter BENSCH for taking your time to answer me. I also didn't know I couldn't apply 5V to GPIO pins when the VDD was unpowered.