Skip to main content
CGrov.1
Associate III
January 14, 2020
Question

Problem setting registers on I2C slave device

I've read through a couple other posts but haven't fount anything that helps me. I am trying to set some registers on a MMC5883 digital magnetometer and can't seem to write to the correct registers. I initialized I2C1 using the graphical Device Configuration Tool, the slave 7-bit address is 0x30. I have PB7 as SDA and PB6 as SCL.

When I go through the debugger the error seems to be at the "status = HAL …." line, as it never returns HAL_OK.

void set_MAG_Regs(){
 
	printf("setting mag slave registers... \n\r");
	HAL_StatusTypeDef status = HAL_OK;
	int i = 0;
	int data [3] = {0x08, 0x03, 0x01};//array of data to set registers
	int addr [3] = {0x08, 0x09, 0x0A};// array data location
 
	 int *register_value;//points to data[]
	 int *register_pointer;//points to addr []
	 register_value = &data[i];
	 register_pointer = &addr[i];
 
	for (i=0; i<4; i++){
 
	status = HAL_I2C_Mem_Write(&hi2c1, 0x30, (uint16_t)register_pointer, I2C_MEMADD_SIZE_16BIT,(uint8_t*)(&register_value), 2, HAL_MAX_DELAY);
 
	if (status != HAL_OK){
			//error handling
				Error_Handler();
				printf("Device failed to set registers \n\r");
		}
 
	i++;
 
	}
 
 
}

This topic has been closed for replies.

8 replies

JoniS
Senior
January 14, 2020

try

status = HAL_I2C_Mem_Write(&hi2c1, (0x30 >> 1), (uint16_t)register_pointer, I2C_MEMADD_SIZE_16BIT,(uint8_t*)(&register_value), 2, HAL_MAX_DELAY);

i cant remember the exact reasoning behind it, but from the time i once used i2c, i believe you had to right shift 8bit value once to get the 7bit address correct.

CGrov.1
CGrov.1Author
Associate III
January 14, 2020

That didn't solve it unfortunately. I did get an error that says "cast from pointer to integer of different size" and indicates the (uint16_t)register_pointer. I changed it to (uint32_t) and it seems to have gotten rid of the error but it's still not writing to registers.

S.Ma
Principal
January 14, 2020

Test this

uint8_t ID = 0x00;
uint8_t SlvAdr = 0x60; // if this doesn't work, try 0x60>>1
uint8_t SubAdr = 0x2F;
 
while(ID!=0x0C) {
status = HAL_I2C_Mem_Read(&hi2c1, SlvAdr, &SubAdr, I2C_MEMADD_SIZE_8BIT,(uint8_t*)(&ID), 1, HAL_MAX_DELAY);
};
 

CGrov.1
CGrov.1Author
Associate III
January 14, 2020

That seems to work! If I understand that code correctly, its reading the data in register 0x2F from device 0x60 and storing it in ID. if I print the value stored in ID I get 536969155. What is the device 0x60? and what does this test?

Seb
ST Employee
January 15, 2020

The spec says the slave address is 0x60 (8 bit). Sometime functions require only 7 bits, so 0x30.

the slave use a 8 bit sub address. at location 0x2F you can read the chip ID which is expected to be 0x0C

You should exit the loop only when the device is detected correctly.

When you write or read 16 bit data, remember the first byte is LSB. (see datasheet).

CGrov.1
CGrov.1Author
Associate III
January 15, 2020

Ahhh ok,I see what its doing now. In that case it is still not working, I thought it had solved that particular issue as it was returning HAL_OK. But it never actually exits that while loop so it must not be reading the chip ID correctly.

I added a line printf( "ID: %d \n\r", ID); inside the while loop to see what was being stored in ID, it only prints the decimal number 97.

I also get an error: "passing argument 3 of 'HAL_I2C_Mem_Read' makes integer from pointer without a cast", which corresponds to "&SubAdr".

 status = HAL_I2C_Mem_Read(&hi2c1, SlvAdr, &SubAdr, I2C_MEMADD_SIZE_8BIT, (uint8_t*)(&ID), 1, HAL_MAX_DELAY);
 

S.Ma
Principal
January 15, 2020

The HAL function headers are out of my head, so here consider it just pseudo code, guidance.

I use a different I2C implementation which is more generic and easier to understand, hence the poor memory on these HAL_I2C functions.

CGrov.1
CGrov.1Author
Associate III
January 15, 2020

OK! thanks for your help. I've realized that the test is returning the device address rather than the device ID so I'm looking into that.

Can I ask what the more generic and easier method is?