roboforum.ru

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

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

Программирование микроконтроллеров AVR, PIC, ARM.
Разработка и изготовление печатных плат для модулей.

Функция в Ассемблере для 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].
Как бы мне сделать что бы он не перескакивал в начало программы?
snayperAlfa
 
Сообщения: 163
Зарегистрирован: 05 июн 2008, 22:03
Откуда: Украина,Одесса
прог. языки: С,Java,SQL если это язык,C++ немного

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

Сообщение blindman » 10 ноя 2008, 19:48

Вероятнее всего, не инициализирован указатель стэка в начале программы.
Проект [[Open Robotics]] - универсальные модули для построения роботов
Модули Open Robotics можно приобрести в магазине shop.roboforum.ru

Day OFF? You must be pulling my leg! Stop making humor before someone sees you, fool!

Аватара пользователя
blindman
 
Сообщения: 4130
Зарегистрирован: 29 апр 2008, 21:15
Откуда: Хабаровск
прог. языки: C,C++,Assembler,PHP,Javascript,Ruby, SPIN,Java(?)
ФИО: Андрей Юрьевич

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                   
snayperAlfa
 
Сообщения: 163
Зарегистрирован: 05 июн 2008, 22:03
Откуда: Украина,Одесса
прог. языки: С,Java,SQL если это язык,C++ немного

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

Сообщение blindman » 10 ноя 2008, 20:15

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

Код: Выделить всёРазвернуть
ldi R16, low(RAMEND)
out SPL, R16
ldi R16, high(RAMEND)
out SPH, R16
Проект [[Open Robotics]] - универсальные модули для построения роботов
Модули Open Robotics можно приобрести в магазине shop.roboforum.ru

Day OFF? You must be pulling my leg! Stop making humor before someone sees you, fool!

Аватара пользователя
blindman
 
Сообщения: 4130
Зарегистрирован: 29 апр 2008, 21:15
Откуда: Хабаровск
прог. языки: C,C++,Assembler,PHP,Javascript,Ruby, SPIN,Java(?)
ФИО: Андрей Юрьевич

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

Сообщение snayperAlfa » 10 ноя 2008, 20:17

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

Кто такой low(RAMEND)?
snayperAlfa
 
Сообщения: 163
Зарегистрирован: 05 июн 2008, 22:03
Откуда: Украина,Одесса
прог. языки: С,Java,SQL если это язык,C++ немного

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() соответственно старший
«Как сердцу выразить себя? … Мысль изреченная есть ложь!»
В этом мире меня подводит доброта и порядочность...
"двое смотрят в лужу, один видит лужу, другой отраженные в ней звезды"
Аватара пользователя
Duhas
 
Сообщения: 6338
Зарегистрирован: 15 сен 2007, 13:03
Откуда: Красноярск
прог. языки: ASM(МК), C(PC)
ФИО: Гагарский Андрей Александрович

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

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

Вообще если почитать даташит на МК, вопросов не возникает обычно. Я помню когда я первую прогу на асме написал для АВРки, дык сразу заработало, и инициализацию стека взял из ДШ или из примеров
Сергей
 
Сообщения: 3744
Зарегистрирован: 29 дек 2004, 23:15
Откуда: Санкт-Петербург
прог. языки: C, C++, C#, Asm
ФИО: Кашликов Сергей

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

Сообщение snayperAlfa » 10 ноя 2008, 20:45

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

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


.org 0
rjmp START

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

START:
snayperAlfa
 
Сообщения: 163
Зарегистрирован: 05 июн 2008, 22:03
Откуда: Украина,Одесса
прог. языки: С,Java,SQL если это язык,C++ немного

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

Сообщение Duhas » 10 ноя 2008, 20:48

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

эта директива располагает все что после нее начиная с адреса 0х50... тоесть это скажется при прошивке МК
«Как сердцу выразить себя? … Мысль изреченная есть ложь!»
В этом мире меня подводит доброта и порядочность...
"двое смотрят в лужу, один видит лужу, другой отраженные в ней звезды"
Аватара пользователя
Duhas
 
Сообщения: 6338
Зарегистрирован: 15 сен 2007, 13:03
Откуда: Красноярск
прог. языки: ASM(МК), C(PC)
ФИО: Гагарский Андрей Александрович

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

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

Duhas, пиши краткий курс :)
Сергей
 
Сообщения: 3744
Зарегистрирован: 29 дек 2004, 23:15
Откуда: Санкт-Петербург
прог. языки: C, C++, C#, Asm
ФИО: Кашликов Сергей

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

Сообщение snayperAlfa » 10 ноя 2008, 20:56

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


Или вставить несколько тысяч NOP. :D (Что называется в лоб)
snayperAlfa
 
Сообщения: 163
Зарегистрирован: 05 июн 2008, 22:03
Откуда: Украина,Одесса
прог. языки: С,Java,SQL если это язык,C++ немного

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

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

Задержки удобно ставить по таймеру если это позволяет девайс
Сергей
 
Сообщения: 3744
Зарегистрирован: 29 дек 2004, 23:15
Откуда: Санкт-Петербург
прог. языки: C, C++, C#, Asm
ФИО: Кашликов Сергей

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

Сообщение Duhas » 10 ноя 2008, 20:59

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

эффективней способов мало.. как вариант использовать таймер... тогда ты сможешь выполнять некоторый код во время задержки..а сдвиг выполнять в прерывании по таймеру...
«Как сердцу выразить себя? … Мысль изреченная есть ложь!»
В этом мире меня подводит доброта и порядочность...
"двое смотрят в лужу, один видит лужу, другой отраженные в ней звезды"
Аватара пользователя
Duhas
 
Сообщения: 6338
Зарегистрирован: 15 сен 2007, 13:03
Откуда: Красноярск
прог. языки: ASM(МК), C(PC)
ФИО: Гагарский Андрей Александрович

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

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

а вопросы есть в вики. Там курс по основам Си для АВР, вот по этим вопросам и делай примеры. Будет здорово и синхронизировано :crazy:
Сергей
 
Сообщения: 3744
Зарегистрирован: 29 дек 2004, 23:15
Откуда: Санкт-Петербург
прог. языки: C, C++, C#, Asm
ФИО: Кашликов Сергей


Вернуться в Микроконтроллеры

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 0

cron