не думал, что дойду до такого, но что-то туплю уже который день, и не могу раступлиться.
проекте часиков такой код:
Код:
int main(void){
show_mode_t show_mode = SHOW_SIMPLE;
mode_t tm, mode = MODE_TIME;
uint8_t sec = 255;
mode_clock_init(mode);
indication(false); // индикация отключается
refresh = true;
sei();
set_sleep_mode(SLEEP_MODE_PWR_SAVE);////
while(1){
while(main_power_miss()){
// пока питания нет
indication(false); // индикация отключается
PORTB=0; // чтобы не было утечек
sec = time.s;
// уходим в сон
do {
sleep_mode();
// пробуждение по прерываию от таймера
refresh = time.s != sec;
} while (!refresh);
if(!main_power_miss()) // это от безнадеги пробовал :(
_delay_ms(100);
}
// при наличии питания
indication(true); // индикация включается
if(time.s != sec){
refresh = true;
sec = time.s;
}
// выводим режим
if(modes[mode].show != NULL)
modes[mode].show(show_mode);
refresh = false;
//if(!played()) SND_PORT &= ~SND_PIN;
// проверки условий разных событий
if(!played() && alarm.s && (time.h == alarm.h) && (time.m == alarm.m))
// принудительно включаем режим будильника, если наступило время
tm = MODE_WAKE;
else
// иначе получаем и обрабатываем событие
tm = modes[mode].exec(get_key_event());
if(tm != mode){
// если возможно - делаем инициализацию нового режима
if(modes[tm].init != NULL)
modes[tm].init(mode);
mode = tm;
refresh = true;
}
}
}
функция проверки потери питания:
Код:
bool main_power_miss(void){
uint16_t tmp;
if(ADCSRA == 0)
return !(PINC & PWR_CHK_PIN); // этот пин заведен на питание +5, цепь отделена диодной развязкой от батарейки
else {
ATOMIC_BLOCK(ATOMIC_RESTORESTATE){
tmp = adc;
}
return (ocr >= OCRMAX) && (tmp < 200); // см. примечание ниже
}
}
примечание: проверка пропадания питания делается не по уровню соответствующего пина, а по сигналу обратной связи с АЦП в регуляторе высокого напряжения для ГРИ: если
ocr достигло максимума, а
adc никак не достигает номинала, значит, питание повышайки отсутствует, т.е. сетевого питания нет. регулятор работает по прерываниям.
функция включения-выключения индикации:
Код:
void indication(bool on){
if(ind_on == on) return;
ind_on = on;
if(ind_on){
TCCR1A = TIMER_OC_CLEAR(1A) | _BV(WGM10);
TCCR1B = TIMER_CLK_DIV_1 | _BV(WGM12);
TIMSK1 = _BV(TOIE1);
ADCSRA = _BV(ADEN) | _BV(ADIE) | _BV(ADATE) | ADC_DIV_4;
ADCSRB = 6; // T1 OVF TRIGGER
ADMUX = ADC_REF_INT_WITH_ECAP;
SPCR |= _BV(SPE);
update_leds(true);
} else {
TCCR1B = 0;
TCCR1A = 0;
SPCR &= ~_BV(SPE);
PORTB = 0;
ADCSRA = 0;
OCR1A = 0;
ocr = 0;
}
}
так вот, проблема в том, что все это работает как-то странно... при пропадании сетевого питания МК засыпает, потребление от батарейки снижается до 10 мкА (на самом деле меньше, просто тестер не показывает). при подаче питания МК просыпается, индикация включается и т.д. однако, иной раз при подаче питания МК не просыпается, или просыпается как-то странно, что индикация не включается, все функции недоступны, высокого напряжения нет. если после этого снова снять питание, ток не падает ниже 5-6 мА, т.е. или МК что-то делает, или это жрет остальная периферия. после попадания в этот клинч помогает только ресет.
грешу на код, но в чем подвох - не могу сообразить. проблема усугубляется тем, что монтаж компактный и никуда не подлезть особо... и что делать и как искать - ума не приложу. главное, что вымораживает - случайность событий: иногда после первого снятия питания не включается, иногда дергаю по 10 раз питание, пока возникнет эффект.
будут какие-то дельные советы, коллеги?
Добавлено after 8 minutes 59 seconds:кстати, иной раз МК засыпает, а ток не падает ниже 0,8 мА... вообще не понимаю ничего
