STM32U575xx - I2C slaves do not send ACK resulting in `HAL_I2C_ERROR_AF` error
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-12-18 3:56 AM - edited ‎2024-12-18 3:57 AM
I have a custom PCB with a STM32U575 for which I generate code using STM32CubeMX.
I am now trying to get I2C to work. Both the I2C1 and I2C2 channels each have one I2C slave. But for both I get the same problem: the slaves do not acknowledge the master messages. The I2C transmission then returns with an error.
For now I am testing with very basic code:
const uint8_t source[1] = {0x00};
HAL_StatusTypeDef status = HAL_I2C_Master_Transmit(&hi2c1, 0x64, source, 1, 1000);
uint32_t errorCode = HAL_I2C_GetError(&hi2c1);
Here status is HAL_ERROR and errorCode is HAL_I2C_ERROR_AF.
I put a logic analyzer on the SDA and SCL channels and I can confirm the slave really doesn't send the expected ACK:
In the yellow region the SDA should be pulled low.
The CubeMX config:
Both are set to 'open drain' as they should be.
Just to try I made a little scan over all 128 I2C addresses, but I don't get an acknowledgement anywhere. I've also tried about all possible I2C configurations, but to no avail.
It's odd both slaves have the same effects, on different channels.
Thanks for any advice!
Solved! Go to Solution.
- Labels:
-
I2C
-
STM32CubeMX
-
STM32U5 series
Accepted Solutions
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-12-18 4:50 AM - edited ‎2024-12-18 4:51 AM
I figured it out and it was right in front of me. I had forgotten to bit-shift the device address by 1. And even my address scan failed here because I only scanned up to 0x7F, not up to 0xFF.
So I can now read the slave status with:
const uint8_t devAddr = 0x64 << 1; // CubeMX uses only the 7 most-significant bits as address
const uint8_t regStatus = 0x00;
state = HAL_I2C_Master_Transmit(&hi2c1, devAddr, ®Status, 1, 1000);
uint8_t status;
HAL_I2C_Master_Receive(&hi2c1, devAddr, &status, 1, 1000);
I feel silly because the docblock clearly states this:
I figured this out because I was looking at the logic analyzer during the address scan and I saw each address scroll by twice (e.g. 0x00, 0x00, 0x01, 0x01, etc.) instead of incrementing each time.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-12-18 4:14 AM
@Robert_149494 wrote:I have a custom PCB !
Post the schematic.
@Robert_149494 wrote:Both the I2C1 and I2C2 channels each have one I2C slave. But for both I get the same problem: the slaves do not acknowledge the master messages.!
What are the slaves? Are you sure you have them correctly enabled, configured, etc ?
Before making a custom PCB, did you test this on a dev board?
That way you should easily be able to test that you have correct pullup values, correct addresses, etc - without any doubts about untested hardware issues ...
A complex system designed from scratch never works and cannot be patched up to make it work.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-12-18 4:50 AM
Note that 7-bit slave address should be left-shifted one bit. Could be it.
Possibly the slave chips are not powered or are miswired.
Get HAL_I2C_IsDeviceReady to return HAL_OK before you do anything else with HAL_I2C.
You've confirmed the SDA/SCL signal exist, which is good. Not a code issue in that case.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-12-18 4:50 AM - edited ‎2024-12-18 4:51 AM
I figured it out and it was right in front of me. I had forgotten to bit-shift the device address by 1. And even my address scan failed here because I only scanned up to 0x7F, not up to 0xFF.
So I can now read the slave status with:
const uint8_t devAddr = 0x64 << 1; // CubeMX uses only the 7 most-significant bits as address
const uint8_t regStatus = 0x00;
state = HAL_I2C_Master_Transmit(&hi2c1, devAddr, ®Status, 1, 1000);
uint8_t status;
HAL_I2C_Master_Receive(&hi2c1, devAddr, &status, 1, 1000);
I feel silly because the docblock clearly states this:
I figured this out because I was looking at the logic analyzer during the address scan and I saw each address scroll by twice (e.g. 0x00, 0x00, 0x01, 0x01, etc.) instead of incrementing each time.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-12-18 4:55 AM
Jinx. Yeah, that was it.
