Вопросы о библиотеке HMC5883L
Сейчас я изучаю структуру библиотек. Я хочу узнать, как хорошие программисты пишут код, каким стратегиям они следуют, какому искусству программист следовал при разработке библиотеки. И насколько важно, чтобы библиотека была написана в хорошо оформленном виде.
Но поскольку я снова и снова исследую библиотеку, мне действительно нужно понять, как следовал программист, и причины, лежащие в основе примененной стратегии.
Пример, который я сейчас изучаю, — это HMC5883L и то, как программист использовал библиотеку Wire для управления разработкой библиотеки. Опытным программистам это должно быть довольно легко, но я действительно изучаю концепции, стратегии и т. д.
Поскольку я говорю снова и снова, у меня возникают разные вопросы, поэтому, чтобы начать это обсуждение, я хочу начать с вопроса о программисте, пишущем две очень похожие функции, которые делают практически одно и то же.
// Читаем байт для регистрации
uint8_t HMC5883L::fastRegister8(uint8_t reg)
{
uint8_t value;
Wire.beginTransmission(HMC5883L_ADDRESS);
#if ARDUINO >= 100
Wire.write(reg);
#else
Wire.send(reg);
#endif
Wire.endTransmission();
Wire.requestFrom(HMC5883L_ADDRESS, 1);
#if ARDUINO >= 100
value = Wire.read();
#else
value = Wire.receive();
#endif
Wire.endTransmission();
return value;
}
// Читаем байт из регистра
uint8_t HMC5883L::readRegister8(uint8_t reg)
{
uint8_t value;
Wire.beginTransmission(HMC5883L_ADDRESS);
#if ARDUINO >= 100
Wire.write(reg);
#else
Wire.send(reg);
#endif
Wire.endTransmission();
Wire.beginTransmission(HMC5883L_ADDRESS);
Wire.requestFrom(HMC5883L_ADDRESS, 1);
while(!Wire.available()) {};
#if ARDUINO >= 100
value = Wire.read();
#else
value = Wire.receive();
#endif
Wire.endTransmission();
return value;
}
Обновление:
Собственно, первую версию программист использовал только в функции HMC5883L.begin();
, но почему?
if ((fastRegister8(HMC5883L_REG_IDENT_A) != 0x48)
|| (fastRegister8(HMC5883L_REG_IDENT_B) != 0x34)
|| (fastRegister8(HMC5883L_REG_IDENT_C) != 0x33))
{
return false;
}
Все остальное в библиотеке использовало вторую версию.
Итак, по сути, эти две функции предназначены для чтения указанного регистра в HMC5883L, мои вопросы:
- в чем разница? Я знаю, что второй функции было уделено особое внимание, но почему?
- Это так важно?
- Есть ли ситуации, требующие какой-либо версии функций?
@R1S8K, 👍0
Обсуждение2 ответа
Лучший ответ:
Честно говоря, вторая версия функции - мусор. Первая версия (почти) правильный способ сделать это. Во второй версии есть вещи, которых там быть не должно. Нет абсолютно никакой причины, по которой создатель библиотеки создал эту вторую функцию.
- Он «ждет» доступности данных, когда эти данные будут доступны в момент завершения
requestFrom()
— поэтому это совершенно избыточно - Он выполняет ложный вызов
beginTransmission()
прямо перед вызовомrequestFrom()
.beginTransmission()
предназначен только для записи, а не для чтения. Там это бессмысленно.
Однако:
- Обе функции выполняют
endTransmission()
послеreceiveFrom()
, что не имеет смысла —endTransmission()
предназначен для балансировки толькоbeginTransmission()
, а неreceiveFrom()
.receiveFrom()
— это полностью автономная функция, не требующая никакой другой обработки.
Эта библиотека, вероятно, не подходит для изучения, чтобы научиться использовать библиотеку Wire. Он содержит код, который указывает на то, что автор сам не имел должного представления о работе библиотеки.
Огромное тебе спасибо, чувак! Я имею в виду, что вы серьезный человек :) Я очень рад, что мои вопросы значительны и важны. Я бы тоже попробовал развивать свою библиотеку, для меня это значит получать все больше и больше навыков, информации и учиться искусству программирования. Мне нужно забыть о своих старых кодах и библиотеках :), @R1S8K
Но если у меня возникнут еще вопросы, стоит ли мне вернуться сюда? Или убрать выбор ответа, пока я не закончу обсуждение темы?, @R1S8K
Если у вас есть новые вопросы, задавайте новые вопросы. Держите его «атомарным» :), @Majenko
все библиотеки HMC5883L для Arduino имеют такое :-) (включая Adafruit), @Juraj
Тогда они все скопировали друг друга :) У меня есть DTWI для чипKIT, который не делает этого - но тогда DTWI работает не так, как Wire..., @Majenko
@Юрай Не **все** из них. У этого 19 звезд, и он очень хорош: https://github.com/sleemanj/HMC5883L_Simple., @Jot
@Jot Спасибо за ссылку :), @R1S8K
Я действительно только сейчас обнаружил, как читать из определенного регистра из HMC5883L, я думал, что смогу прочитать 1-й регистр, и автоматический указатель чипа перенесет меня к следующему, не заканчивая проводную передачу и не начиная чтение нового. что регистрируют, но получается на самом деле так, мне приходится делать две совершенно отдельные проводные передачи. Один для указания регистра для чтения, а второй для чтения этого регистра., @R1S8K
Правильный. Во время инициализации не возникает проблем с чтением или записью одного байта. Если во время работы требуются данные x,y,z, было бы полезно прочитать эти 6 байтов вместе., @Jot
Не существует «быстрого» способа сделать i2c. Если вы уже используете «быстрые» функции в своем коде, вы можете сделать это встроенным вызовом readRegister8.
Приведенная ниже функция считывает байт из HMC5883L.
Если HMC5883L не подключен, Wire.read() возвращает -1. Оно будет преобразовано в возвращаемое значение 0xFF.
// Читаем байт из регистра
uint8_t HMC5883L::readRegister8(uint8_t reg)
{
uint8_t value;
Wire.beginTransmission(HMC5883L_ADDRESS);
Wire.write(reg);
Wire.endTransmission(); // добавляем параметр false для повторного запуска
Wire.requestFrom(HMC5883L_ADDRESS, 1);
value = Wire.read();
return value;
}
Но разве не требуется Wire.endTransmission();
после value = Wire.read();
?, @R1S8K
Нет, никогда, только при записи данных. См.: https://www.arduino.cc/en/Reference/WireEndTransmission. Это одна из ошибок в коде, о которой Маженко упомянул в своем ответе., @Jot
Хорошо, я перемещаюсь по i2c, немного поработал с библиотекой Wire и протестировал несколько строк по чтению каждого регистра. Далее мне нужно создать аналогичный надежный код i2c, который работает с аналогичным управлением данными в ISR и блокирует каждый режим до тех пор, пока он не будет готов., @R1S8K
Да, вы правы, мне следует поставить «false» между операциями записи/чтения. Нашел эту ссылку: ** Если это правда, endTransmission() отправляет сообщение об остановке после передачи, освобождая шину I2C. Если false, endTransmission() отправляет сообщение о перезапуске после передачи**, @R1S8K
- Wire.h не найден!
- Как получить исходные файлы для библиотек Arduino?
- Альтернативы библиотеке Wire для I2C
- Ошибка: invalid application of 'sizeof' to incomplete type 'int []' при попытке вычислить размер массива в библиотеке
- Глобальные переменные занимают много места в динамической памяти.
- Может ли плагин Arduino Eclipse использовать библиотеки, установленные Arduino IDE?
- Включить Guards vs #pragma один раз
- Невозможно использовать библиотеку клавиатуры с Arduino UNO даже после смены прошивки.
Никогда не было «быстрого» способа сделать i2c, это миф. Есть много неправильных способов сделать i2c., @Jot
Да, я все еще изучаю, как на самом деле работает i2c, и разбираюсь с чипами i2c., @R1S8K