I'M UNABLE TO USE I2C ON ARM CORTEX M3 PROCESSOR. WHAT AM I DOING WRONG? WHICH TEST COULD I PERFORM TO FIND THE PROBLEM?
THE ARM IS GD32F130C8 (MASTER DEVICE) AND I'M PROGRAMMING IT WITH KEIL (USING GD32F1x0 Firmware Library) THE SLAVE DEVICE IS MPU-6050 (ACCELEROMETER) I DEFINE THE VARIABLE WITH LOCAL ADDRESS AND MPU-6050 DEVICE:
#define I2C_ACCELEROMETER_ADDRESS 0xD0 //( 0x68 + one bit) #define I2C_OWN_ADDRESS 0x72
THEN I INIT THE I2C PIN THIS WAY:
//Init I2C communication to accelerometer // enable I2C0 clock rcu_periph_clock_enable(RCU_I2C0); // connect PB8 to I2C0_SCL gpio_af_set(GPIOB, GPIO_AF_1, GPIO_PIN_8); // connect PB9 to I2C0_SDA gpio_af_set(GPIOB, GPIO_AF_1, GPIO_PIN_9); gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_8); gpio_output_options_set(GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ,GPIO_PIN_8); gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_9); gpio_output_options_set(GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ,GPIO_PIN_9);
THEN I INIT THE I2C THIS WAY:
void I2C_Accelerometer_init(void){ // configure I2C0 clock i2c_clock_config(I2C0, 100000, I2C_DTCY_2); // configure I2C0 address i2c_mode_addr_config(I2C0, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, I2C_OWN_ADDRESS); // enable I2C0 i2c_enable(I2C0); // enable acknowledge i2c_ack_config(I2C0, I2C_ACK_ENABLE); }
THEN PERIODICALLY (EACH SECOND) I TRY TO GET THE DATA FROM ACCELEROMETER. THERE IS NO ERROR BUT THE VARIABLE "Accelerometer_X_High" IS ALWAYS ZERO (THIS IS BASICALLY MY PROBLEM). THE FOLLOWING CODE IS EXECUTED EACH SECOND. AS YOU CAN SEE I SET POWER MANAGEMENT TO 0, THEN I REQUEST REGISTER WITH ACCELEROMETER DATA, THEN I TRY TO GET THE DATA FROM THE SLAVE DEVICE:
extern uint8_t Accelerometer_X_High; //periodically called by timers in it.c void GetAccelerometerData(void){ uint8_t bytesToReadIndex=0; //WAKE UP ACCELEROMETER (6B 00) // wait until I2C bus is idle while(i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)); // send a start condition to I2C bus i2c_start_on_bus(I2C0); // wait until SBSEND bit is set while(!i2c_flag_get(I2C0, I2C_FLAG_SBSEND)); // send slave address to I2C bus i2c_master_addressing(I2C0, I2C_ACCELEROMETER_ADDRESS, I2C_TRANSMITTER); // wait until ADDSEND bit is set while(!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)); // clear ADDSEND bit i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND); // send a data byte i2c_data_transmit(I2C0,0x6B); //PWR MANAGEMENT // wait until the transmission data register is empty while(!i2c_flag_get(I2C0, I2C_FLAG_TBE)); // send a data byte i2c_data_transmit(I2C0,0x00); //WAKE UP // wait until the transmission data register is empty while(!i2c_flag_get(I2C0, I2C_FLAG_TBE)); // send a stop condition to I2C bus i2c_stop_on_bus(I2C0); while(I2C_CTL0(I2C0)&0x0200); //REQUEST ACELEROMETER DATA (3B ) // wait until I2C bus is idle while(i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)); // send a start condition to I2C bus i2c_start_on_bus(I2C0); // wait until SBSEND bit is set while(!i2c_flag_get(I2C0, I2C_FLAG_SBSEND)); // send slave address to I2C bus i2c_master_addressing(I2C0, I2C_ACCELEROMETER_ADDRESS, I2C_TRANSMITTER); // wait until ADDSEND bit is set while(!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)); // clear ADDSEND bit i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND); // send a data byte i2c_data_transmit(I2C0,0x3B); //ACCELEROMETER REGISTER // wait until the transmission data register is empty while(!i2c_flag_get(I2C0, I2C_FLAG_TBE)); // send a stop condition to I2C bus i2c_stop_on_bus(I2C0); while(I2C_CTL0(I2C0)&0x0200); //now reopen the bus to receive the reply // wait until I2C bus is idle while(i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)); // send a start condition to I2C bus i2c_start_on_bus(I2C0); // wait until SBSEND bit is set while(!i2c_flag_get(I2C0, I2C_FLAG_SBSEND)); // send slave address to I2C bus i2c_master_addressing(I2C0, I2C_ACCELEROMETER_ADDRESS, I2C_RECEIVER); // wait until ADDSEND bit is set while(!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)); // if we receive only one byte: reset ACKEN bit i2c_ack_config(I2C0, I2C_ACK_DISABLE); //clear ADDSEND bit i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND); // if we receive only one byte: send stop condition i2c_stop_on_bus(I2C0); /* wait until the RBNE bit is set */ while(!i2c_flag_get(I2C0, I2C_FLAG_RBNE)); //read a data from I2C_DATA Accelerometer_X_High = i2c_data_receive(I2C0); // if we receive more bytes: send a stop condition to I2C bus //i2c_stop_on_bus(I2C0); while(I2C_CTL0(I2C0)&0x0200); // enable acknowledge i2c_ack_config(I2C0, I2C_ACK_ENABLE); }
It works. I read all the registers. There is no error on the firmware. The only problem is that the chip is not the one that I supposed it to be. I have to find the right part number of accelerometer and find the register to wake it up.
oops!!