Чт ноя 24, 2022 19:40:12
Чт ноя 24, 2022 20:18:13
Чт ноя 24, 2022 22:19:25
Пт ноя 25, 2022 06:45:04
Пт ноя 25, 2022 08:36:14
.macro LMP
LPM
.endmacro
Пт ноя 25, 2022 10:53:22
//==================
.macro Proc_FSM
ldz @0*2
rjmp _Proc_FSM
.endmacro
_Proc_FSM:
lpm XH, Z+ ; Считывание старшего байта адреса состояния автомата.
lpm XL, Z+ ; Считывание младшего байта адреса состояния автомата.
ld r16, X ; Считывание состояния автомата.
lpm r17, Z+ ; Считывание количества состояний автомата.
cp r16, r17
brsh Process_Errors_FSM
lpm XH, Z+
lpm XL, Z
movw ZH:ZL, XH:XL
add ZL, r16
adc ZH, RCLR
shiftlwz
lpm r17, Z+
lpm r16, Z
movw ZH:ZL, r17:r16
ijmp
Process_Errors_FSM:
cli
adiw ZL, 2
lpm r16, Z
rjmp Proc_Errors
//==================
Proc_FSM Tab_FSM_KBD_DRV
//==================
Tab_FSM_KBD_DRV:
.db tab_h(_KEYS), MAX_FSM_KBD_DRV_STATES, tab_h(Tab_Jmp_KBD_DRV), ERR_ID_KBD_DRV
Tab_Jmp_KBD_DRV:
.equ MAX_FSM_KBD_DRV_STATES = 5 // Количество состояний автомата.
.equ _KEYS_INIT = 0
.db tab_h(Keys_Init)
.equ _KEYS_NONE = 1
.db tab_h(Keys_None)
.equ _KEYS_DOWN = 2
.db tab_h(Keys_Down)
.equ _KEYS_WAIT_UP = 3
.db tab_h(Keys_Wait_Up)
.equ _KEYS_UP = 4
.db tab_h(Keys_Up)
Пт ноя 25, 2022 14:15:12
;==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==
; Инициализация переменных
ldi r16, 0x0A ; Константа 10 для умножения
mov r10, r16
; Начальное состояние конечного автомата
ldi ZH, HIGH(FSM_st0)
ldi ZL, LOW (FSM_st0)
sei ; Разрешить прерывания
;==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==
; Основная программа
mainLoop: rjmp mainLoop
;==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==
; Обработка прерывания прихода символа по USART
USART_RXC: in r16, UDR ; Чтение пришедшего символа
out UDR, r16 ; Дублирования пришедшего символа назад
ijmp
;--~--~--~--~--~--~--~--~--~--~--~--~--~--~--~--~--~--~--~--~--~--~--~--~--~--~--~--~--
FSM_st0: ; Состояние 0: распознавание кода команды
cpi r16, 0x70 ; Символ 'p'
breq FSM_st0_0
cpi r16, 0x74 ; Символ 't'
breq FSM_st0_1
cpi r16, 0x50 ; Символ 'P'
breq FSM_st0_0
cpi r16, 0x54 ; Символ 'T'
breq FSM_st0_1
reti
FSM_st0_0: ; Переход в состояние 1
ldi ZH, HIGH(FSM_st1)
ldi ZL, LOW (FSM_st1)
reti
FSM_st0_1: clr r14 ; Инициализация коэффициента деления
clr r15
; Переход в состояние 2
ldi ZH, HIGH(FSM_st2)
ldi ZL, LOW (FSM_st2)
reti
;--~--~--~--~--~--~--~--~--~--~--~--~--~--~--~--~--~--~--~--~--~--~--~--~--~--~--~--~--
FSM_st1: ; Состояние 1: распознавание кода предделителя
subi r16, 0x30 ; Символ '0'
brcs FSM_st1_0
cpi r16, 0x06 ; Диапазон 0 -- 5
brcc FSM_st1_0
ori r16, 0x08
out TCCR1B, r16 ; Установка предделителя
; Переход в состояние 0
ldi ZH, HIGH(FSM_st0)
ldi ZL, LOW (FSM_st0)
FSM_st1_0: reti
;--~--~--~--~--~--~--~--~--~--~--~--~--~--~--~--~--~--~--~--~--~--~--~--~--~--~--~--~--
FSM_st2: ; Состояние 2: ввод коэффициента деления частоты
cpi r16, 0x20 ; Символ ' '
breq FSM_st2_0
cpi r16, 0x0D ; Символ перевода каретки
breq FSM_st2_0
; Ввод коэффициента деления частоты
subi r16, 0x30 ; Символ '0'
brcs FSM_st1_0
cpi r16, 0x0A ; Диапазон 0 -- 9
brcc FSM_st1_0
mul r15, r10 ; Умножение сохранённого значения на 10
mov r15, r0
mul r14, r10
mov r14, r0
add r14, r16 ; Добавление пришедшей цифры к результату
adc r15, r1
reti
FSM_st2_0: ; Установка таймера
out OCR1AH, r15
out OCR1AL, r14
; Переход в состояние 0
ldi ZH, HIGH(FSM_st0)
ldi ZL, LOW (FSM_st0)
reti
;==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==
Пт ноя 25, 2022 14:45:55
Пт ноя 25, 2022 14:54:10
Пт ноя 25, 2022 15:04:27
Пт ноя 25, 2022 15:06:11
Пт ноя 25, 2022 17:35:53
Пт ноя 25, 2022 17:51:42
wait_timer:
rjmp wait_timer ; ожидаем прерывания таймера
Пт ноя 25, 2022 18:27:39
Пт ноя 25, 2022 19:45:59
Пт ноя 25, 2022 22:58:08
Сб ноя 26, 2022 08:51:09
Сб ноя 26, 2022 08:57:05
Сб ноя 26, 2022 10:40:22
Сб ноя 26, 2022 10:52:02
;---------- Таблица переходов
STATES:
.dw STATE_0, STATE_1, STATE_2
STATE_0:
ldi temp0, 0x01 ;Переключаем на следующее состояние
ret
STATE_1:
ldi temp0, 0x02 ;Переключаем на следующее состояние
ret
STATE_2:
ldi temp0, 0x00 ;Переключаем на начальное состояние
ret
; Много телодвижений связано с тем, что в конкретном МК LPM и IJMP или ICALL работают только с парой Z
; Сначала грузим номер текущего состояния из ОЗУ в регистры temp0 и temp1
; За тем выполняем код ниже:
ldi ZL, Low(STATES*2) ; Грузим начальный адрес массива указателей на процедуры
ldi ZH, High(STATES*2)
lsl temp0 ; В регистрах temp0 и temp1 хранится номер текущего состояния. temp0 - младший байт
clr temp1 ; , temp1 - старший. Но тут он не используется, так как состояний не так много было
add ZL, temp0 ;Смещаемся по массиву для выбора нужного указателя
adc ZH, temp1
lpm temp2, Z ; Грузим младший байт адреса
adiw Z, 0x01 ; Смещаемся к старшему байту адрса
lpm temp3, Z ; Грузим старший байт адреса
mov ZL, temp2 ; Заносим байты алреса процедуры в Z
mov ZH, temp3
icall ; Вызываем процедуру
; Тут можем сохранить номер состояния в ОЗУ
Смысл в дополнительной таблице векторов? Лишний расход ПЗУ?