Рано или поздно перед разработчиком встает вопрос о сохранении настроек. Встречаются разные способы:
- Резервный источник питания (как например в часах реального времени или многих магнитолах);
- Постоянная запись сейвов в память – ага, но EEPROM то не резиновая;
- Постоянная запись сейвов во внешнюю память, например во флеш – надо покупать и ждать и делать отдельную разводку;
- Запись сейва при понижении напряжения питания до определенного уровня – то что нужно, о нем и пойдет речь дальше.
Итак нам нужно детектить низкий уровень напряжения, для этого будем юзать встроенный компаратор в pic16f628a. На один из его входов подцепим диод (падение на котором будем считать постоянным и равным примерно 0.6 В), на вторую делитель напряжения, который при нормальном питании выдает напряжение больше этих 0.6 В, а при нужном для нас уровне срабатывания падает ниже. Я взял первый попавшийся диод из закромов и на нем падение оказалось равным 0.77 В. Ну собственно вот нормальные условия:
Так это сделано, теперь надо позаботиться о том, чтобы нашему мк хватило времени на сохранение настроек. Для этого необходимо сделать как минимум две вещи:
1. Добавить на линию питания емкость достаточного номинала, причем добавить не в произвольное место, а после диода перед стабилизатором – диод предотвратит разряд емкости в неправильном направлении:
После стабилизатора ставить не стоит или придется добавлять еще один диод. Я себе поставил с запасом 2.2 мкФ.
2. Позаботиться о том, чтобы разряд емкости происходил как можно медленнее. Для этого можно как минимум повыключать все светящееся, колеблющееся и орущее на всех портах, а потом еще и в стэнд бай можно загнать.
Ну собственно вспоминаем, как использовать компаратор в pic16f628a, дочитываем каким образом он юзается с прерываниями и получаем что-то вот такое:
#include <htc.h> #define _XTAL_FREQ 4000000 __CONFIG(WDTDIS & UNPROTECT & MCLREN & LVPDIS & HS & BOREN); volatile unsigned char temp; void main(void) { __delay_ms(200); __delay_ms(200); __delay_ms(200); __delay_ms(200); __delay_ms(200); //секундная задержка после старта temp = 0; CMCON = 0b00000101; //настраиваем наш компаратор TRISA = 0xFF; TRISB = 0x00; TRISB0 = 1; VRCON = 0x00; PORTB = 0; CMIE = 1; //включаем прерывания компаратора PEIE = 1; GIE = 1; for (;;) { if (!RB0) { __delay_ms(200); temp++; PORTB = temp<<4; //это для проверки числа }//if }//for(;;) }//main void interrupt isr() { if (CMIF) { __delay_ms(20); if (!C2OUT) { PORTB = 0x00; //выключаем все свистелки SLEEP(); //и входим в стенд бай eeprom_write(0x04, temp); //сейвимся eeprom_write(0x05, temp); eeprom_write(0x06, temp); eeprom_write(0x07, temp); }//if c2out CMIF = 0; }//if }//isr
По хорошему надо еще и организовать POR, BOR, но у нас пока что эксперимент и суть и так ясна. Видео эксперимента:
Как видно из записи, емкости вполне достаточно, чтобы записать 4 байта данных, да думаю там еще 4 спокойно запишется, но дальше тесты уже буду делать на pic16f877a когда они придут и внедрять опцию в свой усилок.