cancel
Showing results for 
Search instead for 
Did you mean: 

i2c Error 4

SGian.1
Senior

Hi there !

i work with DS2482 I2c to one wire . After i send the command reset i need the read the status register until i find one bit at 1, so i wrote my routine in this way 

 

static uint8_t DS2482_Status_Register(void)
{
	uint8_t register_status=0;
	uint8_t data=0;

	while(register_status !=0x02 )
	{
		Master_Recive_Data(DS2482_Addr, &data,  1);
//		HAL_Delay(1);
		 dato= data;
		register_status = data;
		register_status &= 0x02;
	}
		
	if(register_status != 0x02)
	{
		return HAL_TIMEOUT;
	}

	return HAL_OK;
	
}

 

when i run the program i recive error 4 from i2C form

void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c)
{
}

 

But if in the code below i put one delay of 1ms everything work perfect . So there is one "elegant" way to resolve the problem  ? or there are other solution  ? 

Thanks a lot

Sergio

1 ACCEPTED SOLUTION

Accepted Solutions
Karl Yamashita
Principal

But if in the code below i put one delay of 1ms everything work perfect . So there is one "elegant" way to resolve the problem  ? or there are other solution  ? 


It's possible that you're not meeting the tBUF requirements so the 1ms delay probably allows the slave to ACK?

 

KarlYamashita_0-1769550890480.png

 

1. Configure a timer to interrupt at a periodic time and in the timer callback, call DS2482_Status_Register.
2. In HAL_I2C_MasterRxCpltCallback you can check to see if the correct I2C peripheral caused the interrupt and set a flag. 

3. In main while loop you can check for the flag and then test data for 0x02. From there you can continue to what you need to do.

 

// configure timer to interrupt at needed time period and in the interrupt callback, call this function
void DS2482_Status_Register(void)
{
	if(HAL_I2C_Mem_Read_IT({arguments}) != HAL_OK)
	{
		Error_Handler();
	}
}

volatile bool dataRdy = {0};

void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c)
{
	if(hi2c == &hi2c1)
	{
		dataRdy = true;
	}
}

int main(void)
{
	// HAL stuff
	
	while(1)
	{
		if(dataRdy)
		{
			dataRdy = false;
			
			if(data == 0x2)
			{
				// do something
			}
					
		}
		
		// other code
	}
}

 

If a reply has proven helpful, click on Accept as Solution so that it'll show at top of the post.
CAN Jammer an open source CAN bus hacking tool
CANableV3 Open Source

View solution in original post

6 REPLIES 6
Andrew Neil
Super User

@SGian.1 wrote:

when i run the program i recive error 4 from i2C


Have you looked-up what error 4 means ?

A complex system that works is invariably found to have evolved from a simple system that worked.
A complex system designed from scratch never works and cannot be patched up to make it work.

Yep , ACK failure from the device . i use two  4,7K pullup resistor and when i send a data i use HAL_I2C_Mem_Read_IT function and i wait until i setup one bit inside this other function 

void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c). And please correct me if i'm wrong but i think when this function is call wanna mean the bus is ready for receive other data 

 

Are you sure you are using the correct slave address?

In particular, be sure that you are correctly presenting it in the byte parameter...

 

A complex system that works is invariably found to have evolved from a simple system that worked.
A complex system designed from scratch never works and cannot be patched up to make it work.
Karl Yamashita
Principal

But if in the code below i put one delay of 1ms everything work perfect . So there is one "elegant" way to resolve the problem  ? or there are other solution  ? 


It's possible that you're not meeting the tBUF requirements so the 1ms delay probably allows the slave to ACK?

 

KarlYamashita_0-1769550890480.png

 

1. Configure a timer to interrupt at a periodic time and in the timer callback, call DS2482_Status_Register.
2. In HAL_I2C_MasterRxCpltCallback you can check to see if the correct I2C peripheral caused the interrupt and set a flag. 

3. In main while loop you can check for the flag and then test data for 0x02. From there you can continue to what you need to do.

 

// configure timer to interrupt at needed time period and in the interrupt callback, call this function
void DS2482_Status_Register(void)
{
	if(HAL_I2C_Mem_Read_IT({arguments}) != HAL_OK)
	{
		Error_Handler();
	}
}

volatile bool dataRdy = {0};

void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c)
{
	if(hi2c == &hi2c1)
	{
		dataRdy = true;
	}
}

int main(void)
{
	// HAL stuff
	
	while(1)
	{
		if(dataRdy)
		{
			dataRdy = false;
			
			if(data == 0x2)
			{
				// do something
			}
					
		}
		
		// other code
	}
}

 

If a reply has proven helpful, click on Accept as Solution so that it'll show at top of the post.
CAN Jammer an open source CAN bus hacking tool
CANableV3 Open Source

Yes about that i'm sure 

now i try  

Thank you guys