I am working on an application running on STM32, which aims to read data from the digimatic spc protocol (mitutoyo device) and then send the data to the raspberry pi via the I2C bus. The Raspberry pi is the master on the I2C bus and the STM32 is the slave.
STM32 reads the data from the digimatic protocol in a cycle. I2C in STM32 operates over an interrupt. So when a request comes from raspberry in STM32, an interrupt is triggered and serviced immediately. The problem is that reading data from the digimatic is interrupted, so bad data is sent via I2C. As soon as the program returns to the place where it ended before the interruption, the reading is already in another phase and the reading of the data is completed with an error.
Has anyone solved a similar problem?
Here is the code to read the data
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_I2C1_Init();
MX_TIM2_Init();
HAL_I2C_EnableListen_IT(&hi2c1);
while (1)
{
//reading data
RQST_LOW();
HAL_Delay(5);
RQST_HIGH();
uint32_t timeout=200;
time=0;
TIM2->CNT=0;
HAL_TIM_Base_Start_IT(&htim2);
for(uint8_t i = 0; i < 13; i++ )
{
uint8_t k=0;
for (uint8_t j = 0; j < 4; j++)
{
while(HAL_GPIO_ReadPin(DG_CLK_GPIO_Port,DG_CLK_Pin) == false && timeout>time)
{
time=(uint32_t)TIM2->CNT;
}
while( HAL_GPIO_ReadPin(DG_CLK_GPIO_Port,DG_CLK_Pin) == true && timeout>time)
{
time=(uint32_t)TIM2->CNT;
}
bitWrite(k, j, (HAL_GPIO_ReadPin(DG_DATA_GPIO_Port,DG_DATA_Pin) & 0x1));
}
rawdata[i] = k;
}
if(!(timeout>time))
{
aTxBuffer[0]=' ';
aTxBuffer[1]=' ';
aTxBuffer[2]=' ';
aTxBuffer[3]=' ';
aTxBuffer[4]=' ';
aTxBuffer[5]=' ';
aTxBuffer[6]=' ';
aTxBuffer[7]=' ';
}
else
{
HAL_TIM_Base_Stop_IT(&htim2);
char buf[7];
for(int lp=0;lp<6;lp++)
{
buf[lp]=rawdata[lp+5]+'0';
}
uint64_t cur_value_int =atoi(buf);
char buf_dec[2];
buf_dec[0] = rawdata[11]+'0';
decimal = atoi(buf_dec);
float cur_value = (float)cur_value_int*(float)pow(10,-decimal);
char buf_sign[2];
buf_sign[0] = rawdata[4]+'0';
int32_t temp = atoi(buf_sign);
if(rawdata[4]==8)
{
cur_value = -cur_value;
}
char buf_unit[2];
buf_unit[0] = rawdata[12]+'0';
temp = atol(buf_unit);
units = (bool)temp;
RQST_LOW();
HAL_Delay(50);
float nearest = roundf(cur_value * 100) / 100;
char array[8] = {0};
sprintf(aTxBuffer, "%.2f", nearest);
}
HAL_Delay(300);
}
}
Here is the I2C interrupt handler code
void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode)
{
UNUSED(AddrMatchCode);
if(hi2c->Instance==I2C1)
{
if(TransferDirection == TRANSFER_DIR_READ)
{
if(HAL_I2C_Slave_Seq_Receive_IT(&hi2c1, (uint8_t *)aRxBuffer, RXBUFFERSIZE, I2C_NEXT_FRAME)!=HAL_OK)
{
Error_Handler();
}
}
else
{
HAL_I2C_Slave_Seq_Transmit_IT(&hi2c1, (uint8_t*)aTxBuffer, 8, I2C_LAST_FRAME);
}
}
}
void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *hi2c)
{
HAL_I2C_EnableListen_IT(&hi2c1); // Restart
}
void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *I2cHandle)
{
if (HAL_I2C_GetError(I2cHandle) != HAL_I2C_ERROR_AF)
{
Error_Handler();
}
}
I will be happy for any advice