Ассемблер (ASM) для AVR в вопросах и ответах

Обсуждаем контроллеры компании Atmel.
akl
Друг Кота
Сообщения: 4444
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение akl »

Как вариант

Код: Выделить всё

   LSR   R17
   ROR   R16
   LSR   R17
   ROR   R16

   LSL   R16
   ROL   R17
   LSL   R16
   ROL   R17
Аватара пользователя
Pink-Pank
Опытный кот
Сообщения: 721
Зарегистрирован: Ср июн 11, 2014 09:43:13
Откуда: США
Контактная информация:

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение Pink-Pank »

Вроде как lsl, lsr не работают с флагом Carry. У Вас потеряются биты.
Fucking static initialization order fiasco
Аватара пользователя
COKPOWEHEU
Говорящий с текстолитом
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение COKPOWEHEU »

Это кто вам сказал? lsr сдвигает вправо, на место 7-го бита ставится 0, 0-й бит помещается в C. lsl - наоборот, на место 0-го ставится 0, 7-й уходит в С.
Аватара пользователя
Jack_A
Друг Кота
Сообщения: 6307
Зарегистрирован: Вт апр 24, 2007 07:45:40
Откуда: Minsk

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение Jack_A »

COKPOWEHEU, вот именно. И бит от первого сдвига потеряется : В С - то он задвинулся, но во втором LSL/LSR не используется, заполняется нулем. Но и вариант zero648 не самый оптимальный.

Лучше всего так, как у aki

Земляк WiseLord меня опередил. Минчане, чего вам не рождествуется, все форумуетесь :)
Последний раз редактировалось Jack_A Ср янв 07, 2015 11:47:13, всего редактировалось 6 раз.
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение WiseLord »

Получается как-то так:

Код: Выделить всё

        |   R17    |   R16    | C
--------+----------+----------
        | abcdefgh | ijklmnop | x
--------+----------+----------+---
LSR R17 | 0abcdefg | ijklmnop | h
ROR R16 | 0abcdefg | hijklmno | p
LSR R17 | 00abcdef | hijklmno | g
ROR R16 | 00abcdef | ghijklmn | o

        |   R17    |   R16    | C
--------+----------+----------
        | abcdefgh | ijklmnop | x
--------+----------+----------+---
LSL R16 | abcdefgh | jklmnop0 | i
ROL R17 | bcdefghi | jklmnop0 | p
LSL R16 | bcdefghi | klmnop00 | j
ROL R17 | cdefghij | klnmop00 | o
Аватара пользователя
СКАЗОЧНИК
Идёт направо - песнь заводит, Налево - сказку говорит.
Сообщения: 5000
Зарегистрирован: Чт апр 21, 2011 17:55:50
Откуда: Иркутск

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение СКАЗОЧНИК »

Вопрос:

Код: Выделить всё

         .equ   DB4      = PORTC7
         .equ   DB5      = PORTВ6
         .equ   DB6      = PORTА0
         .equ   DB7      = PORTD3


Так будет работать? Т.е. я хочу подключить к разным пинам разных портов. Будет ли у меня далее в программе понимать, что DB4 - это PORTC7?
Станислав
Аватара пользователя
Jack_A
Друг Кота
Сообщения: 6307
Зарегистрирован: Вт апр 24, 2007 07:45:40
Откуда: Minsk

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение Jack_A »

Не будет. Директива .equ просто определяет числовой константе символьное имя для более легкого понимания и модификации исходника программы. Ну какое число можно сопоставить в директиве .equ DB4 = PORTC7 идентификатору 'PORTC7' так, чтобы одним числом выражался и адрес порта, и номер бита в нем ? И вообще, директива ассемблера -- не волшебная палочка, которая может делать то, что не может делать машинный код. Ну представьте, что вышеуказанную директиву компилятор принял, и у вас написано выражение, где это DB4 использовано. Какой машинный код будет сгенерирован в этом случае ?
Последний раз редактировалось Jack_A Ср янв 07, 2015 12:16:25, всего редактировалось 1 раз.
Аватара пользователя
СКАЗОЧНИК
Идёт направо - песнь заводит, Налево - сказку говорит.
Сообщения: 5000
Зарегистрирован: Чт апр 21, 2011 17:55:50
Откуда: Иркутск

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение СКАЗОЧНИК »

Блин.... И я об этом думаю. Поэтому и задал вопрос для того, чтобы подтвердить сомнения...
Тогда другой вопрос.
Хочу назначить выводы индикатора на любые пины ЛЮБЫХ портов МК. Как правильно их объявить (определить)? Хочу дальше в программе не заморачиваться и писать ДБ4, а подобие дефайнов само определяло, куда он там подключен.
Станислав
Аватара пользователя
Jack_A
Друг Кота
Сообщения: 6307
Зарегистрирован: Вт апр 24, 2007 07:45:40
Откуда: Minsk

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение Jack_A »

Я думаю, с помощью макросов. Изменяя параметры в вызове макроса или макроопределении, можно изменять назначение разрядов/адресов. А "само" типа "разбирайтесь по своим местам" ничего не сможет, по любому назначения определяются в программе, и для того, чтобы прогу лучше понимать/корректировать макросы -- хороший инструмент.
Аватара пользователя
СКАЗОЧНИК
Идёт направо - песнь заводит, Налево - сказку говорит.
Сообщения: 5000
Зарегистрирован: Чт апр 21, 2011 17:55:50
Откуда: Иркутск

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение СКАЗОЧНИК »

А ведь, точно! Мне же по сути не нужны по отдельности линии DB, мне нужен целиком порт и значение в нем.

Спойлер

Код: Выделить всё

         
         .equ   DB7port = PORTC
         .equ   DB7pin   = 3

         .equ   DB6port = PORTC
         .equ   DB6pin  = 2

         .equ   DB5port = PORTC
         .equ   DB5pin  = 1

         .equ   DB4port = PORTC
         .equ   DB4pin  = 0

         .equ   RSport  = PORTC
         .equ   RSpin   = 5

         .equ   Eport   = PORTC
         .equ   Epin   = 4
      
   
   .MACRO   DATA                  ; Вызываем просто DATA TETRADA, предварительно положив в ТЕТРАДУ то, что нужно вывести.

            lsr @0            ; Сдвигаем вправо, крайний вывалится в С
            brcc Pusto1            ; Если С=0, то переходим по метке
            sbi  DB4port, DB4pin   ; Иначе, выставляем бит в 1
            rjmp Next1            ; Идем проверять следующий
      Pusto1: cbi    DB4port, DB4pin   ; Выставляем бит в 0
         

      Next1:   lsr @0            ; Сдвигаем вправо, крайний вывалится в С
            brcc Pusto2            ; Если С=0, то переходим по метке
            sbi  DB5port, DB5pin   ; Иначе, выставляем бит в 1
            rjmp Next2            ; Идем проверять следующий
      Pusto2: cbi    DB5port, DB5pin   ; Выставляем бит в 0
         

      Next2:   lsr @0            ; Сдвигаем вправо, крайний вывалится в С
            brcc Pusto3            ; Если С=0, то переходим по метке
            sbi  DB6port, DB6pin   ; Иначе, выставляем бит в 1
            rjmp Next3            ; Идем проверять следующий
      Pusto3: cbi    DB6port, DB6pin   ; Выставляем бит в 0
         

      Next3:   lsr @0            ; Сдвигаем вправо, крайний вывалится в С
            brcc Pusto4            ; Если С=0, то переходим по метке
            sbi  DB7port, DB7pin   ; Иначе, выставляем бит в 1
            rjmp Next1            ; Идем проверять следующий
      Pusto4: cbi    DB7port, DB7pin   ; Выставляем бит в 0
         
   
   .ENDM


А так будет работать? Думаю, что будет. Но код не оптимальный... Может кто ткнет носом, как проще вывести то, что находится в флаге переноса прямо на пин нужного порта?
Последний раз редактировалось СКАЗОЧНИК Ср янв 07, 2015 14:15:37, всего редактировалось 1 раз.
Станислав
Аватара пользователя
Леонид Иванович
Друг Кота
Сообщения: 4779
Зарегистрирован: Сб апр 02, 2011 12:40:46
Откуда: Минск
Контактная информация:

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение Леонид Иванович »

Вывод на индикатор с произвольным расположением портов делал так:

Спойлер

Код: Выделить всё

;Write nibble to LCD:
;Input:   temp7..temp4 - data nibble

LCD_WN:   bbrc   temp,7,lwr7_0
   Port_LCD_D7_1      ;D7 <- 1
   rjmp   lwr6   
lwr7_0:   Port_LCD_D7_0      ;D7 <- 0
lwr6:   bbrc   temp,6,lwr6_0
   Port_LCD_D6_1      ;D6 <- 1
   rjmp   lwr5   
lwr6_0:   Port_LCD_D6_0      ;D6 <- 0
lwr5:   bbrc   temp,5,lwr5_0
   Port_LCD_D5_1      ;D5 <- 1
   rjmp   lwr4   
lwr5_0:   Port_LCD_D5_0      ;D5 <- 0
lwr4:   bbrc   temp,4,lwr4_0
   Port_LCD_D4_1      ;D4 <- 1
   rjmp   lwrend   
lwr4_0:   Port_LCD_D4_0      ;D4 <- 0

lwrend:   Port_LCD_E_1      ;E <- 1
   rcall   Delay      ;delay 2 uS
   Port_LCD_E_0      ;E <- 0
   ret
 


Там используется макрос, вот мои макросы:

Спойлер
;***** Macros

.macro clbr ;clear bit in register
cbr @0,exp2(@1)
.endm

.macro stbr ;set bit in register
sbr @0,exp2(@1)
.endm

.macro bbrc ;branch if bit in register clear
sbrs @0,@1
rjmp @2
.endm

.macro bbrs ;branch if bit in register set
sbrc @0,@1
rjmp @2
.endm

.macro bbic ;branch if bit in I/O clear
sbis @0,@1
rjmp @2
.endm

.macro bbis ;branch if bit in I/O set
sbic @0,@1
rjmp @2
.endm

.macro addi ;add immediate
subi @0,-@1
.endm

.macro ldx ;load XL, XH with word
ldi XL,byte1(@0)
ldi XH,byte2(@0)
.endm

.macro ldy ;load YL, YH with word
ldi YL,byte1(@0)
ldi YH,byte2(@0)
.endm

.macro ldz ;load ZL, ZH with word
ldi ZL,byte1(@0)
ldi ZH,byte2(@0)
.endm

.macro table ;load Z pointer
ldi ZL,low (@0*2)
ldi ZH,high(@0*2)
.endm

.macro stdi ;store immediate indirect with displacement
ldi temp,@1
std @0,temp
.endm

.macro ldsx ;load XL, XH from memory
lds XL,@0+0
lds XH,@0+1
.endm

.macro ldsy ;load YL, YH from memory
lds YL,@0+0
lds YH,@0+1
.endm

.macro ldsz ;load ZL, ZH from memory
lds ZL,@0+0
lds ZH,@0+1
.endm

.macro stsx ;store XL, XH in memory
sts @0+0,XL
sts @0+1,XH
.endm

.macro stsy ;store YL, YH in memory
sts @0+0,YL
sts @0+1,YH
.endm

.macro stsz ;store ZL, ZH in memory
sts @0+0,ZL
sts @0+1,ZH
.endm



Описание пинов портов делал так:

Спойлер

Код: Выделить всё

;
Port С:

.equ   DIRC   = 0b11111111      ;Port C direction
.equ   PUPC   = 0b11111111      ;Port C pull-ups

.equ   LCD_D6   = PC1         ;LCD D6 data line
.equ   LCD_D7   = PC3         ;LCD D7 data line

.macro   Port_LCD_D6_0         ;LCD_D6 = 0
   cbi   PORTC,LCD_D6
.endm

.macro   Port_LCD_D6_1         ;LCD_D6 = 1
   sbi   PORTC,LCD_D6
.endm

.macro   Port_LCD_D7_0         ;LCD_D7 = 0
   cbi   PORTC,LCD_D7
.endm

.macro   Port_LCD_D7_1         ;LCD_D7 = 1
   sbi   PORTC,LCD_D7
.endm

Port D:

.equ   DIRD   = 0b11111110      ;Port D direction
.equ   PUPD   = 0b11111111      ;Port D pull-ups
.equ   LCD_W   = PD2         ;LCD W line
.equ   LCD_E   = PD3         ;LCD E line
.equ   LCD_D4   = PD4         ;LCD D4 data line
.equ   LCD_D5   = PD5         ;LCD D5 data line

.macro   Port_LCD_W_0         ;LCD_W = 0
   cbi   PORTD,LCD_W
.endm

.macro   Port_LCD_W_1         ;LCD_W = 1
   sbi   PORTD,LCD_W
.endm

.macro   Port_LCD_E_0         ;LCD_E = 0
   cbi   PORTD,LCD_E
.endm

.macro   Port_LCD_E_1         ;LCD_E = 1
   sbi   PORTD,LCD_E
.endm

.macro   Port_LCD_D4_0         ;LCD_D4 = 0
   cbi   PORTD,LCD_D4
.endm

.macro   Port_LCD_D4_1         ;LCD_D4 = 1
   sbi   PORTD,LCD_D4
.endm

.macro   Port_LCD_D5_0         ;LCD_D5 = 0
   cbi   PORTD,LCD_D5
.endm

.macro   Port_LCD_D5_1         ;LCD_D5 = 1
   sbi   PORTD,LCD_D5
.endm


На ассемблере, правда, не пишу уже 10 лет.
Аватара пользователя
СКАЗОЧНИК
Идёт направо - песнь заводит, Налево - сказку говорит.
Сообщения: 5000
Зарегистрирован: Чт апр 21, 2011 17:55:50
Откуда: Иркутск

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение СКАЗОЧНИК »

:facepalm: Леонид Иванович, я после каждого вашего поста себя таким тупым чувствую... :oops:
Спасибо, конечно за помощь, даже пробую разобраться. ))) Однако надо вопрос с повестки дня снять. Все равно по своему напишу все...
Станислав
Аватара пользователя
Jack_A
Друг Кота
Сообщения: 6307
Зарегистрирован: Вт апр 24, 2007 07:45:40
Откуда: Minsk

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение Jack_A »

Вот от холода и нечего делать :) накропал универсальный макрос. Запуливает содержимое
бита С в нужный разряд нужного порта.

Код: Выделить всё

   .MACRO   C_in_PORT
   brcs   _10
   clt
   rjmp   _15
_10:   set
  ;  Перекинули  бит  С  в  бит  Т,  специально для этих  целей придуманный
_15:   in   temp,@0
   andi   r16,~(1<<@1)
  ;  Считали  порт  и  очистили  нужный  разряд
   bld   r16,@1
   out   @0,temp
  ;  заполнили  разряд  тем  чем  надо  и  закинули  обратно  в  порт.
   .ENDMACRO


Пример вызова : C_in_PORT PORTB,3 temp из диапазона R16...R31 определяется ранее директивой .def
Мож пригодится.
Аватара пользователя
СКАЗОЧНИК
Идёт направо - песнь заводит, Налево - сказку говорит.
Сообщения: 5000
Зарегистрирован: Чт апр 21, 2011 17:55:50
Откуда: Иркутск

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение СКАЗОЧНИК »

Я забубенил так:
Спойлер

Код: Выделить всё

DB_LINE:                     

               lsr  R17                        ; Сдвигаем вправо, крайний вывалится в С
               brcc Pusto1            ; Если С=0, то переходим по метке
               sbi  DB4port, DB4pin            ; Иначе, выставляем бит в 1
               rjmp Next1            ; Идем проверять следующий
         Pusto1:    cbi    DB4port, DB4pin           ; Выставляем бит в 0
         

         Next1:   lsr  R17            ; Сдвигаем вправо, крайний вывалится в С
               brcc Pusto2            ; Если С=0, то переходим по метке
               sbi  DB5port, DB5pin   ; Иначе, выставляем бит в 1
               rjmp Next2            ; Идем проверять следующий
         Pusto2: cbi    DB5port, DB5pin   ; Выставляем бит в 0
         

         Next2:   lsr  R17            ; Сдвигаем вправо, крайний вывалится в С
               brcc Pusto3            ; Если С=0, то переходим по метке
               sbi  DB6port, DB6pin   ; Иначе, выставляем бит в 1
               rjmp Next3            ; Идем проверять следующий
         Pusto3: cbi    DB6port, DB6pin   ; Выставляем бит в 0
         

         Next3:   lsr  R17            ; Сдвигаем вправо, крайний вывалится в С
               brcc Pusto4            ; Если С=0, то переходим по метке
               sbi  DB7port, DB7pin   ; Иначе, выставляем бит в 1
               ret                  ;
         Pusto4: cbi    DB7port, DB7pin   ; Выставляем бит в 0
         
   ret


Блин, выше же выкладывал уже... :facepalm:
Станислав
Аватара пользователя
Jack_A
Друг Кота
Сообщения: 6307
Зарегистрирован: Вт апр 24, 2007 07:45:40
Откуда: Minsk

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение Jack_A »

С использованием бита Т не надо никого никуда двигать.
Аватара пользователя
СКАЗОЧНИК
Идёт направо - песнь заводит, Налево - сказку говорит.
Сообщения: 5000
Зарегистрирован: Чт апр 21, 2011 17:55:50
Откуда: Иркутск

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение СКАЗОЧНИК »

А как же если не двигать будут биты в С вываливаться?, чтобы потом их оттуда брать, потом в Т перекидывать, а дальше уже в порт. Тогды надо по другому задачу сформулировать. :roll:
Как раскидать младшую тетраду байта по различным пинам различных портов. :)
Станислав
Аватара пользователя
Jack_A
Друг Кота
Сообщения: 6307
Зарегистрирован: Вт апр 24, 2007 07:45:40
Откуда: Minsk

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение Jack_A »

Ну тогда конечно... Изначально я понял задачу рулить битами по состоянию бита С. А вообще если биты в портах вразнобой, элегантного решения не получится. Абы работало :)
Аватара пользователя
СКАЗОЧНИК
Идёт направо - песнь заводит, Налево - сказку говорит.
Сообщения: 5000
Зарегистрирован: Чт апр 21, 2011 17:55:50
Откуда: Иркутск

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение СКАЗОЧНИК »

Коты... :cry: Может кому не лень будет, глянет в АВРстудии проект мой. Никак не могу понять, почему у меня руки из жопы... :dont_know:
Проект без ошибок в плане компиляции. Однако, после выхода из подпрограммы инициализации дисплея (по ret) попадает не туда, откуда начал...
Уже исправил одну проблему, когда перекидывало по ret выше на два адреса, а теперь НИЖЕ перекидывает...

З.Ы. За одно можете посмотреть мою реализацию выставления портов данных для индикатора. получилось вроде ОЧЕНЬ даже маленькая. ))))

Код: Выделить всё

DB_LINE:                     ; Выводим тетраду в линии дисплея
            rcall CLR_PORT
            
            sbrc    R18, 4          ; Пропустить слудующую, еслли бит сброшен
            sbi      DB4port, DB4pin   ; Ставим бит
            sbrc    R18, 5          ; Пропустить слудующую, еслли бит сброшен
            sbi      DB5port, DB5pin   ; Ставим бит
            sbrc    R18, 6          ; Пропустить слудующую, еслли бит сброшен
            sbi      DB6port, DB6pin   ; Ставим бит
            sbrc    R18, 7          ; Пропустить слудующую, еслли бит сброшен
            sbi      DB7port, DB7pin   ; Ставим бит         
   ret
Вложения
LCD2313.rar
(9.5 КБ) 139 скачиваний
Станислав
Аватара пользователя
Pink-Pank
Опытный кот
Сообщения: 721
Зарегистрирован: Ср июн 11, 2014 09:43:13
Откуда: США
Контактная информация:

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение Pink-Pank »

СКАЗОЧНИК писал(а):Коты... :cry: Может кому не лень будет, глянет в АВРстудии проект мой. Никак не могу понять, почему у меня руки из жопы... :dont_know:

Дык это не к нам. Это к проктологу. ;-)
А вообще, проверяйте стек. Где-то с push/pop не доглядели
Fucking static initialization order fiasco
Аватара пользователя
СКАЗОЧНИК
Идёт направо - песнь заводит, Налево - сказку говорит.
Сообщения: 5000
Зарегистрирован: Чт апр 21, 2011 17:55:50
Откуда: Иркутск

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение СКАЗОЧНИК »

В том то и дело, что стек инициализирован. Но он используется только самими подпрограммами по (rcall и ret). Я сам ничего в стек не кладу.... :dont_know: Все туда кладет и берет компилятор.
При отладке смотрел. Переполнений не происходит никаких, т.к. их и не может быть... Всего на три или четыре глубины прогружается в стек.

ЗЫ. Я думаю, у меня проблема со структурой самой программы и подключением ИНКЛУДАМИ... Где-то я последовательность нарушаю... Все должно быть элементарно, а я не вижу.
Станислав
Ответить

Вернуться в «AVR»