В каждом проекте приходится ручками прописывать имя_регистра/номер регистра, флаги/номера, переменные в памяти/адреса. При переносимости кусков все приходится переписывать. И не факт, что всегда без ошибок. Сколько раз попадался на том, что некорректно были заданы адреса в памяти, номера флагов. Было и такое, что на поиски ошибок уходило до нескольких дней.
Потерянное время никто вам не вернет. Его не повернуть вспять. И тем более обидно за потерянное время из-за мелочной ошибки.
Поэтому я старался и стараюсь максимально сократить время, затрачиваемое на создание проекта. Созданием макросов, шаблонов. Автоматически определяемые переменные.
С переменными в памяти я решил. Это просто, но пришлось помучиться при пробах. Шаблон:
main.asm:
;=========================================================================
.nolist
.include "mcudef.inc"
.list
;=========================================================================
;=========================================================================
.equ XTAL = 16000000
;=========================================================================
;=============== Функции и глобальные определения проекта ================
#define func(x) High(x), Low(x)
#define NO 0
#define YES 1
#define GLOBAL_TIMERS YES
;=========================================================================
;=========================================================================
;----------- List used register ------------------------------------------
; n/u - Not Used
; = r0 result mul
; = r1 result mul
; = r2 n/u
; = r3 n/u
.def RSREG = r4
.def RCLR = r5
.def RSER = r6
.def EEDREG = r7
; = r8 n/u
; = r9 n/u
; = r10 n/u
; = r11 n/u
; = r12 n/u
; = r13 n/u
; = r14 Used. Keyboard_Driver
; = r15 Used. Keyboard_Driver
;-------------------------------------------------------------------------
.def TEMP = r16
; = r17 Used. Everywhere
; = r18 n/u
; = r19 n/u
; = r20
.def FLAGS = r21
.def CNT = r22
.def STREG = r23 ; Set Task, Set Timer, FSM
.def DATA_L = r24 ; adiw/sbiw
.def DATA_H = r25 ; adiw/sbiw
; = r26 XL
; = r27 XH
; = r28 YL
; = r29 YH
; = r30 ZL
; = r31 ZH
;=========================================================================
;=========================================================================
.set NUM_FLG = -1
.macro Set_Flags
.set NUM_FLG = (NUM_FLG+1)
.equ @0 = NUM_FLG
.endmacro
;-------------------------------------------------------------------------
; Ôëàãè.
; FLAGS:
Set_Flags SYSTEM_TICK_FLG
Set_Flags TIME_OUT_FLG
Set_Flags KEYS_PRESSED_FLG
Set_Flags KEYS_HOLD_FLG
Set_Flags DEFINE_KEYS_FLG
Set_Flags KBD_MSG_FLG
;.equ SYSTEM_TICK_FLG = 0
;.equ TIME_OUT_FLG = 1
;.equ KEYS_PRESSED_FLG = 2
;.equ KEYS_HOLD_FLG = 3
;.equ DEFINE_KEYS_FLG = 4
;.equ KBD_MSG_FLG = 5
;=========================================================================
;=========================================================================
.include "vectors_atmega8535.inc"
.include "macros.inc"
.include "sram.inc"
.include "eeprom.inc"
.include "system_timer.inc"
#if (GLOBAL_TIMERS==YES)
.include "global_timers.inc"
#endif
.include "service_timers.inc"
.include "keyboard_driver_init.inc"
.include "types_keys.inc"
.include "keyboard_driver_def.inc"
.include "keyboard_driver_macros.inc"
.include "keyboard_driver.inc"
.include "process_errors.inc"
;=========================================================================
;=========================================================================
Initial:
;-------------------------------------------------------------------------
Check_WDRF:
in r16,MCUCSR
sbrs r16,WDRF
rjmp Init
cbr r16,1<<WDRF
sbi DDRC,0
out MCUCSR,r16
Empty_Cycle:
rjmp Empty_Cycle
Init:
;-------------------------------------------------------------------------
Init_Stack
;-------------------------------------------------------------------------
;-------------------------------------------------------------------------
clr RCLR
ser FLAGS
mov RSER,FLAGS
;-------------------------------------------------------------------------
;-------------------------------------------------------------------------
Clear_SRAM
;-------------------------------------------------------------------------
;-------------------------------------------------------------------------
Init_Timer2
;-------------------------------------------------------------------------
;-------------------------------------------------------------------------
sei
;-------------------------------------------------------------------------
;----------------------------- Отладка -----------------------------------
out PINA,RSER
;-------------------------------------------------------------------------
;-------------------------------------------------------------------------
Main:
rjmp Main
;=========================================================================
;=========================================================================
Empty_Action:
ret
;=========================================================================
Модули:
system_timer.inc:
;=========================================================================
;------------------- Âûáîð ðàçìåðà ñèñòåìíûõ òàéìåðîâ --------------------
#define SELECT_S_TIMERS_SIZE S_TIMERS_SMALL
#define S_TIMERS_SMALL 0
#define S_TIMERS_LONG 1
#define ST_SIZE ST_SMALL
#define ST_SMALL 2
#define ST_LONG 4
;-------------------------------------------------------------------------
;-------------------------------------------------------------------------
#define SYSTEM_TICK 1 ; Ïåðèîä ñèñòåìíîãî òàéìåðà 1 ìñ
#define SECOND SYSTEM_TICK*1000
#define MINUTE SECOND*60
#define HOUR MINUTE*60
#define DAY HOUR*24
;-------------------------------------------------------------------------
.dseg
;-------------- Ñïèñîê è îïðåäåëåíèÿ ñèñòåìíûõ òàéìåðîâ ------------------
.equ S_TIMERS_QUANTITY = 3 ; Êîëè÷åñòâî ñèñòåìíûõ òàéìåðîâ.
;--------------- Ñïèñîê è ðàçìåð ñèñòåìíûõ òàéìåðîâ ----------------------
.equ ST_ID_0 = 0
.equ ST_ID_1 = 1
.equ ST_ID_2 = 2
.set ST_PROCESS_KEYS = ST_ID_0
.set ST_PERIOD_REPEAT = ST_ID_1
;--------------------- Ôëàãè ñèñòåìíûõ òàéìåðîâ --------------------------
.equ ST_BLOCK_FLG = 0
.equ ST_TIME_OUT_FLG = 1
.equ ST_RERUN_FLG = 2
.equ ST_BLOCK = 1<<ST_BLOCK_FLG
.equ ST_TIME_OUT = 1<<ST_TIME_OUT_FLG
.equ ST_RERUN = 1<<ST_RERUN_FLG
;-------------------------------------------------------------------------
;------------------------- Ñèñòåìíûé òàéìåð ------------------------------
SYSTEM_TIMER:
SYSTEM_TIMER_0:
.byte 1
SYSTEM_TIMER_1:
.byte 1
#if (SELECT_S_TIMERS_SIZE==S_TIMERS_LONG)
SYSTEM_TIMER_2:
.byte 1
SYSTEM_TIMER_3:
.byte 1
#endif
;-------------------------------------------------------------------------
;-------------------- Î÷åðåäü ñèñòåìíûõ òàéìåðîâ ------------------------
S_TIMERS_QUEUE:
.byte S_TIMERS_QUANTITY*(ST_SIZE+1)
;-------------------------------------------------------------------------
.cseg
nop
nop
nop
ret
Осталось только с регистрами разобраться.