Important changes to forums and questions
All forums and questions are now archived. To start a new conversation or read the latest updates go to forums.mbed.com.
6 years, 3 months ago.
I2C PROGRAMMING ON ARM
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); }
acquiring signals with oscilloscope I get the following result:
this is a screenshot with entire signal:
On the signal there are also strange spikes:
Assigned to
6 years, 3 months ago.This means that the question has been accepted and is being worked on.
Did you install external pullup resistors on both SDA and SCL lines? What value? Connecting a logic analyzer to the pins is the next logical step to confirm micro is outputing what you think it's outputing.
posted by Graham S. 19 May 20194,7k resistors. The doubt is on arm programming. I'm sure there is an error on the posted code but I couldn't find an example online
posted by gaucho bacca 20 May 2019I updated my question. please check oscilloscope acquisition and its decoding.
posted by gaucho bacca 27 May 2019It 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.
posted by gaucho bacca 29 May 2019