Цитата(aaarrr @ May 17 2011, 20:19)

Ну, хоть бы пример привели, а то так не интересно.
Могу и пример, но только с тем же 51-м.
Вот тот же UART.
У нас есть сложный протокол по RS-485 где сидит много устройств. Протокол примерно такой.
1-й байт - номер устройства. Если номер наш, то обрабатываем дальше, иначе игнорируем всю посылку.
2-й байт номер протокола тут идут варианты. В зависимости от протокола мы либо принимаем, либо передаем, и количество байт разное. Но реакция должна быть мгновенной, т.е. обрабатывать мы должны на лету, это задано в ТЗ.
Если всю эту хрень делать без прерываний по ожиданию приема/передачи, программа получается простой. Принимаем-сравниваем-переходим на нужную метку.
Примерно так
MOV A,SBUF
M1: CJNE A,#1, M2
;обработка протокола 1
JMP BEGIN
M2: CJNE A,#2, M3
;обработка протокола 2
JMP BEGIN
.... и.т.д.
Но так нельзя - программа только и делает что висит-ждет очередной байт.
А вот по прерываниям простота заканчивается. По любому приему происходит переход на один и тот же адрес обработчика и дальше надо заводить кучу дополнительных флагов чтоб помнить текущую фазу протокола, и оборачивается это кучей запутанных ветвлений.
Вот здесь положение спасает переход по определенному адресу. После обработки очередного байта, мы заносим в переменную адрес следующего обработчика и при следующем прерывании прыгаем сразу в эту точку.
При таком методе программа получается намного проще, а реакция на обработку быстрее.
Поэтому лично я давно делаю обработку UARTа именно так.
Другой более простой случай. Надо дождаться на пине например 1, и тут же среагировать на это. Если в лоб ждать то будет так:
WAIT: JNB P1.0,WAIT
; обработка события
Но тогда цикл может висеть бесконечно долго, нужен выход по таймауту. Обычный метод - ввести в цикл счетчик, его инкрементировать, сравнивать и добавить дополнительный переход. Но цикл многократно удлинится, а с ним и время реакции.
Выход - оставить цикл без счетчика, а ввести таймерное прерывание с возвратом на TIMEOUT:
WAIT: JNB P1.0,WAIT
; обработка события
TIMEOUT:
; идем дальше
Здесь немного другой случай, адресный переход идет не на обработку прерывания, а после возврата, но суть та же.
А еще таким методом можно организовать многозадачность повесив на таймер такой обработчик, чтоб он запоминал адрес предыдущего вызова, а возвращал на адрес следующей, и так перебирал все задачи по кругу.
Цитата(AHTOXA @ May 17 2011, 21:11)

В контроллерах семейства 8051 это делалось для того, чтобы изобразить "вложенные прерывания". В кортексах вложенные прерывания есть изначально, и так извращаться не требуется. То есть, ваш вариант "в определенный момент выйти из прерывания (UART) в требуемую точку, а уж оттуда потом продолжить выполнения с места, где возникло прерывание" практически полностью эквивалентен варианту "в конце прерывания вызвать нужную функцию".
Вовсе нет. Во-первых в 51-х можно сделать вложенное прерывание. Во-вторых как я описал выше, вложенность тут ни при чем