2024-10-25 02:31 AM
Hello,
I'm trying communication between stm32G0 as I2C slave and a rapsberry pi 5 as master.
on pi side, the call is:
self.cpt = (self.cpt + 1) % 255
b = self.bus.read_i2c_block_data(42, self.cpt, 5);
I've seen in several places on the web that there are issues with clock stretching with the pi (and some tests on my side seem to agree). So I'm using NOSTRETCH activated on the microncontroler side.
For testing purpose I'm transmitting the array {0, 1, 2, 3, 4} on the microcontroler and I'm receiving [4, 0, 1, 2, 3] on the pi.
Here's a screenshot. The green line toggles when I put a byte in tx register.
From the reference manual, I found this explanation:
It shows that data should placed in the tx register before the start.
To do that, I tried to put the first byte in tx register during the read frame. The result is slightly different but still wrong : [5, 1, 2, 3, 4]
I managed to make it successfull by sending nothing during the last TXIS interrupt of the frame but I'm not really satisfied with this solution. It looks ugly.
Is it the good way to do it?
Here's the code.
void init(){
// cubemx initialization happened before this.
LL_I2C_EnableIT_ERR(I2C1);
LL_I2C_EnableIT_STOP(I2C1);
LL_I2C_EnableIT_RX(I2C1);
LL_I2C_EnableIT_NACK(I2C1);
LL_I2C_EnableIT_TX(I2C1);
LL_I2C_EnableIT_ADDR(I2C1);
LL_I2C_Enable(I2C1);
}
uint8_t rx = 0;
uint8_t buffer[12] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
static uint8_t tx = 0;
void send_byte()
{
LL_GPIO_TogglePin(debug2_GPIO_Port, debug2_Pin);
LL_I2C_TransmitData8(I2C1, buffer[tx]);
tx++;
}
void I2C1_IRQHandler(void)
{
/* USER CODE BEGIN I2C1_IRQn 0 */
if (LL_I2C_IsActiveFlag_ADDR(I2C1))
{
LL_I2C_ClearFlag_ADDR(I2C1);
if (LL_I2C_GetTransferDirection(I2C1) == LL_I2C_DIRECTION_WRITE)
{
LL_GPIO_SetOutputPin(debug1_GPIO_Port, debug1_Pin);
}
else
{
LL_GPIO_ResetOutputPin(debug1_GPIO_Port, debug1_Pin);
}
}
if (LL_I2C_IsActiveFlag_TXIS(I2C1))
{
{
if (tx < 5)
send_byte();
}
}
if (LL_I2C_IsActiveFlag_OVR(I2C1))
LL_I2C_ClearFlag_OVR(I2C1);
if (LL_I2C_IsActiveFlag_RXNE(I2C1))
{
{
rx = LL_I2C_ReceiveData8(I2C1);
tx = 0;
send_byte(); // put the first byte in tx regsiter before the start condition
}
}
if (LL_I2C_IsActiveFlag_STOP(I2C1))
{
// SET_BIT(I2C1->ISR, I2C_ISR_TXE);
// SET_BIT(I2C1->ISR, I2C_ISR_TXIS);
LL_I2C_ClearFlag_STOP(I2C1);
}
if (LL_I2C_IsActiveFlag_NACK(I2C1))
LL_I2C_ClearFlag_NACK(I2C1);
if (LL_I2C_IsActiveFlag_TCR(I2C1))
{
}
if (LL_I2C_IsActiveFlag_TXE(I2C1))
{
}
}