Как использовать RTC с Arduino и LCD
Как сделать точные часы, используя часы реального времени IC DS1307. Время будет отображаться на ЖК-дисплее.
Требования
- Компьютер под управлением Arduino 1.6.5
- Arduino
- Перемычки
- макетировать
- Детали из списка запасных частей
Вы можете заменить Arduino другой IC из ATMEL, но убедитесь, что у нее есть достаточное количество входных и выходных контактов вместе с возможностями I 2 C. Я использую ATMega168A-PU. Если вы это сделаете, вам понадобится программист. У меня есть программатор AVR MKII ISP.
Рекомендуется, чтобы читатель был знаком с макетированием, программированием в среде Arduino и имел некоторые знания языка программирования C. Следующие две программы не нуждаются в дополнительном объяснении.
Введение
Как микроконтроллеры отслеживают время и дату »// www.google.no/search?client=ubuntu&channel=fs&q=ds1307+dpf&ie=utf-8&oe=utf-8&gfe_rd=cr&ei=zgHsVYWUDKur8weEsb3QDQ#safe=off&channel=fs&q=ds1307+ pdf "target =" _ blank "> DS1307. На этой ИС PIN 7 является выводом SQW / OUT. Вы можете использовать этот вывод для мигания светодиода или для синхронизации микроконтроллера. Мы сделаем обоим. Следующее изображение из таблицы помогает нам понять SQW / OUT.

Эта таблица помогает вам с частотой:
Freq | BIT7 & BIT6 & BIT5 | BIT4 | BIT3 & BIT2 | BIT1 | BIT0 |
---|---|---|---|---|---|
1Гц | 0 | 1 | 0 | 0 | 0 |
4.096Hz | 0 | 1 | 0 | 0 | 1 |
8.192Hz | 0 | 1 | 0 | 1 | 0 |
32.768Hz | 0 | 1 | 0 | 1 | 1 |
Если вы подключите светодиод и резистор к PIN-коду 7 и хотите, чтобы он вспыхнул с частотой 1 Гц, вы записываете 0b00010000 в адрес памяти регистра управления. Если вы хотите 4.096 Гц, вы должны написать 0b000100001. Теперь вам понадобится осциллограф, чтобы увидеть импульсы, так как светодиод мигает так быстро, что он выглядит так, как будто он постоянно включен. Мы используем 1 Гц.
аппаратные средства
Вот блок-диаграмма для того, что мы хотим.

Мы хотим:
- ISP (в системном программировании) для программирования микроконтроллера
- Кнопки для установки времени и даты
- Микроконтроллер для связи с RTC через I 2 C
- Отображение времени и даты на ЖК-дисплее
Принципиальная схема:

Нажмите на изображение, чтобы открыть его в полном размере.
Список запчастей
Это скриншот от Eagle:

Программного обеспечения
Мы будем использовать два разных эскиза в этом практическом руководстве: одно, которое записывает время и дату в RTC, и тот, который считывает время и дату из RTC. Я сделал это так, чтобы у вас был лучший обзор того, что происходит. Мы будем использовать ту же схему, что и выше для обеих программ.
Сначала мы напишем время и дату в RTC, что походит на настройку времени на часах.
Мы используем два переключателя. Один из них - увеличить час, минуту, дату, месяц, год и день недели, а другой - выбирать между ними. Приложение не считывает значения от каких-либо критических датчиков, поэтому мы используем прерывания, чтобы проверить, нажат ли переключатель и обрабатывать отскок переключателя. Для получения дополнительной информации об отказе коммутатора прочтите это.
Следующий код устанавливает значения и записывает их в RTC:
// Include header files #include <Wire.h> #include <LiquidCrystal.h> // LCD pin definitions #define RS 9 #define E 10 #define D4 8 #define D5 7 #define D6 6 #define D7 5 LiquidCrystal lcd(RS, E, D4, D5, D6, D7); // Interrupt 0 is hardware pin 4 (digital pin 2) int btnSet = 0; // Interrupt 1 is hardware pin 5 (digital pin 3) int btnSel = 1; // Interrupt state int togBtnSet = false; int togBtnSel = false; // Time and date variables int tmpHour = 0; int tmpMinute = 0; int tmpDate = 0; int tmpMonth = 0; int tmpYear = 0; int tmpDay = 0; int tmpSecond = 0; int counterVal = 0; // Variable to keep track of where we are in the "menu" int myMenu(6); // 0=Hour, 1=Minutes, 2=date, 3=MOnth, 4=Year, 5=DOW int menuCounter = 0; // A array of the weekday char* days() = { "NA", "Mon", "Tue", "Wed", "Thu", "Fre", "Sat", "Sun" }; void setup() { // Interrupt declaration, execute increaseValue/nextItem function // when btnXXX is RISING attachInterrupt(btnSet, increaseValue, RISING); attachInterrupt(btnSel, nextItem, RISING); Wire.begin(); lcd.begin(16, 2); showWelcome(); } // Interrupt function void increaseValue() { // Variables static unsigned long lastInterruptTime = 0; // Making a timestamp unsigned long interruptTime = millis(); // If timestamp - lastInterruptTime is greater than 200 if (interruptTime - lastInterruptTime > 200) { // Toggle the variable togBtnSet = !togBtnSet; // Increase the counterVal by 1 counterVal+; } // Setting lastInterruptTime equal to the timestamp // so we know we moved on lastInterruptTime = interruptTime; } // Next menuItem Interrupt function void nextItem() { static unsigned long lastInterruptTime = 0; unsigned long interruptTime = millis(); if (interruptTime - lastInterruptTime > 200) { togBtnSel = !togBtnSel; // Increase the menu counter so we move to next item menuCounter+; // Placing the counterVal in the menucounters array position myMenu(menuCounter) = counterVal; // Reset counterVal, now we start at 0 on the next menuItem counterVal = 0; } lastInterruptTime = interruptTime; } // Function that convert decimal numbers to binary byte decToBCD(byte val) { return ((val/10*16) + (val)); } // Short welcome message, now we know everything is OK void showWelcome() { lcd.setCursor(2, 0); lcd.print("Hello world."); lcd.setCursor(3, 1); lcd.print("I'm alive."); delay(500); lcd.clear(); } // Funcion to set the hour void setHour() { lcd.setCursor(0, 0); lcd.print("Set hour. "); // Checks if interrupt has occured = button pressed if (togBtnSet) { // Update array value with counterVal myMenu(menuCounter) = counterVal; lcd.setCursor(7, 1); // Print the new value lcd.print(myMenu(menuCounter)); lcd.print(" "); } else { // Update array value with counterVal myMenu(menuCounter) = counterVal; lcd.setCursor(7, 1); // Print the new value lcd.print(myMenu(menuCounter)); lcd.print(" "); } } // Function to set minutes void setMinute() { lcd.setCursor(0, 0); lcd.print("Set minute. "); if (togBtnSet) { myMenu(menuCounter) = counterVal; lcd.setCursor(7, 1); lcd.print(myMenu(menuCounter)); lcd.print(" "); } else { myMenu(menuCounter) = counterVal; lcd.setCursor(7, 1); lcd.print(myMenu(menuCounter)); lcd.print(" "); } } // Function to set date void setDate() { lcd.setCursor(0, 0); lcd.print("Set date. "); if (togBtnSet) { myMenu(menuCounter) = counterVal; lcd.setCursor(7, 1); lcd.print(myMenu(menuCounter)); lcd.print(" "); } else { myMenu(menuCounter) = counterVal; lcd.setCursor(7, 1); lcd.print(myMenu(menuCounter)); lcd.print(" "); } } // Function to set month void setMonth() { lcd.setCursor(0, 0); lcd.print("Set month. "); if (togBtnSet) { myMenu(menuCounter) = counterVal; lcd.setCursor(7, 1); lcd.print(myMenu(menuCounter)); lcd.print(" "); } else { myMenu(menuCounter) = counterVal; lcd.setCursor(7, 1); lcd.print(myMenu(menuCounter)); lcd.print(" "); } } // Function to set year void setYear() { lcd.setCursor(0, 0); lcd.print("Set year. "); if (togBtnSet) { myMenu(menuCounter) = counterVal; lcd.setCursor(7, 1); lcd.print(myMenu(menuCounter)); lcd.print(" "); } else { myMenu(menuCounter) = counterVal; lcd.setCursor(7, 1); lcd.print(myMenu(menuCounter)); lcd.print(" "); } } // Function to set the day of week void setDOW() { lcd.setCursor(0, 0); lcd.print("Set day (1=mon)."); if (togBtnSet) { myMenu(menuCounter) = counterVal; lcd.setCursor(7, 1); lcd.print(myMenu(menuCounter)); lcd.print(" "); } else { myMenu(menuCounter) = counterVal; lcd.setCursor(7, 1); lcd.print(myMenu(menuCounter)); lcd.print(" "); } } // Write the data to the RTC void writeRTC() { Wire.beginTransmission(0x68); Wire.write(0); // Start address Wire.write(0x00); // seconds Wire.write(decToBCD(myMenu(1))); // convert tmpMinutes to BCD and write them Wire.write(decToBCD(myMenu(0))); // convert tmpHour to BCD and write them Wire.write(decToBCD(myMenu(5))); // convert tmpDay to BCD and write them Wire.write(decToBCD(myMenu(2))); // convert tmpDate to BCD and write them Wire.write(decToBCD(myMenu(3))); // convert tmpMonth to BCD and write them Wire.write(decToBCD(myMenu(4))); // convert tmpYear to BCD and write them Wire.write(0b00010000); // enable 1Hz Square wave on PIN7 Wire.endTransmission(); // close the transmission } // Show the time // You need to use the other program to see the RTC is working void showTime() { lcd.setCursor(0, 0); lcd.print(" "); lcd.print(myMenu(0)); lcd.print(":"); // hour lcd.print(myMenu(1)); lcd.print(":"); lcd.print("00 "); // minute lcd.setCursor(3, 1); lcd.print(days(myMenu(5))); lcd.print(" "); // DOW lcd.print(myMenu(2)); lcd.print("."); // date lcd.print(myMenu(3)); lcd.print("."); // month lcd.print(myMenu(4)); lcd.print(" "); // year // Call the writeRTC function writeRTC(); } void loop() { if (menuCounter == 0) { setHour(); } if (menuCounter == 1) { setMinute(); } if (menuCounter == 2) { setDate(); } if (menuCounter == 3) { setMonth(); } if (menuCounter == 4) { setYear(); } if (menuCounter == 5) { setDOW(); } if (menuCounter == 6) { showTime(); } }
Скачать код
Программа начинается с короткого приветственного сообщения. В этом сообщении говорится, что питание подано, ЖК-дисплей работает и что программа начала работать.
Чтобы читать из RTC и показывать время и дату, вам необходимо запрограммировать свой микроконтроллер на следующую программу. Программа считывает значения времени и даты из RTC и отображает их на ЖК-дисплее.
// Include header files #include <Wire.h> #include <LiquidCrystal.h> // LCD pin definitions #define RS 9 #define E 10 #define D4 8 #define D5 7 #define D6 6 #define D7 5 LiquidCrystal lcd(RS, E, D4, D5, D6, D7); // Pin that will receive clock pulse from RTC int clockPin = 0; // Time and date vaiables byte second; byte minute; byte hour; byte day; byte date; byte month; byte year; // A array of the weekday char* days() = { "NA", "Mon", "Tue", "Wed", "Thu", "Fre", "Sat", "Sun" }; // Function run once void setup() { pinMode(clockPin, INPUT); pinMode(clockPin, LOW); Wire.begin(); lcd.begin(16, 2); showWelcome(); } // Nice welcome message, then we know LCD is OK void showWelcome() { lcd.setCursor(2, 0); lcd.print("Hello world."); lcd.setCursor(3, 1); lcd.print("I'm alive."); delay(500); lcd.clear(); } // Doing this forever void loop() { // While clockPin is high while (digitalRead(clockPin)) { // start the I2C transmission, at address 0x68 Wire.beginTransmission(0x68); // Start at address 0 Wire.write(0); // Close transmission Wire.endTransmission(); // Start to read the 7 binary data from 0x68 Wire.requestFrom(0x68, 7); second = Wire.read(); minute = Wire.read(); hour = Wire.read(); day = Wire.read(); date = Wire.read(); month = Wire.read(); year = Wire.read(); // Formatting and displaying time lcd.setCursor(4, 0); if (hour < 10) lcd.print("0"); lcd.print(hour, HEX); lcd.print(":"); if (minute < 10) lcd.print("0"); lcd.print(minute, HEX); lcd.print(":"); if (second < 10) lcd.print("0"); lcd.print(second, HEX); lcd.setCursor(2, 1); // Formatting and displaying date lcd.print(days(day)); lcd.print(" "); if (date < 10) lcd.print("0"); lcd.print(date, HEX); lcd.print("."); if (month < 10) lcd.print("0"); lcd.print(month, HEX); lcd.print("."); lcd.print(year, HEX); } // end while }
Скачать код
Вывод
В этой статье мы рассмотрели небольшую DS1307 RTC IC от Maxim Integrated. Мы сделали одну программу, которая устанавливает время и дату, и мы сделали еще одну программу для чтения времени и даты. Чтобы проверить, был ли нажат переключатель, мы использовали прерывания. Прерывания также позаботились о переходе переключателя.
Фото и видео

Нажмите на изображение, чтобы открыть его в полном размере.

Нажмите на изображение, чтобы открыть его в полном размере.
Установка времени
Чтение времени
Попробуйте этот проект сами! Получить спецификацию.