Код: Выделить всё
Save2:
Cpi R27, SER2
Brne Save2
Cpi R26, SER1
Brne Save2
Cpi R25, SER0
Brne Save2
Cpi R28, BUT
Brne Save2Код: Выделить всё
Save2:
Cpi R27, SER2
Brne Save2
Cpi R26, SER1
Brne Save2
Cpi R25, SER0
Brne Save2
Cpi R28, BUT
Brne Save2Код: Выделить всё
Save: ; Циклический буфер, последний принятый бит = последнему биту в массиве
Rol R28 ; BUT1
Rol R27 ; SER3
Rol R26 ; SER2
Rol R25 ; SER1
Rol R24 ; HOP4
Rol R23 ; HOP3
Rol R22 ; HOP2
Rol R21 ; HOP1
Bld R28,0 ; Записать текущий бит
Clc ; Снять флаг переноса
Inc Size ; Плюс один бит
Cpi Size, 64 ; Приняли весь пакет?
Brne SaveQuit ; Нет, выйти
; А тут мы приняли все 64 бита!
Clr Temp ; Очистить переменную адреса, она у нас Temp
Mov Time, R21 ; Скопировать в R17(она по совместительству Time) R21
Rcall SaveByte ; Сохранить байт в EEPROM!
Inc Temp ; И так для всех 64 бит или 8 байт
Mov Time, R22
Rcall SaveByte
Inc Temp
Mov Time, R23
Rcall SaveByte
Inc Temp
Mov Time, R24
Rcall SaveByte
Inc Temp
Mov Time, R25
Rcall SaveByte
Inc Temp
Mov Time, R26
Rcall SaveByte
Inc Temp
Mov Time, R27
Rcall SaveByte
Inc Temp
Mov Time, R28
Rcall SaveByte
Save2:
Cpi R27, SER2
Brne Save2
Cpi R26, SER1
Brne Save2
Cpi R25, SER0
Brne Save2
Cpi R28, BUT
Brne Save2
тут уже не работает у меня код ----------------------------------
Sbi DDRB, LED ; LED - на вывод
Sbi PORTB, LED ; Зажечь зеленый светодиод!
Do: Rjmp Do ; И больше ничего не делать, до нажатия кнопки сброса
SaveQuit:
Reti
Дак вот не моя программа то пытаюсь вникнуть и модифицировать под свои нужды.DX168B писал(а):Метод с массивами хорош тем, что так можно сравнить любое количество значений. Будь то 4 значения или 255 значений. Ну и используются для этого всего 3 регистра РОН (не считая регистровых пар Y и Z)
И ещё, Ваш код можно (вернее, нужно!) оптимизировать. Опять же, вместо километра одинаковых действий, можно сделать всего один цикл с адресацией через регистровые пары (это последние 6 регистров РОН) Старайтесь использовать ОЗУ а не рабочие регистры.
Код: Выделить всё
.Equ SER0=0xCC
.Equ SER1=0x87
.Equ SER2=0x7F
.Equ BUT=0x9B
.dseg
buffer: .byte 4
; ...
.cseg
; ...
; Где-то в основной программе
ldi YL, low(buffer) ; загружаем адрес сравниваемой переменной
ldi YH, high(buffer)
rcall compare ; вызываем функцию сравнения.
.db SER0, SER1, SER2, BUT ; Это второй параметр-константа функции сравнения
breq on_led ; Если числа равны, то включаем светодиод
; ...
; где-то ниже
; функция сравнения 4-байтного числа
; в Y хранится адрес сравниваемого числа в ОЗУ
compare:
pop ZH ; грузим адрес константы во FLASH
pop ZL
clc ; сбрасываем флаг переноса
rcall compareByte ; сравниваем 4 байта
rcall compareByte
rcall compareByte
rcall compareByte
ijmp ; Z теперь указывает на следующую команду. На неё и переходим.
compareByte:
ld R0, Y+
lpm R1, Z+
cpc R0, R1
ret
Вот тут немного неточно - надо перейти сначала от слов к байтам и потом вернуться назад. Поскольку тут всегда чётное количество байтов после вызова, возвращаться можно без округления вверх.IfoR писал(а):Код: Выделить всё
; в Y хранится адрес сравниваемого числа в ОЗУ compare: pop ZH ; грузим адрес константы во FLASH pop ZL clc ; сбрасываем флаг переноса rcall compareByte ; сравниваем 4 байта rcall compareByte rcall compareByte rcall compareByte ijmp ; Z теперь указывает на следующую команду. На неё и переходим.
Код: Выделить всё
; в Y хранится адрес сравниваемого числа в ОЗУ
compare:
pop ZH ; грузим адрес константы во FLASH
pop ZL
lsl ZL ;; Переходим от слов к байтам
rol ZH
clc ; сбрасываем флаг переноса
rcall compareByte ; сравниваем 4 байта
rcall compareByte
rcall compareByte
rcall compareByte
lsr ZH ;; Переходим от байтов к словам
rol ZL
ijmp ; Z теперь указывает на следующую команду. На неё и переходим.
Код: Выделить всё
. . .
rcall compareByte ; сравниваем 4 байта
rcall compareByte
rcall compareByte
rcall compareByte
ijmp
. . .
compareByte:
ld R0, Y+
lpm R1, Z+
cpc R0, R1
retКод: Выделить всё
. . .
rcall compareByte_4 ; сравниваем 4 байта
ijmp
. . .
compareByte_4:
rcall compareByte_2
compareByte_2:
rcall compareByte
compareByte:
ld R0, Y+ //*
lpm R1, Z+ //*
cpc R0, R1 //*
retКод: Выделить всё
rcall compareByte_8
rcall comapreByte_2Код: Выделить всё
clc ; сбрасываем флаг переносаа если оформить в виде макроса, то совсем хорошо будетavreal писал(а):зато ещё немного короче
Код: Выделить всё
.macro compare4byte; формат: compare4byte ramaddr, const
ldi YL, low(@0) ; загружаем адрес сравниваемой переменной
ldi YH, high(@0)
rcall compare ; вызываем функцию сравнения.
.dd @1 ; Это второй параметр-константа функции сравнения
.endmКод: Выделить всё
.dseg
var1: .byte 4
.cseg
compare4byte var1, 0x12345678Код: Выделить всё
.macro cpsli; формат: cpsli ramaddr, const
ldi YL, low(@0) ; загружаем адрес сравниваемой переменной
ldi YH, high(@0)
rcall compare ; вызываем функцию сравнения.
.dd @1 ; Это второй параметр-константа функции сравнения
.endm
.Equ SER0=0xCC
.Equ SER1=0x87
.Equ SER2=0x7F
.Equ BUT=0x9B
.dseg
buffer: .byte 4
; ...
.cseg
; ...
; Где-то в основной программе
cpsli buffer, (SER0<<24) | (SER1<<16) | (SER2<<8) | BUT
breq on_led ; Если числа равны, то включаем светодиод
; ...
; где-то ниже
; функция сравнения 4-байтного числа
; в Y хранится адрес сравниваемого числа в ОЗУ
compare:
pop ZH ; грузим адрес константы во FLASH
pop ZL
adiw Z, 2 ; перепрыгиваем через 2 байта
push ZL ; грузим адрес следующей команды
push ZH
sbiw Z, 2
lsl ZL ;; Переходим от слов к байтам
rol ZH
rcall compareByte2 ; сравниваем 4 байта
compareByte2:
rcall compareByte
compareByte:
ld R0, Y+
lpm R1, Z+
cpc R0, R1
ret ; этот ret многое значит...
А-а-а!!! Точно!IfoR писал(а):Ахтунг! Подстава! Команды сдвига в конце сбрасывает SREG! Все труды функции насмарку!![]()
![]()
Зато можно сделать LD R0,-YIfoR писал(а):Кстати, все заметили, что для правильной работы функции при количественном сравнении значений, все значения нужно хранить в обратном порядке байт (в памяти сначала идут младшие байты)?
Эх... Если бы можно было бы сделать "lpm R1, -Z", то можно было бы безболезненно переписать функцию под
Код: Выделить всё
ld R0, -Y
lpm R1, Z+
cpc R0, R1Код: Выделить всё
#define _(x) ((x&0xFF)<<24 | ((x>>8)&0xFF)<<16 | ((x>>16)&0xFF)<<8 | (x>>24)) Код: Выделить всё
cpsli buffer, _(0x123456FE)Код: Выделить всё
.macro cpli; формат: cpli ramaddr, const
ldi YL, low(@0) ; загружаем адрес сравниваемой переменной
ldi YH, high(@0)
rcall compare ; вызываем функцию сравнения.
.db @1&0xFF, (@1>>8)&0xFF, (@1>>16)&0xFF, @1>>24 ; Это второй параметр-константа функции сравнения
.endmКод: Выделить всё
.macro cpsli; формат: cpsli ramaddr, const
ldi YL, low(@0) ; загружаем адрес сравниваемой переменной
ldi YH, high(@0)
rcall compare ; вызываем функцию сравнения.
.db @1&0xFF, (@1>>8)&0xFF, (@1>>16)&0xFF, @1>>24 ; Это второй параметр-константа функции сравнения
.endm
.Equ SER0=0xCC
.Equ SER1=0x87
.Equ SER2=0x7F
.Equ BUT=0x9B
.dseg
buffer: .byte 4
; ...
.cseg
; ...
; Где-то в основной программе
cpsli buffer, (SER0<<24) | (SER1<<16) | (SER2<<8) | BUT
breq on_led ; Если числа равны, то включаем светодиод
; ...
; где-то ниже
; функция сравнения 4-байтного числа
; в Y хранится адрес сравниваемого числа в ОЗУ
compare:
pop ZH ; грузим адрес константы во FLASH
pop ZL
adiw Z, 2 ; перепрыгиваем через 2 байта
push ZL ; грузим адрес слудующей команды
push ZH
sbiw Z, 2
adiw Y, 4
lsl ZL ;; Переходим от слов к байтам
rol ZH
rcall compareByte2 ; сравниваем 4 байта
compareByte2:
rcall compareByte
compareByte:
ld R0, -Y
lpm R1, Z+
cpc R0, R1
ret ; этот ret многое значит..