Программирование AVR AT90USB162: режимы пониженного энергопотребления Fri, August 18 2017  

Поделиться

нашли опечатку?

Пожалуйста, сообщите об этом - просто выделите ошибочное слово или фразу и нажмите Shift Enter.


AT90USB162: режимы пониженного энергопотребления Печать
Добавил(а) microsin   

Система управления питанием (Power Management) микроконтроллера AT90USB162 (и AT90USB82) имеет 5 режимов пониженного энергопотребления (или режимов сна, Sleep Modes) - Idle, Power-save, Power-down, Standby и Extended Standby. Они позволяют коду firmware выключать неиспользуемые модули MCU, что экономит потребляемую энергию. Режимы сна и энергопотребление связаны с работой многих узлов микроконтроллера (настройкой фьюзов, портов ввода/вывода, прерываниями, разрешением/запретом отдельных модулей ядра и периферии), поэтому программирование микроконтроллера для засыпания и выхода из сна является непростой задачей.

ATtiny43U

Статья представляет собой доработанный перевод оригинального даташита Atmel на микроконтроллер AT90USB162. Некоторые секции даташита (которые имеют слабое отношение к режимам сна) в статье упомянуты, но не приведены.

[Управление питанием и режимы сна (Power Management and Sleep Modes)]

Все микроконтроллеры семейства AVR (ATtiny, ATmega) имеет похожие режимы сна, те же самые регистры управления питанием и аналогичные способы программирования режимов пониженного энергопотребления. Отличаются только незначительные детали, связанные со встроенной периферией конкретной модели микроконтроллера. Так что это руководство может быть взято за основу при программировании режимов сна любых микроконтроллеров AVR компании Atmel.

После включения питания или аппаратного сброса микроконтроллер входит в нормальный рабочий режим (Active mode, или non-Idle). Все остальные режимы работы (а их 5) рассматриваются как режимы сна. На самом деле некоторые режимы сна для AT90USB162 функционально совпадают, так что реально есть только 3 различных по функционалу режима пониженного энергопотребления - Idle, Power-down, Standby. Режимы пониженного энергопотребления включаются специальным программированием регистра управления режимами Sleep (Sleep Mode Control Register – SMCR). Ниже показано назначение битов регистра SMCR.

Sleep Mode Control Register – SMCR

AT90USB162-SMCR

Чтобы войти в любой из 5 режимов Sleep, нужно в регистре SMCR установить в лог. 1 бит SE, выбрать битами SM2, SM1, SM0 нужный режим и выполнить инструкцию SLEEP. В таблице 8-1 перечислены различные режимы Sleep и соответствующие им значения битов SMx. Зеленым цветом выделены реально существующие для AT90USB162 режимы.

Таблица 8-1. Выбор режима сна.

SM2 SM1 SM0 Выбранный режим сна
0 0 0 Idle
0 0 1 Зарезервировано
0 1 0 Power-down
0 1 1 Power-save
1 0 0 Зарезервировано
1 0 1 Зарезервировано
1 1 0 Standby(1)
1 1 1 Extended Standby(1)

Примечание (1): режимы Standby рекомендуется использовать только совместно с внешними кварцами или резонаторами.

[Idle Mode]

Когда биты SM2..0 находятся в состоянии 000, бит SE установлен в 1, выполнение инструкции SLEEP вводит MCU в режим ожидания (Idle). Режим Idle останавливает работу ядра CPU, но при этом остается работать ОЗУ (SRAM), таймеры/счетчики (Timer/Counters), порты SPI, порт USB, USART, аналоговый компаратор, Watchdog и система прерываний (interrupt system). При этом останавливается тактовая частота clkCPU и clkFLASH, но все остальные тактовые сигналы продолжают работать.

Режим Idle позволяет микроконтроллеру вернуться обратно в рабочий режим (non-Idle) по событию срабатывания как внешнего прерывания - например, изменение состояния входного порта GPIO), так и от внутреннего прерывания - например, прерывание по переполнению таймера, завершения передачи USART или некоторых прерываний USB (наподобие SOFI, WAKEUPI и проч.). Если не требуется прерывание от аналогового компаратора, то он может быть выключен установкой бита ACD в регистре управления компаратором (Analog Comparator Control and Status Register – ACSR) - это уменьшит энергопотребление в режиме Idle.

[Power-down Mode]

Когда биты SM2..0 записаны в значение 010, выполнение инструкции SLEEP переводит MCU в режим выключения (Power-down mode). В этом режиме выключается внешний тактовый генератор, но внешние прерывания, 2-проводный последовательный интерфейс (2-wire Serial Interface) и Watchdog продолжают работать (если они разрешены). Разбудить MCU (т. е. перевести его в нормальный рабочий режим, non-Idle) могут только внешний аппаратный сброс (External Reset), сброс от сторожевого таймера (Watchdog Reset), сброс от некондиционного питания (Brown-out Reset), совпадение адреса 2-проводного последовательного интерфейса (2-wire Serial Interface), прерывание смены внешнего логического уровня на ножках GPIO (external level interrupt) INT7:4 и INT3:0, прерывание по смене состояния ножки или по асинхронному событию прерывания от USB (только WAKEUPI). Этот режим сна останавливает все основные тактовые частоты, и разрешает работу только асинхронных модулей.

Имейте в виду, что если используется прерывание по смене уровня (level triggered interrupt) для выхода из режима Power-down, этот измененный уровень должен удерживаться некоторое время, чтобы MCU действительно мог проснуться. За подробностями обратитесь к секции Внешние прерывания (External Interrupts).

При выходе из сна есть также некоторая задержка от события пробуждения до активации реального рабочего состояния (non-Idle). Эта задержка позволяет перезапуститься и стать стабильными тактовым импульсам, которые были остановлены. Этот период пробуждения определяется теми же самыми битами фьюзов выбора тактовой частоты (CKSEL Fuses), которые определяют таймаут сброса (Reset Time-out period), как описано в секции Источники тактирования (Clock Sources) даташита (в этой статье секция Clock Sources не приведена). Источники тактирования задаются фьюзами CKSEL3..0.

[Power-save Mode]

Когда биты SM2..0 записаны в значение 011, выполнение инструкции SLEEP переводит MCU в режим экономии питания (Power-save mode). Этот режим идентичен режиму Power-down. Он выделен как отдельный только для сохранения совместимости с более мощными микроконтроллерами.

[Standby Mode]

Когда биты SM2..0 записаны в значение 110, выполнение инструкции SLEEP переводит MCU в режим ожидания (Standby mode). Этот режим идентичен режиму Power-save, за исключением того, что генератор продолжает работать. Благодаря этому выход в нормальный рабочий режим происходит очень быстро, всего за 6 периодов частоты генератора.

[Extended Standby Mode]

Когда биты SM2..0 записаны в значение 111, выполнение инструкции SLEEP переводит MCU в расширенный режим ожидания (Extended Standby mode). Этот режим идентичен режиму Power-save, за исключением того, что генератор продолжает работать. Таким образом, режим Extended Standby Mode функционально совпадает с режимом Standby Mode, и выделен в отдельный режим только в целях сохранения совместимости.

[Отличия друг от друга режимов пониженного энергопотребления]

Здесь будут рассмотрены только те режимы, которые реально отличаются друг от друга - Idle, Power-down, Standby. В таблицах сведены отличия по активным тактовым доменам (Active Clock Domains), активности тактового генератора (работает ли главный источник тактов), источникам пробуждения (Wake-up Sources).

AT90USB162-Sleep-Modes-table8-2

Примечание (1): Рекомендуется использовать только с внешним кварцем или резонатором в качестве источника тактовой частоты. Для INT7:4 работает только прерывание по уровню (level interrupt). Для асинхронных прерываний USB работает только WAKEUPI.

[Регистр управления потреблением (Power Reduction Register)]

Регистр Power Reduction Register, PRR (на самом деле это два регистра PRR0 и PRR1), предоставляет метод для индивидуальной остановки тактов для различной периферии, что позволяет уменьшать энергопотребление. При отключении тактов текущее состояние соответствующего периферийного устройства замораживается, и его I/O регистры не могут читаться или записываться. Ресурсы, занятые остановленной периферией остаются занятыми, следовательно в большинстве случаев перед отключением тактов периферию стоит запретить. Пробуждение остановленного модуля осуществляется путем очистки соответствующего бита в регистре PRR, что включает такты и переводит модуль в то же состояние, в котором он был до отключения.

Выключение модулей работает в режимах Active (non-Idle) и Idle, и это позволяет значительно снизить энергопотребление. На рисунках показано назначение отдельных бит регистров PRR0 и PRR1. Черточками помечены зарезервированные (не используемые) биты.

Power Reduction Register 0 - PRR0

AT90USB162-PRR0

PRTIM0: Power Reduction Timer/Counter0

Запись лог. 1 в этот бит выключает работу модуля таймера/счетчика 0 (Timer/Counter0). Когда Timer/Counter0 разрешен, то он продолжит работу с того места, где был остановлен.

PRTIM1: Power Reduction Timer/Counter1

То же самое, что и PRTIM0, только для Timer/Counter1.

PRSPI: Power Reduction Serial Peripheral Interface

Запись лог. 1 в этот бит выключает работу модуля Serial Peripheral Interface (SPI), так как тактирование его отключается. Когда SPI пробуждается снова, то для корректной работы необходима повторная переинициализация SPI.

Power Reduction Register 1 - PRR1

AT90USB162-PRR1

PRUSB: Power Reduction USB

Запись лог. 1 в этот бит выключает USB путем остановки тактирования этого модуля. Когда USB пробуждается снова, то для корректной работы необходима повторная переинициализация USB.

PRUSART1: Power Reduction USART1

Запись лог. 1 в этот бит выключает USART1 путем остановки тактирования этого модуля. Когда USART1 пробуждается снова, то для корректной работы необходима повторная переинициализация USART1.

[Что нужно учитывать для минимизации энергопотребления]

Для того, чтобы минимизировать энергопотребление системы под управлением AVR, необходимо иметь в виду некоторые особые моменты - какие модули AVR выключать и каким образом. В общем случае всегда желательно использовать режимы сна по максимуму, и режим сна должен быть выбран так, чтобы удовлетворялись только абсолютно необходимые требования по функционированию устройства. Все функции и модули, неиспользуемые в настоящий момент, должны быть запрещены. Некоторые модули AVR требуют отдельного рассмотрения в плане достижения наименьшего возможного энергопотребления.

Analog Comparator

При входе в режим Idle аналоговый компаратор должен быть запрещен, если он не используется. Во всех остальных режимах сна компаратор автоматически запрещается. Однако, если компаратор был запрограммирован для использования на входе внутреннего опорного напряжения (Internal Voltage Reference), то аналоговый компаратор должен быть запрещен вручную во всех режимах сна. Иначе, если этого не делать, то внутренний источник опорного напряжения продолжит работу, независимо от того, используется или нет режим сна. Для того, чтобы выяснить подробности конфигурирования аналогового компаратора, обратитесь к секции Аналоговый компаратор (Analog Comparator).

Brown-out Detector

Если детектор некондиции в напряжении питания (Brown-out Detector) не требуется для работы firmware, то этот модуль должен быть выключен. Если же Brown-out Detector разрешен фьюзами BODLEVEL, то он будет работать и во всех режимах сна, и следовательно, всегда будет потреблять энергию. В режимах глубокого сна это окажет значительное влияние на общее энергопотребление. Чтобы получить подробную информацию по работе Brown-out Detector и его конфигурированию фьюзами, обратитесь к секции Детектирование некондиции питания (Brown-out Detection) даташита.

Internal Voltage Reference

Источник опорного напряжения (Internal Voltage Reference) будет автоматически разрешен, когда он необходим для работы Brown-out Detector, или для Analog Comparator. Если эти два модуля будут запрещены, как описано в соответствующих секциях, то Internal Voltage Reference будет также автоматически запрещен, и не будет потреблять энергию. Перед включением заново пользователь должен снова разрешить опорное напряжение, перед тем как его выход будет использоваться. За подробностями обратитесь к секции Источник опорного напряжения (Internal Voltage Reference) даташита.

Watchdog Timer

Если для работы firmware не нужен сторожевой таймер (Watchdog Timer), то этот модуль должен быть выключен. Если же Watchdog Timer разрешен, то он будет работать во всех режимах сна и следовательно будет потреблять энергию. В режимах глубокого сна это окажет значительное влияние на общее энергопотребление. За подробностями конфигурирования сторожевого таймера обратитесь к секции Прерывания (Interrupts) даташита.

Port Pins

Когда чип вошел в режим сна, все порты ножек (Port Pins) должны быть сконфигурированы на минимальное энергопотребление. Наиболее важно убедиться, что нет ножек, которые выдают ток на активную нагрузку (resistive loads). В тех режимах сна, где тактовая частота ввода вывода I/O (clkI/O) запрещена, входные буферы устройства будут также запрещены. Этим гарантируется, что не будет потребляться мощность входными буферами, когда они не нужны. Но в некоторых случаях нужно отслеживать события внешнего пробуждения, и тогда эти буферы нужно разрешить. За подробностями, какие ножки будут разрешены, обратитесь к секции Разрешение цифрового входа и режимы сна (Digital Input Enable and Sleep Modes) даташита. Если входной буфер разрешен, и входной уровень (входной вывод порта) остался в подвешенном состоянии или имеет входное аналоговое напряжение на уровне VCC/2, то входной буфер будет потреблять излишнюю мощность.

Для аналоговых входных ножек (например, входы компаратора), входной цифровой буфер должен быть всегда запрещен. Входной аналоговый уровень около VCC/2 на ножке входа вызовет значительное потребление тока даже в режиме Active. Цифровые входные буферы могут быть запрещены путем записи в регистр Digital Input Disable Registers (DIDR1). За подробностями обратитесь к секции Регистр запрета входных портов (Digital Input Disable Register 1 – DIDR1) даташита.

On-chip Debug System

Встроенная в чип система отладки (On-chip Debug System) разрешается фьюзом OCDEN (для чипа AT90USB162 это фьюз DWEN), и при входе в режим сна главный тактовый генератор (main clock source) продолжает работать, что следовательно вызывает потребление мощности. В режимах глубокого сна это окажет значительное влияние на общее энергопотребление.

[Прерывания (Interrupts)]

Эта секция описывает специфику, связанную с обработкой прерываний для AVR кристаллов AT90USB82 (и AT90USB162). Общие вопросы, касающиеся сброса и обработки прерываний, см. в секции Сброс и обработка прерывания (Reset and Interrupt Handling) даташита. В таблице 10.1 перечислены все используемые векторы прерывания и сброса.

Таблица 10-1. Вектора (адреса) сброса и прерываний.

Адрес(2) Источник Описание прерывания
1 $0000(1) RESET Сброс от внешнего вывода сброса, при включении питания, от некондиции питания (BOD), сторожевого таймера, сброса по шине USB, и сброса от отладочного интерфейса debugWIRE AVR.
2 $0002 INT0 External Interrupt Request 0
3 $0004 INT1 External Interrupt Request 1
4 $0006 INT2 External Interrupt Request 2
5 $0008 INT3 External Interrupt Request 3
6 $000A INT4 External Interrupt Request 4
7 $000C INT5 External Interrupt Request 5
8 $000E INT6 External Interrupt Request 6
9 $0010 INT7 External Interrupt Request 7
10 $0012 PCINT0 Pin Change Interrupt Request 0
11 $0014 PCINT1 Pin Change Interrupt Request 1
12 $0016 USB General Основной запрос прерывания USB
13 $0018 USB Endpoint Прерывание от конечной точки USB
14 $001A WDT Прерывание от таймаута сторожевого таймера (Watchdog Time-out Interrupt)
15 $001C TIMER1 CAPT Timer/Counter1 Capture Event
16 $001E TIMER1 COMPA Timer/Counter1 Compare Match A
17 $0020 TIMER1 COMPB Timer/Counter1 Compare Match B
18 $0022 TIMER1 COMPC Timer/Counter1 Compare Match C
19 $0024 TIMER1 OVF Timer/Counter1 Overflow
20 $0026 TIMER0 COMPA Timer/Counter0 Compare Match A
21 $0028 TIMER0 COMPB Timer/Counter0 Compare Match B
22 $002A TIMER0 OVF Timer/Counter0 Overflow
23 $002C SPI, STC SPI Serial Transfer Complete
24 $002E USART1 RX USART1 Rx Complete
25 $0030 USART1 UDRE USART1 Data Register Empty
26 $0032 USART1TX USART1 Tx Complete
27 $0034 ANALOG COMP Analog Comparator
28 $0036 EE READY EEPROM Ready
29 $0038 SPM READY Store Program Memory Ready

Примечания к таблице 10-1:

(1) Когда запрограммирован фьюз BOOTRST, микроконтроллер при включении питания или сбросе сделает безусловный переход по адресу бутлоадера (Boot Loader), за подробностями обратитесь к секции Программирование памяти (Memory Programming) даташита (в этой статье секция Memory Programming не приведена).
(2) Когда IVSEL в регистре MCUCR установлен, вектора прерывания будут перенесены на начало секции бутлоадера (Boot Flash Section). Таким образом, адрес каждого вектора прерывания будет равен адресу из таблице плюс адрес начала секции бутлоадера. Кроме того, независимо от версии кристалла 8K/16K, размер векторов прерывания идентичен (и занимает 2 слова) как для 8K, так и для 16K версии.

В таблице 10-2 показано размещение векторов сброса и прерывания для различных комбинаций установок BOOTRST и IVSEL. Если код программы (firmware) никогда не разрешает источник прерывания, то вектора прерывания не используются, и в это место может быть помещен обычный двоичный код программы. Это также относится к случаю, когда вектор сброса находится в секции приложения (Application section) при наличии векторов прерывания в секции бутлоадера (Boot section), и наоборот.

Таблица 10-2. Размещение векторов сброса и прерываний (1).

BOOTRST IVSEL Адрес сброса Вектора прерываний и стартовый адрес
1 0 0x0000 0x0002
1 1 0x0000 Boot Reset Address + 0x0002
0 0 Boot Reset Address 0x0002
0 1 Boot Reset Address Boot Reset Address + 0x0002

Примечание (1): адреса векторов сброса (в зависимости от версии кристалла 8K/16K и фьюзов) показаны в таблице 23-8 даташита. Для фьюза BOOTRST "1" означает, что фьюз не запрограммирован, и "0" означает, что фьюз запрограммирован. Boot Reset Address задается версией кристалла (AT90USB82 или AT90USB162) и состоянием фьюзов BOOTSZ1 и BOOTSZ0.

Регистр MCUCR отвечает за размещение таблицы векторов прерываний.

AT90USB162-MCUCR

IVSEL: Interrupt Vector Select

Когда бит IVSEL очищен (сброшен в 0), вектора прерываний помещены в начало памяти FLASH. Когда этот бит установлен (установлен в 1), вектора прерываний перемещаются на начало секции загрузки (Boot Loader section) памяти FLASH. Реальное значение адреса определяется фьюзами BOOTSZ. Подробности см. в секции Программирование памяти (Memory Programming) даташита (в этой статье секция Memory Programming не приведена). Чтобы избежать нежелательных изменений в положении таблицы векторов прерываний, для изменения бита IVSEL должна быть применена специальная процедура записи:

a. Нужно записать бит Interrupt Vector Change Enable (IVCE) в 1.
b. В течение 4 циклов тактового генератора нужно записать требуемое значение в IVSEL, при этом в IVCE записывается автоматически 0.

Когда эта последовательность выполнена, то прерывания будут автоматически запрещены. Прерывания запрещаются в цикле установки IVCE, и остаются запрещенными после инструкции, которая следует за записью в IVSEL. Если IVSEL не записан, прерывания остаются запрещенными на 4 цикла. Система автозапрета прерываний не влияет на бит I регистра статуса (Status Register).

Примечание: если вектора прерываний размещены в секции бутлоадера и запрограммирован бит защиты загрузки (Boot Lock) BLB02, прерывания запрещены, когда происходит выполнение кода в секции приложения (Application section). Если вектора прерывания размещены в секции приложения (Application section) и запрограммирован бит защиты загрузки (Boot Lock) BLB12, прерывания будут запрещены при выполнении кода в секции бутлоадера (Boot Loader section). За подробностями по битам защиты загрузки (Boot Lock) обращайтесь к секции Программирование памяти (Memory Programming) даташита (в этой статье секция Memory Programming не приведена).

IVCE: Interrupt Vector Change Enable

Бит IVCE должен быть записан в 1, чтобы можно было бы изменить бит IVSEL. IVCE очищается аппаратно в течение 4 циклов после того, как записан бит IVSEL. Установка бита IVCE запретит прерывания, как было описано в описании бита IVSEL. Ниже приведен пример кода изменения бита IVSEL.

;[Пример кода на ассемблере]
; Move_interrupts:
; Enable change of Interrupt Vectors
      ldi r16, (1<<IVCE)
      out MCUCR, r16
; Move interrupts to Boot Flash section
      ldi r16, (1<<IVSEL)
      out MCUCR, r16
      ret
//[Пример кода на C]
void Move_interrupts(void)
{
   /* Enable change of Interrupt Vectors */
   MCUCR = (1<<IVCE);
   /* Move interrupts to Boot Flash section */
   MCUCR = (1<<IVSEL);
}

[Сброс и обработка прерываний (Reset and Interrupt Handling)]

В архитектуре AVR заложено несколько источников прерывания. Эти прерывания и отдельный вектор сброса (Reset Vector) имеют каждый отдельный адрес (вектор) в пространстве памяти программ. Всем прерываниям назначены индивидуальные разрешающие биты, которые должны быть записаны в лог. 1 вместе с общим битом разрешения прерываний (Global Interrupt Enable bit, бит I) в регистре статуса (Status Register, SREG), чтобы соответствующее прерывание было разрешено. В зависимости от программного счетчика прерывания могут быть автоматически запрещены, когда запрограммированы биты защиты (Boot Lock) BLB02 или BLB12. Эта возможность увеличивает защищенность программного обеспечения firmware. Подробности см. в секции Программирование памяти (Memory Programming) даташита (в этой статье секция Memory Programming не приведена).

Самые младшие адреса в памяти программ по умолчанию назначены под размещение векторов (адресов) сброса и прерывания (Reset and Interrupt Vectors). Полный список векторов приведен в секции Прерывания (Interrupts) даташита. Список (таблица 10-1) также определяет фиксированные уровни приоритета для различных прерываний. Прерывания, вектор которых имеют наименьший адрес, обладают наивысшим приоритетом. RESET (сброс) имеет самый высокий приоритет, следующий за ним идет INT0 - внешний запрос прерывания 0 (External Interrupt Request 0). Вектора прерываний могут быть перенесены в секцию бутлоадера (Boot Flash section) путем установки бита IVSEL в регистре управления процессором (MCU Control Register, MCUCR). Дополнительная информация имеется в секции Прерывания (Interrupts) даташита. Вектор сброса также может быть перенесен в начало секции бутлоадера путем программирования фьюза BOOTRST, см. секцию Программирование памяти (Memory Programming) даташита (в этой статье секция Memory Programming не приведена).

Когда происходит прерывание, автоматически очищается флаг глобального разрешения прерываний (Global Interrupt Enable I-bit) в регистре SREG, и все прерывания запрещаются. Код firmware пользователя может записать в бит I лог. 1, чем можно разрешить вложенные прерывания. После этого все разрешенные прерывания могут прервать текущий обработчик прерывания. Бит I автоматически устанавливается, когда выполняется инструкция возврата из прерывания RETI.

Имеется два базовых типа прерываний. Первый тип срабатывает по событию установленного флага прерывания. Для этого типа программный счетчик переносится на действительный вектор прерывания с целью выполнения подпрограммы обработки прерывания, и при этом аппаратно очищается соответствующий флаг. Флаги прерывания могут быть также очищены путем записи в них лог. 1. Если условие прерывания произошло, когда соответствующий бит разрешения прерывания очищен, то прерывания не произойдет, но флаг прерывания установится и этим событие прерывание будет запомнено, пока прерывание не будет разрешено, или флаг не будет очищен программно. Похожим образом, когда общий флаг разрешения прерываний (бит I регистра SREG) сброшен, то обработчики прерываний вызываться не будут, но флаги события прерывания будут устанавливаться и будут запоминать события возникновения условия прерывания до тех пор, пока не будет установлен флаг I и разрешены соответствующие прерывания. После этого обработчики прерывания будут вызываться в установленном приоритетом порядке.

Второй тип прерываний будет срабатывать так долго, как присутствует условие прерывания. Эти прерывания не обязательно имеют соответствующие флаги прерывания. Если условие прерывания исчезло до того, как прерывание было разрешено, то обработчик прерывания не выполнится.

Когда AVR выходит из прерывания, он всегда возвращается к основной программе и выполняет одну или большее количество инструкций перед запуском любого ожидающего выполненияbackground-color: #fafad2;обработчика прерывания.

Имейте в виду, что регистр статуса SREG не сохраняется автоматически при входе в обработчик прерывания, и не восстановляется автоматически при выходе из обработчика прерывания. Все действия по сохранению и восстановлению SREG должен выполнять код пользователя в обработчике прерывания.

Когда используется инструкция CLI для запрета прерываний, все прерывания будут немедленно запрещены. Ни одного обработчика прерывания не будет выполнено после выполнения инструкции CLI, даже если событие прерывания возникло одновременно с выполнением CLI. Пример кода ниже показывает, как это может использоваться для избежания прерываний во время последовательности записи в EEPROM.

;[Пример кода на ассемблере]
      in r16, SREG    ; сохранение SREG
      cli             ; запрет прерываний
      sbi EECR, EEMPE ; запуск записи в EEPROM
      sbi EECR, EEPE
      out SREG, r16   ; восстановление SREG (I-bit)
//[Пример кода на C]
char cSREG;
cSREG = SREG;       /* сохранение SREG */
/* запрет прерываний в течение времени записи */
__disable_interrupt();
EECR |= (1<<EEMPE); /* запуск записи в EEPROM */
EECR |= (1<<EEPE);
SREG = cSREG;       /* восстановление SREG (I-bit) */

Когда используется инструкция SEI для разрешения прерываний, то инструкция, следующая за SEI выполнится перед любым ожидающим выполнения обработчиком прерывания, как показано в примере ниже.

;[Пример кода на ассемблере]
      sei       ; установка бита I, общее разрешение прерываний
      sleep     ; вход в режим сна в ожидании прерывания
; Примечание: вход в режим сна произойдет перед любым ожидающим
; обработки прерыванием (или прерываниями).
//[Пример кода на C]
__enable_interrupt();  /* установка бита I, Global Interrupt Enable */
__sleep();             /* вход в режим сна в ожидании прерывания */
/* Примечание: вход в режим сна произойдет перед вызовом любого ожидающего
обработки прерывания (или прерываний). */

Время реагирования на событие прерывания

Ответ на событие прерывания выполнением кода обработчика для всех разрешенных прерываний AVR занимает по времени минимум 5 циклов тактов. После завершения 5 периодов тактового сигнала будет запущен на выполнение программный адрес вектора для действующего обработчика прерывания. Во время этих 5 тактов программный счетчик адреса проталкивается в стек. Вектор обычно представляет собой команду безусловного перехода на обработчик прерывания, и этот переход занимает еще 3 цикла тактов. Если условие прерывания произошло во время выполнения инструкции, занимающей несколько тактовых циклов, то эта инструкция завершится до обработки прерывания. Если прерывание произошло в момент, когда MCU находится в режиме сна, то время реакции на прерывание увеличивается на 5 периодов тактов. Это увеличение добавляется к времени запуска из выбранного режима сна.

Возврат из прерывания занимает 3 цикла тактов. Во время этих 3 периодов тактов счетчик команд (3 байта) извлекается из стека, указатель стека увеличивается на 3, и устанавливается бит I регистра SREG.

[Внешние прерывания (External Interrupts)]

Внешние прерывания срабатывают от ножек INT7:0 или от любой из ножек PCINT12..0. Нужно заметить, что если прерывания разрешены, то прерывание будет срабатывать для INT7:0 или PCINT12..0 даже если эти ножки сконфигурированы как выходы. Эта особенность дает возможность генерировать программное прерывание (software interrupt).

Прерывание по изменению ножки (Pin change interrupt) PCI0 будет срабатывать, если переключается любая из разрешенных ножек PCINT7:0. Регистр PCMSK0 управляет, какая ножка будет работать на прерывании изменения вывода порта. Прерывание Pin change interrupt PCI1 сработает, если переключается любая из разрешенных ножек PCINT12:8. Регистр PCMSK1 управляет, какая ножка будет работать на прерывании изменения вывода порта. Прерывания Pin change на выводах PCINT12..0 детектируются асинхронно (т. е. не нужна тактовая частота, чтобы сработало прерывание). Следовательно, эти прерывания могут использоваться для пробуждения микроконтроллера из глубокого сна (т. е. могут использоваться и другие режимы сна, отличные от Idle).

Внешние прерывания могут сработать по спаду или фронту логического уровня, или по низкому уровню. Это настраивается, как показано в описании регистров управления внешними прерываниями (External Interrupt Control Registers) - EICRA (INT3:0) и EICRB (INT7:4). Когда внешнее прерывание разрешено, и сконфигурировано как прерывание по уровню (level triggered), то прерывание будет срабатывать тогда, когда ножка удерживается на уровне лог. 0. Имейте в виду, что распознавание и срабатывание прерываний по изменению уровня INT7:4 требует наличия тактов на портах ввода/вывода I/O, как описано в секции Системная тактовая частота и опции тактирования (System Clock and Clock Options) даташита (в этой статье секция System Clock and Clock Options не приведена). Прерывания по низкому уровню и по срезу INT3:0 детектируются асинхронно. Следовательно, эти ножки могут использоваться для пробуждения микроконтроллера из режимов сна, отличающихся от Idle. Такты для I/O останавливаются во всех режимах сна, за исключением режима сна Idle.

Имейте в виду, что если прерывания по уровню используется для пробуждения из режима сна Power-down, требуемый уровень должен удерживаться до полного выхода MCU, чтобы прерывание сработало. Если низкий уровень исчезнет до окончания времени запуска (Start-up Time), то микроконтроллер проснется, но прерывание не сработает. Время запуска задается фьюзами SUT и CKSEL, как описано в секции Системная тактовая частота и опции тактирования (System Clock and Clock Options) даташита.

External Interrupt Control Register A – EICRA

Регистр управления внешними прерываниями EICRA и его биты показаны на рисунке.

AT90USB162-EICRA

ISC31, ISC30, ISC21, ISC20, ISC11, ISC10, ISC01, ISC00: External Interrupt 3..0 Sense Control Bits

Внешние прерывания 3..0 активизируются внешними выводами INT3:0, если установлен флаг I регистра SREG и соответствующая маска прерываний в регистре EIMSK. Уровень и перепады на внешних ножках активизируют прерывание, как показано в таблице 12-1. Перепады на INT3..INT0 детектируются асинхронно (т. е. для этого не нужно тактирование I/O). Импульсы на INT3:0 длиннее, чем 50 нс (tINT, минимальная длина импульса для асинхронного внешнего прерывания) вызовут прерывание. Более короткие импульсы не будут гарантированно вызывать прерывание. Если выбрано прерывание по низкому уровню (low level interrupt), то низкий уровень должен удерживаться до завершения текущей выполняемой инструкции, чтобы могло сработать прерывание. Если прерывание по низкому уровню разрешено, то оно будет вызвать запрос прерывания в течение всего времени, пока ножка удерживается на низком логическом уровне. Когда изменяется любой из битов ISCn, то может сработать прерывание. Таким образом, рекомендуется сначала запретить INTn очисткой бита разрешения прерывания в регистре EIMSK, после этого можно менять соответствующий бит ISCn. И наконец, флаг прерывания INTn должен быть очищен путем записи лог. 1 в соответствующий бит флага (INTFn) регистра EIFR перед тем, как прерывание будет заново разрешено.

Таблица 12-1. Interrupt Sense Control(1).

ISCn1 ISCn0 Описание
0 0 Низкий уровень на выводе INTn генерирует запрос прерывания.
0 1 Любой перепад на выводе INTn асинхронно генерирует запрос прерывания.
1 0 Спад уровня на выводе INTn асинхронно генерирует запрос прерывания.
1 1 Нарастание (фронт)background-color: #fafad2;уровня на выводе INTn асинхронно генерирует запрос прерывания.

Примечание (1): n = 3, 2, 1 или 0. Когда меняют биты ISCn1/ISCn0, прерывания должны быть запрещены путем очистки соответствующего бита разрешения прерывания в регистре EIMSK. Иначе при изменении этих бит может произойти прерывание.

External Interrupt Control Register B – EICRB

AT90USB162-EICRB

ISC71, ISC70, ISC61, ISC60, ISC51, ISC50, ISC41, ISC40: External Interrupt 7..4 Sense Control Bits

Внешние прерывания 7..4 активизируются внешними выводами INT7:4, если установлен флаг I регистра SREG и соответствующая маска прерываний в регистре EIMSK. Уровень и перепады на внешних ножках активизируют прерывание, как показано в таблице 12-3. Значение на ножках INT7:4 запоминается перед детектированием перепадов. Если выбрано прерывание по срезу (edge) или переключению (toggle), то импульсы длиннее одного периода тактов будут вызывать прерывание. Более короткие импульсы не будут гарантированно вызывать прерывание. Помните о том, что тактовая частота CPU может быть ниже, чем частота XTAL, если работает делитель тактовой частоты. Если выбрано прерывание по низкому уровню (low level interrupt), то низкий уровень должен удерживаться до завершения текущей выполняемой инструкции, чтобы могло сработать прерывание. Если прерывание по низкому уровню разрешено, то оно будет вызвать запрос прерывания в течение всего времени, пока ножка удерживается на низком логическом уровне.

Table 12-3. Interrupt Sense Control(1)

ISCn1 ISCn0 Описание
0 0 Низкий уровень на выводе INTn генерирует запрос прерывания.
0 1 Любой перепад на выводе INTn генерирует запрос прерывания.
1 0 Спад уровня между двумя выборками на выводе INTn генерирует запрос прерывания.
1 1 Нарастание (фронт)background-color: #fafad2;уровня между двумя выборками на выводе INTn генерирует запрос прерывания.

Примечание (1): n = 7, 6, 5 или 4. Когда меняют биты ISCn1/ISCn0, прерывания должны быть запрещены путем очистки соответствующего бита разрешения прерывания в регистре EIMSK. Иначе при изменении этих бит может произойти прерывание.

External Interrupt Mask Register – EIMSK

AT90USB162-EIMSK

INT7..INT0: External Interrupt Request 7-0 Enable

Когда любой из бит INT7..INT0 установлен в 1, и установлен бит I в регистре статуса (SREG), то разрешено внешнее прерывание от соответствующей ножки микроконтроллера. Регистры EICRA и EICRB определяют, какой тип активизирования прерывания используется (нарастание или спад, или прерывание по уровню). Активность на этих ножках вызовут прерывание, даже если они настроены как выходы. Это предоставляет способ генерирования программных прерываний.

External Interrupt Flag Register – EIFR

AT90USB162-EIFR

INTF7..INTF0: External Interrupt Flags 7-0

Когда срез (edge) или изменение логического уровня вызывает запрос на прерывание на выводах INT7:0, устанавливается в лог. 1 соответствующий флаг INTF7:0. Если установлен в лог. 1 бит I в регистре SREG, и установлен в лог. 1 соответствующий бит разрешения прерывания INT7:0 в регистре EIMSK, то MCU произведет переход по вектору прерывания. Флаг очищается, когда выполняется процедура обработки прерывание (обработчик прерывания). Альтернативный способ очистки флага - запись в него лог. 1. Эти флаги всегда очищаются, когда INT7:0 сконфигурированы как прерывание по уровню. Имейте в виду, что когда происходит вход в режим сна с запрещенными прерываниями INT3:0, входные буферы этих ножек будут запрещены. Это может привести к тому, что изменение логики во внутренних сигналах приведут к установке флагов INTF3:0. Для подробностей см. секциюbackground-color: #fafad2;Разрешение цифрового входа и режимы сна (Digital Input Enable and Sleep Modes).

Pin Change Interrupt Control Register - PCICR

AT90USB162-PCICR

PCIE1, PCIE0: Pin Change Interrupt Enable 1-0

Когда биты PCIE1, PCIE0 установлены в лог. 1, и установлен в лог. 1 бит I в регистре статуса (SREG), то разрешено прерывание по смене уровня 1/0 (Pin Change interrupt). Любое изменение на любом разрешенном входе PCINT12..8/7..0 приведет к прерыванию. При этом произойдет вызов соответствующего запроса на прерывание и переход по вектору прерывания PCI1/0. Выводы PCINT12..8/7..0 разрешаются индивидуально через регистры PCMSK1 и PCMSK0.

Pin Change Interrupt Flag Register – PCIFR

AT90USB162-PCIFR

PCIF1, PCIF0: Pin Change Interrupt Flag 1-0

Когда изменение логического уровня на любом из выводов PCINT12..8/7..0 вызывает запрос прерывания, то устанавливается в лог. 1 флаг PCIF1/0. Если установлен бит I в SREG и бит PCIE1/0 в PCICR, MCU произведет переход на соответствующий вектор прерывания. Флаг очищается, когда выполняется процедура обработки прерывания. Альтернативный способ очистки флага - запись в него лог. 1.

Pin Change Mask Register 0 – PCMSK0

AT90USB162-PCMSK0

PCINT7..0: Pin Change Enable Mask 7..0

Каждый из битов PCINT7..0 выбирает, разрешено или нет прерывание по смене уровня (pin change interrupt) на соответствующей I/O ножке микроконтроллера. Если любой из битов PCINT7..0 установлен и бит PCIE0 в регистре PCICR установлен, то pin change interrupt разрешено на соответствующей ножке порта I/O. Если PCINT7..0 очищен, то запрещено прерывание pin change на соответствующем выводе I/O.

Pin Change Mask Register 1– PCMSK1

AT90USB162-PCMSK1

PCINT12..8: Pin Change Enable Mask 12..8

Каждый из битов PCINT12..8 выбирает, разрешено или нет прерывание по смене уровня (pin change interrupt) на соответствующей I/O ножке микроконтроллера. Если любой из битов PCINT12..8 установлен и бит PCIE1 в регистре PCICR установлен, то pin change interrupt разрешено на соответствующей ножке порта I/O. Если PCINT12..8 очищен, то запрещено прерывание pin change на соответствующем выводе I/O.

[Аналоговый компаратор (Analog Comparator)]

В этом секции рассматривается программирование компаратора на предмет понижения энергопотребления. Управление компаратором осуществляется через регистр управления и статуса ACSR.

Analog Comparator Control and Status Register – ACSR

AT90USB162-ACSR

ACD: Analog Comparator Disable

Когда этот бит записан в лог. 1, питание компаратора выключается. Этот бит может быть установлен в любое время для выключения компаратора, что уменьшает энергопотребление в режимах Active и Idle. Когда изменяется бит ACD, должно быть запрещено прерывание от компаратора путем очистки бита ACIE в регистре ACSR. Иначе может сработать прерывание от компаратора, когда меняется значение бита ACD.

ACBG: Analog Comparator Bandgap Select

Когда этот бит установлен, на положительный вход компаратора вместо внешнего входа подключается источник фиксированного опорного напряжения. Когда этот бит очищен, AIN0 работает как положительный вход аналогового компаратора. Подробности см. в секции Источник опорного напряжения (Internal Voltage Reference) даташита.

ACO: Analog Comparator Output

Выход аналогового компаратора синхронизирован и напрямую подключен к биту ACO. Синхронизация производит задержку в 1-2 цикла тактов.

ACI: Analog Comparator Interrupt Flag

Этот бит устанавливается аппаратно, когда выход компаратора вызывает срабатывание прерывание, как задано битами ACIS1 и ACIS0 (см. таблицу 22-1). Обработчик прерывания выполняется, если бит ACIE установлен и бит I регистра SREG также установлен. Бит ACI очищается аппаратно, когда выполняется код соответствующего вектора прерывания. Альтернативно бит ACI может быть очищен записью лог. 1 в этот флаг.

ACIE: Analog Comparator Interrupt Enable

Когда этот бит записан в лог. 1, и установлен бит I регистра SREG, то активизируется прерывание от компаратора. Когда ACIE записан в лог. 0, это прерывание запрещено.

ACIC: Analog Comparator Input Capture Enable

Когда бит ACIC равен лог. 1, то он разрешает функцию срабатывания захвата по входу в Timer/Counter1 от аналогового компаратора. В этом случае выход компаратора напрямую подключен к логике захвата по входу, чем обеспечивается подавление шума компаратором и выбор среза срабатывания для прерывания захвата по входу Timer/Counter1. Когда бит ACIC равен лог. 0, то нет соединения между выходом компаратора и функцией захвата по входу. Для того, чтобы компаратор переключал прерывание по входному захвату Timer/Counter1, должен быть установлен бит ICIE1 в регистре TIMSK1.

ACIS1, ACIS0: Analog Comparator Interrupt Mode Select

Эти биты определяют, какие события на выходе компаратора будут вызывать срабатывание прерывания компаратора. Различные варианты установок перечислены в таблице 22-1.

Таблица 22-1. Установки ACIS1/ACIS0

ACIS1 ACIS0 Режим прерывания
0 0 Прерывание компаратора срабатывает на переключении выхода.
0 1 Зарезервировано
1 0 Прерывание компаратора срабатывает на спаде уровня на выходе.
1 1 Прерывание компаратора срабатывает на фронте уровня на выходе.

Когда нужно поменять биты ACIS1/ACIS0, то прерывание аналогового компаратора должно быть запрещено путем очистки бита ACIE. Иначе может произойти прерывание при изменении этих бит.

[Регистр запрета входных портов (Digital Input Disable Register 1 – DIDR1)]

AT90USB162-DIDR1

AIN1D, AIN0D: AIN1, AIN0 Digital Input Disable

Когда эти биты записаны в лог. 1, цифровые входные буферы для ножек AIN1/0 запрещены. Соответствующий регистр PIN будет всегда читаться как 0, если эти биты установлены. Когда аналоговый сигнал прикладывается к выводам AIN1/0 и цифровой вход от этих выводов не нужен, то эти биты должны быть записаны в лог. 1 для уменьшения энергопотребления от цифрового входного буфера.

[Источник опорного напряжения (Internal Voltage Reference)]

Микроконтроллер AT90USB82/162 имеет встроенный внутренний источник опорного напряжения (internal bandgap reference). Этот источник используется для детектора некондиции питания (Brown-out Detection, BOD) и как источник сигнала для положительного входа аналогового компаратора.

Напряжение опорного источника имеет время запуска, которое может повлиять на метод использования источника опорного напряжения. Время запуска указано в таблице 9-4. Чтобы уменьшить энергопотребление, источник опорного напряжения не всегда должен быть включен. Включен источник опорного напряжения в следующих случаях:

1. Когда BOD разрешен (через программирование фьюзов BODLEVEL [2..0]).
2. Когда источник опорного напряжения подключен к аналоговому компаратору (через установку бита ACBG в регистре ACSR).

Таким образом, если BOD не разрешен, после установки бита ACBG пользователь всегда должен позволить источнику опорного напряжения запуститься до того, как начнет использоваться выход аналогового компаратора. Для снижения энергопотребления в режиме Power-down, пользователь может избежать этих трех вышеперечисленных условий, чтобы удостовериться, что источник опорного напряжения будет выключен перед входом в режим Power-down.

Таблица 9-4. Характеристики внутреннего источника опорного напряжения.

AT90USB162-Bandgap-Reference-Characteristics-table9-4

[Разрешение цифрового входа и режимы сна (Digital Input Enable and Sleep Modes)]

Цифровой вход может быть притянут к земле на входе триггера Шмидта (см. рисунок).

AT90USB162-ports

Сигнал, помеченный на рисунке как SLEEP, устанавливается контроллером сна MCU в режимах Power-down, Power-save и Standby, чтобы избежать высокого энергопотребления, если некоторые входные сигналы остались в подвешенном состоянии, или имеют аналоговый входной уровень напряжения около VCC/2.

Сигнал SLEEP запрещает работу для ножек портов в качестве внешних источников прерывания. Если не разрешен запрос на внешнее прерывание для какой-то ножки, то для этой ножки сигнал SLEEP является активным (т. е. запрещает работу этой ножки как входа). Сигнал SLEEP также отменяет различные другие альтернативные функции портов, которые описаны в секции Альтернативные функции портов (Alternate Port Functions) даташита (в этой статье секция Alternate Port Functions не приведена).

Если логический высокий уровень (лог. 1) находится на ножке асинхронного входа внешнего прерывания, сконфигурированной как "прерывание по фронту, спаду или по любой смене логического уровня на выводе" (Interrupt on Rising Edge, Falling Edge, or Any Logic Change on Pin), и при этом внешнее прерывание НЕ разрешено, то соответствующий флаг внешнего прерывания (External Interrupt Flag) будет установлен и вызовет просыпание микроконтроллера из вышеупомянутых режимов сна, как только произойдет запрошенное событие захвата на входах в этих режимах.

Если некоторые ножки не используются, рекомендуется удостовериться, что на них присутствует заданный логический уровень. Даже если цифровые входы запрещены в режимах глубокого сна, как было описано ранее, наличия "плавающих" входов нужно избегать для того, чтобы снизить потребление тока во всех других режимах, где цифровые входы разрешены (Reset, режим Active и режим Idle).

Самый простой метод убедиться в том, что на неиспользованной ножке присутствует заданный уровень - разрешить для неё встроенный внутренний нагрузочный резистор (internal pull-up). В этом случае нужно помнить, что pull-up автоматически запрещается при сбросе. Если важно низкое энергопотребление в состоянии сброса (Reset), то рекомендуется использовать внешний pull-up или pull-down резистор. Прямое подключение неиспользуемых ножек к VCC или GND не рекомендуется, поскольку может вызвать чрезмерный ток потребления, если случайно эти ножки будут настроены как выходы.

[Детектирование некондиции питания (Brown-out Detection)]

Микроконтроллер AT90USB82/162 имеет встроенный аппаратный узел детектирования качества питающего напряжения (On-chip Brown-out Detection, BOD), для мониторинга уровня VCC во время работы. Детектирование осуществляется путем сравнения VCC с фиксированным порогом срабатывания. Этот порог срабатывания может быть выбран путем программирования фьюзов BODLEVEL (см. таблицу 9-2 даташита). Для уменьшения энергопотребления BOD нужно выключить, для чего все биты BODLEVEL 2..0 должны остаться не запрограммированными (в состоянии 111).

[Пример практического программирования режимов сна]

Задача: устройство на микроконтроллере AT90USB162 питается от батарейки, имеет кнопку для управления и светодиодный матричный индикатор АЛС340А1. В нормальном рабочем режиме (Active mode) микроконтроллер постоянно переключает порты для формирования символа на индикаторе (динамическая индикация) и опрашивает кнопку. Нажатие кнопки замыкает ножку порта микроконтроллера на землю, GND. Если эта кнопка не была нажата в течение 10 секунд, то нужно перевести устройство в режим экономии энергии (Power-down mode). При этом все что только возможно, в микроконтроллере должно быть выключено. Если пользователь нажал на кнопку, то устройство должно проснуться и возобновить работу с нужного места.

AVR-USB162-psw-storage-simply-sch

На рисунке показана упрощенная схема устройства, собранного на основе макетной платы AVR-USB162MU [1]. Красными и синими проводами показано подключение анодов и катодов индикатора АЛС340А1 (выходы). Единственный вход - кнопка, подключенная к порту PD0 (INT0). Теперь рассмотрим все моменты, которые нужно рассмотреть, чтобы реализовать нашу задачу. Итак, процесс по шагам.

1. Нужно определиться с режимом сна, который будем использовать. Поскольку наша главная цель - минимум энергопотребления, то очевидно, что это будет режим Power-down. Для пробуждения из Power-down будем использовать асинхронное отслеживание спада лог. уровня на входе внешнего прерывания INT0 (порт PD0 микроконтроллера AT90USB162). Нажатие на кнопку как раз будет вызывать такое прерывание, независящее от работы тактовых генераторов (тактирование I/O в режиме Power-down выключено).

2. Для запуска режима сна можно напрямую обращаться к регистру SMCR микроконтроллера, как описано в даташите, но лучше для удобства воспользоваться для этого готовыми макросами. Тулчейн AVR GCC имеет встроенный набор макросов для этой цели, которые упрощают программирование режима сна микроконтроллеров AVR. Эти макросы описаны в заголовочном файле avr/sleep.h. Для использования sleep.h в проекте обязательно должен быть задан тип AVR, так как внутри sleep.h есть определения макросов сна для различных типов AVR, переключаемые условными операторами времени компиляции. Для проектов AVR GCC тип микроконтроллера задается в makefile строчкой наподобие:

MCU = at90usb162

Пример кода ввода AT90USB162 в режим сна Power-down:

#include <avr/sleep.h>
 
   ...
   set_sleep_mode(SLEEP_MODE_PWR_DOWN);
   sleep_mode();

Для set_sleep_mode в нашем случае можно также указать в качестве параметра SLEEP_MODE_IDLE (режим сна Idle) или SLEEP_MODE_STANDBY (режим сна Standby).

3. Нужно выбрать способ пробуждения микроконтроллера. Несмотря на то, что мы уже знаем, что для пробуждения будет использоваться кнопка на ножке порта PD0, нужно выбрать событие прерывания для входа INT0. Это делается через программирование битов регистра EICRA. Наиболее подходит событие по спаду уровня на INT0, так как это соответствует моменту нажатия на кнопку. Для этого в бит ISC01 регистра EICRA нужно записать единицу (см. таблицу 12-1). Остальные три варианта нам не подойдут - активизация прерывания по низкому уровню вызовет остановку работы устройства при нажатии на кнопку (из-за бесконечного срабатывания прерывания, пока кнопка удерживается), а варианты со срабатыванием по фронту и обеим перепадам (и фронт, и спад) тоже неудобны.

   //Пробуждение (прерывание от кнопки) будет осуществляться 
   // спадом логического уровня на входе кнопки.
   EICRA = 1<<ISC01;

4. Нужно написать обработчик прерывания для события нажатия на кнопку (прерывание от INT0). В нормальном рабочем режиме это прерывание запрещено, и включается оно только в момент входа в режим сна. В обработчике прерывания нужно запомнить факт пробуждения (для этого и нужен wakeupflag) - это очень важный, хотя и неочевидный момент. Флаг пробуждения нужен для того, чтобы выполнить в основной программе при пробуждении какие-то действия - например, не нужно обрабатывать текущее нажатие на кнопку, сбросить какие-то переменные и т. д. И самое главное - нужно запретить прерывание INT0.

//Прерывание от кнопки, которое используется только для пробуждения
ISR(INT0_vect, ISR_BLOCK)
{
   wakeupflag = true;
}
 
//Кусок кода, который выполняется в основной программе
// при выходе из сна. Этот код может вызываться в главном
// цикле процедуры main.
if (wakeupflag)
{
   //Было пробуждение!
   wakeupflag = false;
   EIMSK = 0; //запрет INT0
   ..
}

5. Нужно по таймеру входить в режим Power-down, если не было нажатий на кнопки. При этом также настроить все выходные порты так, чтобы устройство не потребляло энергию. В нашем случае для этого делается вызов AlsDisable, которая переключает порты катодов и анодов индикатора в такое состояние, когда индикатор АЛС340А1 не потребляет ток. Переменная timestamp содержит глобальный инкрементный счетчик времени (инкрементируется по прерыванию таймера), а sleepstamp служит для отслеживания таймаута неактивности кнопки. Перед входом в режим сна разрешается прерывание INT0, которое служит для выхода из сна (перехода из режима Power-down в режим Active).

   if ( 0 == (BTN_PIN & (1 << BTN_ENTER)) )
   {
       sleepstamp = timestamp + SLEEP_TIMEOUT;
   }
   else if (sleepstamp < timestamp)
   {
       AlsDisable();
       EIMSK = (1 << INT0);      //разрешение пробуждения от кнопки
       set_sleep_mode(SLEEP_MODE_PWR_DOWN);
       sleep_mode(); 
   }

6. Нужно позаботиться о том, чтобы выключить всю неиспользуемую аппаратуру микроконтроллера - как в Active mode, так и в Power-down mode. В нашем случае это компаратор, внутренний источник опорного напряжения, Brown-out Detector (BOD), Watchdog, система отладки, неиспользуемые ножки портов. Кое-что нужно настроить фьюзами с помощью программатора (фьюзы WDTON, DWEN, BODLEVELn). Некоторую аппаратуру нужно настраивать программно, в коде firmware. Для аппаратуры, которая не нужна ни в Active mode, ни в Power-down mode, все необходимые действия для настройки аппаратуры можно выполнить один раз, при включении питания (сбросе). Вот так, к примеру, выключается компаратор:

   //Запрет компаратора, и одновременное выключение внутреннего
   // источника опорного напряжения (внимание: фьюзы BODLEVEL надо 
   // запрограммировать на выключение BOD!).
   ACSR = 1 << ACD;

Для аппаратуры, которая используется в Active mode, но не нужна в Power-down mode (к примеру, ножки портов), более тонкую настройку ножек и необходимой аппаратуры можно делать при засыпании и пробуждении. При засыпании нужно выключить все что можно, а при пробуждении обратно включить все, что нужно.

[Ссылки]

1. Макетная плата AVR-USB162, макетная плата AVR-USB162MU.

 

Добавить комментарий


Защитный код
Обновить

Top of Page