ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Четверг
21 ноября
135878 Топик полностью
leon_ (23.10.2008 16:03, просмотров: 323) ответил MBedder на Именно поэтому я и применил FMULx вместе с MULx - все учтено, можешь проверить с любыми N и K. И точность в LSB выражать нет смысла - в зависимости от N и K получатся разные значения. Проценты рулят
Вот два примера, когда Ваша подпрограмма, выставленная в исходниках, работает неправильно. http://src.caxapa.ru/329
http://caxapa.ru/135412.html
;------------------------------------------------------------------------- ; Scaling test code ;------------------------------------------------------------------------- .include <m128def.inc> ldi r16, high(RAMEND) out SPH, r16 ldi r16, low(RAMEND) out SPL, r16 scalings: ; unsigned*signed scaling test ; Проверяем правильность работы Вашей подпрограммы на таких данных ldi r16,low(0x2080) ; coeff = 0,25390625 ldi r17,high(0x2080) ldi r18,low(0x4000) ; myint = 16384 ldi r19,high(0x4000) ; 0,25390625*16384=4160=0x1040 Microsoft Калькулятор rcall scale16us ; r9r8 = 0x1020 ; Результат неправильный!!! ; Это не неточность вычисления а неправильность вычисления ; изза совместного (неправильного) использования fmulх и mulх ; Проверяем правильность работы моей подпрограммы ; У меня диапазон коэффициента -0,5..0,5 в формате 0.16 ldi r20,low(0x4100) ; coeff = 0,25390625 ldi r21,high(0x4100) ldi r22,low(0x4000) ; myint = 16384 ldi r23,high(0x4000) rcall scale16us_ ; r19r18 = 0x1040 ; Результат правильный!!! ; Вывод: Нельзя использовать MULx совместно с FMULx без учета ; сдвига результата последней командой. ; Теперь проверим как Ваш вариант справится с значением 0xB000. ; Это значение нормально попадает в 16-ти разр-й unsigned. И коэф = 0,75 ldi r16,low(0x6000) ; coeff = 0,75 ldi r17,high(0x6000) ldi r18,low(0xB000) ; myint = 45056 ldi r19,high(0xB000) ; 0,75*45056=33792=0x8400 Microsoft Калькулятор ; Сразу видно что не помещается в 16-ти разр-й signed ; Вместо положительного результата ожидается отрицательный rcall scale16us ; r9r8 = 0x8400 = -31744 ; Результат неправильный!!! ; Вывод: Нельзя использовать FMULx для unsigned*signed scaling, ; возможно переполнение. ; Проверяем правильность работы моей подпрограммы ; У меня диапазон коэффициента -0,5..0,5 в формате 0.16 ; Поэтому такое-же двоичное значение означает другое десятичное ldi r20,low(0x6000) ; coeff = 0,75/2=0,375 ldi r21,high(0x6000) ldi r22,low(0xB000) ; myint = 45056 ldi r23,high(0xB000) ; 0,375*45056=16896=0x4200 Microsoft Калькулятор rcall scale16us_ ; r19r18 = 0x4200 ; Результат правильный!!! ; Переполнение при тех-же двоичных данных не возникает. rjmp scalings ;------------------------------------------------------------------------- ;------------------------------------------------------------------------- ; Scaling routines ;------------------------------------------------------------------------- ;------------------------------------------------------------------------- ; Scales unsigned int r19r18 by signed r17r16 value ; presented as signed fractional (0x8000 = -1, 0x7FFF = +0.99998) ; ; Only r16..r23 registers can be used as operands ; due to the xMULSx command limitations ; ; Result stored in r9r8 ; 15 program words, 18 clocks + ret ; ; (c) 2008 leon_, MBedder ; scale16us: clr r2 fmulsu r17,r19 ; r19r18 = 23456, r17r16 =~ -0.76543*32768 movw r8,r0 mul r18,r16 mov r7,r1 mul r19,r16 add r7,r0 adc r8,r1 adc r9,r2 fmulsu r17,r18 sbc r9,r2 add r7,r0 adc r8,r1 adc r9,r2 ; r9r8 =~ 23456*-0.76543 ~= 0xB9DC =~ -17956 ret ;------------------------------------------------------------------------- ; 3. Беззнаковые данные, знаковый коэффициент и знаковый результат. ; данные АЦП в диапазоне 0x0000..0xFFFF | 0.16-> 0,0..1,0 | 0.16-> 0,0..1,0 ; коэффициент в диапазоне 0x8000..0x7FFF | 0.16-> -0,5..0,5 | 16.0-> -32767..32767 ; результат в диапазоне 0x8000..0x7FFF | 0.16-> -0,5..0,5 | 16.0-> -32767..32767 ; r19:r18:r17:r16 = r23:r22 * r21:r20 scale16us_: clr r2 mulsu r21, r23 movw r18, r0 mul r22, r20 mov r17, r1 mul r23, r20 add r17, r0 adc r18, r1 adc r19, r2 mulsu r21, r22 sbc r19, r2 add r17, r0 adc r18, r1 adc r19, r2 ret