cancel
Showing results for 
Search instead for 
Did you mean: 

lsm6ds3 registers problem

EPora.1
Associate II

Hi everyone!

I'm using a custom board with an stm32l051 and an lsm6ds3(and two 4.7kohm pull-ups). I am setuping the I2C1 (pins PB7 SDA and PB8 SCL). then I do the IMU setup in which I write some values to control registers on the IMU. then I read the IMU who am I reg and it says 0x6A (should be 0x69) and when I read every other register they are all at zero accept of the CTRL9_XL reg that is 0xE0. I don't really understand what is happening.

I'd love to hear your opinions.

Many thanks, Eyal Porat

The I2C setup:

void I2C_Setup()
{
	
	
	/*
	I2C1 SCL -> PB8
	I2C1 SDA -> PB7
	*/
	
	//enable the I2C perefiral
	RCC->APB1ENR |= RCC_APB1ENR_I2C1EN;  //enable the I2C1
	RCC->IOPENR |= RCC_IOPENR_GPIOBEN; // Enable GPIOB CLOCK
 
	
	
	
	//MODER:
	//00: Input mode
	//01: Generel prupose output mode
	//10: Alternate function mode
	//11: Analog mode
	GPIOB ->MODER &= ~(3 << 14);
	GPIOB ->MODER &= ~(3 << 16);
	GPIOB ->MODER |= (1 << 15); //set GPIO PB7 as alternate function
	GPIOB ->MODER |= (1 << 17); //set GPIO PB8 as alternate function
	
	
	//OTYPER:
	//0: Output push_pull (reset state)
	//1: Output open-drain
	GPIOB ->OTYPER |= (1 << 7); //open-drain
	GPIOB ->OTYPER |= (1 << 8); //open-drain
	
	//OSPEEDR:
	//x0: Low speed
	//01: Medium speed
	//11: High speed
	GPIOB ->OSPEEDR |= (3 << 14); //very High speed
	GPIOB ->OSPEEDR |= (3 << 16); //very High speed
	
	//PUPDR:
	//00: No pull-up, pull-down
	//01: Pull-up
	//10: Pull-down
	//11: Reserved
	GPIOB ->PUPDR |= (1 << 14); //set GPIO PB7 to pull up
	GPIOB ->PUPDR |= (1 << 16); //set GPIO PB8 to pull up
	
 
	
	//GPIO PB7 AF1 -> I2C1_SDA
	//GPIO PB8 AF4 -> I2C1_SCL
	GPIOB ->AFR[0] |= (1 << 28); //PB7 AF1
	GPIOB ->AFR[1] |= (1 << 2); //PB8 AF4
	
	//set the I2C timing register acording to cubeMX
	//I2C1 ->TIMINGR = 0x00300F38;
	I2C1 ->TIMINGR = 0x00707CBB;
	
	I2C1 ->CR2 &= ~(1 << 11); //set the addressing method to 7-bit
	I2C1 ->CR2 |= (1 << 12); //set the HEAD10R bit
	
	
	I2C1 ->CR1 &= ~(1 << 0); //disable the I2C
	while(I2C1->CR1 & (1 << 0)); //wait for the I2C to turn off
	I2C1 ->CR1 |= (1 << 0); //enable the I2C
	
	
	
}

the IMU setup:

void IMU_Setup(uint8_t address)
{
	
	//set up the CTRL1_XL accel register
	//01100000 - 0x60
	///typ_write(address, 0x10, 0x60);
	typ_write(address, 0x10, 0x60);
	
	//set up the CTRL2_G gyro register
	//01100000 - 0x60
	///typ_write(address, 0x11, 0x60);
	//typ_write(address, 0x11, 0x60);
	typ_write(address, 0x11, 0x60);
	
	typ_write(address, 0x18, 0x00); /////////////////////
	
	typ_write(address, 0x13, 0x02); /////////////////////
	
	
	//set up gyro data ready interupt on interupt 1
	typ_write(address, 0x0D, 0x2);
	
	//set up accelerometer data ready interupt on interupt 2
	typ_write(address, 0x0E, 0x1);
	
	typ_write(address, 0x0B, 0x80);
	
}

the I2C read and write operations:

void typ_write(uint8_t address, uint8_t reg, uint8_t data)
{
	while(I2C1->ISR & (1 << 15)); //wait for the busy flag to turn off
	
	I2C1 ->CR1 &= ~(1 << 0); //disable PE peripheral bit
	
	I2C1 ->CR2 &= ~(I2C_CR2_SADD); //clear the slave address bits
	I2C1 ->CR2 |= address; //set the slave address
	
	I2C1 ->CR2 &= ~(I2C_CR2_NBYTES); //clear the nbytes bits
	I2C1 ->CR2 |= (1 << 16); //set the size of bytes to be transmitted
	
	I2C1 ->CR2 &= ~(1 << 10); //config a write operation
	
	I2C1 ->CR2 &= ~(1 << 25); // disable autoend
	
	I2C1 ->CR1 |= (1 << 0); //enable peripheral
	
	
	I2C1 ->CR2 |= (1 << 13); //set the I2C start bit on
	while(!(I2C1->ISR & (1 << 0))); //wait for the TXE bit to set
 
	I2C1 ->TXDR = reg; //set the adrress to read from
	while(!(I2C1->ISR & (1 << 6))); //wait for transfer
	
	
	I2C1 ->CR2 &= ~(I2C_CR2_NBYTES); //clear the nbytes bits
	I2C1 ->CR2 |= (1 << 16); //set the size of bytes to be transmitted
	
	I2C1 ->CR2 &= ~(1 << 10); //config a write operation
 
	I2C1 ->CR2 |= (1 << 25); // enable autoend
	
	I2C1 ->CR2 |= (1 << 13); //set the I2C start bit on
	while(!(I2C1->ISR & (1 << 0))); //wait for the TXE bit to set
 
	I2C1 ->TXDR = data; //set the adrress to read from
	//while(!(I2C1->ISR & (1 << 6))); //wait for transfer //not relevent when auto end is high
}
 
void typ_read(uint8_t address, uint8_t reg, uint8_t *buff, uint8_t size)
{
	while(I2C1->ISR & (1 << 15)); //wait for the busy flag to turn off
	
	
	I2C1 ->CR1 &= ~(1 << 0); //disable PE peripheral bit
	
	I2C1 ->CR2 &= ~(I2C_CR2_SADD); //clear the slave address bits
	I2C1 ->CR2 |= address; //set the slave address
	
	I2C1 ->CR2 &= ~(I2C_CR2_NBYTES); //clear the nbytes bits
	I2C1 ->CR2 |= (1 << 16); //set the size of bytes to be transmitted
	
	I2C1 ->CR2 &= ~(1 << 10); //config a write operation
	
	I2C1 ->CR2 &= ~(1 << 25); // disable autoend
	
	I2C1 ->CR1 |= (1 << 0); //enable peripheral
	
	
	I2C1 ->CR2 |= (1 << 13); //set the I2C start bit on
	while(!(I2C1->ISR & (1 << 0))); //wait for the TXE bit to set
 
	I2C1 ->TXDR = reg; //set the adrress to read from
	while(!(I2C1->ISR & (1 << 6))); //wait for transfer //not relevent when auto end is high
	
	
 
	I2C1 ->CR2 &= ~(I2C_CR2_NBYTES); //clear the nbytes bits
	I2C1 ->CR2 |= (size << 16); //set the size of bytes to be received
	
	I2C1 ->CR2 |= (1 << 10); //config a read operation
 
	I2C1 ->CR2 |= (1 << 25); // enable autoend
	
	I2C1->CR2 |= I2C_CR2_START; // send start condition again
	
	uint16_t count = 0;
	
	while (count < size)
	{
		//while(!(I2C1->ISR & (1 << 2))){};
		while(!((I2C1->ISR & I2C_ISR_RXNE) == (I2C_ISR_RXNE)));
		buff[count++] = I2C1 ->RXDR; //fill the buffer with incoming data
	}
 
}

 0693W00000Nse3ZQAR.png

3 REPLIES 3
Andrew Neil
Evangelist III

have you used an oscilloscope to look at what's actually happening on the wires?

https://electronics.stackexchange.com/a/473799

Thanks for the comment!

I looked at the signal yesterday and it seems ok. I'll upload a picture later cause I don't have enough hands at the moment:)

Eyal

Also, from what I see in the scope the read data is correct