2020-05-20 06:17 AM
Hi,
I've been trying to get the SMBus working as a master, writing a few commands to a slave device to control some LEDs.
I have managed to get the code working, but I don't quite understand why it is working.
The code I currently have (which fails):
uint8_t statusBuffer[] = {
TCA6507_COMMAND_AUTOINC_SELECT, // Start from SELECT0 and auto-increment
0x60, // LED 6 and 7 should blink
0x60, // LED 6 and 7 should blink
0x60 // LED 6 and 7 should blink
};
// Transmit the data to the device
if (HAL_SMBUS_Master_Transmit_IT(&hsmbus2, TCA6507_ADDRESS, statusBuffer,
sizeof(statusBuffer), SMBUS_FIRST_AND_LAST_FRAME_NO_PEC) != HAL_OK) {
// production code should return an error
}
// // Wait for the transmission to end
// while (HAL_SMBUS_GetState(&hsmbus2) != HAL_SMBUS_STATE_READY) {
// // Wait here
// }
Because I have rows 14-17 commented out, the code does not work and the LEDs do not light up. If I uncomment the lines, everything works as expected. But why do I have to wait there like that?
A little bit about the setup:
I'm using FreeRTOS and this is the only function in a task that is run every 5 seconds or so. Also the call to this function is gated with an if-clause and a boolean type variable, allowing it to be called only once.
uint8_t bDone = 0;
TCA6507_ControlDef ledControl;
for(;;) {
if (bDone == 0) {
updateLedControl(ledControl);
bDone = 1;
}
vTaskDelay(5000);
}
So the call is made only once (just to make sure there are no issues with an ongoing transmission when a new call is made.
I only have the H7 and the TCA6507 connected together.
This is from an example for STM32091C_EVAL in the FW package for F0 V1.11.0
if (HAL_SMBUS_Master_Transmit_IT(&SmbusHandle, DeviceAddr, &buffertx[0], /*sizeof(buffertx)*/2, SMBUS_FIRST_AND_LAST_FRAME_NO_PEC) != HAL_OK)
{
return TSENSOR_ERROR;
}
while(HAL_SMBUS_GetState(&SmbusHandle) != HAL_SMBUS_STATE_READY);
It has the same kind of code (this is what I used as an example actually). But there is no explanation why that while() -loop is required after calling the transmit function.
Anyone have an answer?
Also, my interrupts for the SMBus are mostly empty, apart from CubeMX generated code:
void I2C2_EV_IRQHandler(void)
{
/* USER CODE BEGIN I2C2_EV_IRQn 0 */
/* USER CODE END I2C2_EV_IRQn 0 */
HAL_SMBUS_EV_IRQHandler(&hsmbus2);
/* USER CODE BEGIN I2C2_EV_IRQn 1 */
/* USER CODE END I2C2_EV_IRQn 1 */
}
/**
* @brief This function handles I2C2 error interrupt.
*/
void I2C2_ER_IRQHandler(void)
{
/* USER CODE BEGIN I2C2_ER_IRQn 0 */
/* USER CODE END I2C2_ER_IRQn 0 */
HAL_SMBUS_ER_IRQHandler(&hsmbus2);
/* USER CODE BEGIN I2C2_ER_IRQn 1 */
/* USER CODE END I2C2_ER_IRQn 1 */
}
Since I don't need any error or event handling at this moment specifically. I think.
Also, I found this (it's not advertised among the regular Cube packages in CubeMX) from the ST website:
https://www.st.com/en/embedded-software/x-cube-smbus.html
Am I supposed to be using this? And if one looks inside a file called:
stm32_SMBUS_stack.c , on row 1751 is this:
result = HAL_SMBUS_Master_Transmit_IT( pStackContext->Device, address, com_buffer, size, xFerOptions );
if (result != HAL_OK )
{
pStackContext->StateMachine |= SMBUS_SMS_ERROR;
}
But now, the while() loop we saw previously is not there. How come?
Best regards
2020-05-20 07:18 AM
Hi,
the TCA6507 looks like a I2C device to me. Did you connect the SMBA of STM32 with EN of the TCA6507?
Did you try to use I2C functions?
Kind regards
Daniel
2020-05-20 09:50 PM
Hi,
TCA6507 can operate in both modes, SMbus and I2C. I haven't tried I2C functions since the SMBus functions seem to work.
I'm just wondering about the questions I had in the original post:
In my boot code, I do enable the device through a GPIO.
Best regards