этот код тут совершенно ни при чем...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
СКАЗОЧНИК писал(а):Другой вопрос. Как создать в АВРСтудио ЕЕПРОМ файл? А то я старые значения затер...
Код: Выделить всё
.eseg
.org 0x01
EE_PARAM:
.db 0x55, 0xAA
.dw 0x55AA
Код: Выделить всё
;*************************************************************************
;========== EEPROM ===================
;*************************************************************************
;Так как возможна случайная запись в EEPROM в случае сбоя питания, то:
;1 - В микроконтроллере включить контроль снижения напряжения питания.
;2 - Первый (0x00) байт никогда не используется.
;3 - После ресета обнулить указатель адреса EEPROM.
;Решения для увеличения ресурса EEPROM:
;4 - Перед записью считывается байт, предназначенный для записи,
;проверяется на равенство с записываемым, если байты равны, то переход
;к записи следующего байта.
;5 - В конце работы с EEPROM обнулить указатель адреса.
#if (EEPROM==YES)
.macro Read_EEPROM
ldix @0 ; Указатель адреса EEPROM.
ldiy @1 ; Указатель адреса SRAM.
ldi CNT,@2 ; Количество байтов.
rcall _Read_EEPROM
.endmacro
_Read_EEPROM:
sbic EECR,EEWE
rjmp _Read_EEPROM
.ifdef EEARH
out EEARH,XH
.endif
out EEARL,XL
sbi EECR,EERE
sbi EECR,EERE
in EEDREG,EEDR
st Y+,EEDREG
adiw XL,1
dec Cnt
brne _Read_EEPROM
.ifdef EEARH
out EEARH,RClr
.endif
out EEARL,RClr
ret
EERead:
sbic EECR,EEWE
rjmp EERead
sbi EECR,EERE
sbi EECR,EERE
in EEDREG,EEDR
ret
EEWrite:
sbic EECR,EEWE
rjmp EEWrite
out EEDR,EEDREG
sbi EECR,EEMWE
sbi EECR,EEWE
ret
Write_EEPROM:
sbic EECR,EEWE
rjmp Write_EEPROM
.ifdef EEARH
out EEARH,YH
.endif
out EEARL,YL
ld EEDREG,X
out EEDR,EEDREG
sbi EECR,EEMWE
sbi EECR,EEWE
adiw XL,1
adiw YL,1
dec Cnt
brne Write_EEPROM
.ifdef EEARH
out EEARH,RClr
.endif
out EEARL,RClr
ret
Write_Param_EEPROM:
; LDIX Param_SRAM
; LDIY Param_EEPROM
; ldi Cnt,Param_Size
W_P_E_0:
sbic EECR,EEWE
rjmp W_P_E_0
.ifdef EEARH
out EEARH,YH
.endif
out EEARL,YL
ld r17,X
rcall EERead
cp r17,EEDREG
breq W_P_E_2
mov EEDREG,r17
W_P_E_1:
sbic EECR,EEWE
rjmp W_P_E_1
.ifdef EEARH
out EEARH,YH
.endif
out EEARL,YL
rcall EEWrite
W_P_E_2:
adiw XL,1
adiw YL,1
dec Cnt
brne W_P_E_0
.ifdef EEARH
out EEARH,RClr
.endif
out EEARL,RClr
ret
; Считывание параметров.
Read_Write_Param:
; LDIX Param_SRAM
; LDIY Param_EEPROM
; ldi Cnt,Param_Size
; rcall Read_EEPROM
ret
#endif
Код: Выделить всё
;--- деление 16 бит в R21:R20 на 8 бит в R16 ---
;------ целая часть в R20, остаток в R21 -------
div_16_8_8_8: ; 16 битов (2 байта) делим на 8 битов (1 байт), получаем целую часть 8 битов (1 байт) и остаток 8 битов (1 байт)
ldi R18, 8 ; делаем 8 циклов сдвига делимого/результата
div_16_8a:
lsl R20
rol R21
brcs div_16_8b ; если в результате сдвига влево появился перенос, то сразу же идем на вычитание, мимо сравнения
cp R21, R16
brcs div_16_8c ; если меньше, то пропускаем вычитание
div_16_8b:
sub R21,R16
sbr R20, 1
div_16_8c:
dec R18
brne div_16_8a
ret
;--- деление 32 бита в R23:R22:R21:R20 на 16 бит в R17:R16 ---
;--------- целая часть в R21:R20, остаток в R23:R22 ----------
div_32_16_16_16: ; 32 бита (4 байта) делим на 16 битов (2 байта), и получаем целую часть 16 битов (2 байта) и остаток 16 битов (2 байта)
ldi R18, 16 ; делаем 16 циклов сдвига делимого/результата
div_32_16a:
lsl R20
rol R21
rol R22
rol R23
brcs div_32_16b ; если в результате сдвига влево появился перенос, то сразу же идем на вычитание, мимо сравнения
cp R22, R16
cpc R23, R17
brcs div_32_16c
div_32_16b: ; если меньше, то пропускаем вычитание
sub R22,R16
sbc R23,R17
sbr R20, 1
div_32_16c:
dec R18
brne div_32_16a
ret
;--- умножение 16 бит в R21:R20 на 16 бит в R17:R16 ---
;----------- результат в R23:R22:R21:R20 --------------
mul_16x16_32: ; 16 битов (2 байта) умножаем на 16 битов (2 байта) и получаем в результате 32 бита (4 байта)
mov R18, R20
mov R19, R21
mul R21, R17 ; старший * старший '
movw R23:R22, R1:R0 ; старшая пара результата
mul R18, R16 ; младший * младший
movw R21:R20, R1:R0 ; младшая пара результата
mul R19, R16 ; старший * младший
add R21, R0
adc R22, R1
mul R18, R17 ; младший * старший
add R21, R0
adc R22, R1
adc R23, R31
ret
Код: Выделить всё
;--- калибровка тока или напряжения ---
calibr_zamer:
mov R16, R4 ; передадим замер в сомножитель
mov R17, R5 ; в первом сомножителе (R21:R20) уже находится калибровчный коэффициент
rcall mul_16x16_32
ldi R16, low(1024)
ldi R17, high(1024) ; делим на 1024, так как результат АЦП - 10-битный
rcall div_32_16_16_16
;--- округление числа после деления ---
okruglenie:
lsl R22 ; сдвигаем остаток от деления влево - умножение на 2
rol R23
cp R22, R16 ; сравниваем удвоенный остаток с делителем
cpc R23, R17
brlo end_okrug ; если меньше, то ничего не делаем
inc R20 ; а если больше или равно, то прибавляем 1 к целой части результата деления
brne end_okrug
inc R21
end_okrug:
mov R4, R20
mov R5, R21 ; вернем в регистры прокалиброванные ток или напряжение
ret
Код: Выделить всё
clr R23 ; в R22:R21:R20 уже находится набранное время, очистим старший байт
ldi R16, low(3600)
ldi R17, high(3600) ; после деления на 3600 в целой части результата получаеи количество часов, а в остатке получаем количество секунд
rcall div_32_16_16_16 ; остаток меньше 3600
ldi R16, 10 ; сразу же делим целую часть первого деления на 10,
rcall div_16_8_8_8 ; и получаем в целой части результата десятки часов, а в остатке получаем единицы часов
ldi R18, '0'
add R18, R20 ; десятки часов
rcall write_lcd
ldi R18, '0'
add R18, R21 ; единицы часов
rcall write_lcd
ldi R18, ':' ; выведем двоеточие
rcall write_lcd
mov R21, R23 ; переместим остаток в делимое
mov R20, R22
clr R23 ; очистим старшие байты
clr R22
ldi R16, low(600) ; после деления количества секунд на 600 получаем десятки минут,
ldi R17, high(600)
rcall div_32_16_16_16 ; остаток меньше 600
ldi R18, '0'
add R18, R20 ; десятки минут
rcall write_lcd
mov R21, R23
mov R20, R22 ; переместим остаток первого деления в делимое
ldi R16, 60 ; после деления на 60 получаем единицы минут
rcall div_16_8_8_8 ; остаток меньше 60
ldi R18, '0'
add R18, R20 ; единицы минут
rcall write_lcd
ldi R18, ':' ; выведем двоеточие
rcall write_lcd
mov R20, R21 ; переместим остаток от последнего деления в делимое
clr R21 ; очистим старший байт
ldi R16, 10 ; после деления на 10
rcall div_16_8_8_8 ; получаем в целой части результата десятки секунд, а в остатке получаем единицы секунд
ldi R18, '0'
add R18, R20 ; десятки секунд
rcall write_lcd
ldi R18, '0'
add R18, R21 ; единицы секунд
rcall write_lcd
end_vyvod_sekynd:
надеюсь, считываются они тоже "каждый третий такт"? вы об этом умолчали...12val12 писал(а):со входа 8 бит порта каждый третий такт записывается его состояние A
на другой 8 бит порт выход выводится на 20 тактов задержаннный A[i-20]
это очевидно12val12 писал(а):Думаю что таким образом темп записи будет гораздо меньше чем каждый третий такт
да?12val12 писал(а):в общем ОЗУ исключается. только регистры и порты
1 такт - чтение из порта.12val12 писал(а):Напомню записывается каждый третий такт
Код: Выделить всё
.dseg
buf:
.byte 256
.cseg
ldi XL, lo(buf)
ldi r17, hi(buf)
ldi YL, lo(buf)+20
loop:
mov XH, r17 ; 1 такт
mov YH, r17 ; 1 такт, итого 2
in r16, PINB ; 1 такт, итого 3
st Y+, r16 ; 2 такта, итого 5
ld r16, Х+ ; 2 такта, итого 7
out PORTD, r16 ; 1 такт, итого 8
rjmp loop ; 2 такта, итого 10
Код: Выделить всё
1 in r0,PORTA
out portB,r5
nop nop
in r1,PORTA
out portB,r6
nop nop
in r2,PORTA
out portB,r7
nop nop
in r3,PORTA
out portB,r8
nop nop
in r4,PORTA
out portB,r9
nop nop
in r5,PORTA
out portB,r10
nop nop
in r6,PORTA
out portB,r0
nop nop
in r7,PORTA
out portB,r1
nop nop
in r8,PORTA
out portB,r2
nop nop
in r9,PORTA
out portB,r3
nop nop
in r10,PORTA
out portB,r4
jmp 1 это сначала нужно разработать новый процессор, в котором джамп выполняется за 1 такт.12val12 писал(а):возможно заджампить в начало за 1 такт ?
я насчитал 26 тактов (4 * 6 + 2 = 26 - от чтения в r0 до вывода из r0).12val12 писал(а):тут задержка >22 тактов