ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Воскресенье
30 июня
269300
mazur (28.08.2011 22:02 - 30.08.2011 18:30, просмотров: 6478)
Может, вы сочтете это бредом и начнете опять гонять меня поганой метлой за ассемблер, но я все равно решил это выложить. Может кому пригодится. Итак, Switch-Case технология мне не понравилась сразу. Если состояний автомата много, то код просто неприлично раздувается. Тогда на помощь приходит индексный переход. Насколько я слышал, компиляторы это и делают при оптимизации. Накидывая в очередной раз что-то вроде этого: FSM: ldiy _KEYS_FLAGS ldd FLAGS,Y+DISP_KEYS_FLAGS clr ZH ldd ZL,Y+DISP_KEYS cpi ZL,_QUANT_KEYS_STATES brsh Process_Errors_KBD_DRV subi ZL,LOW(-Table_KBD_DRV) sbci ZH,HIGH(-Table_KBD_DRV) shiftlwz lpm r17,Z+ lpm r16,Z movw ZH:ZL,r17:r16 icall std Y+DISP_KEYS_FLAGS,FLAGS ret Process_Errors_KBD_DRV: cli ldi r16,_ERROR_KBD_DRV rjmp Process_Errors Table_KBD_DRV: .db tab_h(Keys_Init) .db tab_h(Keys_None) .db tab_h(Keys_Down) .db tab_h(Keys_Wait_Up) .db tab_h(Keys_Up) Я подумал, может преврать это в макрос или в подпрограмму? Но недавно я вспомнил, как ReAl подсказал использовать ldd\std вместо lds\sts. Прикинул и накидал один обработчик автоматов вместо нескольких. На первый взгляд, выигрыш слабый, но, заменяются все куски кода "Process_Errors_KBD_DRV" на один "Process_Errors_FSM". И все подпрограммы индексного перехода объединяются в одну подпрограмму. А если автоматов много, то выигрыш очень существенный. Во всяком случае, лично я увидел в этом смысл. .dseg ;================================================================================================== _PROC_FSM: ; Состояние автомата. .byte 1 _QUANT_STATES_FSM: ; Количество состояний автомата. .byte 1 _TABLE_FSM_H: ; Таблица обработчиков состояний автомата. .byte 1 _TABLE_FSM_L: ; Таблица обработчиков состояний автомата. .byte 1 _ERROR_FSM: ; Номер ошибки автомата. .byte 1 ;================================================================================================== .cseg ;================================================================================================== .macro Init_FSM ldix _PROC_FSM lds r16,@0 ; Состояние автомата. st X+,r16 ldiz @1*2 ldi CNT,4 rcall _Init_FSM .endmacro _Init_FSM: lpm r16,Z+ st X+,r16 dec CNT brne _Init_FSM sbiw XL,5 ret ;================================================================================================== Process_FSM: clr ZH ld ZL,X+ ld r16,X+ cp ZL,r16 brsh Process_Errors_FSM ld r17,X+ ld r16,X+ add ZL,r16 adc ZH,r17 shiftlwz lpm r17,Z+ lpm r16,Z movw ZH:ZL,r17:r16 ijmp Process_Errors_FSM: cli adiw XL,2 ld r16,X rjmp Process_Errors ; Пример: .include "fsm.inc" .include "kbd_drv.inc" Def_Num_Err _ERROR_KBD_DRV Def_Num_Err _ERROR_KEYS .equ DEBOUNC_DELAY = 20 .dseg _KEYS_FLAGS: .byte 1 .equ KEYS_PRESSED_FLG = 0 .equ DEFINE_KEYS_FLG = 1 _KEYS: .byte 1 .equ _QUANT_KEYS_STATES = 5 .equ _KEYS_INIT = 0 .equ _KEYS_NONE = 1 .equ _KEYS_DOWN = 2 .equ _KEYS_WAIT_UP = 3 .equ _KEYS_UP = 4 _KEYS_PREV: .byte 1 _KEYS_CURRENT: .byte 1 _KEYS_CODE: .byte 1 .equ DISP_KEYS_FLAGS = 0 .equ DISP_KEYS = 1 .equ DISP_KEYS_PREV = 2 .equ DISP_KEYS_CURRENT = 3 .equ DISP_KEYS_CODE = 4 .cseg KBD_DRV: Scan_Keys Init_FSM _KEYS,Table_KBD_DRV_FSM rcall Process_FSM sbrc FLAGS,DEFINE_KEYS_FLG rcall Define_Keys std Y+DISP_KEYS_FLAGS,FLAGS ret Keys_Init: Init_KBD_DRV Set_State _KEYS,_KEYS_NONE Keys_None: Set_State _KEYS,_KEYS_DOWN Keys_NONE_End: ret Keys_DOWN: Set_State _KEYS,_KEYS_WAIT_UP ret Keys_Not_DOWN: Set_State _KEYS,_KEYS_NONE Keys_DOWN_End: ret Keys_WAIT_UP: Set_State _KEYS,_KEYS_UP Keys_WAIT_UP_END: ret Keys_UP: Set_State _KEYS,_KEYS_NONE ret Keys_Not_UP: Set_State _KEYS,_KEYS_WAIT_UP Keys_UP_End: ret Table_KBD_DRV_FSM: .db _QUANT_KEYS_STATES,tab_h(Table_KBD_DRV),_ERROR_KBD_DRV Table_KBD_DRV: .db tab_h(Keys_Init) .db tab_h(Keys_None) .db tab_h(Keys_Down) .db tab_h(Keys_Wait_Up) .db tab_h(Keys_Up) Table_Keys_Code: .db 0b00000001, 0 .db 0b00000010, 1 .db 0b00000100, 2 .db 0b00001000, 3 .db 0b00010000, 4 .db 0b00100000, 5 .db 0b01000000, 6 .db 0b10000000, 7 Table_Proc_Codes_Keys_FSM: .db _QUANT_KEYS_CODE,tab_h(Table_Proc_Codes_Keys),_ERROR_KEYS Table_Proc_Codes_Keys: .db tab_h(Process_Enter) .db tab_h(Process_Ecs) .db tab_h(Process_Up) .db tab_h(Process_Down) .db tab_h(Process_Plus) .db tab_h(Process_Minus)