I2C ПРОГРАММИРОВАНИЕ НА РУКАХ - PullRequest
0 голосов
/ 19 мая 2019

Я не могу использовать I2C в процессе ARM CORTEX M3.Что я делаю неправильно?Какой тест я могу выполнить, чтобы найти проблему?

Это GD32F130C8 (мастер), и я программирую его с помощью KEIL (с помощью библиотеки микропрограмм GD32F1x0)

Подчиненный - это MPU-6050 (акселерометр)

Я определил переменную с локальным адресом и устройством MPU-6050:

      #define I2C_ACCELEROMETER_ADDRESS 0xD0 //( 0x68 + one bit)
      #define I2C_OWN_ADDRESS 0x72

Затем я инициализировал I2C PIN следующим образом:

    //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);

Затем я инициализировал I2C следующим образом:

    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);
    }

Затем периодически (каждую секунду) я пытаюсь получить данные от акселерометра.Нет ошибки, но переменная «accelerometer_x_high» всегда равна нулю (это в основном моя проблема).

Следующий код выполняется каждую секунду.Как видите, я устанавливаю управление питанием на 0, затем запрашиваю регистр с данными акселерометра, затем пытаюсь получить данные от ведомого устройства:

    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);

    }

, получая сигналы с помощью осциллографа, я получаю следующий результат:communication decoded

это скриншот со всем сигналом: http://www.tr3ma.com/Dati/IMG_1526.JPG

На сигнале также присутствуют странные пики:

http://www.tr3ma.com/Dati/spike1.JPG

http://www.tr3ma.com/Dati/spike2.JPG

http://www.tr3ma.com/Dati/spike3.JPG

http://www.tr3ma.com/Dati/spike4.JPG

1 Ответ

0 голосов
/ 29 мая 2019

Работает.Я создал цикл для чтения всех регистров и смог прочитать все содержимое чипа.На прошивке ошибки нет.Единственная проблема в том, что чип не тот, который я предполагал.Я должен найти правильный номер акселерометра и найти регистр, чтобы разбудить его.

...