Прерывания по таймеру и спящий режим
- Войдите на сайт для отправки комментариев
Ср, 25/11/2015 - 20:58
Всем привет. Делая проект столкнулся с трудностями.
Есть прерывания по таймеру1, настроенного на 1 сек. В нем происходит декремент оперделенного счетчика и часть некого кода. Нужно сделать так, чтобы по прерыванию от таймера контроллер влючался делал инкремент, выкполнял некий кусок кода, затем засыпал, и потом снова просыпался от прерывания по таймеру. Я пытался сделать, но все срабатывало 1 раз. Гуглил до дыр в клавитуре
Весь код:
#include <OneWire.h> #include <DallasTemperature.h> #include <avr/io.h> #include <avr/interrupt.h> #include <avr/sleep.h> #include <avr/power.h> #define ONE_WIRE_BUS 10 OneWire oneWire(ONE_WIRE_BUS); DallasTemperature sensors(&oneWire); int i = 2; int Tmax=50, Tmin=51; String cmd; struct Tsensor { public: uint8_t* Taddress; float T; void Measure(){ sensors.requestTemperatures(); T = sensors.getTempC(Taddress); Serial.print(" sensor temp: "); Serial.println(T); } Tsensor(uint8_t a[]): Taddress(a) {} }; struct Relay { public: bool stat; int pin; Relay(bool s, int p) { stat = s; pin = p; } }; struct Cam { public: String cmd; bool CamFlag; int pin; int wakeup_period; int Timer_WD; int Timer_Rep; void CamPowerON(){ if(CamFlag){ digitalWrite(pin,LOW); delay(10000); digitalWrite(pin,HIGH); Timer_WD=180; CamFlag=1; } } void CamPowerOFF(){ delay(10000); CamFlag=0; digitalWrite(pin,LOW); } void DecrementTimers(){ Timer_WD--; //Timer_Rep--; } void ReadCMD(){ if (Serial.available()) { cmd = Serial.readString(); if (cmd == "SET_WATCHDOG") {Serial.println(cmd);} else if (cmd == "POWEROFF") {Serial.println(cmd);} else if (cmd == "CHECKBATTERY") {Serial.println(cmd);} else if (cmd == "SET_TIMER") {Serial.println(cmd);} else if (cmd == "CHECK_TIMER") {Serial.println(cmd);} else if (cmd == "SET_WAKEUP_PERIOD") {Serial.println(cmd);} else if (cmd == "SINCHRONIZE_TIMER") {Serial.println(cmd);} else if (cmd == "SET_MIN_BATTERY") {Serial.println(cmd);} else if (cmd == "RESET_WATCHDOG") {Serial.println(cmd);} else if (cmd == "CHECK_WATCHDOG") {Serial.println(cmd);} else if (cmd == "SET_FIRST_WATCHDOG") {Serial.println(cmd);} else if (cmd == "POWERDOWN_BATTERY") {Serial.println(cmd);} else if (cmd == "CHECK_FIRST_WATCHDOG") {Serial.println(cmd);} else if (cmd == "CHECK_FLAG") {Serial.println(cmd);} else if (cmd == "CHECK_WAKEUP_PERIOD") {Serial.println(cmd);} else if (cmd == "SET_MIN_BAT_L") {Serial.println(cmd);} else if (cmd == "SET_MIN_BAT_H") {Serial.println(cmd);} else if (cmd == "SET_START_BAT_LEV") {Serial.println(cmd);} } } Cam(){ Timer_WD=180; pin=7; } }; uint8_t f[2][8] = {{0x28, 0xFF, 0x79, 0x54, 0x71, 0x15, 0x01, 0x09}, {0x28, 0xFF, 0xC2, 0x63, 0x74, 0x15, 0x03, 0x71}}; Tsensor ThermalSensor[2] = {f[0], f[1]}; Relay OptRelay[2] = {{false, 5}, {false, 6}}; Cam Camera; /*void Measure(){ for(i=0;i<2;i++){ sensors.requestTemperatures(); ThermalSensor[i].T = sensors.getTempC(ThermalSensor[i].Taddress); Serial.print(" sensor temp: "); Serial.println(ThermalSensor[i].T); } }*/ void HeatingCheck() { for (i = 0; i < 2; i++) { if (ThermalSensor[i].T < Tmin && OptRelay[i].stat == false) { digitalWrite(OptRelay[i].pin, LOW);//on OptRelay[i].stat == true; } if (ThermalSensor[i].T > Tmax && OptRelay[i].stat == true) { digitalWrite(OptRelay[i].pin, HIGH);//off OptRelay[i].stat == false; } } } void setup() { cli(); TCCR1A = 0; TCCR1B = 0; TIMSK1 |= (1 << TOIE1); TCNT1=0x0BDC; TCCR1B |= (1 << CS12); sei(); Serial.begin(9600); sensors.begin(); for (i = 0; i < 2; i++) { sensors.setResolution(ThermalSensor[i].Taddress, 9); pinMode(OptRelay[i].pin, OUTPUT); digitalWrite(OptRelay[i].pin, HIGH); //change } } ISR(TIMER1_OVF_vect){ for(i=0;i<2;i++){ ThermalSensor[i].Measure(); } //HeatingCheck(); Camera.DecrementTimers(); //Camera.ReadCMD(); Serial.print("WD "); Serial.println(Camera.Timer_WD); } void loop() { }
Что интересует меня:
ISR(TIMER1_OVF_vect){ Декремент; Кусок некого кода }
Пробовал использовать MsTimer2 и пихать туда set_sleep_mode - в итоге и луп крутится и прерывание работает
во первых чтобы МК засыпал в loop() надо вставить команды на засыпание в режим IDLE
во вторых такие тяжелые функции как Serial.print нельзя ставить внутри обработчиков прерываний иначе у вас начнутся пропуски событий и поломкой всей логики
в третьих вы использовали обычный режим таймера, кто за вас будет грузить нужное значение в счетчик TCNT1? В таком МК как мега328 для вашей задачи есть специальный режим CTC, нужное значение счетчика грузится в OCR1 один раз, обработчик делается не на OVF, а на COMPA
axill, списибо за ответ. Я читал про режим СТС на забугорном форуме, попробую применить. Хм, а можно использовать библиотеку MsTimer2 для упрощения, или все таки регистрами оперировать? Как я понял в луп надо засунуть это: