Технический форум по робототехнике.
snayperAlfa » 10 ноя 2008, 19:21
- Код: Выделить всё • Развернуть
.include "m16def.inc"
[1]
...
povtor:
out PORTD,r17
CALL delay
[2] out PORTD,r18
rjmp povtor
delay:
ldi r25,255
zad:
dec r25
brne zad
ret
Хочу сделать функция на асме как в Си. команда
- Код: Выделить всё • Развернуть
CALL delay
работает нормально и вызывает delay.Он успешно отрабатывается и когда доходит очередь до команды
ret, Debuger переводит курсор не к сегменту [2], а к сегменту [1].
Как бы мне сделать что бы он не перескакивал в начало программы?
blindman » 10 ноя 2008, 19:48
Вероятнее всего, не инициализирован указатель стэка в начале программы.
snayperAlfa » 10 ноя 2008, 19:52
Вот как бы вся программа:
- Код: Выделить всё • Развернуть
.include "m16def.inc"
ldi r16,0xFF ;255
out DDRD,r16
ldi r17,0x00
out PORTD,r17
ldi r17,0x01 ;PIND=0 0 ON
ldi r18,0x02 ;PIND=1 2 ON
ldi r19,0x04 ;PIND=2 4 ON
ldi r20,0x08 ;PIND=3 8 ON
ldi r21,0x10 ;PIND=4 16 ON
ldi r22,0x20 ;PIND=5 32 ON
ldi r23,0x40 ;PIND=6 64 ON
ldi r24,0x80 ;PIND=7 128 ON
povtor:
out PORTD,r17
CALL delay
out PORTD,r18
CALL delay
out PORTD,r19
CALL delay
out PORTD,r20
CALL delay
out PORTD,r21
CALL delay
out PORTD,r22
CALL delay
out PORTD,r23
CALL delay
out PORTD,r24
CALL delay
rjmp povtor
delay:
ldi r25,3
zad:
dec r25
brne zad
ret
blindman » 10 ноя 2008, 20:15
надо инициализировать стэк в самом начале программы
- Код: Выделить всё • Развернуть
ldi R16, low(RAMEND)
out SPL, R16
ldi R16, high(RAMEND)
out SPH, R16
snayperAlfa » 10 ноя 2008, 20:17
Ух ты! Заработало, спасибо! Щас буду разбираться чако это такое ты написал.
Кто такой low(RAMEND)?
Duhas » 10 ноя 2008, 20:24
прога увы ужасна ))) ну у кого не бывает по началу...
для начала сдвиг делается гораздо проще...есть прям такая команда ROL или ROR.. влево и право соответственно....
+ про стек.. в начале программы необходимо написать
- Код: Выделить всё • Развернуть
ldi tmp1,low(RAMEND) ; сдесь устанавливаем границы стека
out SPL,tmp1
ldi tmp1,high(RAMEND)
out SPH,tmp1
где tmp1 любой регистр.. в моем случае R16.. присвоить регистру имя можно так:
.def tmp1 = R16
начало программы рекомендуется начинать так:
- Код: Выделить всё • Развернуть
.org 0
rjmp START
.org 0x50
START:
суть в том, что начиная с 0 адреса лежат вектора прерываний, а диже если они не используются имеет смысл их обойти и расположить свой код после их области.. директива .org задает адрес для следующей за ней команды...
вашу программу я бы переписал так:
- Код: Выделить всё • Развернуть
.include "m16def.inc"
.def tmp1 = R16
;.def tmp2 = R17
.org 0 ; .org определяет адрес для следующих мнемоник
rjmp START ; тут осуществляем переход к метке старт минуя вектора прерываний
.org 0x50
START:
ldi tmp1,low(RAMEND) ; сдесь устанавливаем границы стека
out SPL,tmp1
ldi tmp1,high(RAMEND)
out SPH,tmp1
ldi tmp1,0xFF ;255
out DDRD,tmp1
ldi tmp1,0x00
out PORTD,tmp1
ldi tmp1, 1
povtor:
out PORTD, tmp1 ; вывод в порт значения аккамулятора
call delay ; тут все ясно )
rol tmp1 ;сдвиг влево (с ним одна проблема после того ак единица)
brcc povtor ;попадет в старший разряд то после повторнго сдвига в младшем
rol tmp1 ;бите будет ноль, и нужно еще раз сдвинуть... что тут и сделано
rjmp povtor ;сдвиг выполняется через бит C... проверяем его и если он равен 1
; сдвигаем еще
delay:
ldi r25,3
zad:
dec r25
brne zad
ret
Добавлено спустя 3 минуты 12 секунд:RAMEND по идее двухбайтный верхний адрес памяти.. определен в описании контроллера что подключается в первой строке программы... low() дает младший байт адреса high() соответственно старший
Сергей » 10 ноя 2008, 20:44
Вообще если почитать даташит на МК, вопросов не возникает обычно. Я помню когда я первую прогу на асме написал для АВРки, дык сразу заработало, и инициализацию стека взял из ДШ или из примеров
snayperAlfa » 10 ноя 2008, 20:45
Большое спасибо за пояснения
А если написать так
- Код: Выделить всё • Развернуть
.org 0
.org 0x50
rjmp START
START:
.org 0
rjmp START
.org 0x50 ; ведь тогда эта директива не выполняется,или я не прав?
START:
Duhas » 10 ноя 2008, 20:48
а директивы они и не выполняются ))) они для компилятора а не для мК
эта директива располагает все что после нее начиная с адреса 0х50... тоесть это скажется при прошивке МК
Сергей » 10 ноя 2008, 20:49
Duhas, пиши краткий курс
snayperAlfa » 10 ноя 2008, 20:56
Как эфективнеё создавать задержки? Я пока знаю только такой способ:
- Код: Выделить всё • Развернуть
delay:
ldi r25,3
zad:
dec r25
brne zad
ret
Или вставить несколько тысяч NOP.
(Что называется в лоб)
Сергей » 10 ноя 2008, 20:59
Задержки удобно ставить по таймеру если это позволяет девайс
Duhas » 10 ноя 2008, 20:59
на счет курса.. список вопросов давайте я накатаю проги с коментами .. и пояснений )))
эффективней способов мало.. как вариант использовать таймер... тогда ты сможешь выполнять некоторый код во время задержки..а сдвиг выполнять в прерывании по таймеру...
Сергей » 10 ноя 2008, 21:02
а вопросы есть в вики. Там курс по основам Си для АВР, вот по этим вопросам и делай примеры. Будет здорово и синхронизировано