Страница 229 из 400

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

Добавлено: Ср июн 18, 2014 00:26:16
baghear
Еще такой вопрос, для чего умножают число которое хотят преобразовать на 0х67?
И потом старшую тетраду умножают на 4?
Код:

BcdByteTo:
// divide value by 10
ldi BCD_MUL, 0x67 // multiplicative inverse of 10
mul BCD_MUL, BCD_VALUE
mov BCD_TEMP, r1
lsr BCD_TEMP
lsr BCD_TEMP

// BCD_TEMP now - result of division and high nibble of BCD

// multiple back to calculate reminder (low nibble of BCD)
ldi BCD_MUL, 10
mul BCD_TEMP, BCD_MUL
sub BCD_VALUE, r0

// BCD_VALUE now - reminder and low nibble of BCD

// join low and high nibbles
swap BCD_TEMP
andi BCD_TEMP, 0xF0
or BCD_VALUE, BCD_TEMP
ret

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

Добавлено: Ср июн 18, 2014 07:34:08
akl
baghear писал(а):Еще такой вопрос, для чего умножают...на 0х67?
И потом старшую тетраду умножают на 4?
По мне, это замена операции деления умножением. X/10=X*K*256/10*256; отсюда K=256/10=25,6. Но, это довольно грубый коэффициент, поэтому разработчик программы преобразования BIN-BCD искусственно умножает его на 4 с округлением в большую сторону, т.е. K=4*256/10=102,4~103(0x67), а затем уже в программе делит сдвигами вправо полученное число на 4. На истинность не претендую.

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

Добавлено: Ср июн 18, 2014 11:29:43
baghear
Опишите подробнее пожалуйста как Вы заменили деление умножением.
У Вас деление в выражении с обоих сторон от равно
X/10=X*K*256/10*256

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

Добавлено: Ср июн 18, 2014 11:58:05
WiseLord
Там просто много опечаток в формуле.
Принцип простой - чтобы разделить на 10, можно для начала умножить на какой-то коэффициент, чтобы потом можно было сдвигом получить результат.

Например: X / 10 = X * 205 / 2050

Т.е., чтобы разделить на 10, можно сначала умножить на 205, а потом разделить на 2050. А разделить на 2050 - это почти то же самое, что разделить на 2048, или сдвинуть на 11 вправо. По крайней мере, для X от 0 до 1023 это так.

Можно и на другие коэффициенты умножать. Если умножать на 0x67 (103), то получится:

X / 10 = X * 103 / 1030.
А разделить на 1030 - это почти то же самое, что разделить на 1024, или сдвинуть на 10 вправо. Но это работает уже только для чисел от 0 до 170.

В принципе, подобным образом можно просчитать любое деление на константу (не только 10), главное подобрать коэффициент, дающий в делителе число, чуть большее степени двойки. Чем ближе оно к степени двойки, тем для большего диапазона входных чисел результат будет верен.
Например,

X / 19 = X * 27 / 513 ~ X * 27 / 512, верно для X от 0 до 512.

X / 7 = X * 293 / 2051 ~ X * 293 / 2048, верно для X от 0 до 682.

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

Добавлено: Ср июн 18, 2014 12:13:50
akl
akl писал(а):X/10=X*K*256/10*256
Согласен, не корректная запись. Ещё раз X/10=X*(256/256)/10. Если обозначить подчёркнутое как K=256/10, то получим X/10=X*K/256. Ещё в тему.
WiseLord писал(а):главное подобрать коэффициент
Ничего не надо подбирать.

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

Добавлено: Ср июн 18, 2014 16:29:41
nirq
исходные данные: BCD_VALUE (0..255)

А.

BCD_VALUE / .10 = результат (0..255)
256 * 4 * ( BCD_VALUE / 10 ) = старший байт от результата, два раза сдвинутого влево (0..26112 , помещаемся в 15 бит)
( 256 * 4 / 10 ) * BCD_VALUE = старший байт от результата, два раза сдвинутого влево

256 * 4 / 10 = 102.4 ~ 103 = 0x67, округлили в большую сторону

0x67 * BCD_VALUE = старший байт от результата, два раза сдвинутого влево, плюс "(как это будет сказать по-русски reminder, напоминалка?)" (0..26265, даже и так помещаемся в 15 бит)

Б.

от результата умножения берём только старший байт и двигаем его ещё два раза влево, т.е. умножаем на 4
внимание: ( 0..26265 * 4 ) уже может не поместиться в 16 бит !!!
как сделать, чтобы оно туда гарантированно поместилось? ограничить исходное BCD_VALUE.
каким максимально возможным значением его ограничить?
решаем уравнение 0x67 * BCD_VALUE * 4 <= 0xFFFF, получается BCD_VALUE <= 0x9F = 159

Или нет.

... дальше в исходном коде идёт камент "// BCD_TEMP now - result of division and high nibble of BCD" и магическая магия, а я иду кушать.
Но общий смысл такой, что "ремайндер после округления 102.4 до 0х67" не выбрасывается, а как-то потом учитывается в готовом результате.

Нуевовжопу такие "рационализации". Один вые потешил своё лично кульхацкерское самолюбие, другому потом отлаживать это всё, а третьему поддерживать и развивать проэхт, состоящий из вот такого вот.
Одинкуй глаза пользователя не различат цифры, обновляющиеся заметно чаще, чем раз в секунду. А за секунду это всё можно посчитать тупо вычитанием, в фоновом режиме (в майнлупе), не мешая никаким более важным задачам.

Даже пословица есть народная: "увидишь рационализатора - убей!".


___
(смутившая описка поправлена, это было очень важно, зато трудно на фоне "еррор 502" и т.п)

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

Добавлено: Чт июн 19, 2014 01:11:01
baghear
BCD_VALUE / .10 = результат (0..255)
Результат будет 0...25 или не так понял?
256 * 4 * ( BCD_VALUE / 10 )
Откуда появилось 256?

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

Добавлено: Чт июн 19, 2014 09:12:07
akl
Деление на 256 осуществляется простым отбрасыванием младшего байта.

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

 mul BCD_MUL, BCD_VALUE   ; умножить X на 4*256/10
 mov BCD_TEMP, r1   ; разделить результат на 256
 lsr BCD_TEMP
 lsr BCD_TEMP   ; разделить результат на 4. В итоге получить X/10

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

Добавлено: Чт июн 19, 2014 12:08:20
baghear
Спасибо akl, этот кусочек понял.

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

Добавлено: Чт июн 19, 2014 13:08:17
akl
Хорошо, пошли дальше

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

	ldi BCD_MUL, 10
	mul BCD_TEMP, BCD_MUL   ; получить число десятков результата
	sub BCD_VALUE, r0   ; получить число единиц

;// BCD_VALUE now - reminder and low nibble of BCD
;// join low and high nibbles
	swap BCD_TEMP	  ; старшую тетраду на своё место
	andi BCD_TEMP, 0xF0   ; лишняя команда
	or BCD_VALUE, BCD_TEMP   ; склеить тетрады
Внимание. Этот код правильно преобразовывает числа в диапазоне 0...99!!!

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

Добавлено: Чт июн 19, 2014 16:15:54
baghear
Разобрался!!!
Спасибо :))
То что это код работает до 99 понятно.
Может у Вас есть код который работает до 999, на асм?

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

Добавлено: Чт июн 19, 2014 16:48:45
akl
В принципе, есть. Код довольно легко меняется как в сторону увеличения так уменьшения, подходит для камней без аппаратной поддержки умножения.

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

Добавлено: Чт июн 19, 2014 17:07:34
FreshMan
как известно ресет вызывается тремя способами:
- при включении питания
- при нажатии кнопки
- с помощью watchdog
а если я сделаю прыжок на нулевой адрес, будет ли оный ресет равносильный первым трем ?

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

Добавлено: Чт июн 19, 2014 17:20:43
ibiza11
FreshMan писал(а):будет ли оный ресет равносильный первым трем ?
не будет.

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

Добавлено: Чт июн 19, 2014 17:46:44
FreshMan
почему ?

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

Добавлено: Чт июн 19, 2014 17:53:13
ARV
потому что аппаратный сброс производит инициализацию периферии, например, обнуляет все регистры DDRх и PORTx, а что там у вас делается по нулевому адресу - известно только вам.

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

Добавлено: Пт июн 20, 2014 13:20:14
Seriyvolk
Привет всем! Есть один канал АЦП, и есть клавиатура из 4-х кнопок, к нему подключённая. Единственное, чего нет, так это защиты от дребезга контактов, из-за чего АЦП иногда неверно интерпретирует нажатую кнопку. Интересует кто как борется с этим дребезгом. Больше даже интересен не сам код, сколько принцип, да так чтоб оно работало хорошо и быстро! :))

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

Добавлено: Пт июн 20, 2014 17:30:59
Shinen
Seriyvolk писал(а):Есть один канал АЦП, и есть клавиатура из 4-х кнопок, к нему подключённая. Интересует кто как борется с этим дребезгом.
Методов много и выбор зависит от ресурсов.
Например адц работает в цикле. С частотой например 15Гц. Берем результат и запоминаем в буфер на 3 результата выбрасывая более старые. Нажатие считаем если последнии результаты равны. Необходимо учитывать шум в измерениях, например выбрасывать младшие биты сдвигом, пори этом инкрементнуть, если последний сдвинутый был 1 (округление).

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

Добавлено: Пт июн 20, 2014 17:54:15
Seriyvolk
Вот как раз шум АЦП и интересен. Какой порядок цифр ожидать, если вести речь конкретно о тини13?

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

Добавлено: Пт июн 20, 2014 19:03:53
nirq
(здесь был выебон не по делу)