В данной статье мы рассмотрим создание цифровых часов на основе платы MSP430G2 и модуля часов реального времени (RTC module) DS3231. Отображать время и дату в нашем проекте мы будем на экране ЖК дисплея 16x2. MSP-EXP430G2 представляет собой плату разработки, также известную как LaunchPad, от компании Texas Instruments. Данная плата позволяет производить программирование всей линейки микроконтроллеров MSP430. Если вы только начали знакомство с данной платой, то рекомендуем прочитать статью про начало работы с ней.
Ранее на нашем сайте мы уже рассматривали аналогичные проекты цифровых часов на основе других микроконтроллеров (плат):
- часы реального времени на ESP32 и модуле DS3231;
- на микроконтроллере PIC и RTC модуле DS3231;
- часы реального времени с будильником на основе Arduino;
- бинарные часы на светодиодах с использованием Arduino;
- часы на Arduino и 4-х разрядном семисегментном индикаторе;
- умные часы (Smart Watch) на основе Arduino, OLED дисплея и смартфона.
Необходимые компоненты
- Плата MSP430G2 LaunchPad (купить на AliExpress).
- Модуль часов реального времени DS3231 (купить на AliExpress).
- Потенциометр 10 кОм (купить на AliExpress).
- ЖК дисплей 16х2 (купить на AliExpress).
- Соединительные провода.
- Макетная плата.
Что такое RTC модуль DS3231
DS3231 – это модуль часов реального времени (Real Time Clock, RTC). Он используется для хранения информации о времени и дате во множестве электронных устройств во всем мире. В своем составе он имеет собственную батарейку, поэтому он сохраняет информацию о времени и дате даже когда питание основного устройства (в которое он входит) отключается или когда производится сброс устройства (микроконтроллера). То есть если мы один раз установим дату и время в модуле он будет хранить их постоянно, до тех пор пока не истощится его батарейка. В настоящее время существует несколько различных микросхем реального времени: DS1307, DS3231 и т.д.
Внешний вид модуля DS3231 показан на следующем рисунке.
Схема проекта
Схема подключения модуля часов реального времени DS3231 к плате MSP430G2 представлена на следующем рисунке.
Поскольку модуль DS3231 работает по протоколу I2C, поэтому его контакты Serial Clock (SCL) и Serial Data (SDA) необходимо подключить к соответствующим I2C контактам плате MSP430G2 – контакт 9 (PIN 2.1, SCL) и контакт 10 (PIN 2.2, SDA).
MSP430 работает от 3.3V, но нам будут необходимы 5V для питания ЖК дисплея и модуля DS3231. Для этого можно использовать небольшой лайфхак, описанный в данной статье – 5V можно получить с джампера TP1, расположенного рядом с USB разъемом платы.
Объяснение кода программы
Полный код программы приведен в конце статьи, здесь же мы кратко рассмотрим его основные фрагменты. Для написания программы мы будем использовать среду Energia IDE являющуюся фактически аналогом Arduino IDE.
Для работы с модулем часов реального времени DS3231 нам потребуется специальная библиотека, которую можно скачать по следующей ссылке. Также нам будут необходимы библиотека Wire (для связи по протоколу I2C) и библиотека для работы с ЖК дисплеем – обе эти библиотеки уже предустановлены в Energia IDE, дополнительно устанавливать их не нужно.
Первым делом в программе подключим библиотеку для I2C связи между модулем DS3231 и MSP430. Контакты SDA и SCK уже прописаны в этой библиотеке, поэтому отдельно нам их объявлять уже не нужно.
1 |
#include <Wire.h> |
Далее подключим библиотеку RTClib.h для работы с модулем RTC и библиотеку LiquidCrystal.h для работы с ЖК дисплеем.
1 2 |
#include "RTClib.h" #include <LiquidCrystal.h> |
Затем создадим объект для работы с модулем часов реального времени.
1 |
RTC_DS3231 rtc; |
После этого объявим массив из 7 элементов для хранения в нем дней недели.
1 |
char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; |
Для подключения ЖК дисплея мы будем использовать контакты платы RS (P2.0), EN (P1.4), D4 (P1.5), D5 (P2.3), D6 (P2.4), D7 (P2.5).
1 |
LiquidCrystal lcd(8 ,6, 7,11,12,13); |
В функции void setup() мы инициализируем ЖК дисплей и укажем размеры его экрана и модуль часов реального времени. Метод begin() для ЖК дисплея должен быть вызван до того, как подавать на него команды для отображения информации на его экране.
1 2 3 4 5 6 7 8 9 |
void setup () { lcd.begin(16, 2); lcd.setCursor(3,0); lcd.print("RTC Clock"); delay(3000); lcd.clear(); rtc.begin(); // rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); } |
Примечание: в приведенном фрагменте кода закомментированная строчка крайне важна – с помощью нее можно установить актуальные дату и время в вашем модуле часов реального времени если они у вас не установлены. После того как при первом запуске программы вы их установите эту строчку кода необходимо будет закомментировать иначе при каждом сбросе платы или подаче на нее питания у вас снова будет устанавливаться это же время.
В функции loop мы будем считывать время и дату из модуля RTC и сохранять их в соответствующей переменной, после чего отображать их на экране ЖК дисплея с помощью функции lcd.print().
1 2 3 4 5 6 7 |
void loop () { DateTime now = rtc.now(); lcd.clear(); lcd.setCursor(3,0); lcd.print(now.day(), DEC); lcd.print("/");…. ……. |
Исходный код программы
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
#include <Wire.h> #include "RTClib.h" #include <LiquidCrystal.h> RTC_DS3231 rtc; char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; LiquidCrystal lcd(8 ,6, 7,11,12,13); void setup () { lcd.begin(16, 2); lcd.setCursor(3,0); lcd.print("RTC Clock"); delay(3000); lcd.clear(); rtc.begin(); // rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); } void loop () { DateTime now = rtc.now(); lcd.clear(); lcd.setCursor(3,0); Serial.print(now.year(), DEC); Serial.print('/'); lcd.print(now.day(), DEC); lcd.print("/"); lcd.print(now.month(), DEC); lcd.print("/"); lcd.print(now.year(), DEC); lcd.setCursor(1,5); lcd.print(daysOfTheWeek[now.dayOfTheWeek()]); lcd.print(","); lcd.print(now.hour(), DEC); lcd.print(":"); lcd.print(now.minute(), DEC); lcd.print(":"); lcd.print(now.second(), DEC); delay(1000); } |