Ассемблер (ASM) для AVR в вопросах и ответах
Re: Ассемблер (ASM) для AVR в вопросах и ответах
А чем оно лучше ADIW, SBIW ? Тем, что флаги не трогает ?
- Starichok51
- Модератор
- Сообщения: 19039
- Зарегистрирован: Сб авг 14, 2010 15:05:51
- Откуда: г. Озерск, Челябинская обл.
Re: Ассемблер (ASM) для AVR в вопросах и ответах
именно тем и лучше.
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Не всегда лучше.
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Просто очень древний приём.
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Ёще раз благодарю за ответы! Помогите пожалуйста решить еще одну проблему в этом же проекте. Я использую АЦП МК Atmega8, он десятибитный.
Необходимо напряжение от 0 до (примерно) 5 Вольт разбить на 511 шагов. Для этого мне надо использовать всего девять бит регистров преобразования ADCL, ADCH. Если использовать все десять бит, то в младшем бите регистра ADCL появляется сигнал ошибки, видимо вызванный шумом МК и внешними наводками. Поэтому я пытаюсь сделать так: сначала копирую содержимое регистра ADCL в регистр XL, ADCH в XH. Далее мне надо сделать логический сдвиг вправо всей регистровой пары X c переносом младшего бита регистра ХH в старший бит XL. При этом, младший "вытесненный" бит регистра XL мне не нужен, а в старший бит регистра ХH надо записать ноль. Далее уже работать с этим числом. Таким образом я хочу с эмитировать девяти разрядный АЦП. Подскажите как сделать логический сдвиг вправо всей регистровой пары X?
Картинку прилагаю
Необходимо напряжение от 0 до (примерно) 5 Вольт разбить на 511 шагов. Для этого мне надо использовать всего девять бит регистров преобразования ADCL, ADCH. Если использовать все десять бит, то в младшем бите регистра ADCL появляется сигнал ошибки, видимо вызванный шумом МК и внешними наводками. Поэтому я пытаюсь сделать так: сначала копирую содержимое регистра ADCL в регистр XL, ADCH в XH. Далее мне надо сделать логический сдвиг вправо всей регистровой пары X c переносом младшего бита регистра ХH в старший бит XL. При этом, младший "вытесненный" бит регистра XL мне не нужен, а в старший бит регистра ХH надо записать ноль. Далее уже работать с этим числом. Таким образом я хочу с эмитировать девяти разрядный АЦП. Подскажите как сделать логический сдвиг вправо всей регистровой пары X?
Картинку прилагаю
- Вложения
-
- Логический сдвиг.jpg
- (88.01 КБ) 399 скачиваний
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Снижать разрешение АЦП как то не очень.
Получили усечение. Хотя, правильнее сделать округление
Код: Выделить всё
LSR XH
ROR XLПолучили усечение. Хотя, правильнее сделать округление
Код: Выделить всё
LSR XH
ROR XL
CLR R0
ADC XL,R0
ADC XH,R0
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Спасибо akl. Попробую.
-
Alexeyslav
- Друг Кота
- Сообщения: 4550
- Зарегистрирован: Чт май 05, 2011 21:26:34
- Откуда: Украина, Славутич
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Если младший бит смущает шумом, значение можно всегда пропустить через фильтр подвижного окна. И использовать все 10 бит.
Re: Ассемблер (ASM) для AVR в вопросах и ответах
[uquote="Starichok51",url="/forum/viewtopic.php?p=3542126#p3542126"]4 байта сдвинуть 4 раза и без swap займет 16 циклов (а не тактов).
Именно поэтому я и спрашивал про быстрее 16 циклов/тактов.
Starichok51, pyzhman, BOB51 спасибо!
4epemyxa спасибо за вариант кода с умножением!
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Здравствуйте! Помогите решить проблему с АЦП в МК 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?
Если настраиваю тактовую частоту МК 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?
-
Alexeyslav
- Друг Кота
- Сообщения: 4550
- Зарегистрирован: Чт май 05, 2011 21:26:34
- Откуда: Украина, Славутич
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Скорей ньюансы со считыванием регистров. Там имеется защёлка, когда один регистр читаешь то пока второй не прочитаешь защёлка не уберётся и новое значение в регистр не попадёт. Если у вас такая каша в программе происходит что работаете то в 8-битном режиме то в 10-битном просто тогда для 8 бит читайте оба регистра как и в 10-битном режиме. Видимо при переключениях и последующем чтении происходит срабатывание защелки.
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Порядок чтения тоже важен.
Спойлер
Код: Выделить всё
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 GORe: Ассемблер (ASM) для AVR в вопросах и ответах
Благодарю akl и Alexeyslav за ответы! Сейчас попробую исправить.
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Скорей ньюансы со считыванием регистров. Там имеется защёлка, когда один регистр читаешь то пока второй не прочитаешь защёлка не уберётся и новое значение в регистр не попадёт.
Попадёт, не путайте людей.
Я всё-всё узнAю и стану профессором.
Re: Ассемблер (ASM) для AVR в вопросах и ответах
ADMUX (ADLAR = 1)
in XH, ADCH
in XL, ADCL
in XH, ADCH
in XL, ADCL
МКС, если вам достаточно 8 старших бит от АЦП, то выровненный в лево результат читайте из старшего регистра АЦП, а младший не трогайте совсем.
При чтении из младшего регистра доступ к регистрам АЦП блокируется пока не прочитаете старший. Т.е. АЦП не сможет поместить новое значение в регистры пока не прочитаете в программе старший регистр!
Поэтому или пользуетесь только старшим регистром или читаете сначала младший, а потом старший.
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Alexeyslav, akl, dgrett, Kavka - очень выручили ребята! Все так и было! Проблема исчезла после перестановки порядка считывания регистров (ADCL затем ADCH). Очень благодарен!!!
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Эх, давно это было...
Слегка
модифицированный вариант.
Вместо того, чтобы сладко спать, я до сего времени пытался запустить Ваш макрос.
Z_h_e, как же я вас понимаю.
Данный макрос коварен.
Если Вы напишите 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
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
-
Wladimir_TS
- Друг Кота
- Сообщения: 5066
- Зарегистрирован: Вс фев 15, 2009 01:04:58
- Откуда: Kaluga
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Что-то крепко торможу - поясните пожалуйста.
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 ВЫХОД
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 в вопросах и ответах
В DS на меги явно указано когда для режима 9 идет занесение. За счет буфера можно заносить не заботясь о глюках. Актуальное значение в OCR1A будет выполнено в следующих, после переноса циклах.

Спойлер
- Вложения
-
- M8515_COMP9.PNG
- (76.06 КБ) 403 скачивания
-
Wladimir_TS
- Друг Кота
- Сообщения: 5066
- Зарегистрирован: Вс фев 15, 2009 01:04:58
- Откуда: Kaluga
Re: Ассемблер (ASM) для AVR в вопросах и ответах
А величина этого BOTTOM чем определяется - так как похоже не до 65535 считает и по коду вопрос стоит.
