Ассемблер (ASM) для AVR в вопросах и ответах
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Еще такой вопрос, для чего умножают число которое хотят преобразовать на 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
И потом старшую тетраду умножают на 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 в вопросах и ответах
По мне, это замена операции деления умножением. X/10=X*K*256/10*256; отсюда K=256/10=25,6. Но, это довольно грубый коэффициент, поэтому разработчик программы преобразования BIN-BCD искусственно умножает его на 4 с округлением в большую сторону, т.е. K=4*256/10=102,4~103(0x67), а затем уже в программе делит сдвигами вправо полученное число на 4. На истинность не претендую.baghear писал(а):Еще такой вопрос, для чего умножают...на 0х67?
И потом старшую тетраду умножают на 4?
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Опишите подробнее пожалуйста как Вы заменили деление умножением.
У Вас деление в выражении с обоих сторон от равно
X/10=X*K*256/10*256
У Вас деление в выражении с обоих сторон от равно
X/10=X*K*256/10*256
- WiseLord
- Друг Кота
- Сообщения: 4905
- Зарегистрирован: Чт апр 11, 2013 11:19:59
- Откуда: Минск
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Там просто много опечаток в формуле.
Принцип простой - чтобы разделить на 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.
Принцип простой - чтобы разделить на 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 в вопросах и ответах
Согласен, не корректная запись. Ещё раз X/10=X*(256/256)/10. Если обозначить подчёркнутое как K=256/10, то получим X/10=X*K/256. Ещё в тему.akl писал(а):X/10=X*K*256/10*256
Ничего не надо подбирать.WiseLord писал(а):главное подобрать коэффициент
Re: Ассемблер (ASM) для AVR в вопросах и ответах
исходные данные: 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" и т.п)
А.
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" и т.п)
Последний раз редактировалось nirq Чт июн 19, 2014 15:45:18, всего редактировалось 6 раз.
Re: Ассемблер (ASM) для AVR в вопросах и ответах
BCD_VALUE / .10 = результат (0..255)
Результат будет 0...25 или не так понял?
256 * 4 * ( BCD_VALUE / 10 )
Откуда появилось 256?
Результат будет 0...25 или не так понял?
256 * 4 * ( BCD_VALUE / 10 )
Откуда появилось 256?
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Деление на 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 в вопросах и ответах
Спасибо akl, этот кусочек понял.
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Хорошо, пошли дальше
Внимание. Этот код правильно преобразовывает числа в диапазоне 0...99!!!
Код: Выделить всё
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 ; склеить тетрады
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Разобрался!!!
Спасибо
То что это код работает до 99 понятно.
Может у Вас есть код который работает до 999, на асм?
Спасибо
То что это код работает до 99 понятно.
Может у Вас есть код который работает до 999, на асм?
Re: Ассемблер (ASM) для AVR в вопросах и ответах
В принципе, есть. Код довольно легко меняется как в сторону увеличения так уменьшения, подходит для камней без аппаратной поддержки умножения.
Re: Ассемблер (ASM) для AVR в вопросах и ответах
как известно ресет вызывается тремя способами:
- при включении питания
- при нажатии кнопки
- с помощью watchdog
а если я сделаю прыжок на нулевой адрес, будет ли оный ресет равносильный первым трем ?
- при включении питания
- при нажатии кнопки
- с помощью watchdog
а если я сделаю прыжок на нулевой адрес, будет ли оный ресет равносильный первым трем ?
Tell Me The Truth
- ibiza11
- Поставщик валерьянки для Кота
- Сообщения: 1900
- Зарегистрирован: Сб фев 21, 2009 13:11:40
- Откуда: Москва
Re: Ассемблер (ASM) для AVR в вопросах и ответах
не будет.FreshMan писал(а):будет ли оный ресет равносильный первым трем ?
Ставим плюсы: )
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18544
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
потому что аппаратный сброс производит инициализацию периферии, например, обнуляет все регистры DDRх и PORTx, а что там у вас делается по нулевому адресу - известно только вам.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Привет всем! Есть один канал АЦП, и есть клавиатура из 4-х кнопок, к нему подключённая. Единственное, чего нет, так это защиты от дребезга контактов, из-за чего АЦП иногда неверно интерпретирует нажатую кнопку. Интересует кто как борется с этим дребезгом. Больше даже интересен не сам код, сколько принцип, да так чтоб оно работало хорошо и быстро! 
Прибор, защищённый предохранителем, сгорает первым, защитив предохранитель. Закон Мерфи.
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Seriyvolk писал(а):Есть один канал АЦП, и есть клавиатура из 4-х кнопок, к нему подключённая. Интересует кто как борется с этим дребезгом.
Методов много и выбор зависит от ресурсов.
Например адц работает в цикле. С частотой например 15Гц. Берем результат и запоминаем в буфер на 3 результата выбрасывая более старые. Нажатие считаем если последнии результаты равны. Необходимо учитывать шум в измерениях, например выбрасывать младшие биты сдвигом, пори этом инкрементнуть, если последний сдвинутый был 1 (округление).
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Вот как раз шум АЦП и интересен. Какой порядок цифр ожидать, если вести речь конкретно о тини13?
Прибор, защищённый предохранителем, сгорает первым, защитив предохранитель. Закон Мерфи.
Re: Ассемблер (ASM) для AVR в вопросах и ответах
(здесь был выебон не по делу)
Последний раз редактировалось nirq Пт июн 20, 2014 19:36:32, всего редактировалось 1 раз.