2024-09-19 04:27 AM
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.
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.
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, :)
Solved! Go to Solution.
2024-09-20 01:29 AM
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:
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.
2024-09-19 05:51 AM
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.
2024-09-19 06:01 AM - edited 2024-09-20 12:18 AM
@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]
2024-09-19 10:33 AM
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 :)
2024-09-19 10:39 AM
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
2024-09-20 12:12 AM
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
2024-09-20 01:29 AM
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:
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.