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

Обсуждаем контроллеры компании Atmel.
Ответить
Встал на лапы
Аватара пользователя
Сообщения: 117
Зарегистрирован: Ср окт 15, 2014 12:45:46
Откуда: Анапа

Сообщение Jetetex »

всем доброго времени. Помогите разобратся с АЦП в ATtiny13. Собрал в протеусе, написал код, все работает меряет и через 2 сдвиговых выдает результат измерений в чистом (двоичном) виде. Вопрос: как пересчитать значения этого кода - это %, разность или напряжение в двоичной форме?

Attiny 13;
Proteus 8.
код правда без украшательств, я его еще ковыряю..
Спойлер;==============
; Main.asm file generated by New Project wizard
;
; Created: Пн авг 7 2017
; Processor: ATtiny13
; Compiler: AVRASM (Proteus)
;==============

;==============
.org 0 ;Задание нулевого адреса старта программы
rjmp reset ;Безусловный переход к метке reset
.org 9 ;Задание адреса прерывания по окончанию преобразования АЦП
rjmp ADC_complete;Безусловный переход к метке ADC_complete

reset: ;Начало раздела инициализации контроллера
ldi r16,RAMEND ;Загрузка в регистр r16 адреса верхней границы ОЗУ
out SPL, r16 ;Копирование значения из r16 в регистр указателя стека SPL
ldi r16,0b11110111;Загрузка в r16 единиц в нулевой и четвертый биты
out DDRB,r16 ;Переключение выводов PB0 и PB4 на выход
;ldi r16,(1<<ADLAR)|(1<<MUX0)|(1<<MUX1);См. описание программы
ldi r16,(1<<MUX0)|(1<<MUX1);См. описание программы
out ADMUX,r16 ;Копирование из r16 в ADMUX
ldi r16,(1<<ADEN)|(1<<ADSC)|(1<<ADIE)|(1<<ADPS1);См.опис.
out ADCSRA,r16 ;Копирование из r16 в ADCSRA
ldi r17,0
sei ;Глобальное разрешение прерываний

main: ;Основной цикл программы

ldi r16,(1<<ADEN)|(1<<ADSC)|(1<<ADIE)|(1<<ADPS1);См.опис.
out ADCSRA,r16 ;Копирование из r16 в ADCSRA


ldi r20,255
d:
dec r20
brne d
rcall shift

rjmp main ;Конец основного цикла программы

ADC_complete:;Начало обработчика прерывания от АЦП
in r17,ADCL
in r16,ADCH ;Копирование в регистр r16 результата преобразования

reti ;Возврат из прерывания

shift:
cbi portb,0
ldi r19,16
mov r18,r16
mov r21,r17
sh1:
sbrs r18,7 ;Если 7-й бит в регистре r16 равен 1, пропустить след. строку
cbi PORTB,1 ;Установить 4-й бит PORTB (выключить LED2)
sbrc r18,7 ;Если 7-й бит в регистре r16 равен 0, пропустить след. строку
sbi PORTB,1 ;Сбросить 4-й бит в регистре PORTB (включить LED2)
nop
nop

sbi portb,0
cbi portb,0

rol r21
rol r18

dec r19
nop
brne sh1

cbi portb,2
sbi portb,2
cbi portb,2
ret
Вложения
ADC_volt.zip
(100.28 КБ) 243 скачивания
Если я чего-то не знаю, это не говорит о моем невежестве, а только о том, что раньше этот вопрос лежал вне сферы моих интересов.
Реклама
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

Jetetex писал(а):Вопрос: как пересчитать значения этого кода - это %, разность или напряжение в двоичной форме?
Вы спрашиваете что значит код АЦП?
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Реклама
Встал на лапы
Аватара пользователя
Сообщения: 117
Зарегистрирован: Ср окт 15, 2014 12:45:46
Откуда: Анапа

Сообщение Jetetex »

да.
Мои мысли таковы - опорное напр (5 вольт ) / 2^10 (10 разр ацп) = некое напряжение (0.0048 вольт). Затем результат работы ацп умножаем на эти самые 0.0048 и получаем измеренное напряжение.

Где я ошибся? (просто не мог не ошибится :) )
Последний раз редактировалось Jetetex Вт авг 08, 2017 18:37:09, всего редактировалось 1 раз.
Если я чего-то не знаю, это не говорит о моем невежестве, а только о том, что раньше этот вопрос лежал вне сферы моих интересов.
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

Так то в ДШ написано как считать. Код 0 - это ноль на АЦП. Код 1023 - это напряжение на АЦП >= ИОН. 512 - значит половина ИОН.

Добавлено after 12 minutes 57 seconds:
Jetetex писал(а):Где я ошибся?
А Вы и не написали, что сделали, что ожидали и что получили.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Реклама
Эиком - электронные компоненты и радиодетали
Встал на лапы
Аватара пользователя
Сообщения: 117
Зарегистрирован: Ср окт 15, 2014 12:45:46
Откуда: Анапа

Сообщение Jetetex »

Пока писАл вопросы и измывался над Proteus'ом - разобрался. максимальное значение регистров результата = ИОН = 2047 (2^1+2^2+2^3+...+2^9+2^10 = 00000011 11111111 ) таким образом самый младший бит, тот который 2^1, имеет значение 0.0024 вольта, самый старший 2^10 = 2.46. Далее переводим умножая 0.0024 на десятичный эквивалент полученого результата.

Тоесть
..
512 = 25% ИОН
..
1024 = 50%
..
1536 = 75%
2047 = 100%

PS. С ДШ у меня проблемы. Она все на англицком.
Если я чего-то не знаю, это не говорит о моем невежестве, а только о том, что раньше этот вопрос лежал вне сферы моих интересов.
Реклама
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

Максимальное 10ое число это 1023. Как Вы 2047 получили?

Вот формула из ДШ, тут обычная математика.
Изображение

Правда мне непонятно почему в формуле 1024, а не 1023.

Добавлено after 1 minute 11 seconds:
Мои мысли таковы - опорное напр (5 вольт ) / 2^10 (10 разр ацп) = некое напряжение (0.0048 вольт). Затем результат работы ацп умножаем на эти самые 0.0048 и получаем измеренное напряжение.
Правильные же мысли были, не мудрите.
Вложения
adc.gif
(1.61 КБ) 835 скачиваний
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Реклама
Встал на лапы
Аватара пользователя
Сообщения: 117
Зарегистрирован: Ср окт 15, 2014 12:45:46
Откуда: Анапа

Сообщение Jetetex »

[uquote="Z_h_e",url="/forum/viewtopic.php?p=3158592#p3158592"]Максимальное 10ое число это 1023. Как Вы 2047 получили?[/uquote]

Мне самому теперь не понятно. :oops:
Если я чего-то не знаю, это не говорит о моем невежестве, а только о том, что раньше этот вопрос лежал вне сферы моих интересов.
Друг Кота
Аватара пользователя
Сообщения: 4906
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Z_h_e писал(а):Правда мне непонятно почему в формуле 1024, а не 1023.
Может, потому что так оно и есть?.

Любые значения в диапазоне [0..1) - это 0, [1..2) - это 1, ..., [1023..1024) - это 1023, всё выше - тоже 1023.

АЦП изменяет весь диапазон 0..1024, просто именно верхнюю границу отобразить не может. Вот в формуле и фигурирует 1024, что, к счастью, сильно упрощает вычисления.
Контактная информация:
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

Возьмем для примера гипотетическое АЦП 2х разрядное (просто на нем нагляднее будет) .
Пускай ИОН 5 В. АЦП выдало код 3. По аналогии считаем 2^2/3*5=6,67В. Плохая математика получается. Конечно чем больше разрядность, тем менее это заметно.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Встал на лапы
Аватара пользователя
Сообщения: 117
Зарегистрирован: Ср окт 15, 2014 12:45:46
Откуда: Анапа

Сообщение Jetetex »

Чисто в порядке бреда - может потому что "0" тоже может быть результатом измерения, отсюда имеем 1024, скажем так, варианта
Если я чего-то не знаю, это не говорит о моем невежестве, а только о том, что раньше этот вопрос лежал вне сферы моих интересов.
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

Конечно 0 может быть результатом АЦП. Но я специально привел пример 2х разрядного АЦП, чтобы было понятно что я тут считаю не так с математикой.
В реале, для 10 битного АЦП, да еще и при шумящем младшем бите (это в лучшем случае) - это не имеет особого значения. Просто считайте меня занудой :).
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Друг Кота
Аватара пользователя
Сообщения: 4906
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

[uquote="Z_h_e",url="/forum/viewtopic.php?p=3158621#p3158621"]Возьмем для примера гипотетическое АЦП 2х разрядное (просто на нем нагляднее будет) .
Пускай ИОН 5 В. АЦП выдало код 3. По аналогии считаем 2^2/3*5=6,67В. Плохая математика получается. Конечно чем больше разрядность, тем менее это заметно.[/uquote]
Что-то я не совсем понял, что это Вы посчитали.

Формула по аналогии будет ADC = Vin/Vref * 2^2, откуда Vin = ADC * Vref / (2^2)

В нашем гипотетическом случае Vin = ADC * 5 / 4. (Vin = ADC * 5 / 3, если брать 2^2-1).

Как по мне, первая картинка, под первую формулу, правильнее:

Изображение
Контактная информация:
Прорезались зубы
Аватара пользователя
Сообщения: 211
Зарегистрирован: Пт окт 21, 2011 14:39:31

Сообщение FeCat »

Может не совсем в тему, но...
Пишу на с, asm не знаю совершенно, не могу понять почему ATMega32, во время выполнения программы, как будто виснет. Если во время "зависания" была включена отладка и нажать останов, то останавливается вот тут:

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

--- No source file -------------------------------------------------------------
0000037E  LSL R30		Logical Shift Left 
0000037F  ROL R31		Rotate Left Through Carry 
00000380  LPM R0,Z+		Load program memory and postincrement 
00000381  LPM R31,Z		Load program memory 
00000382  MOV R30,R0		Copy register 
00000383  IJMP 		Indirect jump to (Z) 
00000384  CLI 		Global Interrupt Disable 
00000385  RJMP PC-0x0000		Relative jump                           // вот тут получается останов
00000386  NOP 		Undefined 
00000387  NOP 		Undefined 
00000388  NOP 		Undefined 
00000389  NOP 		Undefined 
0000038A  NOP 		Undefined 
0000038B  NOP 		Undefined 
0000038C  NOP 		Undefined 
0000038D  NOP 		Undefined 
0000038E  NOP 		Undefined 
0000038F  NOP 		Undefined 
00000390  NOP 		Undefined 
00000391  NOP 		Undefined 
00000392  NOP 		Undefined 
Правильно ли я понимаю, что "RJMP PC-0x0000" это, что то вроде перехода по адресу относительно команды, а т.к. параметр нулевой, получается переход на саму себя, т.е. вечный while(1)?
Т.к. перед этим стоит CLI - глобальный запрет прерываний, вся эта петрушка вероятно из-за какого то аппаратного сбоя в МК или программе, это своеобразный стоп работы(максимизация ошибки). В самой программе ничего такого нет, т.е. это компиллятор по умолчанию добавляет(Atmel Studio 7.0)?
Если отбросить железные проблемы, то почему такое может происходить?
akl
Друг Кота
Сообщения: 4473
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Сообщение akl »

По мне,
FeCat писал(а):это компиллятор по умолчанию добавляет
в конце программы, а вот косвенный переход по адресу в указателе Z выбрасывает в заадресное пространство mega32. Как вариант, компилируете для камня с адресным пространством >32к.
Это не хвост, это антенна
Сообщения: 1495
Зарегистрирован: Ср июн 25, 2008 15:19:44

Сообщение Demiurg »

[uquote="FeCat",url="/forum/viewtopic.php?p=3158782#p3158782"]...[/uquote]
Этот кусок аварийный. Если какой-нибудь сбой, незапланированное прерывание, то программа уйдет на выполнение этого кода. Глобальный запрет прерываний, cli и rjmp PC+0 - глухое зацикливание программы. Возможно у вас включено какое-то прерывание, а обработчика нет. Компилятор в таких случаях автоматом делает такие программные заглушки.
Контактная информация:
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18791
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

Demiurg писал(а):Возможно у вас включено какое-то прерывание, а обработчика нет. Компилятор в таких случаях автоматом делает такие программные заглушки.
avr-gcc в этом случае не зацикливает программу, а перебрасывает её на нулевой вектор, т.е. выполняет пересброс.

avr-gcc автоматически генерирует последовательность cli; jmp PC - 0; только в одном месте: там, где происходит выход из main.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

WiseLord писал(а):Как по мне, первая картинка, под первую формулу, правильнее:
Не надо было приводить даже такие картинки, в ДШ есть график на котором указано что Vref выше 0x3FF. И формулу расчета я не пытался оспаривать, как сделали разрабы камня, так и надо считать. Просто мои зачерепные опилки желают, чтобы максимум АЦП соответствовал опоре.
WiseLord писал(а):Что-то я не совсем понял, что это Вы посчитали.
Что тут может быть непонятного, хрень какую-то насчитал я. :oops: Хотел показать, что код АЦП не будет соотвествовать ИОН никогда и показал :)) .

Добавлено after 8 minutes 29 seconds:
ARV писал(а):avr-gcc в этом случае не зацикливает программу, а перебрасывает её на нулевой вектор, т.е. выполняет пересброс.
Можно вставить обработчик по умолчанию ISR(__vector_default), но он же тоже не циклит, если сам это не сделаешь.
FeCat писал(а):Если отбросить железные проблемы, то почему такое может происходить?
А Вы запустите в симуляторе код и в окне дизассемблера должно быть указано к какому участку исходного кода соответствует машинный.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Это не хвост, это антенна
Сообщения: 1495
Зарегистрирован: Ср июн 25, 2008 15:19:44

Сообщение Demiurg »

ARV писал(а):в одном месте: там, где происходит выход из main.
И где же у нас выход из майн? Если майн вызывается.
Контактная информация:
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18791
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

Demiurg писал(а):И где же у нас выход из майн?
я пометил место, где он :)))

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

int main(void){
   
} <<<< вот где-то тут
если посмотреть листинг, который генерирует avr-gcc, то можно увидеть ОБЯЗАТЕЛЬНО такой (не считая адресов, конечно) кусочек:

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

  32:	14 d0       	rcall	.+40     	; 0x5c <main>
  34:	19 c0       	rjmp	.+50     	; 0x68 <_exit>

; что-то там всякое


00000068 <_exit>:
  68:	f8 94       	cli

0000006a <__stop_program>:
  6a:	ff cf       	rjmp	.-2      	; 0x6a <__stop_program>

обратите внимание на вход в main и выход из него

Добавлено after 9 minutes 57 seconds:
Кстати, вот другой кусочек, поясняющий, как avr-gcc обслуживает прерывания, для которых нет обработчика (bad_interrupt):

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

00000000 <__vectors>:
   0:	12 c0       	rjmp	.+36     	; 0x26 <__ctors_end>
   2:	19 c0       	rjmp	.+50     	; 0x36 <__bad_interrupt>
   4:	18 c0       	rjmp	.+48     	; 0x36 <__bad_interrupt>
   6:	17 c0       	rjmp	.+46     	; 0x36 <__bad_interrupt>
   8:	17 c0       	rjmp	.+46     	; 0x38 <__vector_4>
   a:	15 c0       	rjmp	.+42     	; 0x36 <__bad_interrupt>
   c:	14 c0       	rjmp	.+40     	; 0x36 <__bad_interrupt>
   e:	13 c0       	rjmp	.+38     	; 0x36 <__bad_interrupt>
  10:	12 c0       	rjmp	.+36     	; 0x36 <__bad_interrupt>
  12:	11 c0       	rjmp	.+34     	; 0x36 <__bad_interrupt>
  14:	10 c0       	rjmp	.+32     	; 0x36 <__bad_interrupt>
  16:	0f c0       	rjmp	.+30     	; 0x36 <__bad_interrupt>
  18:	0e c0       	rjmp	.+28     	; 0x36 <__bad_interrupt>
  1a:	0d c0       	rjmp	.+26     	; 0x36 <__bad_interrupt>
  1c:	0c c0       	rjmp	.+24     	; 0x36 <__bad_interrupt>
  1e:	0b c0       	rjmp	.+22     	; 0x36 <__bad_interrupt>
  20:	0a c0       	rjmp	.+20     	; 0x36 <__bad_interrupt>
  22:	09 c0       	rjmp	.+18     	; 0x36 <__bad_interrupt>
  24:	08 c0       	rjmp	.+16     	; 0x36 <__bad_interrupt>

00000026 <__ctors_end>:
  26:	11 24       	eor	r1, r1
  28:	1f be       	out	0x3f, r1	; 63
  2a:	cf e5       	ldi	r28, 0x5F	; 95
  2c:	d4 e0       	ldi	r29, 0x04	; 4
  2e:	de bf       	out	0x3e, r29	; 62
  30:	cd bf       	out	0x3d, r28	; 61
  32:	14 d0       	rcall	.+40     	; 0x5c <main>
  34:	19 c0       	rjmp	.+50     	; 0x68 <_exit>

00000036 <__bad_interrupt>:
  36:	e4 cf       	rjmp	.-56     	; 0x0 <__vectors>
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Это не хвост, это антенна
Сообщения: 1495
Зарегистрирован: Ср июн 25, 2008 15:19:44

Сообщение Demiurg »

ARV писал(а):...
Вы не учитываете одну очень важную вещь. И это говорит о том, что вы не ассемблерщик. Пусть даже и так, вы обязаны заглядывать в дизасм. Иначе как вы оцениваете работу МК в тяжелых случаях.

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

   rcall main
Подсказка. Main вызван, а стек сорван.
Последний раз редактировалось Demiurg Ср авг 09, 2017 16:21:38, всего редактировалось 1 раз.
Контактная информация:
Ответить

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