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 the reading of data from the digimatic is interrupted, and as soon as the program returns to where it left off before the interruption, it can read bad data.
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
question from:
https://stackoverflow.com/questions/65882669/stm32-reading-data-from-digimatic-spc-and-communication-via-i2c-at-the-same-time 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…