Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Операции над большими числами
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
NickSmith
Для программирования DDS синтезатора, мне надо вычислять код частоты..
Исходные:
Есть константа в виде 5050. Далее мне нужно эту константу разделить на 1000 затем полученный результат разделить на 1 умноженную на 2^28
У полученного результата то что будет после запятой округлить в большую сторону..
Как все это выполнить на асме?? Я нашел только стандартные процедуры деления, которые описаны в апнотах. Но у них нет деления для нецелых числе. Точней только для 1 байтных чисел есть..

Подскажите, как бы все это реализовать??
rx3apf
Цитата(NickSmith @ Mar 8 2010, 23:23) *
Подскажите, как бы все это реализовать??

Или плавучку делать, или изначально умножить делимое на двойку соответствующей степени, таким образом, чтобы после всех делений результат оставался целым с требуемой точностью.
NickSmith
Цитата(rx3apf @ Mar 8 2010, 23:39) *
Или плавучку делать, или изначально умножить делимое на двойку соответствующей степени, таким образом, чтобы после всех делений результат оставался целым с требуемой точностью.

Не очень понимаю как это должно выглядеть??
rx3apf
Цитата(NickSmith @ Mar 8 2010, 23:41) *
Не очень понимаю как это должно выглядеть??

Нужно поделить 5050 на 1000 без потери значимости ? Множим 5050 на 2^10 (5171200, или 4EE800 hex), полученное число делим на 1000. Получилось 5171. Однако результат только выглядит как целое число, а на самом деле это дробное значение 5.0498, в формате 6.10 (двоичных разрядов). Должным образом масштабируя исходные данные, можно работать с дробными числами с помощью простой целочисленной арифметики. Ну, а если нужно что-то серьезное - тогда делать плавучку...
NickSmith
Цитата(rx3apf @ Mar 9 2010, 00:19) *
Должным образом масштабируя исходные данные, можно работать с дробными числами с помощью простой целочисленной арифметики. Ну, а если нужно что-то серьезное - тогда делать плавучку...

А где бы об этом почитать?? Не очень понятно как возникает степень 2, от чего я отталкиваюсь??
Мою задачу можно решить подобным образом??
rx3apf
Цитата(NickSmith @ Mar 9 2010, 00:59) *
А где бы об этом почитать?? Не очень понятно как возникает степень 2, от чего я отталкиваюсь??

Степень двойки выбирается, исходя из требуемой разрядности и точности промежуточных и окончательного результата. В моем примере можно было бы взять не 2^10, а, скажем, 2^12, тогда результат был бы 20684, это было бы то же самое число 5.0498, но в формате 4.12. Однако результат округлен неправильно (взята только целая часть), поэтому точности это не прибавило. Надо бы взять 2^13, а после деления на 1000 еще поделить на 2 простым сдвигом и округлить (это проще, чем проверять остаток от деления). И результат станет 5.0500 (в формате 4.12). Где почитать - так вот сейчас не подскажу, кажется, я в это вникал по каким-то аппликухам к MSP430 (много лет прошло, уж не помню).
Цитата
Мою задачу можно решить подобным образом??

Почему нет ? Простая арифметика, надо просто прикинуть требуемые разрядности, превратить простым умножением на константу (2 в подходящей степени) все дробные значения в целые и с ними работать.
NickSmith
Цитата(rx3apf @ Mar 9 2010, 01:52) *
Почему нет ? Простая арифметика, надо просто прикинуть требуемые разрядности, превратить простым умножением на константу (2 в подходящей степени) все дробные значения в целые и с ними работать.

А я думаю, а если как то сократить мою формулу.. Она рассчитана на 4 байтовые числа, в моем же случае результат в основном двухбайтовый.. Я не могу сообразить, с какой стороны к этому подходить??
Еще как вариант, увеличение и уменьшение уже готового числа, но дело в том, что шаг как я пронаблюдал всегда разный. Иногда на два а иногда и на пять.. Это нужно какой то анализ проводить.. По моему проще вычислять по формуле нужное значение..
cant
Вам нужно не числа сокращать, а формулу. Тобишь оптимизировать вычисления.

Гуглите в сторону чисел с фиксированной запятой, про что Вам rx3apf и говорит
=GM=
Цитата(NickSmith @ Mar 8 2010, 20:23) *
Есть константа в виде 5050. Далее мне нужно эту константу разделить на 1000 затем полученный результат разделить на 1 умноженную на 2^28. У полученного результата то что будет после запятой округлить в большую сторону.

Поточнее определите, что вам нужно. Следуя вашей формуле, вы получите значение (5050/1000)/2^28=1.88127Е-8, по-моему это не то число, которое вы ожидали.
NickSmith
Цитата(=GM= @ Mar 9 2010, 15:28) *
Поточнее определите, что вам нужно. Следуя вашей формуле, вы получите значение (5050/1000)/2^28=1.88127Е-8, по-моему это не то число, которое вы ожидали.

Действительно ошибся. Не на 1000 а на 100.
Получится 13555,99053
а если округлить то 13556 в шестнадцатеричном будет 34F4
=GM=
Как вы вычисляете-то? Что ж из вас ответы клещами приходится тянуть!
NickSmith
Цитата(=GM= @ Mar 9 2010, 20:21) *
Как вы вычисляете-то? Что ж из вас ответы клещами приходится тянуть!

Так как же мне это злодейство побороть.. Уже пол дня в раздумьях и гуглении нахожусь и ничего толкового пока что не нашел..

Цитата(=GM= @ Mar 9 2010, 15:28) *
Поточнее определите, что вам нужно. Следуя вашей формуле, вы получите значение (5050/1000)/2^28=1.88127Е-8, по-моему это не то число, которое вы ожидали.

И опять я ошибся

Правильно это будет выглядеть так:
(5050/10^8)/1*2^28
Если это делать без единицы, то получается ерунда почему то..
формула выглядит так
Значение регистра = выходная частота в мегагерцах/ частота тактового генератора в мегагерцах*2^28

У меня же частоты в герцах и получается буквально одно слово..
Частота тактового генератора в а моем случае 1 мегагерц
rx3apf
Цитата(NickSmith @ Mar 9 2010, 21:45) *
И опять я ошибся

Правильно это будет выглядеть так:
(5050/10^8)/1*2^28
Если это делать без единицы, то получается ерунда почему то..

А "с единицей" - так не просто ерунда, а вообще просто форменный бред, поскольку практического смысла умножение не единицу не имеет. Приведенная формула тоже никуда не годится - все ж в регистр синтезатора загружают целое число, а тут в любом случае дробное (и очень маленькое). Короче, разбирайтесь с математикой, и лишь потом - с переложением _правильных_ формул в их реализацию для микроконтроллера...
NickSmith
Цитата(rx3apf @ Mar 9 2010, 22:24) *
А "с единицей" - так не просто ерунда, а вообще просто форменный бред, поскольку практического смысла умножение не единицу не имеет. Приведенная формула тоже никуда не годится - все ж в регистр синтезатора загружают целое число, а тут в любом случае дробное (и очень маленькое). Короче, разбирайтесь с математикой, и лишь потом - с переложением _правильных_ формул в их реализацию для микроконтроллера...

Ну да целое число. То, что после запятой округляется или в большую или в меньшую сторону...
Я думаю так сделать:
я храню значение в виде 5050, на самом деле это для формулы должно быть 10^-8 т.е я могу 5050/1*2^28 полученный результат разделить на 10^8..
Но тут возникают вопросы, как мне округлить числа после запятой??
И может быть как то можно это все сократить??

Я тоже так подумал, что с 1 единицей что без нее разницы нет.. Но вот попробуйте в экселе это сделать без нее.. Тогда действительно бред
=GM=
Правильно так: (5050/10^8)*2^28 =0x13BA0000000/0x5F5E100=0x34F4=13556
NickSmith
Цитата(=GM= @ Mar 9 2010, 23:29) *
Правильно так: (5050/10^8)*2^28 =0x13BA0000000/0x5F5E100=0x34F4=13556

А я вот тут подумал, а если подойти к задаче с дугой стороны.
Я посмотрел, что прибавление или вычитание из кода идет с шагом или 2 или 3.
Закономерность вроде как тоже есть.. Изменение на 2 происходит после двух подряд изменений на три и так пять раз, после чего три раза подряд изменение на три и цикл снова..
2333 233 233 233 233 233 23332......
Может быть по такому пути проще идти и не городить огород со сложной математикой..
Только как бы это привязать к какому либо значению?? Или придется тупо на каких то хитрых циклах делать??
rx3apf
Цитата(NickSmith @ Mar 10 2010, 00:25) *
Только как бы это привязать к какому либо значению?? Или придется тупо на каких то хитрых циклах делать??

Фигней не надо заниматься, а ? Всего-то нужно тривиальное деление 40 / 20 битов. Простейший цикл сдвиг-сравнение-вычитание.
NickSmith
Цитата(rx3apf @ Mar 10 2010, 00:31) *
Фигней не надо заниматься, а ? Всего-то нужно тривиальное деление 40 / 20 битов. Простейший цикл сдвиг-сравнение-вычитание.

А по подробней можно??
rx3apf
Цитата(NickSmith @ Mar 10 2010, 00:33) *
А по подробней можно??

Ну как делается деление "столбиком" ? Так и здесь - сдвигаем делимое в накопитель остатка, сравниваем остаток с делимым, если больше либо равен - вычитаем делимое из остатка и записываем "1" в результат. Иначе не вычитаем и записываем "0". Для удобства регистр делителя и результата совмещается, по окончанию операции частное будет в том же накопителе. Реализации под конкретную платформу - практически всегда есть в аппликухах...
NickSmith
Цитата(rx3apf @ Mar 10 2010, 01:55) *
Ну как делается деление "столбиком" ? Так и здесь - сдвигаем делимое в накопитель остатка, сравниваем остаток с делимым, если больше либо равен - вычитаем делимое из остатка и записываем "1" в результат. Иначе не вычитаем и записываем "0". Для удобства регистр делителя и результата совмещается, по окончанию операции частное будет в том же накопителе. Реализации под конкретную платформу - практически всегда есть в аппликухах...

Т.е делать все по формуле..
Хорошо, а как быт с округлением результатов? у меня же ведь на выходе получается число с запятой.. А в демо программе, как я понял результат расчетов округляется или в большую или в меньшую сторону?
Как поделить и умножить я разберусь, а вот как быть с остатком..
Я делаю это на tiny2313 там есть пример математики с большими числами.. Но он очень громоздок.. Что то строк под 150 по моему.. По этому я и подумал пойти простым путем и поиграть с увеличением или уменьшением готовой константы.. Кода по моему всяко меньше получится??
_Pasha
Нажмите для просмотра прикрепленного файла
Цитата
Приближение действительного числа рациональными дробями с заданным ограничением для знаменателя
Genadi Zawidowski
Цитата
tiny2313

Взяли бы мегу восьмую и писали на WinAVR - достаточно эффективные встроенные функции деления 64/64 есть.
rx3apf
Цитата(NickSmith @ Mar 10 2010, 02:03) *
Т.е делать все по формуле..
Хорошо, а как быт с округлением результатов? у меня же ведь на выходе получается число с запятой.. А в демо программе, как я понял результат расчетов округляется или в большую или в меньшую сторону?
Как поделить и умножить я разберусь, а вот как быть с остатком..

Я уже говорил, как это сделать проще. Делимое взять вдвое больше, а после деления частное еще раз поделить вдвое простым сдвигом и по состоянию бита переноса добавить единичку к результату.
Цитата
Я делаю это на tiny2313 там есть пример математики с большими числами.. Но он очень громоздок.. Что то строк под 150 по моему..

Жуть какая... Вот деление 32 / 16. Добавить по одному регистру в делимое, частное и остаток, будет требуемые 40 / 24...
CODE

;----------------------------------------------------------------------
; Деление XH:XL:YH:YL / ZH:ZL
; Используются регистры r0, r1, temp
;----------------------------------------------------------------------

Div32:
clr r0
clr r1
ldi temp,32 ; счетчик
Div32_1:
lsl YL
rol YH
rol XL
rol XH ; сдвиг делимого
rol r1
rol r0 ; и остатка (r0:r1)
cp r1,ZL
cpc r0,ZH ; можно вычесть делитель ?
brlo Div32_2 ; нет
ori YL,$01 ; иначе "1" в частное
sub r1,ZL
sbc r0,ZH
Div32_2:
dec temp
brne Div32_1 ; цикл деления

; В XH:XL:YH:YL содержится результат деления

ret
NickSmith
Цитата(rx3apf @ Mar 10 2010, 10:44) *
Я уже говорил, как это сделать проще. Делимое взять вдвое больше, а после деления частное еще раз поделить вдвое простым сдвигом и по состоянию бита переноса добавить единичку к результату.

Жуть какая... Вот деление 32 / 16. Добавить по одному регистру в делимое, частное и остаток, будет требуемые 40 / 24...

Огромное спасибо за пример..
Но я все равно под запутался. Выше писали:
Цитата
Правильно так: (5050/10^8)*2^28 =0x13BA 0000 000/0x5F5E100=0x34F4=13556

Но получается не 0x34F4, 0x34F3
Вот если взять делимое на 1 ноль больше, то результат будет 0x34f3f
Если младшую тетраду младшего байта как то обрабатывать по условию, то и получится округление.. Прав??
rx3apf
Цитата(NickSmith @ Mar 10 2010, 13:48) *
Но получается не 0x34F4, 0x34F3
Вот если взять делимое на 1 ноль больше, то результат будет 0x34f3f
Если младшую тетраду младшего байта как то обрабатывать по условию, то и получится округление.. Прав??

Мать-перемать... Ну сколько можно объяснять ? Надо взять делимое вдвое больше (умножить на 2^29), а потом частное поделить еще на 2 сдвигом вправо, и по состоянию переноса прибавить или не прибавляь 1 (т.е. для avr сделать adc. Для приведенной мной программы - lsr xh ror xl ror yh ror yl adc yl,temp adc yh,temp adc xl,temp adc xh temp). Конеччно, это можно сделать и контролем остатка, но так - проще. Естественно, в примере с конкретными числами разрядность можно сократить на 8 битов, поэтому достаточно деление 40 / 24.
NickSmith
Цитата(rx3apf @ Mar 10 2010, 13:56) *
Мать-перемать... Ну сколько можно объяснять ? Надо взять делимое вдвое больше (умножить на 2^29), а потом частное поделить еще на 2 сдвигом вправо, и по состоянию переноса прибавить или не прибавляь 1 (т.е. для avr сделать adc. Для приведенной мной программы - lsr xh ror xl ror yh ror yl adc yl,temp adc yh,temp adc xl,temp adc xh temp). Конеччно, это можно сделать и контролем остатка, но так - проще. Естественно, в примере с конкретными числами разрядность можно сократить на 8 битов, поэтому достаточно деление 40 / 24.

Все, теперь понял ход вашей мысли..
ae_
Цитата(NickSmith @ Mar 10 2010, 19:01) *
Все, теперь понял ход вашей мысли..

Если я правильно понял, нужно вычислять выражение вида a*b/c, где a - частота, которую нужно получить, b - разрядность 28 bit, c - частота кварца. Причём, b и c - константы. вычисляем b/c = 2^28/10^8 = 2.68435456. Получается, нужно только одно умножение a*k, где k=2.68435456. проверяем для 5050*k=13555.990528.
Так как плавающая точка всё равно не нужна и в синтезатор загружаем целые числа, то вместо k надо взять N=k<<16 или k<<24 или сколько там нужно разрядов для этого синтезатора, и работаем только с целочисленным умножением. Пример для 16-bit результата: N=k*2^16=0x2AF32, 5050*N=0x34F40054, старшие два байта и есть искомое 0x34F4
NickSmith
Цитата(ae_ @ Mar 10 2010, 18:14) *
Если я правильно понял, нужно вычислять выражение вида a*b/c, где a - частота, которую нужно получить, b - разрядность 28 bit, c - частота кварца. Причём, b и c - константы. вычисляем b/c = 2^28/10^8 = 2.68435456. Получается, нужно только одно умножение a*k, где k=2.68435456. проверяем для 5050*k=13555.990528.
Так как плавающая точка всё равно не нужна и в синтезатор загружаем целые числа, то вместо k надо взять N=k<<16 или k<<24 или сколько там нужно разрядов для этого синтезатора, и работаем только с целочисленным умножением. Пример для 16-bit результата: N=k*2^16=0x2AF32, 5050*N=0x34F40054, старшие два байта и есть искомое 0x34F4

Изящный способ, но у него с округлением проблемы... А у меня это критично.. Хотя так конечно было бы проще..
ae_
Цитата(NickSmith @ Mar 11 2010, 01:12) *
Изящный способ, но у него с округлением проблемы... А у меня это критично.. Хотя так конечно было бы проще..

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

Для вычисления значения фазы существует формула:
значение регистра фазы = (значение фазы *4096)/2Пи и Но получается полная ерунда.. С их расчетами никак не сходится.. Например значение регистра для фазы 90 градусов получается 0х0400 в их примерах.
Если же делать по этой формуле то получается 58671 или 0xE52F
Что не так?
rezident
Цитата(NickSmith @ Mar 11 2010, 00:44) *
Что не так?
Дык значение фазы-то в радианах должно быть выражено, а не в градусах rolleyes.gif Ну либо замените 2*Π в вашей формуле на 360 градусов wink.gif
NickSmith
Цитата(rezident @ Mar 11 2010, 01:49) *
Дык значение фазы-то в радианах должно быть выражено, а не в градусах rolleyes.gif Ну либо замените 2*Π в вашей формуле на 360 градусов wink.gif

Спасибо.. Действительно все сошлось сразу...
NickSmith
Что то не получается у меня переделать умножение из апликух, которое "mpy16u" - 16x16 Bit Unsigned Multiplication, что бы оно стало 24х16. Что я не так делаю??

CODE
.def mc16uL =r16 ;multiplicand low byte
.def mc16uH =r17 ;multiplicand high byte
.def mp16uL =r18 ;multiplier low byte
.def mp16uH =r19 ;multiplier high byte
.def mp16UM=r20
.def m16u0 =r18 ;result byte 0 (LSB)
.def m16u1 =r19 ;result byte 1
.def m16u2 =r20 ;result byte 2
.def m16u3 =r21 ;result byte 3 (MSB)
.def mcnt16u =r22 ;loop counter

;***** Code

ex: nop;;
nop
nop

ldi mc16ul,low(5050)
ldi mc16uh,high(5050)
ldi mp16ul,0x31
ldi mp16uh,0xAF
ldi mp16um,0x02
;
mpy16u: clr m16u3 ;clear 2 highest bytes of result
clr m16u2
ldi mcnt16u,24;init loop counter
lsr mp16uH
ror mp16uL
ror mp16uM

m16u_1:
brcc noad8 ;if bit 0 of multiplier set

add m16u2,mc16uL;add multiplicand Low to byte 2 of res
adc m16u3,mc16uH;add multiplicand high to byte 3 of res

noad8: ror m16u3 ;shift right result byte 3
ror m16u2 ;rotate right result byte 2
ror m16u1 ;rotate result byte 1 and multiplier High
ror m16u0 ;rotate result byte 0 and multiplier Low;
dec mcnt16u ;decrement loop counter
brne m16u_1 ;if not done, loop more
rjmp ex
NickSmith
Пробовал менять местами множимое и множитель с добавление регистра, но все то же..
=GM=
Поменяйте порядок сдвига, как показано ниже, и будет вам щастье
Код
noad8:    ror    m16u3;shift right result byte 3
    ror    m16u1;rotate result byte 1 and multiplier High
    ror    m16u0;rotate result byte 0 and multiplier Low;
    ror    m16u2;rotate right result byte 2

На будущее, не надо именовать один и тот же регистр разными именами, это моветон. Да, и откажитесь от таких ужасных обозначений переменных, почему не взять просто prod0, prod1, prod2, prod3, a0,a1, b0, b1, b2?
rx3apf
Цитата(NickSmith @ Mar 12 2010, 02:52) *
Что то не получается у меня переделать умножение из апликух, которое "mpy16u" - 16x16 Bit Unsigned

Мда.. Не понос, так золотуха... Я не понял, надо что, реализовать это чудо на младших представителях семейства AVR, "тиньках" ? Нет ? Тогда на кой, простите, икс, брать _такую_ реализацию ? Есть же на то команда mul. Да, многоразрядное умножение довольно "развесистое", но все ж быстрее, чем цикл, да и компактнее при таких разрядностях. Блин, дал же _готовое_ деление, по регистру прибавить - и больше ничего не надо...
NickSmith
Цитата(=GM= @ Mar 12 2010, 16:31) *
На будущее, не надо именовать один и тот же регистр разными именами, это моветон. Да, и откажитесь от таких ужасных обозначений переменных, почему не взять просто prod0, prod1, prod2, prod3, a0,a1, b0, b1, b2?

Счастье не наступило.. Все равно не верный результат умножения..

Цитата(rx3apf @ Mar 12 2010, 17:03) *
Мда.. Не понос, так золотуха... Я не понял, надо что, реализовать это чудо на младших представителях семейства AVR, "тиньках" ? Нет ? Тогда на кой, простите, икс, брать _такую_ реализацию ? Есть же на то команда mul. Да, многоразрядное умножение довольно "развесистое", но все ж быстрее, чем цикл, да и компактнее при таких разрядностях. Блин, дал же _готовое_ деление, по регистру прибавить - и больше ничего не надо...


Я же писал. Я работаю с tiny2313. В нем к сожалению нет mul. Приходится что то изобретать.. Деление слишком громоздкое получается, аж под 750 тактов..
rx3apf
Цитата(NickSmith @ Mar 13 2010, 13:10) *
Я же писал. Я работаю с tiny2313. В нем к сожалению нет mul.


Ну тогда ладно wink.gif Хотя платформа для задачи не самая лучшая - mega8 стоит столько же, но такие вещи делаются быстрее.
Цитата
Приходится что то изобретать.. Деление слишком громоздкое получается, аж под 750 тактов..

Чтобы реализовать через умножение при той же точности результата, разрядность придется увеличивать, и как бы не получилось еще больше. А по реализации - умножение "в столбик" еще проще, проверили бит множителя, если "1" - прибавили множимое к аккумулятору. Затем сдвинули множитель для следующей проверки, и множимое тоже сдвинули (умножили на 2). И так до конца множителя. Вот только множимое придется расширить до разрядности аккумулятора, и все вместе это будет довольно долго...
NickSmith
Цитата(rx3apf @ Mar 13 2010, 13:28) *
Ну тогда ладно wink.gif Хотя платформа для задачи не самая лучшая - mega8 стоит столько же, но такие вещи делаются быстрее.

Я еще только начинаю знакомиться с современными микропроцессорами.. Просто мне попались толковые книжки по 2313 вот я ее и взял за основу.. Изначально я вообще хотел на 89С2051 делать, но с ней очень хлопотно и неудобно.. А меги я изучу обязательно..
Цитата(rx3apf @ Mar 13 2010, 13:28) *
Чтобы реализовать через умножение при той же точности результата, разрядность придется увеличивать, и как бы не получилось еще больше. А по реализации - умножение "в столбик" еще проще, проверили бит множителя, если "1" - прибавили множимое к аккумулятору. Затем сдвинули множитель для следующей проверки, и множимое тоже сдвинули (умножили на 2). И так до конца множителя. Вот только множимое придется расширить до разрядности аккумулятора, и все вместе это будет довольно долго...

А есть ли какие нибудь толковые книжки, где бы об этом можно было почитать.. Я к сожалению разбазарил свою библиотеку по электронике и выч. технике, правда я ее собирал в конце 80ч в начале 90 х, но помню, что там были книжки, в которых эти вещи очень доходчиво описывались с очень понятными примерами.. Во всяком случае во времена Z80 у меня с этим проблем не возникало.. Сейчас все забыл напрочь.
rx3apf
Цитата(NickSmith @ Mar 13 2010, 14:09) *
Я еще только начинаю знакомиться с современными микропроцессорами.. Просто мне попались толковые книжки по 2313 вот я ее и взял за основу.. А меги я изучу обязательно..

Да там разницы-то, по большому счету, никакой. Есть некоторое количество дополнительных команд, более развитая периферия.

Цитата
А есть ли какие нибудь толковые книжки, где бы об этом можно было почитать.. Я к сожалению разбазарил свою библиотеку по электронике и выч. технике, правда я ее собирал в конце 80ч в начале 90 х, но помню, что там были книжки, в которых эти вещи очень доходчиво описывались с очень понятными примерами..

Наверное, Левенталь и прочие ? Я большую часть выкинул уже за ненадобностью, неактуально нынче...
Цитата
Во всяком случае во времена Z80 у меня с этим проблем не возникало.. Сейчас все забыл напрочь.

Я как-то давно уже книжками не пользуюсь, тут как втянешься, так оно как-то само собой (и, по моим ощущениям, на asm для 8-битных RISC пишется проще и быстрее, чем на Z80). Ну, аппликухи еще поглядеть (и от других платформ тоже, для общего развития). Сейчас вообще набегут "сионисты", скажут, что ассемблер надо выкинуть и писать на ЯВУ wink.gif
NickSmith
Цитата(rx3apf @ Mar 13 2010, 14:18) *
Да там разницы-то, по большому счету, никакой. Есть некоторое количество дополнительных команд, более развитая периферия.


Я это понял, что у них сделана унифицированная система. Если ты изучил один, то можно сказать, что изучил все.. разница лишь в специфических командах, которые где то есть а где то нет.

Цитата(rx3apf @ Mar 13 2010, 14:18) *
Я как-то давно уже книжками не пользуюсь, тут как втянешься, так оно как-то само собой (и, по моим ощущениям, на asm для 8-битных RISC пишется проще и быстрее, чем на Z80). Ну, аппликухи еще поглядеть (и от других платформ тоже, для общего развития). Сейчас вообще набегут "сионисты", скажут, что ассемблер надо выкинуть и писать на ЯВУ wink.gif

Это да, практика великая вещь. А я последние лет 15 паяльник брал раз в год, что бы где то проводок припаять отвалившийся.. Вот сейчас опять сильный интерес появился и вспоминать все приходится. Но это не беда руки то все равно все помнят.
А асм мне у AVR понравился. Действительно удобный. Главное логику понять.. Хотя си я планирую изучить тоже. Тут уже надо по задаче смотреть на чем лучше писать..
NickSmith
Имеется формула код фазы = ( a*b )/c где а =значение фазы в градусах, b = 2^12, c = 360 например: (90*4096)/360=1024. Значение фазы у меня хранится в виде 90*10^2.
Далее я 2^12/360 = 11,38. 11,38 я возвожу в 10^2. В итоге у меня получается 900*1138=1024200 и что бы мне привести это к нужному виду, я делю это на 1000..
А можно ли как то это свести к одному действию?? желательно делению...
ae_
Цитата(NickSmith @ Mar 14 2010, 18:12) *
Имеется формула код фазы = ( a*b )/c где а =значение фазы в градусах, b = 2^12, c = 360 например: (90*4096)/360=1024. Значение фазы у меня хранится в виде 90*10^2.
...

360°/4096=0.088, т.е. хранить в 12-bit регистре число градусов 0...360 не выйдет точнее, чем 0.1° (округляем 0.088 в большую сторону до целого десятичного разряда).
Отсюда и формат хранения переменной должен быть не 90*10^2, а 90*10=900, т.е. 0...3599
Далее, надо получить из 900 код 1024, а из 3599->4095. N = 0x91AD
т.е. берёте фазу в виде 0...3599, умножаете на 0x91AD (используя алгоритм беззнакового mul16x16 из appnote), результат (32-bit) сдвигаете влево на один разряд. старшие два байта = код фазы
(900*N)<<1 = 0x2002434<<1 = 0x4004868. отбрасываем младшие 16 бит, получаем 0x400 (1024)
(3599*N)<<1 = 0x7FFFF23<<1 = 0xFFFFE46. -//- получаем 0xFFF (4095)
NickSmith
Цитата(ae_ @ Mar 14 2010, 18:25) *
Далее, надо получить из 900 код 1024, а из 3599->4095. N = 0x91AD
т.е. берёте фазу в виде 0...3599, умножаете на 0x91AD (используя алгоритм беззнакового mul16x16 из appnote), результат (32-bit) сдвигаете влево на один разряд. старшие два байта = код фазы
(900*N)<<1 = 0x2002434<<1 = 0x4004868. отбрасываем младшие 16 бит, получаем 0x400 (1024)
(3599*N)<<1 = 0x7FFFF23<<1 = 0xFFFFE46. -//- получаем 0xFFF (4095)

Огромнейшее спасибо!!!
А как получается N? какие преобразования надо было для этого сделать??
ae_
Цитата(NickSmith @ Mar 15 2010, 07:05) *
Огромнейшее спасибо!!!
А как получается N? какие преобразования надо было для этого сделать??

Выполните вычисления в обратном порядке, неужели это так сложно ?
N=(0x0FFFFFFF/3599)>>1
Сдвиг вправо "волшебного" числа N и сдивг влево 32-бит результата при вычислении нужен лишь для того, что бы уместиться в 16-бит арифметику.
rezident
Цитата(NickSmith @ Mar 15 2010, 04:05) *
А как получается N? какие преобразования надо было для этого сделать??
Дык очевидно же!
1024/900*32768=37282,7=37283=0x91A3
4095/3599*32768=37283,9=37284=0x91A4
Сдвиг влево эквивалентно умножению на 2. А отбрасывание младших 16- бит эквивалентно делению на 2^16=65536.
Конечная формула такая X*N*2/2^16, где X- это значение фазы с шагом 0,1° (0,1°*10=1) в диапазоне от 0 до 359,9°(359,9°*10=3599). А N это "магическое число" для хранения дробного коэффициента пересчета в формате целого числа.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.