shads писал(а):Причем мой любимый метод настроить одно прерывание например 10кгц (обрабатываются скоростные процедуры, как например 1wire, обработка радиообмена, и т.д.)
Ну так я делал на старых классических 51-ых, где катастрофически не хватало таймеров.
Одна оставшаяся свободной половинка давала прерывание раз в 256 циклов процессора и от него всё плясало. Кстати, одна из программ дожила до где-то семи тысяч строк на С плюс около трёх на асме. Это было последнее, что я на 51-ых делал.
Все прерывания были на асме для скорости.
Часть обработки на асме для компактности не сильно в ущерб скорости (там практически прямой шитый код был). Если бы не то, что поначалу был зажат 16-килобайтным ПЗУ, то этого и не делал бы. Но потом все равно не влезло, в итоге в 32 килобайтах было занято 25. Не думаю, что на чистом асме назад в 16 К влез бы, там одних знакогенератора и текстовых строк было килобайт 8, а 17 килобайт из-под С в 8 килобайт на асме всё равно не влезли бы.
В таких случаях программа на С общается с прерываниями через буфера и флаги запуска действия и готовности выполнения. Не забывать такие флаги на С квалифицировать как volatile, иногда и буфера желательно.
Но сейчас вроде ж с таймерами полегче, нет нужды вешать всё на один (точнее, на одно прерывание от него).
Ну например, у нас есть кварц 7.3728 и 8-битный таймер с каналами сравнения.
Ставим таймеру прескалер 64.
Переполнение таймера получаем 7372800/64/256 = 450 герц, для той же динамической индикации. Ну и там уже не жалко времени на доделиватели для 10 мс и 1 сек программных таймеров для «просто службы времени».
Теперь один из каналов сравнения настраиваем на прерывание по сравнению и в прерывании передвигаем точку сравнения в будущее, причём как опора не текущее состояние таймера, а предыдущее значение регистра сравнения, тогда сетка будет равномернее, ошибка не будет накапливаться.
Код: Выделить всё
...
; // OCR0A += 12;
in r16, OCR0A
subi r16, -12
out OCR0A, r16
Получим прерывание 7372800/64/12 = 9600 Гц, это программный UART, передача.
Приём аналогично, только по прерыванию по спаду стартового бита в OCR0B заносим значение TCNT0 с отступом вперёд на пол или полтора бита (в зависимости от того, будем ли ловить ошибку старт-бита) и некоторой коррекцией на задержку обработки этого прерывания от спада.
Если прерывание от спада далать по input capture, то тогда легче, просто OCR1B = ICR1 + (в зависимости от длины бита и задачи).
Таким образом для обслуживания soft-UART занято аж три прерывания, два из которых работают с одним автоматом (машиной состояний) на приём. Но зато они возникают только тогда, когда они нужны.
По завершению передачи прерывание TX OCR0A просто запрещается (в конце отработки стопового бита — если в буфере передачи нет других байтов). Пока не приёл стартовый бит на приём, OCR0B тоже запрещено.
Если это вешать на один таймер, то надо было бы хотя бы на 28.8 килогерца проверять состояние входной линии RX, не пришёл ли стартовый бит. И прерывание лупило бы постоянно, даже когда никто ничего не присылает.
Конечно, можо и такую методику облегчения нагрузки и всё на асме писать, но если оно надо. А нагружать все в одно прерывание с тем, чтобы оно часть работы каждый раз делало впустую (а иначе нельзя, пропустит) — какой смысл?
После расталкивания по разным прерываниям уже можно решить, кто может подождать и в начале тех прерываний разрешать вложенные.
Иногда это и не нужно, так как каждое прерывание получается довольно простое, С-компилятор не сохраняет/восстанавливает по полтора десятка регистров, чо благотворно сказывается на времени обработки.
Иногда это невозможно -- в одной из небольших (около 8 килобайт вместе с printf, это С++ с шаблонами для размножения обработчиков прерываний из одного шаблона) программ на меге64 у меня все шесть OCR от 16-битных таймеров и еще 6 внешних прерываний задействованы. Плюс UART на компьютер, еще два прерывания, итого 14. Так и немного

Это был 6-канальный приёмник чего-то LIN-подобного с настройкой частоты по первому байту пакета. Все 6 каналов равноправны, выделять какой-то один и в остальных разрешать вложенные прерывания просто нет смысла.
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.