Из этого замечания на 30 стр. DS, следует, что выход из POWER-DOWN будет только при низком уровне на INT0.mig-11101 писал(а):...
Попробуйте так
Из этого замечания на 30 стр. DS, следует, что выход из POWER-DOWN будет только при низком уровне на INT0.mig-11101 писал(а):...
akl писал(а):Из этого замечания на 30 стр. DS, следует, что выход из POWER-DOWN будет только при низком уровне на INT0.mig-11101 писал(а):...
Попробуйте так
Код: Выделить всё
.DSEG
Variables: .byte 3
Variavles2: .byte 1
.CSEG
; Переменная лежит в памяти, сначала надо ее достать.
LDS R16, Variables ; Считать первый байт Variables в R16
LDS R17, Variables+1 ; Считать второй байт Variables в R17
LDS R18, Variables+2 ; Ну и третий байт в R18
; Теперь прибавим к ней 1, т.к. AVR не умеет складывать с константой, только
; вычитать, приходиться извращаться. Впрочем, особых проблем не доставляет.
SUBI R16,(-1) ; вообще то SUBI это вычитание, но -(- дает +
SBCI R17,(-1) ; А тут перенос учитывается. Но об этом потом.
SBCI R18,(-1) ; Математика в ассемблере это отдельная история
STS Variables,R16 ; Сохраняем все как было.
STS Variables+1,R17
STS Variables+2,R18Код: Выделить всё
SUBI R16,(-1) ; вообще то SUBI это вычитание, но -(- дает +
SBCI R17,(-1) ; А тут перенос учитывается. Но об этом потом.
SBCI R18,(-1) ; Математика в ассемблере это отдельная историяКод: Выделить всё
SUBI (Rd,K8) вычитание константы Rd=Rd-K8
SBCI (Rd,K8) вычитание константы с переносом Rd=Rd-K8-C
DX168B писал(а):Видать отправляешь в этот порт целый байт.
Отправив целый байт целиком в порт, ты влияешь на все выводы этого порта.
Если одна часть выводов, например порта D, настроена на выход, а другая на вход, то
лучше управлять выходами порта по отдельности и отслеживать
входы тоже по отдельности(как я писАл выше).
Ещё 2 полезные команды:
sbi - подать на отдельную ногу лог. 1 (подать ток)
cbi - подать на отдельную ногу лог. 0 (убрать ток)
А вот синтаксис:Код: Выделить всё
sbi PortD, 0 ;Запустить ногу PD0
cbi PortD, 0 ;Отрубить ногу PD0
sbi PortD, 1 ;Запустить ногу PD1
cbi PortD, 1 ;Отрубить ногу PD1
sbi PortD, 2 ;Запустить ногу PD2
cbi PortD, 2 ;Отрубить ногу PD2
sbi PortD, 3 ;Запустить ногу PD3
cbi PortD, 3 ;Отрубить ногу PD3
; И т.д.

SII писал(а):C -- флаг переноса/заёма. Устанавливается в операциях сложения, вычитания, сравнения и сдвигов. С его помощью осуществляется, например, сложение или вычитание многобайтовых величин (собственно, тут пример именно такой).
ldi work,0
ldi work1,0
ldi work2,0
del3_0:
inc work
cpi work,30
brne del3_1
ret
del3_1:
inc work1
cpi work1,255
brne del3_1
jmp del3_2
del3_2:
inc work2
cpi work2,5
brne del3_2
jmp del3_0
SII писал(а):Это Вам надо хорошо разобраться с двоичной арифметикой вообще -- как складываются и вычитаются двоичные числа "на бумаге" (тогда увидите, как возникают переносы и заёмы), а после этого -- как производится сложение-вычитание чисел, имеющих большую разрядность, чем используемый процессор (в Вашем случае процессор 8-разрядный, а числа -- 16-разрядные, но сама идея не зависит от конкретной разрядности). У всех компьютерных архитектур этот флаг присутствует, поэтому не играет роли, AVR это, PIC, IA-32... В общем, это основа основ
Код: Выделить всё
0001000110001100Код: Выделить всё
0001001010001010next_time_H:;
; *
ldi work,0x00; *
out TIMSK,work;запретить прерывания таймерoв
ldi ZH,High(speed_value_delays_H1*2); *
ldi ZL,Low(speed_value_delays_H1*2); *
; *
; *
;
; *
add ZL,BLDC_cnt;указать адрес ячейки таблицы
adc ZH,work
;*
lpm; извлечь из флеш-памяти *
mov t_count1_H,r0;вывести значение
; *
out TCNT1H,t_count1_H;отправить в таймер *
ldi work,0b00000100;разрешить прерывание по переполнению *
out TIMSK,work ; *
; *
ret ;*
;*************************************
next_time_L:;
; *
ldi work,0x00; *
out TIMSK,work;запретить прерывания таймерoв
ldi ZH,High(speed_value_delays_L*2); *
ldi ZL,Low(speed_value_delays_L*2); *
; *
; *
;
; *
add ZL,BLDC_cnt;
adc ZH,work
;
; *
lpm; *
mov t_count1_L,r0; *
out TCNT1L,t_count1_L; *
ldi work,0b00000100; *
out TIMSK,work ; *
; *
ret ;*
speed_value_delays_L:
.db 0b11111111, 0b00000100, 0b00000100, 0b11111100, 0b00000100, 0b10010010, 0b00000100, 0b11111010, 0b00000000, 0b01001000
.db 0b11111010, 0b01010010, 0b01000110, 0b11111110, 0b10000100, 0b11001110, 0b00000100, 0b00001000, 0b00000010, 0b11011110
.db 0b10100110, 0b01011010, 0b00000100, 0b10011010, 0b00100110, 0b10101000, 0b00100000, 0b10011000, 0b11111100, 0b01100000
.db 0b11000100, 0b00010100, 0b01100100, 0b10110100, 0b00000100, 0b01000000, 0b10000110, 0b11000010, 0b11111110, 0b00111010
.db 0b01101100, 0b10011110, 0b11010000, 0b00000010, 0b00101010, 0b01010010, 0b10000100, 0b10100010, 0b11001010, 0b11110010
.db 0b00010000, 0b00111000, 0b01010110, 0b01110100, 0b10010010, 0b10110000, 0b11001110, 0b11100010, 0b00000000, 0b00010100
.db 0b00110010, 0b01000110, 0b01100100, 0b01111000, 0b10001100, 0b10100000, 0b10110100, 0b11001000, 0b11011100, 0b11110000
.db 0b00000100, 0b00011000
T1_OVER1:
OUT TCCR1B,ZERO ;остановить таймер
OUT TCNT1H,ZERO
OUT TCNT1L,ZERO
RCALL NEXT
OUT TIFR,_FF ; сброс флагов Т1
OUT TCCR1B,A ; запусить таймер
NEXT:
ldi ZH,High(T_speed1*2); *
ldi ZL,Low(T_speed1*2); *
add ZL,BLDC_cnt ;указать адрес ячейки таблицы
adc ZH,ZERO
LPM; извлечь из флеш-памяти *
OUT TCNT1H,R0;отправить в таймер *
ADIW ZL,1
LPM
OUT TCNT1L,R0;отправить в таймер *
INC BLDC_cnt ; только для теста!!!!!!!
INC BLDC_cnt ; только для теста!!!!!!!
ret ;*
Если это мега16, то проще использовать команду LPM Rxx,Z+
Liv абсолютно прав и для данного случая, ведь из таблички извлекается больше одного байта. Если уж на асме писать, то зачем делать хуже, чем сделает С-компилятор?Roman Venom писал(а):Проще, если требуется последовательно извлекать из таблички. А если изменение счётчика должно происходить, допустим, по нажатию кнопки, то не очень.
Код: Выделить всё
...
adc ZH,ZERO
LPM R0, Z+
OUT TCNT1H,R0
; и эта команда оказалась не нужна ; ADIW ZL,1
LPM
OUT TCNT1L,R0
...Код: Выделить всё
...
adc ZH, ZERO
LPM R0, Z+ ; младший
LPM ZL, Z ; старший
OUT TCNT1H, ZL ; старший
OUT TCNT1L, R0 ; младший
...