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 унутре прерывания использовать нельзя.
С "нельзя" я согласен, но не так категорично. Нельзя не потому, что работать не будет, а чисто концептуально, потому, что это плохая идея. Технически же, всё работает без проблем. Попробуйте вот такой скетч:
void setup() { Serial.begin(57600); // // Таймер 1 дергается раз в секунду // TCCR1A = 0; // CTC, пины отключены TCCR1B = bit(WGM12) | bit(CS12) | bit(CS10); // CTC + делитель 1024 OCR1A = 15625; // 15625*1024/16 = 1000000 микросекунд TIMSK1 = bit(OCIE1A); // } void loop() {} ISR(TIMER1_COMPA_vect) { static int counter = 0; Serial.println(++counter); }Вполне себе считает секунды и в сериал выводит.
С "нельзя" я согласен, но не так категорично. Нельзя не потому, что работать не будет, а чисто концептуально, потому, что это плохая идея.
Дак и я с Вами согласен. Просто, на той ступеньке обучения, куда только-только вползает ТС, Serial в прерывании использовать нельзя. Пока нельзя. :)
А вообще, мне иногда просто писать лень. Я уже зарекся писать здесь какие-либо длиннотексты. :)