Приветствую! Не могу решить казалось бы простую задачу.
Имеем: - Контроллер ATMega 644PA (так же проверялось на 644А)
- Часовой кварц на тактирование таймера 2
- Контроллер тактируется кварцем 8МГц, выставлен фьюз CKDIV8, т.е. тактовая 1МГц.
- Режим энергосбережения: Power-save
- Компилятор CodeVisionAVR 2.05.3 и 3.12
Необходимо: - Максимальное энергосбережение (длительное батарейное питание).
- Получать 3 прерывания OCR2A, OCR2B, T2OVF с частотой 32Гц. Контроллер проснулся по OCR2A, дернул одной ногой, уснул. Проснулся по OCR2B, дернул другой ногой, уснул. Проснулся по T2OVF, изменил счетчик, уснул.
Реализация: - Т2 работает постоянно, прерывание OVF включено постоянно. Делитель частоты кварца PCK/2. Получаем прерывания 128 раз в секунду. Ставим счетчик на переменной от 0 до 3. На каждое 3е значение счетчика разрешаем прерывания OCR2A и OCR2B. В остальные значения счетчика прерывания по совпадению запрещены.
Проблема: - Не срабатывают прерывания OCR2A и OCR2B, или следуют сразу после T2OVF, т.е. не в свое время. Если закомментировать #asm("sleep"), то всё работает как нужно.
Попытки исправить: - Менял фьюзы, не уверен что выставлено правильно ибо понимаю не до конца. Стоит кварц на 8Мгц, но так же фьюз делителя на 8, т.е. тактовая 1 МГц. Соответственно какой фьюз выставить, на 1 или 8Мгц? Пробовал CKSEL3..0 111, 110,101. Разницы не заметил. Далее CKSEL0 и SUT1..0. Пробовал разные варианты. По даташиту CKSEL нужно ставить в 1, т.к. у меня crystal oscillator, а не ceramic resonator. При выборе ceramic потребление ниже, зато с применением SLEEP прерывания OCR2A и OCR2B “колбасятся” влево-вправо. Видимо таймер останавливается или сбивается. Не понимаю как такое может происходить. При изменении на crystal стабильность на порядок лучше, но теряются или некорректно отрабатываются прерывания OCR2A и OCR2B.
- Пытался сбрасывать флаги прерываний OCR2A и OCR2B. В результате они могли просто не появляться или же опять срабатывать не постоянно, а через раз.
- Менял режим энергосбережения. В IDLE таких проблем нет. Если закомментировать SLEEP то всё так же работает как надо.
Работаю в железе. Протеус не использую. Результат смотрю осцилографом.
Читал даташит. Каких-то явных ограничений не увидел. Контроллер должен просыпаться от любого из прерываний Т2. Сильно прошу не пинать, программирование не моя сфера, но есть желание разобраться. И прежде чем написать сюда много раз читал документацию и форумы. Явного решения не увидел. Да и мало кто с энергосбережением заморачивался.
Отвечать смогу только по вечерам, так как на работе интернета нет и все коммуникации запрещены…
Приму любые наставления, исправления и попытки помочь разобраться.
Исходный код:
Осциллограммы: