Electrical – Getting Accelerometer values from MPU 6050

atmega328pavrembedded

I m trying to read accelerometer values from mpu 6050 in atmega328p (Arduino UNO). I want an embedded c program that's why don't wanna use any external lib. So I read about I2C protocol, read the datasheet of MPU 6050, register sheet of MPU 6050 and developed a code as per my understanding.
Here's the code

#include<avr/io.h>
const int MPU_addr=0x68;
void i2c_init() {
  TWSR=0x00;
  TWBR=0x48;
  TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA);
}

void i2c_start() {
  TWCR=(1<<TWEN)|(1<<TWINT)|(1<<TWSTA);
  while((TWCR&(1<<TWINT))==0);  
}

void i2c_stop() {
  TWCR=(1<<TWEN)|(1<<TWINT)|(1<<TWSTO);
}

void i2c_write(uint8_t data) {
  TWDR=data;
  TWCR=(1<<TWINT)|(1<<TWEN);
  while((TWCR&(1<<TWINT))==0);  
}

uint8_t i2c_read(unsigned char isLast) {
  if(isLast==0) {
    TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWEA);
  }
  else {
    TWCR=(1<<TWINT)|(1<<TWEN);
  }
   return TWDR;
}

int main() {
  uint16_t i;
  i2c_init();
  i2c_start();
  i2c_write((MPU_addr<<1)|(1<<0));
  i2c_write(0x6B);
  i2c_write(0);
  i2c_stop();
  Serial.begin(9600);
  while(1) {
    i2c_start();
    i2c_write((MPU_addr<<1)|(1<<0));
    i2c_write(0x3B);
    i2c_start();
    i2c_write((MPU_addr<<1)|(0x00));
    i=(i2c_read(0)<<8)|i2c_read(0);
    Serial.println(i,BIN);
  }
return 1;
}

The problem is in the while loop, the program hangs after the i2c_start(); call.
I have checked this by putting a Serial.println("a"); after that line, but nothing gets printed on the serial monitor. I have also checked that the program enters the while loop successfully. So can anybody help where is the problem in the code?

Note:
1. All the i2c function(s) are in accordance with the book "The Avr microcontroller and the embedded system using assembly and C" by Ali Mazidi".

Best Answer

Looking at the datasheet of the 328p (page 297), it seems like you're handling the TWINT bit wrong.

By the datasheet, the bit is never cleared by the hardware, which is what you're seeing. It's set by the hardware instead.

By a quick skim over the code, what you could simply do would be inverting the logic around the TWINT - clearing it to make it do stuff, and waiting for it to become set again.