|
|
  |
как сделать в Keil-ском C51 несколько прерываний с одного таймера? |
|
|
|
Mar 2 2007, 14:54
|
Группа: Новичок
Сообщений: 7
Регистрация: 12-07-06
Пользователь №: 18 771

|
можно ли как-то просто организовать в Keil-ском C51 прерывания по таймеру с одного таймера: 0,5мсек для вызова п/программ с временем выполнения < 0,5 мсек, 50 мсек - для п/п < 50 мсек 1 сек - для п/п < 1 сек Чтобы обеспечить их паралельное выполнение.
Раньше было что-то такое
Hand_Timer3:
; проверки повторности вхождения, стека, ; сбросы флагов прерываний, watchdog-а, ; проталкивание в стек регистров lcall Call_RetI ; разрешение новых прерываний
; ввод данных с АЦП, счетных (внешних импульсов) входов в буфер ; управление выходами с точностью 0,5 мсек (например ; фазовое управление тиристорами) ; отсчет задержек в 0,5 мсек
inc c50msec CJNE c50msec,#100,End_Interrupt ; 50 мсек mov c50msec,#0
; проверка повторного вхождения на этот уровень ; первичная обработка введенных данных (фильтрация), управление ; медленными устройствами (модуляция ЖКИ, пускатели), ; обработка дребезга кнопок и тому подобное ; вычисления управляющих воздействий регуляторов (ПИ,ПИД) ; отсчет задержек в 50 мсек
inc cSecond CJNE cSecond,#20,End_Interrupt ; 1 sec mov cSecond,#0 ; ; проверка повторного вхождения на этот уровень ; отсчет времени, отсчет задержек в секундах
End_Interrupt:
; восстановление регистров из стека
ret
Call_RetI: RetI ; разрешение повторных прерываний
|
|
|
|
|
Mar 5 2007, 12:56
|
Частый гость
 
Группа: Свой
Сообщений: 119
Регистрация: 29-11-05
Из: Украина, Черкассы
Пользователь №: 11 564

|
Обычно хватает таймера 1кГц Был случай необходимости 10кГц: дла равномерности загрузки процессора основной цикл 1мс разбивался на примерно равновременные модули с вызовом 0.1мс В общем случае (мой личный подход  ): если требуется <0.1мс - использовать асинхронные прерывания (м.б. даже внешний RS-триггер, хотя обычно достаточно стандартных Int 0,1) Или вопрос о другом?
|
|
|
|
|
Mar 6 2007, 08:04
|
Группа: Новичок
Сообщений: 7
Регистрация: 12-07-06
Пользователь №: 18 771

|
Цитата(LMT @ Mar 5 2007, 18:47)  Я так понял, у автора что-то вроде иерархии периодических задач с разной длительностью спячки. Я обычно программирую таймер на наименьший квант времени, которому кратны периоды всех задач, а сами задачи разбиваю на конечные автоматы, состояние которых зависит от внешних событий и внутреннего счётчика квантов. Общий цикл блокируется на "привете" от обработчика таймера. По событию "кванта" каждая задача активируется по очереди. В итоге получается монстр  , суть которого отражена в приведённом автором примере. Именно так, только я все не могу понять: у меня формально не цикл, а прерывание таймера в котором "натыкано" на разных уровнях иерархии разные задачи по длительности выполнения. Мне на вопрос и в других конфах, говорят о цикле в фоновой программе (main) которая запускает задачи по семафорам от обработчика таймера. НО в фоновой программе и своих задач хватает, точнее я там обычно размещаю задачи с непредсказумым временем выполнения, но требующих обработки, например - прием и передача на "хост" данных по последовательному каналу.
|
|
|
|
|
Mar 6 2007, 09:28
|
Участник

Группа: Свой
Сообщений: 54
Регистрация: 22-02-07
Пользователь №: 25 599

|
Ага, Вам нужна так называемая преемптивность, т.е. срочный и безусловный захват процессора по внешнему событию (в данном случае от таймера) задачей с наивысшим приоритетом. По моему в отсутсвие RTOS, которая Вам предоставила бы средства для этого, подход через обработчик самый естественный. Цитата у меня формально не цикл, а прерывание таймера в котором "натыкано" на разных уровнях иерархии разные задачи по длительности выполнения Не, аппаратное прерывание оканчивается на "lcall Call_RetI".
|
|
|
|
|
Mar 6 2007, 11:20
|
Группа: Новичок
Сообщений: 7
Регистрация: 12-07-06
Пользователь №: 18 771

|
Цитата(LMT @ Mar 6 2007, 11:28)  Ага, Вам нужна так называемая преемптивность, т.е. срочный и безусловный захват процессора по внешнему событию (в данном случае от таймера) задачей с наивысшим приоритетом. По моему в отсутсвие RTOS, которая Вам предоставила бы средства для этого, подход через обработчик самый естественный. Теперь вопрос сначала: как это сделать на С? вставку ассемблерную - вызов LCALL RETI? Мне кажеться будут глюки связанные с сохранением контекста компилятором при входе в прерывание. Цитата Цитата
у меня формально не цикл, а прерывание таймера в котором "натыкано" на разных уровнях иерархии разные задачи по длительности выполнения
Не, аппаратное прерывание оканчивается на "lcall Call_RetI". Это да, но возрат управления фоновой программе произойдет только при выходе.
|
|
|
|
|
Mar 6 2007, 13:05
|
Участник

Группа: Свой
Сообщений: 54
Регистрация: 22-02-07
Пользователь №: 25 599

|
Также, наверное: Код #pragma src
int raddr; char Counter = 0; // Dummy var
void Hello(void) { // Do something ++ Counter; #pragma asm ; Restore context here #pragma endasm }
void falarm (void) interrupt 1 using 3 { #pragma asm push raddr + 1 push raddr reti #pragma endasm }
void main(void) { raddr = (int)Hello; while(1); } По ассемблерному выходу понять, чего спасать надо, и принимать меры по ходу.
|
|
|
|
|
Mar 7 2007, 11:45
|
Частый гость
 
Группа: Свой
Сообщений: 151
Регистрация: 21-02-06
Пользователь №: 14 561

|
Цитата(Osti @ Mar 2 2007, 14:54)  можно ли как-то просто организовать в Keil-ском C51 прерывания по таймеру с одного таймера: 0,5мсек для вызова п/программ с временем выполнения < 0,5 мсек, 50 мсек - для п/п < 50 мсек 1 сек - для п/п < 1 сек Чтобы обеспечить их паралельное выполнение. ...я бы подпрограммы с периодом < 0,5 мсек вызывал в обработчике прерывания (при условии что подпрограммы достаточно короткие), а остальные (50 мсек и 1 сек) в основном цикле программы через флаги... не имеет смысла городить все в одном обработчике прерывания
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|