Введение
Хотели когда-нибудь добавить часы реального времени в свой проект на Arduino, но не имели под рукой оборудования? С Velxio вы можете симулировать I2C RTC (DS1307) прямо в браузере. В этом руководстве мы создадим простой I2C-ридер, который получает текущее время и дату с виртуального DS1307 и выводит их в монитор последовательного порта. Никаких внешних библиотек не требуется — только встроенная библиотека Wire.

Обзор схемы
Этот пример удивительно прост, так как DS1307 уже встроен в виртуальную плату Arduino Uno. Никаких внешних компонентов или проводов добавлять не нужно. Шина I2C (SDA на A4, SCL на A5) внутренне подключена к DS1307 по адресу 0x68. Единственный компонент — сама плата Arduino Uno.

Для начала откройте редактор Velxio и выберите Arduino Uno из палитры компонентов. DS1307 встроен в среду симуляции, поэтому добавлять его отдельно не нужно. Схема готова к работе.
Обзор кода
Давайте разберем код шаг за шагом.
Подключение и определение
#include <Wire.h>
#define DS1307_ADDR 0x68
Мы подключаем библиотеку Wire для I2C-связи и определяем I2C-адрес DS1307 как 0x68.
Преобразование BCD в десятичное число
byte bcdToDec(byte val) {
return ((val >> 4) * 10) + (val & 0x0F);
}
DS1307 хранит значения времени в двоично-десятичном формате (BCD). Эта вспомогательная функция преобразует байт BCD в обычное десятичное число.
Настройка
void setup() {
Wire.begin();
Serial.begin(9600);
Serial.println("===========================");
Serial.println(" DS1307 RTC Reader (I2C)");
Serial.println("===========================");
Serial.println();
}
Мы инициализируем шину I2C и последовательный порт со скоростью 9600 бод. Затем выводим заголовок.
Основной цикл
void loop() {
// Устанавливаем указатель регистра на 0 (секунды)
Wire.beginTransmission(DS1307_ADDR);
Wire.write(0x00);
Wire.endTransmission();
// Запрашиваем 7 байт: сек, мин, час, день_нед, число, месяц, год
Wire.requestFrom(DS1307_ADDR, 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());
// Выводим отформатированное время
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: ");
if (date < 10) Serial.print("0");
Serial.print(date);
Serial.print("/");
if (month < 10) Serial.print("0");
Serial.print(month);
Serial.print("/20");
if (year < 10) Serial.print("0");
Serial.println(year);
} else {
Serial.println("Error: Could not read RTC");
}
delay(1000);
}
В цикле мы сначала устанавливаем указатель регистра DS1307 на 0 (регистр секунд), отправляя один байт 0x00. Затем запрашиваем 7 байт от RTC. DS1307 возвращает секунды, минуты, часы, день недели, число, месяц и год в формате BCD. Мы маскируем старший бит секунд (бит 7 — флаг остановки часов) и два старших бита часов (биты 6-7 — режим/AM-PM). После преобразования выводим время и дату с ведущими нулями. Если доступно менее 7 байт, выводим ошибку. В конце ждем 1 секунду.
Ключевые концепции
- I2C-связь: Библиотека Wire управляет протоколом I2C.
beginTransmission()начинает запись,write()ставит данные в очередь,endTransmission()отправляет их.requestFrom()читает байты от ведомого устройства. - Формат BCD: DS1307 хранит время в BCD, где каждый полубайт представляет десятичную цифру. Функция
bcdToDec()преобразует его. - Адресация регистров: Доступ к внутренним регистрам DS1307 осуществляется путем сначала записи адреса регистра, а затем чтения или записи данных.
- Маскирование битов: Старший бит регистра секунд (CH) указывает на остановку часов; мы маскируем его с помощью
& 0x7F. Старшие биты регистра часов указывают на 12/24-часовой режим; мы маскируем их с помощью& 0x3F.
Частые ошибки и советы по отладке
- Неправильный I2C-адрес: Убедитесь, что адрес равен 0x68 (7-битный). Если вы используете 8-битный адрес, сдвиньте его влево на 1.
- Отсутствие подтягивающих резисторов: В реальном оборудовании линии I2C требуют подтягивающих резисторов. В Velxio они симулируются внутренне.
- Монитор последовательного порта не отображается: Убедитесь, что скорость передачи совпадает (9600). Нажмите на иконку монитора последовательного порта на панели инструментов редактора.

- Ошибки компиляции: Проверьте, что вы подключили
Wire.h. Код не использует внешних библиотек. - RTC не отвечает: Если вы видите “Error: Could not read RTC”, возможно, I2C-связь не удалась. Проверьте адрес и подключение.
Предлагаемые расширения
- Установка времени: Добавьте код для установки времени DS1307 через последовательный ввод.
- Вывод на LCD: Используйте I2C-дисплей для отображения времени.
- Функция будильника: Реализуйте будильник, используя регистры будильника DS1307.
- Логирование данных: Записывайте временные метки в EEPROM или на SD-карту.
Попробуйте сами
Готовы увидеть это в действии? Откройте живой пример на Velxio и нажмите кнопку Run. Вы увидите, как время обновляется каждую секунду в мониторе последовательного порта.
Запустить I2C RTC Reader на Velxio

Удачной симуляции!