2022-06-22 09:00 AM
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
}
}
2022-06-22 09:24 AM
have you used an oscilloscope to look at what's actually happening on the wires?
2022-06-22 09:28 AM
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
2022-06-22 09:53 AM
Also, from what I see in the scope the read data is correct