roboforum.ru

Технический форум по робототехнике.

Функция в Ассемблере для AVR

Функция в Ассемблере для AVR

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].
Как бы мне сделать что бы он не перескакивал в начало программы?

Re: Функция в Ассемблере для AVR

blindman » 10 ноя 2008, 19:48

Вероятнее всего, не инициализирован указатель стэка в начале программы.

Re: Функция в Ассемблере для AVR

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                   

Re: Функция в Ассемблере для AVR

blindman » 10 ноя 2008, 20:15

надо инициализировать стэк в самом начале программы

Код: Выделить всёРазвернуть
ldi R16, low(RAMEND)
out SPL, R16
ldi R16, high(RAMEND)
out SPH, R16

Re: Функция в Ассемблере для AVR

snayperAlfa » 10 ноя 2008, 20:17

Ух ты! Заработало, спасибо! Щас буду разбираться чако это такое ты написал.

Кто такой low(RAMEND)?

Re: Функция в Ассемблере для AVR

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() соответственно старший

Re: Функция в Ассемблере для AVR

Сергей » 10 ноя 2008, 20:44

Вообще если почитать даташит на МК, вопросов не возникает обычно. Я помню когда я первую прогу на асме написал для АВРки, дык сразу заработало, и инициализацию стека взял из ДШ или из примеров

Re: Функция в Ассемблере для AVR

snayperAlfa » 10 ноя 2008, 20:45

Большое спасибо за пояснения :good:

А если написать так
Код: Выделить всёРазвернуть
   
.org   0     
.org   0x50
rjmp   START
START:     


.org 0
rjmp START

.org 0x50 ; ведь тогда эта директива не выполняется,или я не прав?

START:

Re: Функция в Ассемблере для AVR

Duhas » 10 ноя 2008, 20:48

а директивы они и не выполняются ))) они для компилятора а не для мК

эта директива располагает все что после нее начиная с адреса 0х50... тоесть это скажется при прошивке МК

Re: Функция в Ассемблере для AVR

Сергей » 10 ноя 2008, 20:49

Duhas, пиши краткий курс :)

Re: Функция в Ассемблере для AVR

snayperAlfa » 10 ноя 2008, 20:56

Как эфективнеё создавать задержки? Я пока знаю только такой способ:
Код: Выделить всёРазвернуть
   
delay:   
   ldi r25,3
   zad:
   dec r25
   brne zad
ret


Или вставить несколько тысяч NOP. :D (Что называется в лоб)

Re: Функция в Ассемблере для AVR

Сергей » 10 ноя 2008, 20:59

Задержки удобно ставить по таймеру если это позволяет девайс

Re: Функция в Ассемблере для AVR

Duhas » 10 ноя 2008, 20:59

на счет курса.. список вопросов давайте я накатаю проги с коментами .. и пояснений )))

эффективней способов мало.. как вариант использовать таймер... тогда ты сможешь выполнять некоторый код во время задержки..а сдвиг выполнять в прерывании по таймеру...

Re: Функция в Ассемблере для AVR

Сергей » 10 ноя 2008, 21:02

а вопросы есть в вики. Там курс по основам Си для АВР, вот по этим вопросам и делай примеры. Будет здорово и синхронизировано :crazy:


Rambler\'s Top100 Mail.ru counter