Введение
Хотели когда-нибудь добавить часы реального времени (RTC) в свой проект, но не имели под рукой нужного оборудования? С Velxio вы можете симулировать полное чтение I2C RTC, используя Raspberry Pi Pico и виртуальный DS1307 — прямо в вашем браузере. В этом руководстве мы разберём схему, код и ключевые концепции, чтобы вы могли уверенно использовать I2C-коммуникацию в своих проектах.
Разбор схемы
Давайте начнём с рассмотрения схемы. Откройте пример в Velxio, и вы увидите следующие компоненты:

Схема проста: Raspberry Pi Pico (nano-rp2040) подключён к двум светодиодам и виртуальному DS1307 RTC (не показан как отдельный компонент — RTC встроен в симуляцию). Светодиоды используются как визуальные индикаторы активности I2C.
- Светодиод (синий): Подключён к пину D12 (линия SDA) через синий провод. Его анод (A) соединён с D12, а катод (C) — с GND.1 через чёрный провод.
- Светодиод (жёлтый): Подключён к пину D10 (линия SCL) через оранжевый провод. Его анод (A) соединён с D10, а катод (C) — с GND.1 через чёрный провод.
Оба светодиода используют общий земляной контакт (GND.1). Шина I2C состоит из линий SDA (данные) и SCL (тактирование). Часы DS1307 RTC внутренне подключены к этим линиям по адресу 0x68. Светодиоды не обязательны для I2C-коммуникации, но они дают визуальный сигнал о переключении линий.
Чтобы собрать эту схему самостоятельно, вы можете использовать палитру компонентов Velxio:

Найдите “Raspberry Pi Pico” и “LED”, затем соедините их, как описано. Панель инструментов холста помогает масштабировать и располагать компоненты:

Разбор кода
Теперь давайте углубимся в код. Скетч использует библиотеку Wire (встроенную) для связи с DS1307 через I2C. Вот полный код:
// Raspberry Pi Pico — I2C DS1307 RTC Read
// Reads time from virtual RTC at address 0x68
#include <Wire.h>
byte bcdToDec(byte val) {
return ((val >> 4) * 10) + (val & 0x0F);
}
void setup() {
Serial.begin(115200);
delay(500);
Wire.begin();
Serial.println("=== Pico I2C RTC Read ===");
Serial.println("Reading DS1307 at 0x68 (system time)");
Serial.println();
}
void loop() {
// Set register pointer to 0
Wire.beginTransmission(0x68);
Wire.write(0x00);
Wire.endTransmission();
// Read 7 bytes: sec, min, hr, dow, date, month, year
Wire.requestFrom(0x68, 7);
if (Wire.available() >= 7) {
byte sec = bcdToDec(Wire.read() & 0x7F);
byte min = bcdToDec(Wire.read());
byte hr = bcdToDec(Wire.read() & 0x3F);
byte dow = bcdToDec(Wire.read());
byte date = bcdToDec(Wire.read());
byte month = bcdToDec(Wire.read());
byte year = bcdToDec(Wire.read());
const char* days[] = {"", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
Serial.print("Time: ");
if (hr < 10) Serial.print('0'); Serial.print(hr); Serial.print(':');
if (min < 10) Serial.print('0'); Serial.print(min); Serial.print(':');
if (sec < 10) Serial.print('0'); Serial.print(sec);
Serial.print(" Date: ");
Serial.print(days[dow]); Serial.print(' ');
if (date < 10) Serial.print('0'); Serial.print(date); Serial.print('/');
if (month < 10) Serial.print('0'); Serial.print(month); Serial.print('/');
Serial.print("20"); if (year < 10) Serial.print('0'); Serial.println(year);
} else {
Serial.println("RTC not responding!");
}
delay(1000);
}
Как это работает
-
Настройка: Мы запускаем последовательную связь на скорости 115200 бод и инициализируем шину I2C с помощью
Wire.begin(). Часы DS1307 находятся по адресу 0x68. -
Цикл: Каждую секунду мы:
- Отправляем
beginTransmissionна адрес 0x68, записываем 0x00 (указатель регистра на регистр секунд) и завершаем передачуendTransmission. - Запрашиваем 7 байт от RTC с помощью
Wire.requestFrom(0x68, 7). - Читаем каждый байт и преобразуем из BCD (двоично-десятичного кода) в десятичный с помощью вспомогательной функции
bcdToDec. - Форматируем и выводим время и дату в последовательный монитор.
- Отправляем
-
Преобразование BCD: DS1307 хранит значения времени в формате BCD. Например, байт
0x45представляет 45 в BCD (4*10 + 5 = 45). ФункцияbcdToDecизвлекает цифру десятков (старший полубайт) и цифру единиц (младший полубайт) и объединяет их. -
Маскирование: Мы применяем маски к определённым регистрам:
- Секунды:
& 0x7Fочищает бит CH (остановка часов). - Часы:
& 0x3Fочищает бит режима 12/24 часа (предполагается 24-часовой режим).
- Секунды:
Ключевые концепции
- Протокол I2C: Двухпроводная последовательная шина (SDA, SCL) для связи между микроконтроллерами и периферийными устройствами. Каждое устройство имеет уникальный адрес.
- Библиотека Wire: Встроенная библиотека I2C для Arduino. Используйте
Wire.begin()для подключения к шине,Wire.beginTransmission(addr)для начала общения с устройством,Wire.write()для отправки данных,Wire.endTransmission()для завершения иWire.requestFrom(addr, count)для чтения байтов. - Формат BCD: Многие RTC используют BCD для упрощения отображения. Вам нужно преобразовывать в десятичный формат для удобочитаемого вывода.
- Карта регистров: DS1307 имеет определённую карту регистров: секунды (0x00), минуты (0x01), часы (0x02), день недели (0x03), дата (0x04), месяц (0x05), год (0x06).
Частые ошибки и советы по отладке
- Неправильный I2C-адрес: Перепроверьте адрес устройства. DS1307 обычно имеет адрес 0x68 (7-битный). Если вы получаете “RTC not responding!”, проверьте адрес.
- Отсутствие подтягивающих резисторов: В реальном оборудовании линии I2C требуют подтягивающих резисторов. В Velxio они симулируются внутренне, поэтому добавлять их не нужно.
- Несоответствие скорости передачи: Убедитесь, что скорость последовательного монитора соответствует 115200.
- Указатель регистра не установлен: Всегда устанавливайте указатель регистра перед чтением. Код записывает 0x00, чтобы указать на регистр секунд.
- Ошибки маскирования: Забывание маскировать бит CH (секунды) или бит режима 12/24 часа (часы) может дать неверные значения.
Предлагаемые расширения
- Установка времени: Добавьте код для записи текущего времени в RTC. Используйте
Wire.write()для установки каждого регистра. - Функция будильника: Реализуйте будильник, который включает светодиод при достижении определённого времени.
- Отображение на LCD: Используйте I2C LCD для отображения времени вместо последовательного монитора.
- Несколько RTC: Попробуйте читать данные с двух разных I2C-устройств на одной шине.
Попробуйте сами!
Готовы экспериментировать? Откройте живой пример в Velxio и запустите симуляцию. Вы увидите время, выводимое в последовательный монитор каждую секунду. Измените код, чтобы изменить интервал обновления или добавить новые функции.
Запустить пример Pico I2C RTC Read
Удачной симуляции!