Вт фев 24, 2015 21:05:03
Вт фев 24, 2015 22:20:38
Ср фев 25, 2015 07:52:17
.INCLUDE "m8def.inc"
.equ delta=8
.CSEG
.ORG $0000
START:
LDI R20,0b00000110
OUT DDRB,R20 ; начальный вывод 0
LDI R21,HIGH(512-delta)
OUT OCR1AH,R21
LDI R21,LOW(512-delta)
OUT OCR1AL,R21
LDI R21,HIGH(512+delta)
OUT OCR1BH,R21
LDI R21,LOW(512+delta)
OUT OCR1BL,R21
LDI R20,$B3 ; режим 10-bit PHASE CORRECT
OUT TCCR1A,R20
LDI R20,$01
OUT TCCR1B,R20
; каждые Fo/1024 формировать перепады на выходах PB2(OC1B) и PB1(OC1A)
; с защитным интервалом 2*delta тактов
RJMP PC
Ср фев 25, 2015 20:28:25
Чт мар 05, 2015 11:24:21
Вт апр 21, 2015 19:40:04
Пн июн 08, 2015 07:58:46
; Общий вход в прерывания.
; Перед вызовом сохранить R16
; Здесь сохраняются SREG, R17,18, X и Z
IntEn:
pop r16 ; Достаем адрес возврата
sts reta1,r16 ; из стека и сохраняем его
pop r16 ; в статической памяти.
sts reta1+1,r16 ; Прерывания здесь закрыты,
; reta1, если где и использую,
; то тоже при закрытых прерываниях
; Далее сохраняемся
in r16,SREG;
push r16
push r17
push r18
push xh
push xl
push zh
push zl
lds zh,reta1 ; и вызовем продолжение, как сопрограмму.
lds zl,reta1+1 ; Оно закончится ret'ом, после его выполнения
icall ; вернемся сюда.
; Восстановимся
pop zl
pop zh
pop xl
pop xh
pop r18
pop r17
pop r16
out SREG,r16
; Восстановим R16, сохраненный перед вызовом inten
pop r16
reti ; и чао-какао!
Interrupt_Label: ; Сюда ссылается один из (r)jmp из таблицы векторов
push r16
rcall inten
... ; Здесь располагается индивидуальная программа обслуживания
... ; этого конкретного прерывания
ret ; Заканчивается она RET'ом, а не RETI. Регистр R16 будет восстановлен позже,
; в общей программе, о нем заботиться не нужно.
TIM0_OVF: ; Timer0 Overflow Handler
push r16
rcall inten
ldi r16,(256-225)
out TCNT0,R16
lds r16,T0OflCnt
inc r16
sts T0OflCnt,r16
tst r16
brne L2
nop
nop
L2: ret
TOWait:
sts toDadr,XL
sts toDadr+1,XH
sts towfg,r16
pop r16
sts toRadr,r16
pop R16
sts toRadr+1,r16
ret
USART_UDRE: ; UDR Empty Handler
push r16
rcall inten
lds zh,toRadr
lds zl,toRadr+1
lds xl,toDadr
lds xh,toDadr+1
ijmp
TTYOUT: ; Первый вызов - синхронный
ldi r16,1 ; Взведем флаг "Есть данные на передачу"
sbi UCSRB,UDRIE ; разрешим прерывание для передачи данных через USART
rcall towait ; и вызываем "ожидание". На самом деле это выход из
; программы, сюда вернемся асинхронно, после прерывания
ldi r17,1 ; Передадим заголовок
out udr,r17 ; (байты 0x01, 0x00)
ldi r17,0 ;
out udr,r17 ;
; А это - цикл побайтовой передачи данных из буфера (Х), в конце - 0x00
tto1:
ld r16,x+
tst r16
brne tto2
cbi UCSRB,UDRIE
rjmp tto3
tto2: out udr,r16
tto3: rcall towait
rjmp tto1
cli
rcall ttyout
sei
Пн июн 08, 2015 08:04:12
akl писал(а):Здравствуйте. Недавно, на соседнем форуме был задан вопрос о быстром умножении 24-разрядных чисел. Было предложено использование алгоритма Дональда Кнута. В результате появился код, который выполняет
Умножение 24р*24р=48р выполняется за 75 тактов и занимает 65 слов
Умножение 32р*32р=64р выполняется за 134 такта и занимает 117 слов
Формат представления чисел старший-младший
Пн июн 08, 2015 08:21:05
; Программа деления 78 разрядного числа на 78 разрядное число
; R0...R9-ДЕЛИМОЕ, R10...R19-ДЕЛИТЕЛЬ!!!!R0...R9-РЕЗУЛЬТАТ
; R20...R29-РЕЗУЛЬТАТ,ZL-TEMP, ZH-ZERO
;**********************************************************************
GDIV_ERROR:
SET
GDIV_OUT2:
RET
DIV:
CLT ; сбос флага ошибки, если это не было сделано при входе в программу
CLR ZH ; zero-регистр
CLR R20
CLR R21
CLR R22
CLR R23
CLR R24
CLR R25
CLR R26
CLR R27
CLR R28
CLR R29 ; начальное значение результата
;**********************************************************************
; проверка области допустимых значений делимого и делителя
TST R0
BRMI GDIV_ERROR ; делимое отрицательное, ERROR
CP R19,R29
CPC R18,R28
CPC R17,R27
CPC R16,R26
CPC R15,R25
CPC R14,R24
CPC R13,R23
CPC R12,R22
CPC R11,R21
CPC R10,R20
BREQ GDIV_ERROR ; YES,DELITEL=0, ERROR
CP R29,R9
CPC R28,R8
CPC R27,R7
CPC R26,R6
CPC R25,R5
CPC R24,R4
CPC R23,R3
CPC R22,R2
CPC R21,R1
CPC R20,R0
BREQ GDIV_OUT2 ; YES,DELIMOE=0, REZULTAT=0
CP R9,R19
CPC R8,R18
CPC R7,R17
CPC R6,R16
CPC R5,R15
CPC R4,R14
CPC R3,R13
CPC R2,R12
CPC R1,R11
CPC R0,R10
BRPL DIV_GO1 ; NO, DELITEL<DELIMOGO
RJMP DIV_OUT1
DIV_GO1:
BRNE DIV_GO
RJMP DIV_EQU ; делитель=делимому, результат=1
;***************************************************************************
; выравнивание порядков делителя с делимым
;***************************************************************************
DIV_GO:
CLR ZL ; очистить счетчик сдвигов
DIV1:
CP R19,R9
CPC R18,R8
CPC R17,R7
CPC R16,R6
CPC R15,R5
CPC R14,R4
CPC R13,R3
CPC R12,R2
CPC R11,R1
CPC R10,R0
BRCC DIV2 ; YES,DELITEL>DELIMOGO
LSL R19
ROL R18
ROL R17
ROL R16
ROL R15
ROL R14
ROL R13
ROL R12
ROL R11
ROL R10 ; DELITEL*2
INC ZL
CPI ZL,80
BRNE DIV1
;***************************************************************************
; порядкок делителя найден с превышением
;***************************************************************************
DIV2:
T_DIV0:
CLT
LSL R9
ROL R8
ROL R7
ROL R6
ROL R5
ROL R4
ROL R3
ROL R2
ROL R1
ROL R0 ; делимое или остаток*2
CP R19,R9
CPC R18,R8
CPC R17,R7
CPC R16,R6
CPC R15,R5
CPC R14,R4
CPC R13,R3
CPC R12,R2
CPC R11,R1
CPC R10,R0 ; делитель больше делимого ?
BRCS T_DIV20 ; да,оставляем в 0 сооответствующий разряд результата
SET ; нет, взвести в 1 сооответствующий разряд результата
T_DIV20:
ROL R29
ROL R28
ROL R27
ROL R26
ROL R25
ROL R24
ROL R23
ROL R22
ROL R21
ROL R20
BRTS T_DIV40
SUB R9,R19
SBC R8,R18
SBC R7,R17
SBC R6,R16
SBC R5,R15
SBC R4,R14
SBC R3,R13
SBC R2,R12
SBC R1,R11
SBC R0,R10
T_DIV40:
DEC ZL
BRNE T_DIV0
;***************************************************************************
; проверка остатка для округления результата
DIV_OUT:
LSL R9
ROL R8
ROL R7
ROL R6
ROL R5
ROL R4
ROL R3
ROL R2
ROL R1
ROL R0 ; остаток*2 или 0.ххх*2
CP R9,R19
CPC R8,R18
CPC R7,R17
CPC R6,R16
CPC R5,R15
CPC R4,R14
CPC R3,R13
CPC R2,R12
CPC R1,R11
CPC R0,R10 ; делитель больше остатка или остаток >0.5 ?
BRCS DIV_OUT1 ; нет, остаток <0.5
; да остаток > 0.5, добавить 1
;***************************************************************************
DIV_EQU:
SEC
ADC R29,ZH
ADC R28,ZH
ADC R27,ZH
ADC R26,ZH
ADC R25,ZH
ADC R24,ZH
ADC R23,ZH
ADC R22,ZH
ADC R21,ZH
ADC R20,ZH
DIV_OUT1:
MOV R0,R20
MOV R1,R21
MOV R2,R22
MOV R3,R23
MOV R4,R24
MOV R5,R25
MOV R6,R26
MOV R7,R27
MOV R8,R28
MOV R9,R29
CLT
RET
;END
Пн июн 08, 2015 09:26:21
Пн июн 08, 2015 10:26:17
Не всегда (далеко не всегда) это критично. Программа обслуживания конкретного прерывания, обычно, короткая - максимум - десяток-другой команд, а чаще всего - меньше. Большие же действия лучше исполнять "в фоне".BOB51 писал(а):По АВРкину варианту... ( по посту afz )
Надо сначала прерывание текущего уровня закрыть, а уж затем на "хвост" переходить.
Ибо пока будет действовать текущее прерывание все другие прерывания будут недоступны.
Зачем? Чем ему плохо в стеке? Если же задержка от прерывания до реакции на него сильно критична, то этим приемом лучше не пользоваться.BOB51 писал(а):Т.Е. более оптимально подстановка адреса сопровождающей подпрограммы в стек и RETI с последующим RET из сопровождающей подпрограммы.
in rn,SREG
ldi r16,low (prog)
push r16
ldi r16,high (prog)
push r16
reti
Одначе там несколько нюансов по SREGу - запись не в стек, а в один из регистров регистрового файла
Я бы в таком случае не стал открывать прерывания "для всех", то есть в общей части. Если уж приспичило их открыть, то это надо делать в индивидуальном обслуживании, предварительно сняв у устройства бит разрешения прерываний от него, а затем сделав SEI. Ну, и, окончив эти (длительные) действия сделал бы CLI, взвел бит разрешения прерываний от устройства и вышел. Естественно, такое можно делать только с устройствами, которые могут подождать. Но лучше, все-таки, перенести длительную обработку в фон.BOB51 писал(а): и на момент восстановления окантовка из
prog:
; собственно текст программы
CLI
out SREG,rn ; n=2-15
SEI
RET
Правда это только в случае, ежли прерывание данного уровня не произойдет ранее, чем закончится его "хвост" обработки - иначе потребуется "флажковый семафор" для отработки "наложения в период исполнения".
Пн июн 08, 2015 14:47:23
Вт июн 23, 2015 15:03:54
Пн июн 29, 2015 05:32:57
Я надеялся скопипастить...akl писал(а):Для AVR использую такую. Она, правда, примитивна как лом и, наверно, не очень смотрится в этой теме, но в качестве основы, думаю, пойдёт.
Пн июл 13, 2015 13:37:48
Сб авг 08, 2015 20:27:53
baghear писал(а):Вопрос снят разобрался.
Сб авг 08, 2015 22:57:57
Вс авг 09, 2015 01:22:17
Вс авг 09, 2015 07:50:49
Вс авг 09, 2015 14:04:31