|
- |
Сохранение SREG в прерываниях |
Зачем
вообще сохранять SREG в прерываниях?
Сохранять нужно не только SREG, а все, что используется в основной программе и может быть изменено в прерывании. Прерывание поому и прерывание, что может возникнуть в любой момент времени. Например, между вот этими двумя командами:
Что будет, если в этом прерывании будет изменен, например, признак C в SREG ? Будет переход не в зависимости от результата сравнения R18 и R22, а в зависимости от того, что делалось в прерывании. То есть - случайно. То есть - у микроконтроллера съезжает крыша и он делает совсем не то, что от него требовалось... Вообще-то возможен вариант, когда ничего сохранять не надо. Например, в прерывании вы выставляете флажок, сообщающий основной программе о том, что оно имело место быть, например: Timer0int:
Команда LDI биты признаков в SREG не меняет, изменение регистра FLAG вполне "законное" - следовательно, такой обработчик "правильный". Если же вы захотите установить только один бит регистра FLAGI, нужно SREG сохранять - так как команда SBR признаки меняет, являясь, по сути, командой ORI. В этом случае обработчик должен выглядеть так: Timer0int:
Тут следует заметить, что в весьма популярном среди начинающих микроконтроллере AT90s1200 стека нет (точнее, есть, но аппаратный - только для сохранения адреса возврата) и команд PUSH / POP, соответственно, тоже. В этом случае отведите один регистр только для сохранения в нем SREG, обработчик примет вид: Timer0int:
И в завершение совет использующим Algorithm Builder. Не забывайте, что регистры R16 и R17 используются в макрорасширениях, например, если вы используете команду
То генерируется следующая последовательность команд:
Следовательно, при достаточно сложном обработчике лучше не умничать, а сохранить эти регистры. Иначе потом, вставив одну команду, рискуете получить занимательный геморрой с поиском крайне трудноловимой ошибки. Не будете же вы каждый раз просматривать листинг (хотя - на мой взгляд - дело очень полезное!)
|
(с)nml 08-Dec-2006