cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F103C8 and MPU 6050 I2C connection problem

DAlat.1
Associate II

I'm trying to read temperature data in realtime , here is my code

#include "stm32f10x.h"
#include "LCD.h"
#include "MPU_6050.h"
 
void	I2C_init(void);
void	I2C_write(uint8_t devAddress, uint8_t regAddress, uint8_t data);
void 	I2C_read(uint8_t devAddress, uint8_t regAddress, uint8_t *data);
 
int 	main()
{
	RCC->APB2ENR |= PORTB;
	
	initPin(GPIOC, PIN14);
	initTimers();
	
	initLCD();
	
	I2C_init();
	
	uint8_t tempH = 0;
	uint8_t tempL = 0;
	int16_t temp = 0;
	
	while(1)
	{		
		I2C_read(MPU6050_W, MPU6050_RA_TEMP_OUT_H, &tempH);
		waitMs(2);
		I2C_read(MPU6050_W, MPU6050_RA_TEMP_OUT_L, &tempL);
		waitMs(2);
 
		temp = (tempH<<8)|tempL;
		temp /= 340;
		temp += 36;
		printNumber(temp);
	}
}
 
void	I2C_init(void)
{
	RCC->APB1ENR |= RCC_APB1ENR_I2C1EN;
	I2C1->CR2 |= 36;
	I2C1->CCR |= 180;
	I2C1->TRISE |= 37;
	// enable ACK
	I2C1->CR1 |= I2C_CR1_ACK;
	// set PORTB PB6, PB7 alternate function
	GPIOB->CRL |= GPIO_CRL_CNF6 | GPIO_CRL_MODE6;
	GPIOB->CRL |= GPIO_CRL_CNF7 | GPIO_CRL_MODE7;
	// enable peripheral
	I2C1->CR1 |= I2C_CR1_PE;
	// MPU6050_RA_PWR_MGMT_1 = 0x6B
	I2C_write (MPU6050_W, MPU6050_RA_PWR_MGMT_1, 0b00000000);
}
 
void	I2C_write(uint8_t devAddress, uint8_t regAddress, uint8_t data)
{
	while((I2C1->SR2 & I2C_SR2_BUSY) == I2C_SR2_BUSY);
	
	// send START
	I2C1->CR1 |= I2C_CR1_START;
	while(!(I2C1->SR1 & I2C_SR1_SB));
	(void) I2C1->SR1;
 
	// by writing DR clear SB flag and send address
	I2C1->DR = devAddress;
	while(!(I2C1->SR1 & I2C_SR1_ADDR));
	// clear ADDR flag
	(void)I2C1->SR1;
	(void)I2C1->SR2;
	
	// send slave register address
	I2C1->DR = regAddress;
	while(!(I2C1->SR1 & I2C_SR1_TXE));
 
	// send data and clear TXE flag
	I2C1->DR = data;
	while(!(I2C1->SR1 & I2C_SR1_BTF));
 
	// send stop
	I2C1->CR1 |= I2C_CR1_STOP;
	while((I2C1->SR2 & I2C_SR2_BUSY) == I2C_SR2_BUSY);
}
 
void 	I2C_read(uint8_t devAddress, uint8_t regAddress, uint8_t *data)
{
	I2C1->CR1 |= I2C_CR1_ACK;
	// send START
	I2C1->CR1 |= I2C_CR1_START;
	while(!(I2C1->SR1 & I2C_SR1_SB));
	(void)I2C1->SR1;
 
	// send DEV ADDRESS
	I2C1->DR = devAddress;
	while(!(I2C1->SR1 & I2C_SR1_ADDR));
	(void)I2C1->SR1;
	(void)I2C1->SR2;
 
	// send register address
	I2C1->DR = regAddress;
	while(!(I2C1->SR1 & I2C_SR1_TXE));
	I2C1->CR1 |= I2C_CR1_STOP; 
	
	// send START
	I2C1->CR1 |= I2C_CR1_START;
	while(!(I2C1->SR1 & I2C_SR1_SB));
	(void)I2C1->SR1;
	
	// send DEVADDRESS in read mode
	I2C1->DR = MPU6050_R;
	while(!(I2C1->SR1 & I2C_SR1_ADDR));
	(void)I2C1->SR1;
	(void)I2C1->SR2;
	
	// read DATA + NACK
	I2C1->CR1 &= ~I2C_CR1_ACK;
	while(!(I2C1->SR1 & I2C_SR1_RXNE));
	
	*data = I2C1->DR;
	
	// send STOP
	I2C1->CR1 |= I2C_CR1_STOP;
}

it prints temperature ONLY once i.e reads TEMP_H and TEMP_L, BUT

then when it trying to read TEMP_H again, it stucks inside of I2C_read's start flag loop.

while(!(I2C1->SR1 & I2C_SR1_SB));

What I'm doing wrong? why it's not reading temperature second times?

1 REPLY 1
DAlat.1
Associate II

maybe I have wrong frequencies?