We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
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); }
Looking at the decoded bits I find that the communication exactly follows the code lines. It just seems that the received byte is 0x00. I will try to query all registers. Pullup resistors are 4,7k. The board with its original firmware was working, but i don't have it since it is not opensource. So there is no hardware problem.
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!!