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

Обсуждаем контроллеры компании Atmel.
Аватара пользователя
Kavka
Мудрый кот
Сообщения: 1810
Зарегистрирован: Чт июн 10, 2010 08:55:35
Откуда: Сибирские Афины

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

Сообщение Kavka »

Время в худшем случае надо минимизировать.

Ладно. Пока хватит этого. Может со временем ещё что-то в голову придёт.
Всем кто участвовал :) , отдельно Engineer_Keen - спасибо.
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Аватара пользователя
BOB51
Друг Кота
Сообщения: 15553
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

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

Сообщение BOB51 »

есть хорошее решение... но... у аврки нетуть команд простого вращения данных (только через С)... :cry:
jiffypop
Родился
Сообщения: 1
Зарегистрирован: Ср июн 05, 2013 20:12:15

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

Сообщение jiffypop »

не получается реализовать часы-секундомер на AT89C51
в протеусе на индикаторах считает только до 09:09
помогите
Спойлер

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

    
 ;----------
 bank0    EQU    00000000B  ;определение банков данных
 bank1    EQU    00001000B 
                           
 ktdi     EQU    60550      ;коэффициент пересчета счетчика
                           
 ;----------
            ;
          bseg
          org 0
 bufT:    Dbit   1
 flag  :    Dbit   1                           
          DSEG              ;
          ORG    25H       
 timsec:  DS     1   ;
               ;
                           
          ORG    30H       
 timdop:  DS     1          ; 1/200 секунды
 tim:     DS     4          ; значение времени
 tim1:    ds     4          ;
 nomR:    DS     1          ;номер активного индикатора
 freq:    ds     1          ;
 ksec:    ds     1          ;кол-во секунд в минуте
 kmin:    ds     1          ;макс значение 3 разряда
 k4:      ds     1          ;макс значение 2 разряда
 k2:      ds     1          ;макс значение 1 разряда
 
                           
          ORG    60H        ;
 stack:   DS     20H        ; стека
                           
 ;##########################################################
 ;##              переопр-ие векторов irq                 ##
 ;##########################################################
          CSEG             
          ORG    0000H      ;
          jmp    init       ;
                           
          ORG    0003H      ;
          reti              ;
                           
          ORG    000BH      ;
          jmp    dnind      ;
                           
          ORG    0013H      ;
          reti              ;
                           
          ORG    001BH      ;
          reti              ;
                           
          ORG    0023H      ;
          reti              ;
                           
 ; ----------
          ORG    0030H         
 init:    mov    sp,#(stack-1)  ; начальные значения  времени
                               
          mov    tim,#0         ; и коэффициентов пересчета 
          mov    tim+1,#0       ;
          mov    tim+2,#0       
          mov    tim+3,#0       
          mov    nomR, #0   
          mov    freq, #200d
          mov    ksec, #60d
          mov    kmin, #6d
          mov    k4, #4d   
          mov    k2,#2d 
          clr    flag           ;разрешение увеличения счетчика времени
                               
 ; ---------- Значение счетчика, маски прерываний, режим работы счетчика
          mov    TMOD,#00000001B    ;
          mov    TH0,#(high ktdi)   ;
          mov    TL0,#(low ktdi)    ;
          mov    IE,#10000010B      ;
          mov    IP,#00000010B      ;
          mov    TCON,#00010000B    ;
                               
                               
 main:                          ;  проверка нажатия клавши установки минут
 aa:      setb    p3.4          ;
          mov     c, p3.4       ;
          jnc  smin             ;

          setb    p3.5          ;  проверка нажатия клавши установки часов
          mov     c, p3.5       ;
          jnc  shour            ;

          setb    p3.7          ;  проверка нажатия клавши перехода в режим секундомера
          mov     c,p3.7
          jnc     tmode           

          jmp aa
 smin:    mov     timsec, #59
          mov     timdop, #199  ;+ минута
          call     dnind       
          mov     timsec, #0
          mov     timdop, #0   
         

 a1:      setb    p3.4
          mov     c, p3.4       ; ждем, когда пользователь уберет руки с кнопки
          jnc  a1
          jmp aa

 shour:   
          push   tim+3
          push   tim+2
         
          mov    tim+3, #9
          mov    tim+2, #5
          mov    timsec, #59    ; + час
          mov    timdop, #199
          call   dnind
          pop    tim+2          ;восстановление значения времени
          pop    tim+3   

 a2:      setb    p3.5
          mov     c, p3.5       ; ждем, когда пользователь уберет руки с кнопки
          jnc  a2
          jmp aa
 
 
tmode:    mov    tim1, tim      ;режим секундомера
          mov    tim1+1, tim+1  ;сохранение текущего времени
          mov    tim1+2, tim+2  ;
          mov    tim1+3, tim+3
          mov    tim,#0         ;
          mov    tim+1,#0       ; обнуление счетчиков
          mov    tim+2,#0       ;
          mov    tim+3,#0       ;

;----------         
tmode1:   mov    ksec, #1           
          mov    timsec, #0     ;коэффициент пересчета времени для секундомера(он же считает сотые)
          mov    kmin, #10
          mov    freq, #2
          mov    k4, #9
          mov    k2, #9
         
st2:      setb   p3.5           ;остановка секундомера с обнулением

          mov    c, p3.5
          jc     st1
          setb   flag           ; запрет увеличения значений секундомера
          mov    tim,#0         
          mov    tim+1,#0       
          mov    tim+2,#0       
          mov    tim+3,#0 

          jmp    st2
           


st1:       setb p3.5         

           setb   p3.4        ; остановка без обнуления
           mov    c, p3.4
           jc   st5
st55:     
           setb    flag       ; запрет увеличения значений секундомера
           setb p3.5
           jmp    st1

st5:
           
;----------
          clr    flag         ;  остаемся в режиме секундомера
          setb   p3.7         ;  пока нажата кнопка
          mov    c, p3.7      ;
          jnc    tmode1       ;
         

          mov    freq, #200   ;возврат к режиму часов
          mov    ksec,#60
          mov    kmin, #6
          mov    k4, #4
          mov    k2, #2
         
                       
          mov    tim, tim1          ; и восстановление на дисплее текущего времени
          mov    tim+1,tim1+1       ;
          mov    tim+2,tim1+2       
          mov    tim+3,tim1+3
          jmp    aa       
                             
 dnind:   push   ACC                ;сохранения acc и psw
          push   PSW             
          mov    PSW,#bank1         ; банк номер 1
          mov    TH0,#(high ktdi)   ;
                 
          mov    TL0,#(low ktdi)    ;
                                 
 ; ----------          ;вывод на индикаторы
          mov    a,nomR             ;
 ;         rrc    a               
 ;        mov    p1, #0            ; подаем на выводы p3.0, p3.1 значений
 ;         mov    p3.0,c            ; текущего индикатора
 ;         rrc    a                 ;
 ;         mov    p3.1,c            ;
          mov p3, nomR
                                 
                                    ; Вывод точки
          mov    a,nomR           
          cjne   a,#1,dn1           ; Проверка номера разряда
          mov    c,timsec.0         ; Мерцание точки
          jmp    dn2               
 dn1:     setb   c                  ; Точку выключаем
 dn2:     mov    bufT,c             ; Помещаем результат в буфер точки
                                 
                                    ; Вывод символа
          add    a,#tim             ; Вычисляем адрес в буфере
          mov    r0,a             
          mov    a,@r0              ; Чтение кода символа из буфера
          call   prind              ; вывод на индикатор
          inc    nomR               ; Увеличение номера текущего разряда
          mov    a,nomR           
          cjne   a,#4,dn3           ; Это последний разряд?
          mov    nomR,#0            ; Если да, то перейти на первый
 dn3:                         
                                 
 ;---------- Делитель на 200
         
         jb     flag,  dnif
         inc    timdop 
         
          mov    a,timdop         
          cjne   a,freq,dniF     
          mov    timdop,#0       
                                 
 ;---------- секунд
          inc    timsec           
          mov    a,timsec         
          cjne   a,ksec,dniF       
          mov    timsec,#0       
                                 
 ;---------- Счет основного таймера
          inc    tim+3              ; Единицы минут
                                                                              
         
          mov    a,tim+3         
          cjne   a,#10d,dniF       
          mov    tim+3,#0         
                                 
          inc    tim+2              ; Десятки минут       
          mov    a,tim+2         
          cjne   a,kmin,dniF       
          mov    tim+2,#0         
                                 
          inc    tim+1              ; Единицы часов
          mov    a,tim+1         
          cjne   a,k4,dn4         
          mov    a,tim           
          cjne   a,k2,dniF       
          mov    tim,#0           
          mov    tim+1,#0         
          jmp    dniF             
 dn4:     cjne   a,#10,dniF       
          mov    tim+1,#0         
          inc    tim                ;  Десятки часов
                                 
 ;----------  Завершающие команды
 dniF:    pop    PSW             
          pop    ACC             
          reti                   
                                 
 
                           
                         
;###########################################
;##   процедура вывода числа на дисплей   ##
;###########################################
prind:   push   psw        ; Сохранение регистра PSW в стеке
         push   DPH        ; Сохранение регистра DPTR в стеке (старш.)
         push   DPL        ; (младш. Половина)
         mov    DPTR,#zg   ; Загрузка начала таблицы знакогенератора
         movc   a,@a+DPTR  ; Считывание кода цифры в аккумулятор
         mov    c,bufT     ; Считывание буфера точки
         mov    acc.7,c    ; Запись значения тоски в старший разряд
         mov    p1,a       ; Вывод полученного кода в порт P1
         pop    DPL        ; Восстановление регистра DPTR (младш.)
         pop    DPH        ; (старш. Половина)
         pop    psw        ; Восстановление регистра psw
         ret               ; Выход из подпрограммы
                           
                           
;----------
; таблица соответствия чисел коду, который надо подавать на индикатор
;----------
                           
         ORG    0700H      ; поближе к концу
;----------
zg:      DB     11000000B  ; число  0
         DB     11111001B  ; число  1
         DB     10100100B  ; число  2
         DB     10110000B  ; число  3
         DB     10011001B  ; число  4
         DB     10010010B  ; число  5
         DB     10000010B  ; число  6
         DB     11111000B  ; число  7
         DB     10000000B  ; число  8
         DB     10010000B  ; число  9
         
  end   
Последний раз редактировалось Gudd-Head Чт июн 06, 2013 10:25:06, всего редактировалось 1 раз.
Причина: Нарушение п.2.5 Правил Форума
Alexeyslav
Друг Кота
Сообщения: 4550
Зарегистрирован: Чт май 05, 2011 21:26:34
Откуда: Украина, Славутич
Контактная информация:

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

Сообщение Alexeyslav »

А что говорит отладчик? Попробуй запустить алгоритм счета отдельно под отладчиком в бесконечном цикле.
Аватара пользователя
1essor1
Нашел транзистор. Понюхал.
Сообщения: 162
Зарегистрирован: Вс дек 09, 2012 12:14:44

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

Сообщение 1essor1 »

Разбираю АЦП в тине13 по даташиту. Не совсем ясно назначение этих двух регистров:
СпойлерИзображение

ADCSRB - если мы запускаем множественные преобразования, то выбираем то, от чего они будут запускаться, так?
Допустим, если записать 010 в ADTS[2:0] то преобразования будут начинаться по каждому внешнему прерыванию INT0, да?

А DIDR0 для чего? И каково его практическое значение?
Я так понял, что там речь идет об отключении цифрового буффера на пине, используемом для АЦП, и что данное отключение позволит снизить потребление энергии?
SmarTrunk
Друг Кота
Сообщения: 6014
Зарегистрирован: Чт ноя 26, 2009 11:16:50
Откуда: Москва

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

Сообщение SmarTrunk »

С DIDR0 все понятно - если по какому-то выводу используется АЦП, то соответствующий бит DIDR0 ставим 1, запрещая цифровой буфер. Зачем? А не будет лишний раз дергаться при изменении входного (аналогового) напряжения, что может повысить точность АЦП и, возможно, слегка уменьшит потребление.
Alexeyslav
Друг Кота
Сообщения: 4550
Зарегистрирован: Чт май 05, 2011 21:26:34
Откуда: Украина, Славутич
Контактная информация:

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

Сообщение Alexeyslav »

Именно. Там не просто потребление, а тот факт что цифровой вход будет работать параллельно аналоговому, и когда напряжение будет колебаться около порога срабатывания цифрового входа - он будет очень часто переключатся что помимо шума в измерениях даст еще и повышенное потребление.
SmarTrunk
Друг Кота
Сообщения: 6014
Зарегистрирован: Чт ноя 26, 2009 11:16:50
Откуда: Москва

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

Сообщение SmarTrunk »

С ADCSRB - похоже да, выбирается, от чего они будут запускаться. Если вообще разрешен автоматический запуск АЦП битом ADATE регистра ADCSRA.
Аватара пользователя
1essor1
Нашел транзистор. Понюхал.
Сообщения: 162
Зарегистрирован: Вс дек 09, 2012 12:14:44

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

Сообщение 1essor1 »

Спасибо за помощь! :beer: Теперь всё ясно.

Возник еще вопрос по поводу использования режима ADC noise reduction. Я понял это делается так: настраиваемся на этот режим, настраиваем и включаем АЦП, разрешаем прерывания, но преобразование не запускаем. Далее уходим в сон командой SLEEP - запускается преоразование, по окончанию которого поступившее прерывание разбудит мк? Всё так?
Опять же насколько высока реальная практическая ценность сего режима? Имеет смысл его использовать?
Alexeyslav
Друг Кота
Сообщения: 4550
Зарегистрирован: Чт май 05, 2011 21:26:34
Откуда: Украина, Славутич
Контактная информация:

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

Сообщение Alexeyslav »

Огромная ценность. Контроллер в момент измерения спит, а значит на АЦП не действуют шумы от работы внутренних узлов. Именно с этой целью введен такой режим работы.
Аватара пользователя
1essor1
Нашел транзистор. Понюхал.
Сообщения: 162
Зарегистрирован: Вс дек 09, 2012 12:14:44

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

Сообщение 1essor1 »

Есть пользовательский флаг Т, который чертовски удобен, но его одного мало. Можно ли взять какой-нибудь регистр, и сделать из него регистр с флагами, чтобы каждый бит был отдельным флагом, в идеале обозванный своим именем. И я так понимаю придется писать макросы ветвления, в зависимости установлен флаг или нет(на подобии BRTC и BRTS)?

Как вообще лучше поступить в данной ситуации?

P.S. допустим так

.def FLAG_REG = r16

.equ flag7 = 7
.equ flag6 = 6
.equ flag5 = 5
.equ flag4 = 4
.equ flag3 = 3
.equ flag2 = 2
.equ flag1 = 1
.equ flag0 = 0

установка флага
ldi FLAG_REG, (1<<flag5)

сброс флага
ldi FLAG_REG, (0<<flag5)

А как организовать ветвление по установленному/сброшеному пока не придумал :dont_know:
Аватара пользователя
ploop
Модератор
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

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

Сообщение ploop »

Сбросить и установить флаг с помощью LDI не получится. Надо использовать SBR, CBR (кстати, которые аналогичны ANDI и ORI по кодам инструкций)

А ветвления - SBRS/SBRC

Я часто такие приёмы использую. А написав короткие макросы из одной команды получим почти аналоги флага T.
Alexeyslav
Друг Кота
Сообщения: 4550
Зарегистрирован: Чт май 05, 2011 21:26:34
Откуда: Украина, Славутич
Контактная информация:

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

Сообщение Alexeyslav »

нет так не выйдет... LDI ты установишь флаг но напрочь затрешь все остальные.

я использую макросы:

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

 .macro set_bit
  SET
  BLD   @0,@1
.endmacro

.macro clear_bit
  CLT
  BLD   @0,@1
.endmacro

.macro go_if_set
 BST    @0,@1
 BRTS   @2
.endmacro

.macro go_if_clear
 BST    @0,@1
 BRTC   @2
.endmacro


0-вой параметр можно заменить на константу, в твоем случае FLAG_REG

или для каждого регистра сделать именные макросы, чтобы каждый раз не указывать имя регистра к которому он привязан. А если часто используешь макрос к конкретному биту, то можно сделать индивидуальные макросы.
Аватара пользователя
1essor1
Нашел транзистор. Понюхал.
Сообщения: 162
Зарегистрирован: Вс дек 09, 2012 12:14:44

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

Сообщение 1essor1 »

ploop, а у меня как раз этих команд в справочнике почему то не было :dont_know: Я уж тут велосипед стал изобретать, с масками и сравнениями :)))

Alexeyslav, спасибо за наработки! Только одно но. Вы же используете флаг Т в макросах, не стоит ли по заходу в макрос топить содержимое регистра SREG в стеке, а потом доставать. Вдруг этот флаг используется, а здесь он произвольным образом изменится?
Alexeyslav
Друг Кота
Сообщения: 4550
Зарегистрирован: Чт май 05, 2011 21:26:34
Откуда: Украина, Славутич
Контактная информация:

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

Сообщение Alexeyslav »

Слишком накладно выходит. Как правило, если доходишь до того уровня что есть необходимость использовать эти макросы, то флаг T у тебя не используется. А это происходит когда есть необходимость использовать два флага и больше. поэтому, используй макросы и забудь про индивидуальное использование этого флага. А ежели все-таки используешь, то добавь сохранение в стеке регистра флагов, это сразу добавит на одну операцию лишних 10 тактов(+4 ячейки памяти программ на каждую операцию с флагом) и опять же потребует один свободный регистр(а если нет - то +4 такта на его сохранение). не слишком уж много сложностей для реализации простых флагов? Проще забыть про использование флага T и пользоваться макросами.
Аватара пользователя
ploop
Модератор
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

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

Сообщение ploop »

ploop, а у меня как раз этих команд в справочнике почему то не было :dont_know: Я уж тут велосипед стал изобретать, с масками и сравнениями :)))

А, возможно их добавили для новых версий AVR - 48-88-168. Я говорю же, то их код совпадает, что и операций ANDI и ORI, то есть ваш велосипед с масками вовсе не велосипед.

Проще забыть про использование флага T и пользоваться макросами.

Вы про собственный регистр с флагами?
Alexeyslav
Друг Кота
Сообщения: 4550
Зарегистрирован: Чт май 05, 2011 21:26:34
Откуда: Украина, Славутич
Контактная информация:

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

Сообщение Alexeyslav »

Да я про регистр с флагами. флаг T при этом рассматривается как оперативный, наравне с флагом переноса(у вас же не возникает желание хранить какой-либо признак во флаге переноса дольше чем это необходимо?).
Аватара пользователя
ploop
Модератор
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

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

Сообщение ploop »

Нет конечно. Я его использую чаще с командами BLD-BST (как в макросе у вас выше)
SmarTrunk
Друг Кота
Сообщения: 6014
Зарегистрирован: Чт ноя 26, 2009 11:16:50
Откуда: Москва

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

Сообщение SmarTrunk »

ploop писал(а):А, возможно их добавили для новых версий AVR - 48-88-168. Я говорю же, то их код совпадает, что и операций ANDI и ORI
Да нет, для ATmega8 они прекрасно есть. Интересно, что SBR совпадает с ANDI, а CBR имеет такой же код, но константа инвертируется компилятором, ведь обнуляются биты, соответствующие единицам константы.

Каких-то команд может не быть в какой-то таблице, т.к. полно книг по AVR (большинство), где рассматриваются древние МК, и/или таблица команд дана урезаной.
Alexeyslav
Друг Кота
Сообщения: 4550
Зарегистрирован: Чт май 05, 2011 21:26:34
Откуда: Украина, Славутич
Контактная информация:

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

Сообщение Alexeyslav »

SBR это вроде синоним ORI.

Но у меня прикол был с CBR - по алгоритму идет очистка одной половинки байта, затем SWAP и вторая половинка, точно такой же командой. в AVRStudio первая команда CBR не делает ничего! а вторая срабатывает... точно так же себя ведет протеус(вот что странно), после замены на ANDI с нужной константой - все работает на ура, хотя код команды в прошивке ТОЧНО ТАКОЙ ЖЕ. Пипец, 3 дня потерял чтобы найти эту заковырку. Никогда не думал что проблема может воспроизвестись в двух совершенно разных программах.
Ответить

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