реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> как сделать в Keil-ском C51 несколько прерываний с одного таймера?
Osti
сообщение Mar 2 2007, 14:54
Сообщение #1





Группа: Новичок
Сообщений: 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 ; разрешение повторных прерываний
Go to the top of the page
 
+Quote Post
gala
сообщение Mar 5 2007, 12:56
Сообщение #2


Частый гость
**

Группа: Свой
Сообщений: 119
Регистрация: 29-11-05
Из: Украина, Черкассы
Пользователь №: 11 564



Обычно хватает таймера 1кГц
Был случай необходимости 10кГц:
дла равномерности загрузки процессора основной цикл 1мс разбивался на примерно равновременные
модули с вызовом 0.1мс

В общем случае (мой личный подход smile.gif):
если требуется <0.1мс - использовать асинхронные прерывания
(м.б. даже внешний RS-триггер, хотя обычно достаточно стандартных Int 0,1)

Или вопрос о другом?
Go to the top of the page
 
+Quote Post
LMT
сообщение Mar 5 2007, 16:47
Сообщение #3


Участник
*

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



Я так понял, у автора что-то вроде иерархии периодических задач с разной длительностью спячки. Я обычно программирую таймер на наименьший квант времени, которому кратны периоды всех задач, а сами задачи разбиваю на конечные автоматы, состояние которых зависит от внешних событий и внутреннего счётчика квантов. Общий цикл блокируется на "привете" от обработчика таймера. По событию "кванта" каждая задача активируется по очереди. В итоге получается монстр biggrin.gif biggrin.gif , суть которого отражена в приведённом автором примере.
Go to the top of the page
 
+Quote Post
Osti
сообщение Mar 6 2007, 08:04
Сообщение #4





Группа: Новичок
Сообщений: 7
Регистрация: 12-07-06
Пользователь №: 18 771



Цитата(LMT @ Mar 5 2007, 18:47) *
Я так понял, у автора что-то вроде иерархии периодических задач с разной длительностью спячки. Я обычно программирую таймер на наименьший квант времени, которому кратны периоды всех задач, а сами задачи разбиваю на конечные автоматы, состояние которых зависит от внешних событий и внутреннего счётчика квантов. Общий цикл блокируется на "привете" от обработчика таймера. По событию "кванта" каждая задача активируется по очереди. В итоге получается монстр biggrin.gif biggrin.gif , суть которого отражена в приведённом автором примере.


Именно так, только я все не могу понять: у меня формально не цикл, а прерывание таймера в котором "натыкано" на разных уровнях иерархии разные задачи по длительности выполнения. Мне на вопрос и в других конфах, говорят о цикле в фоновой программе (main) которая запускает задачи по семафорам от обработчика таймера. НО в фоновой программе и своих задач хватает, точнее я там обычно размещаю задачи с непредсказумым временем выполнения, но требующих обработки, например - прием и передача на "хост" данных по последовательному каналу.
Go to the top of the page
 
+Quote Post
LMT
сообщение Mar 6 2007, 09:28
Сообщение #5


Участник
*

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



Ага, Вам нужна так называемая преемптивность, т.е. срочный и безусловный захват процессора по внешнему событию (в данном случае от таймера) задачей с наивысшим приоритетом. По моему в отсутсвие RTOS, которая Вам предоставила бы средства для этого, подход через обработчик самый естественный.

Цитата
у меня формально не цикл, а прерывание таймера в котором "натыкано" на разных уровнях иерархии разные задачи по длительности выполнения

Не, аппаратное прерывание оканчивается на "lcall Call_RetI".
Go to the top of the page
 
+Quote Post
Osti
сообщение Mar 6 2007, 11:20
Сообщение #6





Группа: Новичок
Сообщений: 7
Регистрация: 12-07-06
Пользователь №: 18 771



Цитата(LMT @ Mar 6 2007, 11:28) *
Ага, Вам нужна так называемая преемптивность, т.е. срочный и безусловный захват процессора по внешнему событию (в данном случае от таймера) задачей с наивысшим приоритетом. По моему в отсутсвие RTOS, которая Вам предоставила бы средства для этого, подход через обработчик самый естественный.

Теперь вопрос сначала: как это сделать на С? вставку ассемблерную - вызов LCALL RETI? Мне кажеться будут глюки связанные с сохранением контекста компилятором при входе в прерывание.


Цитата
Цитата


у меня формально не цикл, а прерывание таймера в котором "натыкано" на разных уровнях иерархии разные задачи по длительности выполнения

Не, аппаратное прерывание оканчивается на "lcall Call_RetI".


Это да, но возрат управления фоновой программе произойдет только при выходе.
Go to the top of the page
 
+Quote Post
LMT
сообщение Mar 6 2007, 13:05
Сообщение #7


Участник
*

Группа: Свой
Сообщений: 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);
}


По ассемблерному выходу понять, чего спасать надо, и принимать меры по ходу.
Go to the top of the page
 
+Quote Post
tag
сообщение Mar 7 2007, 11:45
Сообщение #8


Частый гость
**

Группа: Свой
Сообщений: 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 сек) в основном цикле программы через флаги... не имеет смысла городить все в одном обработчике прерывания
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 27th July 2025 - 17:29
Рейтинг@Mail.ru


Страница сгенерированна за 0.01408 секунд с 7
ELECTRONIX ©2004-2016