Обсуждаем контроллеры компании Atmel.
Ответить

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

Вс янв 20, 2019 11:31:29

А чем оно лучше ADIW, SBIW ? Тем, что флаги не трогает ?

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

Вс янв 20, 2019 13:02:45

именно тем и лучше.

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

Вс янв 20, 2019 13:54:24

Не всегда лучше.

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

Вс янв 20, 2019 14:09:06

Просто очень древний приём.

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

Вс янв 20, 2019 20:11:06

Ёще раз благодарю за ответы! Помогите пожалуйста решить еще одну проблему в этом же проекте. Я использую АЦП МК Atmega8, он десятибитный.
Необходимо напряжение от 0 до (примерно) 5 Вольт разбить на 511 шагов. Для этого мне надо использовать всего девять бит регистров преобразования ADCL, ADCH. Если использовать все десять бит, то в младшем бите регистра ADCL появляется сигнал ошибки, видимо вызванный шумом МК и внешними наводками. Поэтому я пытаюсь сделать так: сначала копирую содержимое регистра ADCL в регистр XL, ADCH в XH. Далее мне надо сделать логический сдвиг вправо всей регистровой пары X c переносом младшего бита регистра ХH в старший бит XL. При этом, младший "вытесненный" бит регистра XL мне не нужен, а в старший бит регистра ХH надо записать ноль. Далее уже работать с этим числом. Таким образом я хочу с эмитировать девяти разрядный АЦП. Подскажите как сделать логический сдвиг вправо всей регистровой пары X?
Картинку прилагаю
Вложения
Логический сдвиг.jpg
(88.01 KiB) Скачиваний: 355

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

Пн янв 21, 2019 00:54:41

Снижать разрешение АЦП как то не очень.
Код:
LSR XH
ROR XL

Получили усечение. Хотя, правильнее сделать округление
Код:
LSR XH
ROR XL
 CLR R0
ADC XL,R0
ADC XH,R0

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

Пн янв 21, 2019 05:47:41

Спасибо akl. Попробую.

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

Вт янв 22, 2019 00:35:52

Если младший бит смущает шумом, значение можно всегда пропустить через фильтр подвижного окна. И использовать все 10 бит.

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

Пт янв 25, 2019 16:55:38

4 байта сдвинуть 4 раза и без swap займет 16 циклов (а не тактов).

Именно поэтому я и спрашивал про быстрее 16 циклов/тактов. :)

Starichok51, pyzhman, BOB51 спасибо!

4epemyxa спасибо за вариант кода с умножением!

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

Сб янв 26, 2019 18:20:06

Здравствуйте! Помогите решить проблему с АЦП в МК ATmega8!
Если настраиваю тактовую частоту МК 2 МГц от встроенного генератора без кварца, использую восьмибитный результат преобразования по входам ADC0 и ADC1, тактовая частота АЦП при измерениии на ADC0 и ADC1 = 1 Мгц, 5 бит регистра ADMUX (ADLAR = 1) не меняется при переключении с ADC0 на ADC1. То при такой конфигурации программа далее идеально работает:

main:
ldi R16, 0b00100001
out ADMUX, R16
ldi R16, 0b11000001
out ADCSRA, R16
m1: in R16, ADCSRA
sbrc R16, 6
rjmp m1
in R17, ADCH
out OCR2, R17

ldi R16, 0b00100000
out ADMUX, R16
ldi R16, 0b11000001
out ADCSRA, R16
m2: in R16, ADCSRA
sbrc R16, 6
rjmp m2
in R18, ADCH

\
\ ;дальнейшие вычисления
\

rjmp main

Если настраиваю тактовую частоту МК 2 МГц от встроенного генератора без кварца, использую восьмибитный результат преобразования по входу ADC1 и десятибитный результат по входу ADC1, тактовая частота АЦП ADC1 = 1 Мгц, а ADC0 = 125 Кгц. 5 бит регистра ADMUX ADLAR = 1- при опросе входа ADC1 и ADLAR = 0 - при опросе входа ADC1, то программа с редкими ошибками, но работает:

main:
ldi R16, 0b00100001
out ADMUX, R16
ldi R16, 0b11000001
out ADCSRA, R16
m1: in R16, ADCSRA
sbrc R16, 6
rjmp m1
in R17, ADCH
out OCR2, R17

ldi R16, 0b00000000
out ADMUX, R16
ldi R16, 0b11000100
out ADCSRA, R16
m2: in R16, ADCSRA
sbrc R16, 6
rjmp m2
in XH, ADCH
in XL, ADCL

\
\ ;дальнейшие вычисления
\

rjmp main

А если в этой программе убрать опрос входа ADC1 из цикла, то опрос ADC0 в цикле срабатывает однократно, а затем перестает работать с двухбайтным числом регистра XL, XH. Хотя эти два преобразования с ADC0 и ADC1 нужны для разных, не связанных друг с другом, участков программы

ldi R16, 0b00100001
out ADMUX, R16
ldi R16, 0b11000001
out ADCSRA, R16
m1: in R16, ADCSRA
sbrc R16, 6
rjmp m1
in R17, ADCH
out OCR2, R17


main:
ldi R16, 0b00000000
out ADMUX, R16
ldi R16, 0b11000100
out ADCSRA, R16
m2: in R16, ADCSRA
sbrc R16, 6
rjmp m2
in XH, ADCH
in XL, ADCL

\
\ ;дальнейшие вычисления
\

rjmp main

Такое ощущение, что надо все время все время полностью перезагружать АЦП - выключить, потом опять включить и настроить. Подскажите где проблема? Есть ли нюансы при переключения АЦП с одной частоты на другую, при переключении входов, при переключении 5 бита – ADLAR?

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

Вс янв 27, 2019 02:06:11

Скорей ньюансы со считыванием регистров. Там имеется защёлка, когда один регистр читаешь то пока второй не прочитаешь защёлка не уберётся и новое значение в регистр не попадёт. Если у вас такая каша в программе происходит что работаете то в 8-битном режиме то в 10-битном просто тогда для 8 бит читайте оба регистра как и в 10-битном режиме. Видимо при переключениях и последующем чтении происходит срабатывание защелки.

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

Вс янв 27, 2019 04:54:29

Порядок чтения тоже важен.
Спойлер
Код:
ldi R16, 0b00100001
out ADMUX, R16
   LDI   R16,0b11000001
   out ADCSRA, R16
m1:
   SBIC   ADCSRA,6
   RJMP   M1
   IN   R0,ADCL
   in R17, ADCH
   out OCR2, R17
main:
ldi R16, 0b00000000
out ADMUX, R16
   ldi R16, 0b11010100
;ldi R16, 0b11000100
out ADCSRA, R16
m2:
   SBIC   ADCSRA,6
   RJMP   M2

   in XL,ADCL
   in XH,ADCH

;   in XH, ADCH
;   in XL, ADCL

   RJMP   GO

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

Вс янв 27, 2019 05:42:00

Благодарю akl и Alexeyslav за ответы! Сейчас попробую исправить.

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

Вс янв 27, 2019 08:34:38

Скорей ньюансы со считыванием регистров. Там имеется защёлка, когда один регистр читаешь то пока второй не прочитаешь защёлка не уберётся и новое значение в регистр не попадёт.

Попадёт, не путайте людей.

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

Вс янв 27, 2019 10:12:55

ADMUX (ADLAR = 1)

in XH, ADCH
in XL, ADCL

МКС, если вам достаточно 8 старших бит от АЦП, то выровненный в лево результат читайте из старшего регистра АЦП, а младший не трогайте совсем.
При чтении из младшего регистра доступ к регистрам АЦП блокируется пока не прочитаете старший. Т.е. АЦП не сможет поместить новое значение в регистры пока не прочитаете в программе старший регистр!
Поэтому или пользуетесь только старшим регистром или читаете сначала младший, а потом старший.

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

Вс янв 27, 2019 17:09:17

Alexeyslav, akl, dgrett, Kavka - очень выручили ребята! Все так и было! Проблема исчезла после перестановки порядка считывания регистров (ADCL затем ADCH). Очень благодарен!!!

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

Пн янв 28, 2019 07:26:04

Эх, давно это было...
Вместо того, чтобы сладко спать, я до сего времени пытался запустить Ваш макрос.
Z_h_e, как же я вас понимаю. :) :tea:
Данный макрос коварен. :) Если Вы напишите PUSH Я1, то компилятор выдаст ошибку, а если ENTER Я1, то компилятор это проглотит и регистр не будет сохранен. Так что тут проще вляпаться, чем перечислять ПушиПопы.
при наличии таких мощных макросов слабО сделать так, чтобы эта ситуация обрабатывалась? ;)

Слегка :))) модифицированный вариант.
Спойлер
Код:
; ----------
; Авторы: ARV, Z_h_e, Kavka с форума radiokot.ru
; ----------

#include <avr/io.h>

.macro  ENTER   arg:vararg                              ; макрос имеет переменное число параметров
    .set    selector, 0                                 ; в этой переменной будем отмечать нужные регистры
    .set    sel_sreg, 0                                 ; в этой переменной будем отмечать сохранение SREG

; перебераем аргументы и проверяем на допустимость
    .irp    reg,\arg
        .set    ch, 1
        .irp    p, r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,r13,r14,r15,r16,r17,r18,r19,r20,r21,r22,r23,r24,r25,r26,r27,r28,r29,r30,r31
            .if (\p == \reg)                            ; если аргументом макроса совпадает с элементов из списка
                .set    ch, 0
            .endif
        .endr
        .irp    p, R0,R1,R2,R3,R4,R5,R6,R7,R8,R9,R10,R11,R12,R13,R14,R15,R16,R17,R18,R19,R20,R21,R22,R23,R24,R25,R26,R27,R28,R29,R30,R31
            .if (\p == \reg)
                .set    ch, 0
            .endif
        .endr
        .irp    p, xl,xh,yl,yh,zl,zh,sreg,XL,XH,YL,YH,ZL,ZH,SREG
            .if (\p == \reg)
                .set    ch, 0
            .endif
        .endr
        .if ( ch )
            ; ругаемся если аргумент не опознан... :-)
            .print "Error: macro ENTER - unkown register"
            .err
        .endif
    .endr

; перебрать аргументы и отметить их битами в selector
    .irp    reg,\arg
        .set    i, 0
        ; надо перечислить все регистры по порядку!!!
        .irp    p, r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,r13,r14,r15,r16,r17,r18,r19,r20,r21,r22,r23,r24,r25,r26,r27,r28,r29,r30,r31
            .if (\p == \reg)                            ; если аргументом макроса совпадает с элементов из списка
                .set    selector ,(selector | (1 << i)) ; сделаем отметку в нужном бите
            .endif
            .set    i, i+1                              ; и продолжим счет
        .endr
    .endr
    .irp    reg,\arg
        .set    i, 0
        .irp    p, R0,R1,R2,R3,R4,R5,R6,R7,R8,R9,R10,R11,R12,R13,R14,R15,R16,R17,R18,R19,R20,R21,R22,R23,R24,R25,R26,R27,R28,R29,R30,R31
            .if (\p == \reg)
                .set    selector ,(selector | (1 << i))
            .endif
            .set    i, i+1
        .endr
    .endr

    ; альтернативные названия регистров
    .irp    reg,\arg
        .set    i, 26
        ; надо перечислить все регистры в соответствии с номерами
        .irp    p, XL,XH,YL,YH,ZL,ZH
            .if (\p == \reg)
                .set    selector ,(selector | (1 << i))
            .endif
            .set    i, i+1
        .endr
    .endr
    .irp    reg,\arg
        .set    i, 26
        .irp    p, xl,xh,yl,yh,zl,zh
            .if (\p == \reg)
                .set    selector ,(selector | (1 << i))
            .endif
            .set    i, i+1
        .endr
    .endr

    ; проверяем список аргументов на SREG
    .irp    reg,\arg
        .irp    p, SREG, sreg
            .if (\p == \reg)
                .set    selector ,(selector | 1)        ; сделаем отметку для r0
                .set    sel_sreg ,1                     ; сделаем отметку для SREG
            .endif
        .endr
    .endr

    ; сохраняем регистры
   
    ; сначала r0
    .if (selector & (1))
        push    r0
    .endif

    ; потом SREG
    .if (sel_sreg)
        in      r0, _SFR_IO_ADDR(SREG)                  ; _SFR_IO_ADDR(SREG) - извлекаем адрес порта
        push    r0
    .endif

    ; наконец все остальные, перебрать биты selector от МЛАДШЕГО к старшему и сохранить нужные регистры
    .set    i, 1
    .irp    p, r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,r13,r14,r15,r16,r17,r18,r19,r20,r21,r22,r23,r24,r25,r26,r27,r28,r29,r30,r31
        .if (selector & (1<< i))
            push    \p
        .endif
        .set    i, i+1
    .endr

.endm


;----------
.macro LEAVE
    .set    i, 31
    ; регистры до r1
    .irp    p, r31,r30,r29,r28,r27,r26,r25,r24,r23,r22,r21,r20,r19,r18,r17,r16,r15,r14,r13,r12,r11,r10,r9,r8,r7,r6,r5,r4,r3,r2,r1
        .if selector &(1<< i)
            ; если бит в маске установлен - регистр извлекается из стека
            pop \p
        .endif
        ; перебор битов ведется в обратном порядке!!!
        .set    i, i - 1
    .endr
    .if (sel_sreg)
        pop     r0
        out     _SFR_IO_ADDR(SREG), r0
    .endif
    .if (selector & (1))
        pop     r0
    .endif

.endm


; Например, вот такой исходник

;.global main
;main:
;ENTER r2,r3,SREG,ZH,ZL
;nop
;LEAVE

; Тут нужен препроцесор, т.к. avr-as его не умеет,
; а определения регистров ввода-вывода прописаны
; в Си-шных заголовочных файлах (привет SREG :-) ).
; С помощью вот таких командочек
; avr-gcc -E -mmcu=atmega48 gnu-as_macros.S | avr-as -mmcu=atmega48 -
; avr-objdump -d a.out
; Получим вот такой код

;00000000 <main>:
;   0:   0f 92           push    r0
;   2:   0f b6           in      r0, 0x3f        ; 63
;   4:   0f 92           push    r0
;   6:   2f 92           push    r2
;   8:   3f 92           push    r3
;   a:   ef 93           push    r30
;   c:   ff 93           push    r31
;   e:   00 00           nop
;  10:   ff 91           pop     r31
;  12:   ef 91           pop     r30
;  14:   3f 90           pop     r3
;  16:   2f 90           pop     r2
;  18:   0f 90           pop     r0
;  1a:   0f be           out     0x3f, r0        ; 63
;  1c:   0f 90           pop     r0


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

Вт янв 29, 2019 14:40:41

Что-то крепко торможу - поясните пожалуйста.

AVR MEGA использую таймер 1 в режиме WGM10 =1, WGM11 =0, WGM12 =0, WGM13 =1

От скольких и до скольких считает собственно таймер и в какой момент обновляется позиция по которой переключается ШИМ выход ? Не момент переключения выхода а момент с которого число для сравнения, загруженное в OCR1A(B) будет актуально. При каком значении таймера. (предполагаю что 0)

А второй вопрос - вот такой код : (Ячейка может содержать значения 1-4), R1=0, P1-P4 - метки на некие программные действия, ВЫХОД - ничего не делать как вообще работает и зачем он такой сложный...

lds r24, Ячейка
lds r25, Ячейка


cpi r24, 2
cpc r25, R1
breq P2
cpi r24, 3
cpc r25, R1
brcc P3
sbiw r24, 1
brne ВЫХОД
rjmp P1

P3:
cpi r24, 3
cpc r25, R1
breq P4

sbiw r24, 4
brne ВЫХОД

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

Вт янв 29, 2019 15:02:17

В DS на меги явно указано когда для режима 9 идет занесение. За счет буфера можно заносить не заботясь о глюках. Актуальное значение в OCR1A будет выполнено в следующих, после переноса циклах.
СпойлерИзображение
Вложения
M8515_COMP9.PNG
(76.06 KiB) Скачиваний: 328

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

Вт янв 29, 2019 15:29:57

А величина этого BOTTOM чем определяется - так как похоже не до 65535 считает и по коду вопрос стоит.
Ответить