RTC DS1307 прерывание через SQW и считывание времени
- Войдите на сайт для отправки комментариев
Ср, 23/05/2018 - 17:50
Здравствуйте, бьюсь уже N-ные сутки. Собрал в Proteus небольшую схему: Arduino Uno + часы DS1307
Задача проста до безобразия. Вывод SQW часов настроен на 1Hz и генерирует прерывание int0 на Arduino. Соответственно, при прерывании считываю с часов время. Почему просто не читаю в loop? потому что в loop будут другие задачи, с delay(), и имеет место считывать время через прерывание. С часами работаю с помощью библиотеки RTCLib. Собственно, проблема в том, что работа зависает при считывании времени с часов с помощью функции rtc.now()... Прерывание работает исправно. Код пока сыроватый, надо рефакторить, все, что не связно с часами закомментил.

#include <Key.h> #include <Keypad.h> #include <RTClib.h> #include <Wire.h> #include <LiquidCrystal_I2C.h> #define LIGHT_MODE_ON 1 #define LIGHT_MODE_OFF 0 RTC_DS1307 rtc; LiquidCrystal_I2C lcd(0x27,20,4); // set the LCD address to 0x27 for a 16 chars and 2 line display DateTime dateTime; volatile unsigned int timerSec = 0; const byte ROWS = 4; const byte COLS = 3; bool isRealTime = true; bool isMenu = false; int indexMenu = 1; char Keys[ROWS][COLS] = { {'3','2','1'}, {'6','5','4'}, {'9','8','7'}, {'#','0','*'} }; byte rowPins[ROWS] = { 11, 10, 9, 8 }; byte colPins[COLS] = { 16, 15, 14 }; Keypad keypad = Keypad(makeKeymap(Keys), rowPins, colPins, ROWS, COLS); int led_red = 7; int led_yellow = 6; int led_green = 5; int led_green_right = 4; /*ISR (TIMER0_COMPA_vect) { timerSec++; if(timerSec == 5000) { timerSec = 0; // то, что нам надо делать каждую секунду //Serial.println('2'); //showLCDbyTimer(); } }*/ void setup() { Serial.begin(9600); //init interrupt int0 //init LEDS pinMode(led_red, OUTPUT); pinMode(led_yellow, OUTPUT); pinMode(led_green, OUTPUT); pinMode(led_green_right, OUTPUT); //init LCD lcd.init(); lcd.init(); // Print a message to the LCD. lcd.backlight(); lcd.setCursor(3,0); lcd.print("Hello, Serg!"); lcd.setCursor(2,1); lcd.print("Arduino Svetofor!"); lcd.setCursor(0,2); lcd.print("Powered by Serg"); //init Real Time Clock rtc.begin(); if (! rtc.isrunning()) { Serial.println("RTC is NOT running!"); // following line sets the RTC to the date & time this sketch was compiled rtc.adjust(DateTime(__DATE__, __TIME__)); } rtc.writeSqwPinMode(SquareWave1HZ); delay(1000); lcd.clear(); //init interrupt RTC pinMode(2, INPUT_PULLUP); attachInterrupt(0, showLCDbyTimer, FALLING); Serial.println("start"); //init timer /* TCCR0A |= (1 << WGM01); OCR0A = 0xF9; TIMSK0 |= (1 << OCIE0A); TCCR0B |= (1 << CS01) | (1 << CS00); sei(); dateTime = rtc.now();*/ } void doSvetofor(int lightMode) { if(lightMode == LIGHT_MODE_ON) { digitalWrite(led_yellow, LOW); digitalWrite(led_green, LOW); digitalWrite(led_green_right, LOW); digitalWrite(led_red, HIGH); delay(1000); digitalWrite(led_yellow, HIGH); delay(1000); digitalWrite(led_red, LOW); delay(1500); digitalWrite(led_yellow, LOW); digitalWrite(led_green, HIGH); delay(9000); digitalWrite(led_green, LOW); delay(500); digitalWrite(led_green, HIGH); delay(500); digitalWrite(led_green, LOW); delay(500); digitalWrite(led_green, HIGH); digitalWrite(led_yellow, HIGH); delay(500); digitalWrite(led_green, LOW); delay(500); digitalWrite(led_green, HIGH); delay(500); digitalWrite(led_green, LOW); digitalWrite(led_yellow, LOW); digitalWrite(led_red, HIGH); delay(1000); digitalWrite(led_green_right, HIGH); delay(10000); digitalWrite(led_green_right, LOW); delay(500); digitalWrite(led_green_right, HIGH); delay(500); digitalWrite(led_green_right, LOW); delay(500); digitalWrite(led_green_right, HIGH); delay(500); digitalWrite(led_green_right, LOW); } else { digitalWrite(led_red, HIGH); digitalWrite(led_yellow, HIGH); digitalWrite(led_green, HIGH); digitalWrite(led_green_right, HIGH); } } void incIndexMenu() { if(indexMenu == 3) { indexMenu = 1; } else { indexMenu++; } } void showDateTime() { Serial.println("rtc.now"); DateTime now = rtc.now(); Serial.println(now.second()); /* if(now.hour()>11) { lcd.setCursor(14, 1); lcd.print("PM"); } else { lcd.setCursor(14, 1); lcd.print("AM"); } lcd.setCursor(0, 0); lcd.print("Date-"); lcd.print(now.day(), DEC); lcd.print('/'); lcd.print(now.month(), DEC); lcd.print('/'); lcd.print(now.year(), DEC); lcd.print(' '); lcd.setCursor(0, 1); if (now.hour()<10) lcd.print('0'); lcd.print("Time-"); if(now.hour()>12) { lcd.print(now.hour()-12, DEC); } else { lcd.print(now.hour(), DEC); } lcd.print(':'); if (now.minute()<10) lcd.print('0'); lcd.print(now.minute(), DEC); lcd.print(':'); if (now.second()<10) lcd.print('0'); lcd.print(now.second(), DEC); lcd.setCursor(0, 3); int dayofweek = now.dayOfTheWeek(); switch(dayofweek){ case 1: lcd.print("Monday"); break; case 2: lcd.print("Tuesday"); break; case 3: lcd.print("Wednesday"); break; case 4: lcd.print("Thursday"); break; case 5: lcd.print("Friday"); break; case 6: lcd.print("Saturday"); break; case 0: lcd.print("Sunday"); break; delay(1000); }*/ } void showMenu() { doSvetofor(LIGHT_MODE_OFF); //светофор в режим конфигурирования switch(indexMenu) { case 1: lcd.setCursor(0,0); lcd.print("-->"); lcd.print(" 06:00 - 12:00"); lcd.setCursor(0,1); lcd.print(" 12:00 - 18:00"); lcd.setCursor(0,2); lcd.print(" 18:00 - 00:00"); break; case 2: lcd.setCursor(0,0); lcd.print(" 06:00 - 12:00"); lcd.setCursor(0,1); lcd.print("--> 12:00 - 18:00"); lcd.setCursor(0,2); lcd.print(" 18:00 - 00:00"); break; case 3: lcd.setCursor(0,0); lcd.print(" 06:00 - 12:00"); lcd.setCursor(0,1); lcd.print(" 12:00 - 18:00"); lcd.setCursor(0,2); lcd.print("--> 18:00 - 00:00"); break; default: break; } } void showLCDbyTimer() { // char key = keypad.getKey(); /* if(key) { /*Serial.println(key); if(isMenu) { switch(key) { case '#': showDateTime(); isMenu = false; isRealTime = true; lcd.clear(); break; case '0': incIndexMenu(); showMenu(); break; default: Serial.print("keeek - ne prokatilo"); break; } } else if(isRealTime) { Serial.println("knock - isRunTime"); switch(key) { case '*' : // листаем меню isMenu = true; isRealTime = false; lcd.clear(); showMenu(); break; default: //выводим также рантайм Serial.println("keeek - ne prokatilo"); showDateTime(); break; } } */ /* } else { Serial.println("else"); if(isMenu) { Serial.println("Show menu"); // showMenu(); } else if(isRealTime) { // showDateTime(); } else { Serial.println("kwa"); } }*/ showDateTime(); } void loop() { //dateTime = rtc.now(); //doSvetofor(LIGHT_MODE_ON); }
при входе в прерывание, прерывания автоматически запрещаются. Serial унутре прерывания использовать нельзя.
Попробуйте поставить команду sei(); между строками №№ 155 и 156.
Попробуйте поставить команду sei(); между строками №№ 155 и 156.
Спасибо большое! Добавив sei(), все заработало! Но как это объяснить? Библиотека для работы с часами испульзует прерывания?
Serial использует
ТС, хоть ты и закомментил остальной код, но он просто бросается в глаза. С таким количество делеев в функции "Светофор" у тебя никакое меню работать не будет в принципе. Осваивай миллис и конечные автоматы, иначе очень быстро уткнешься в бесконечные тормоза в программе.
Serial унутре прерывания использовать нельзя.
С "нельзя" я согласен, но не так категорично. Нельзя не потому, что работать не будет, а чисто концептуально, потому, что это плохая идея. Технически же, всё работает без проблем. Попробуйте вот такой скетч:
Вполне себе считает секунды и в сериал выводит.
С "нельзя" я согласен, но не так категорично. Нельзя не потому, что работать не будет, а чисто концептуально, потому, что это плохая идея.
Дак и я с Вами согласен. Просто, на той ступеньке обучения, куда только-только вползает ТС, Serial в прерывании использовать нельзя. Пока нельзя. :)
А вообще, мне иногда просто писать лень. Я уже зарекся писать здесь какие-либо длиннотексты. :)