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

)
Пытаюсь заставить работать аксель 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