Странно это слышать от вас. Да запросто это сделать в программе Main Loop. Стараюсь писать свои программы без долгих зацикливаний. Потихоньку перетаскиваю этот принцип на си. К примеру ваш пример. С дисплеем. https://www.youtube.com/watch?v=F2SZjORyGD8
Main:
wdr
rcall Service_Timers
rcall Drv_Lcd
rcall KBD_DRV
rcall Proc_Menu
rjmp Main
Простой цикл подпрограмм. Что такое Service_Timers? Это обработка программных таймеров, где шаг установки таймера 1 мс (можно взять шаг 10, 100 мс), неточность плюс-минус несколько мкс тут уже абсолютно некритична. Макрос установки Set_Timer, макрос проверки Proc_Timer. В прерывании каждые 1 мс устанавливается флаг SYS_TICK_FLG. В Service_Timers проверяется этот флаг. Сброшен флаг, выход. Установлен флаг, пробежка по всем таймерам, инкремент каждого установленного таймера. Если время вышло, установка флага TIME_OUT_FLG. В подпрограммах, где используются программные таймеры, происходит следующим образом:
Взято из старого проекта на асме.
Drv_Lcd:
sbrc FSM_FLAGS, DRV_LCD_RUN_FLG
rjmp DRV_LCD_Run
Drv_Lcd_Init:
setb FSM_FLAGS, DRV_LCD_RUN_FLG
Set_Timer Par_Tim_Drv_Lcd // Установка таймера. Ниже параметры таймера в памяти программ.
Drv_Lcd_Run:
Proc_Timer Par_Tim_Drv_Lcd // Проверка таймера.
brtc Drv_Lcd_Run_End // Если время не вышло, переход на Drv_Lcd_Run_End.
sbrs FSM_FLAGS, SEND_CHAR_FLG
rjmp DRV_LCD_Send_Addr
Drv_Lcd_Send_Char:
rjmp Drv_Lcd_Run_End
Drv_Lcd_Send_Addr:
setb FSM_FLAGS, SEND_CHAR_FLG
Drv_Lcd_Run_End:
ret
//-------------------------------------------------------------------
//-------------------------------------------------------------------
Par_Tim_Drv_Lcd:
par_timer ST_DRV_LCD, 1<<ST_UNLOCK_FLG, DRV_LCD_TIME
//===================================================================
Пример на автомате:
Proc_FSM_Heater:
Proc_FSM Table_FSM_Proc_Heat
//------------------------------------------------------------------------
Proc_Heat_Init_1: // Инициализация портов ввода-вывода.
cbi RED_LED_PORT, RED_LED
sbi RED_LED_DDR, RED_LED
cbi GREEN_LED_PORT, GREEN_LED
sbi GREEN_LED_DDR, GREEN_LED
cbi PLUG_PORT, PLUG
sbi PLUG_DDR, PLUG
Set_Timer Par_Timer_Proc_Heat_Init
Set_State _PROC_HEAT_INIT_2
ret
Proc_Heat_Init_2: // Ожидание завершения задержки.
Proc_Timer Par_Timer_Proc_Heat_Init
brtc Proc_Heat_Init_2_End
setb FSM_FLAGS, PROC_HEAT_RUN_FLG // Установка флага, признака, что модуль готов к работе.
Set_State _PROC_HEAT_WAIT_ON
Proc_Heat_Init_2_End:
ret
Proc_Heat_Init_Blow_1: // Инициализация режима продувки.
rcall Switch_Off_Proc_Heat_Err // Отключение модуля индикации ошибок.
rcall Set_Fan_Speed_Blow_1 // Установка скорости вентилятора.
plug_on // Включение свечи накаливания.
set_fan_on // Установка модуля управления вентилятором на разгон.
led_mode_blow // Индикация режима продувки.
Set_Timer Par_Timer_Blow_1
ret
Proc_Heat_Blow_1:
Proc_Timer Par_Timer_Blow_1
brtc Proc_Heat_Blow_1_End
Set_State _PROC_HEAT_SET_WAIT_FIRE_SENS
Proc_Heat_Blow_1_End:
ret
Proc_Heat_Set_Wait_Fire_Sens:
rcall set_pump_on // Включение модуля насоса.
Set_Timer Par_Timer_Fire_Sens
Set_State _PROC_HEAT_WAIT_FIRE_SENS
ret
Как видите, в подпрограммах нет долгих зацикливаний. В том проекте шаг 1 мс. Соответственно, время обработки всех подпрограмм, при любых ветвлениях, в цикле не должно превышать 1 мс. Так что спокойно ставьте задержки хоть "таймаут в один год", и делайте спокойно свои дела в других подпрограммах.
Видео-пример по ссылке. Рыскание символа это проверка дисплея при быстрых изменениях на экране.
-
- А если, к примеру, у вас Proc_Heat_Init_2 ожидания не дождется ("один год"), то у вас вся Main loop от этого в пробку встанет? - Ксения(25.07.2013 13:23)
- Вы про программный косяк или как работает Proc_Timer? Или про то, что RTOS по времянке или завершению задачи переключится на другую? mazur(838 знак., 25.07.2013 15:22 - 15:35)
- А если, к примеру, у вас Proc_Heat_Init_2 ожидания не дождется ("один год"), то у вас вся Main loop от этого в пробку встанет? - Ксения(25.07.2013 13:23)