Кто любит RISC в жизни, заходим, не стесняемся.
Ответить

Аксель и libopencm3

Пт окт 27, 2023 16:14:12

Здравствуйте, товарищи! Задавал вопрос на другом форуме, не отвечают, задам здесь (если еще всем не надоел :)) )

Пытаюсь заставить работать аксель LSM303DLHC на плате stm32f3discovery. Неприятным сюрпризом оказалось, что i2c интерфейс на f3 сильно отличается от других stm-ок и по этой причине я решил использовать libopencm3 (вернее небольшую ее часть, которую чуть-чуть изменил). Проблема наступает тогда, когда я пытаюсь прочитать значения, представленные 2мя байтами.

Поясню. Чтение регистра (любой регистр представленный одним байтом, условно CTRL_REG1_A ) успешно отдает мне ожидаемые значения, однако чтения OUT_X_L_A вместе с OUT_X_H_A ( и им подобных по осям Y и Z) возвращает всегда 0, как не крути плату. Изначально я делал подобно тому, как было в примерах самой либы. Пример из либы:
Код:
cmd = ACC_STATUS;
i2c_transfer7(I2C1, I2C_ACC_ADDR, &cmd, 1, &data, 1);
cmd = ACC_OUT_X_L_A;
i2c_transfer7(I2C1, I2C_ACC_ADDR, &cmd, 1, &data, 1);
acc_x = data;
cmd = ACC_OUT_X_H_A;
i2c_transfer7(I2C1, I2C_ACC_ADDR, &cmd, 1, &data, 1);
acc_x |= ((uint16_t)data << 8);

К сожалению, такой вариант не сработал.

Далее я внимательно читаю документацию на акселерометр и вижу там следующее:
In order to read multiple bytes, it is necessary to assert the most significant bit of the sub-
address field. In other words, SUB(7) must be equal to 1 while SUB(6-0) represents the
address of the first register to be read.


После чего пишу вот так:
Код:
#define I2C_MULTIPLE_RWBIT   (uint8_t)0x80
 
uint8_t cmd;
uint8_t data[6];
cmd = LSM303_OUT_X_L_A | I2C_MULTIPLE_RWBIT;
/* 6 is cause 2 byte * 3 value * xyz */
i2c1_transfer7(I2C_ACC_ADDR, &cmd, 1, &data, 6);
*X= (int16_t)(data[1] << 8 | data[0]);
*Y = (int16_t)(data[3] << 8 | data[2]);
*Z = (int16_t)(data[5] << 8 | data[4]);


Данный вариант также не работает, не работают и многие подобные ему. Знающие люди, подскажите, пожалуйста, как прочитать значение представленное двумя байтами из акселерометра?
P.S. На всякий случай код функции i2c1_transfer7(), т.к. закрадывается нехорошее подозрение на счет весьма непонятного FIXME, оставленного разработчиками:
Код:
void i2c1_transfer7(uint8_t addr, const uint8_t *w, size_t wn, uint8_t *r, size_t rn)
{
   /*  waiting for busy is unnecessary. read the RM */
   if (wn) {
      i2c1_set_7bit_address(addr);
      i2c1_set_write_transfer_dir();
      i2c1_set_bytes_to_transfer(wn);
      if (rn) {
         i2c1_disable_autoend();
      } else {
         i2c1_enable_autoend();
      }
      i2c1_send_start();

      while (wn--) {
         bool wait = true;
         while (wait) {
            if (i2c1_transmit_int_status()) {
               wait = false;
            }
            while (i2c1_nack()); /* FIXME Some error */
         }
         i2c1_send_data(*w++);
      }
      /* not entirely sure this is really necessary.
       * RM implies it will stall until it can write out the later bits
       */
      if (rn) {
         while (!i2c1_transfer_complete());
      }
   }

   if (rn) {
      /* Setting transfer properties */
      i2c1_set_7bit_address(addr);
      i2c1_set_read_transfer_dir();
      i2c1_set_bytes_to_transfer(rn);
      /* start transfer */
      i2c1_send_start();
      /* important to do it afterwards to do a proper repeated start! */
      i2c1_enable_autoend();

      for (size_t i = 0; i < rn; i++) {
         while (i2c1_received_data() == 0);
         r[i] = i2c1_get_data();
      }
   }
}


Добавлено after 6 minutes 35 seconds:
Наверное, стоит закрепить ссылку на даташит https://www.st.com/en/mems-and-sensors/lsm303dlhc.html
Вложения
lsm303dlhc.pdf
(813.52 KiB) Скачиваний: 21

Re: Аксель и libopencm3

Сб окт 28, 2023 15:33:22

Так, товарищи, самостоятельно решил проблему. Не могу предположить, где конкретно заключалась ошибка, поскольку переписал все на cmsis и таки заработало, хоть и не сразу. Просто хочется отметить, что libopencm3, не смотря на хвалу некоторых оказалась неспособной решить свою задачу и остаются вопросы на счет другой перефирии, например, куда более сложного usb. "Плюсом" идут еще и нерабочие примеры для самой же либы и непонятный FIXME в коде. Вероятно, всё таки писать на cmsis в конечном итоге лучше и удобнее.

P.S. можно ли как то закрыть свой тред?
Ответить