MPASM 5.77 PCPWM_3F_4431.ASM 3-15-2018 8:55:29 PAGE 32 LOC OBJECT CODE LINE SOURCE TEXT VALUE M 000340 00066 AngDone: 00067 00068 SinTableLoad Angle_2+2,PDC1L ; номер элемента и адрес куда заслать 0000 M local ExitMul,Done,ZeroPoint, MaxPoint,OvrLoad,OvrLoad1 M ; Повторяющийся код оформлен макросом. M ; На входе - байт угла, на выходе - засылаем в ШИМ указанного № M ; Внутри - максимально оптимизированный код выборки таблицы синусов, умножения на амплитуду, M ; нормализации до необходимого значение для PCPWM, вывода в модулятор. M ; Выполняется 18 750*3 = 56 250 Гц - каждая команда дорога. M ; Почему-то регистры скважности идут обратным порядком - старший - младший. Разные школы ? M ;Tab16Load macro A_Arg,TableAdr; Загрузка указателей таблицы 16 бит M Tab16Load Angle_2+2,Table_Sinus ; Замена на макрос для ухода от ввода повторяющегося кода 000340 C11D FFF6 M movff Angle_2+2,TBLPTRL ; индекс выборки 000344 6AF7 M clrf TBLPTRH,ACCESS ; Готовим место 000346 36F6 M rlcf TBLPTRL,F,ACCESS ; удваиваем указатель таблицы 000348 36F7 M rlcf TBLPTRH,F,ACCESS ; перед сложением с базой 00034A 90F6 M bcf TBLPTRL,0,ACCESS ; Чистим младший бит удвоения 00034C 6AF8 M clrf TBLPTRU,ACCESS ; для указателя таблицы M Add24L TBLPTRL,ACCESS,Table_Sinus ; Прибавляем начальный адрес таблицы к смещению M ; Результат будет B=B+A M ; movf ArgA,W ,A1A ; Младший байт 00034E 0E?? M movlw low(Table_Sinus) ; 000350 26F6 M addwf TBLPTRL,F,ACCESS ; ; А + В, результат В=B+A M M ; movf ArgA+1,W,A1A ; средний байт M M errorlevel -311 ; Убираем Message[311] ибо задолбало 000352 0E?? M movlw high(Table_Sinus) ; M errorlevel +311 ; Возвращаем Message[311] M M ;btfsc _C ; Если в прошлом Перенос M ;incfsz WREG,W,A1A ; Увеличим Старший БАЙТ Слагаемого на 1, 000354 22F7 M addwfc TBLPTRL+1,F,ACCESS ; и сложим старшие байты - результат в В M M ; movf ArgA+2,W,A1A ; Старший байт 000356 0E?? M movlw upper(Table_Sinus) ; M ;btfsc _C ; Если в прошлом Перенос M ;incfsz WREG,W,A1A ; Увеличим Старший БАЙТ Слагаемого на 1, 000358 22F8 M addwfc TBLPTRL+2,F,ACCESS ; и сложим старшие байты - результат в В M M ; clrf TBLPTRH,ACCESS ; Готовим место M ; movff Angle_8,TBLPTRL ; Старший байт угла - есть адрес выборки M ; rlcf TBLPTRL,F,ACCESS ; удваиваем указатель таблицы M ; rlcf TBLPTRH,F,ACCESS ; перед сложением с базой M ; bcf TBLPTRL,0,ACCESS ; Чистим младший бит удвоения M ;; clrf TBLPTRU,ACCESS ; для указателя таблицы M ; Add24L TBLPTRL,ACCESS,Table_Sinus ; Прибавляем начальный адрес таблицы к смещению M ; M ; Знаковые 16 бит на без знаковое положительное 8 бит M ;PCPWM_Amp;, ACCESS ; амплитуда поля синтезатора, без знаковая, ACCESS M ;PCPWM_AmpSin;,BANKED; Буфер Амплитуды синусоиды после вычислений V/F M ;Syn16 :2 ; Выборка из таблицы синусов, BANKED MPASM 5.77 PCPWM_3F_4431.ASM 3-15-2018 8:55:29 PAGE 33 LOC OBJECT CODE LINE SOURCE TEXT VALUE M ;SynMulBuf :4; Буфер умножения синуса на амплитуду, BANKED M ;FXMTab1608U macro D_Arg,A1D,A_Arg,A1A;16 бит из таблицы на 8 бит без знака M FXMTab1608U SynMulBuf,BANKED,PCPWM_AmpSin,BANKED ; Проверка макроса 00035A 0009 M tblrd*+ ; Читаем младший байт синуса 00035C 50F5 M movf TABLAT,W,ACCESS ; Младший байт 16 бит синуса M M ; mulwf PCPWM_Amp,ACCESS; множим на единственный байт 00035E 032D M mulwf PCPWM_AmpSin,BANKED; Буфер Амплитуды синусоиды после вычислений V/F M M movff16 PRODL,SynMulBuf ; амплитуды, спасаем результат 000360 CFF3 F121 M movff PRODL,SynMulBuf ; Младший 000364 CFF4 F122 M movff PRODL+1,SynMulBuf+1 ; Старший 000368 6B23 M clrf SynMulBuf+2,BANKED ; чистим старшие байты результата M ; clrf SynMulBuf+3,BANKED ; от умножения на 0 00036A 0009 M tblrd*+ ; Читаем старший байт синуса M ; movf Syn16+1,W,BANKED; Старший байт 16 бит синуса 00036C 50F5 M movf TABLAT,W,ACCESS ; Старший байт 16 бит синуса M ; movf Syn16+1,BANKED ; Старший байт 16 бит синуса сохраняем для истории M M ; mulwf PCPWM_Amp,ACCESS; множим на единственный байт амплитуды 00036E 032D M mulwf PCPWM_AmpSin,BANKED;; Буфер Амплитуды синусоиды после вычислений V/F M 000370 50F3 M MOVF PRODL,W,ACCESS; ; Складывание 16 бит 000372 2722 M ADDWF SynMulBuf+1,F,BANKED; результата 8*8 000374 50F4 M MOVF PRODH,W,ACCESS ; с накопителем 32 бита 000376 2323 M ADDWFC SynMulBuf+2,F,BANKED; со смещением 1 байт M ; CLRF WREG,ACCESS; ; ADD16 Macro ; Старший байт позже будет M ; ADDWFC SynMulBuf+3,F,BANKED ; отброшен M ;заменяющего код ниже: M ; tblrd*+ ; Читаем младший байт синуса M ; ;movff TABLAT,Syn16;PDC_16L ; Пока без умножения на амплитуду в канал-0 M ; ; movf Syn16,W,BANKED ; Младший байт 16 бит синуса M ; movf TABLAT,W,ACCESS ; Младший байт 16 бит синуса M ; M ;; mulwf PCPWM_Amp,ACCESS; множим на единственный байт M ; mulwf PCPWM_AmpSin,BANKED; Буфер Амплитуды синусоиды после вычислений V/F M ; M ; movff16 PRODL,SynMulBuf ; амплитуды, спасаем результат M ; clrf SynMulBuf+2,BANKED ; чистим старшие байты результата M ;; clrf SynMulBuf+3,BANKED ; от умножения на 0 M ; M ; tblrd*+ ; Читаем старший байт синуса M ; M ;; movf Syn16+1,W,BANKED; Старший байт 16 бит синуса M ; movf TABLAT,W,ACCESS ; Старший байт 16 бит синуса M ;; movf Syn16+1,BANKED ; Старший байт 16 бит синуса сохраняем для истории M ; M ;; mulwf PCPWM_Amp,ACCESS; множим на единственный байт амплитуды M ; mulwf PCPWM_AmpSin,BANKED; Буфер Амплитуды синусоиды после вычислений V/F M ; M ; MOVF PRODL,W,ACCESS; ; Складывание 16 бит M ; ADDWF SynMulBuf+1,F,BANKED; результата 8*8 M ; MOVF PRODH,W,ACCESS ; с накопителем 32 бита MPASM 5.77 PCPWM_3F_4431.ASM 3-15-2018 8:55:29 PAGE 34 LOC OBJECT CODE LINE SOURCE TEXT VALUE M ; ADDWFC SynMulBuf+2,F,BANKED; со смещением 1 байт M ;; CLRF WREG,ACCESS; ; ADD16 Macro ; Старший байт позже будет M ;; ADDWFC SynMulBuf+3,F,BANKED ; отброшен M ; M ; btfss Syn16+1,7,BANKED ; Знак Старший байт 16 бит синуса 000378 AEF5 M btfss TABLAT,7,ACCESS ; Знак Старший байт 16 бит синуса 00037A D??? M bra ExitMul M M ; movf PCPWM_Amp,W,ACCESS; множим на единственный байт 00037C 512D M movf PCPWM_AmpSin,W,BANKED; Буфер Амплитуды синусоиды после вычислений V/F; M 00037E 5F23 M subwf SynMulBuf+2,F,BANKED; со смещением 2 байт M ; bc OvrLoad1 ; Никогда не должно произойти, отладка M ; Beeper_Toggle M ;OvrLoad1 M M ; CLRF WREG,ACCESS; Старший байт Б всегда =0 M ; subwfb SynMulBuf+3,F,BANKED; самый старший байт результата 000380 M ExitMul M ; Отладка показала что здесь имеем знаковое число размаха от 8 355 585 до -8 355 585 M ; Для возврата к беззнаковому - надо прибавить эти пол диапазона к результату M ;Края диапазона при максимальной амплитуде должны соответствовать 0 и 2048 регистра PDC, середина, котор ая = 0 = 1024 PDC. M ;0=0гр=0000=00000000==средняя точка пвм M ;64=90гр=7fff=007f7f01=максимум ПВМ, удвоенный буде FEFE02, после сдвигов - 7F7 M ;128=180гр=0000=00000000=средняя точка пвм, после коррекции FEFE02 M ;192=270гр=8001=ff8080ff=минимум ПВМ=после коррекции = 00000000000 M ;255=359гр=fcdc=fffcdf24=почти ноль, после коррекции = 7c5e25 - почти средняя точка 000380 0E01 M movlw 0x01; ; Складывание 32 бит результата с константой 0x7f7f01 000382 2721 M ADDWF SynMulBuf+0,F,BANKED; младший 000384 0E7F M movlw 0x7F; ; Складывание 32 бит результата с константой 0x7f7f01 000386 2322 M ADDWFC SynMulBuf+1,F,BANKED; средний-1 000388 0E7F M movlw 0x7F; ; Складывание 32 бит результата с константой 0x7f7f01 00038A 2323 M ADDWFC SynMulBuf+2,F,BANKED; средний-2 M ; bnc OvrLoad ; Никогда не должно произойти, отладка M ; Beeper_Toggle M ; OvrLoad M M ; CLRF WREG,ACCESS; ; Старший байт Б всегда =0 M ; ADDWFC SynMulBuf+3,F,BANKED; старший M M ; movff16 SynMulBuf+0,PCPWM_SMB+0; :4 ; Отладочный для вывода на экран BANK0 M ; movff16 SynMulBuf+2,PCPWM_SMB+2; :4 ; Отладочный для вывода на экран BANK0 M M ; Обнаруженный глюк с вычислителем фазы при раскрутке мотора - заставляет усложнить вычислитель фазы. M ; 16 бит синуса * 8 бит амплитуды = 24 бита, прибавляем точку нуля, усекаем до 16 бит. M ; 16 бит выходного значения сравниваем с верхним и нижним порогом ограничителей, присваиваем пороги при пересечении. M ; вычитаем нижний порог для смещения точки 0. M ; Ограниченные 16 бит для превращения в 11-12 бит ШИМ - умножаем на коэффициент 16 бит, M ; результат 32 бита усекаем до 11-12 бит M ; Вычитание нижнего порога с обнулением при заёме 00038C 0E99 M movlw low(0xFFFF/0xA);,;,W ,A1A ; Младший байт 10% от 0xFFFF MPASM 5.77 PCPWM_3F_4431.ASM 3-15-2018 8:55:29 PAGE 35 LOC OBJECT CODE LINE SOURCE TEXT VALUE 00038E 5F22 M subwf SynMulBuf+1,F,BANKED ; Вычитаем А из В, результат в: В=B-A M 000390 0E19 M movlw high(0xFFFF/0xA);,;,W,A1A ; Старший байт, 10% от 0xFFFF M ; btfss _C ; Если в прошлом вычитании Заем M ; incfsz ArgA+1,W,A1A ; Увеличим Старший БАЙТ Вычитаемого на 1, 000392 5B23 M subwfb SynMulBuf+2,F,BANKED ; и вычтем старшие байты - результат в В 000394 E3?? M bnc ZeroPoint ;При заёме - обнуление выхода M 000396 0ECC M movlw low(0xFFFF-0xFFFF/0x5);,;,W ,A1A ; Младший байт 10% от 0xFFFF 000398 5D22 M subwf SynMulBuf+1,W,BANKED ; Вычитаем А из В для сравнения M 00039A 0ECC M movlw high(0xFFFF-0xFFFF/0x5);,;,W,A1A ; Старший байт, 10% от 0xFFFF 00039C 5923 M subwfb SynMulBuf+2,W,BANKED ; и вычтем старшие байты - результат в В 00039E E2?? M bc MaxPoint ;При отсутствии заёма - Максимальное значение M ; Выходное значение зажато между границами, теперь его надо отмасштабировать из ХХХХ в строго 11 бит нап ример M ; 16х16=32 с отбрасыванием 16 бит как метод. M ; 65536-13107=52 428 надо в 4096 превратить - множитель = 2560=A00. M ;FXM1616U2 macro D_Arg,A1D,A_Arg,A1A,B_Arg,A1B,_Work,A1W; ; Подразумевается в памяти Младший-Старший ба йт идут M ; FXM1616U2 SynMulBuf+4, bnk, SynMulBuf+1, bnk, PCPWM_MK1+0, bnk, SynMulBuf+0, bnk; Умножаем на коэфф M FXM1680U SynMulBuf+4, bnk, SynMulBuf+1, bnk, PCPWM_MK1+0, bnk;, SynMulBuf+0, bnk; Умножаем на коэфф M ; Результат будет D=A*B ; Умножение 16*(8+0) без знаковое, A и В сохраняется без изменений, у Б младший байт =0 M ; Удобен для масштабирования 16 бит в 32 бита через умножение на 1 байт коэффициент или вместо сдвигов M ; Результат можно в А засылать если А 4 байта. M ; Нет обходимости в 1 байт буферок для промежуточного хранения M ; MULW: ;Multiplication 16bit * 8+0bit -> 32bit M ;detailed: M ; A_Arg+1:A_Arg+0 * B_Arg+1:B_Arg+0 -> A_Arg+3:A_Arg+2:A_Arg+1:A_Arg+0 M ; B_Arg value remains. M ; Примерно 29-12 тактов, примерно столько же слов ПЗУ M ; Контрольную проверку умножения делением сделал, ошибок нет M 0003A0 5123 M movf SynMulBuf+1+1,w,bnk ; Старшие байты 0003A2 0342 M mulwf PCPWM_MK1+0+1,bnk ; B_Arg+1 * A_Arg+1 0003A4 CFF4 F128 M movff PRODH,SynMulBuf+4+3 ; перемножаем, получаем 0003A8 CFF3 F127 M movff PRODL,SynMulBuf+4+2 ; старшие байты результата M 0003AC 5122 M movf SynMulBuf+1+0,w,bnk ; Младшие байты - нужен ниже M ;mulwf B_Arg+0,A1B ; B_Arg+0 * A_Arg+0 =0 M ;movff PRODH,_Work ; перемножаем, получаем =0 0003AE 6B25 M clrf SynMulBuf+4+0,bnk;movff PRODL,D_Arg+0 ; Младшие байты результата, =0 M M ; однако второй байт результата через буфер ибо нужен ещё M ; A_Arg+0 in WREG unchanged 0003B0 0342 M mulwf PCPWM_MK1+0+1,bnk ; B_Arg+1 * A_Arg+0 M M ;movf PRODL,w,ACCESS ; Средние байты множим, прибавляем M ;addwf _Work,f,A1W ; Add cross M ;movff PRODL,_Work - ниже он теряется MPASM 5.77 PCPWM_3F_4431.ASM 3-15-2018 8:55:29 PAGE 36 LOC OBJECT CODE LINE SOURCE TEXT VALUE M 0003B2 50F4 M movf PRODH,w,ACCESS ; products 0003B4 2727 M addwf SynMulBuf+4+2,f,bnk ; к накопителю результата со смещением в 1 байт M 0003B6 6AE8 M clrf WREG,ACCESS ; с учётом переноса 0003B8 2328 M addwfc SynMulBuf+4+3,f,bnk ; M M ;movf A_Arg+1,w,A1A ; Старший байт А ещё не изменялся M ;mulwf B_Arg+0,A1B ; B_Arg+0 * A_Arg+1 =0 M ;movf PRODL,w,ACCESS ; Средние байты множим, прибавляем =0 M ;movf _Work,w,A1W;addwf _Work,w,A1W ;Add cross _C=0 0003BA 6F26 M movwf SynMulBuf+4+1,bnk ; 0003BC 50F4 M movf PRODH,w,ACCESS ; products 0003BE 2727 M addwf SynMulBuf+4+2,f,bnk ; к накопителю результата со смещением в 1 байт 0003C0 6AE8 M clrf WREG,ACCESS ; с учётом переноса 0003C2 2328 M addwfc SynMulBuf+4+3,f,bnk ; M M ; FXM1680U C_Arg,BANKED ,A_Arg,BANKED ,B_Arg,BANKED;, Math_Work+3,BANKED ; M M ; movf A_Arg+1,w,A1A ; Старшие байты M ; mulwf B_Arg+1,A1B ; B_Arg+1 * A_Arg+1 M ; movff PRODH,D_Arg+3 ; перемножаем, получаем M ; movff PRODL,D_Arg+2 ; старшие байты результата M ; M ;; movf A_Arg+0,w,A1A ; Младшие байты M ;; mulwf B_Arg+0,A1B ; B_Arg+0 * A_Arg+0=0 **************** M ;; movff PRODH,_Work ; перемножаем, получаем M ;; movff PRODL,D_Arg+0 ; Младшие байты результата, M ;; однако второй байт результата через буфер ибо нужен ещё M ;; A_Arg+0 in WREG unchanged M ; mulwf B_Arg+1,A1B ; B_Arg+1 * A_Arg+0 M ; movf PRODL,w,ACCESS ; Средние байты множим, прибавляем M ; addwf _Work,f,A1W ; Add cross M ; movf PRODH,w,ACCESS ; products M ; addwfc D_Arg+2,f,A1D ; к накопителю результата со смещением в 1 байт M ; clrf WREG,ACCESS ; с учётом переноса M ; addwfc D_Arg+3,f,A1D ; M ; M ; ;movf A_Arg+1,w,A1A ; Старший байт А ещё не изменялся M ; ;mulwf B_Arg+0,A1B ; B_Arg+0 * A_Arg+1 = 0 **************** M ; ;movf PRODL,w,ACCESS ; Средние байты множим, прибавляем M ; ;addwf _Work,w,A1W ;Add cross M ; clrf ;movwf D_Arg+1,A1D ; M ; ;movf PRODH,w,ACCESS ; products M ; ;addwfc D_Arg+2,f,A1D ; к накопителю результата со смещением в 1 байт M ; clrf WREG,ACCESS ; с учётом переноса M ; addwfc D_Arg+3,f,A1D ; M ; M M 0003C4 C127 FF77 M movff SynMulBuf+6,PDC1L ; Младший модулятор 0003C8 C128 FF76 M movff SynMulBuf+7,PDC1L-1 ; Старший модулятор 0003CC D??? M bra Done MPASM 5.77 PCPWM_3F_4431.ASM 3-15-2018 8:55:29 PAGE 37 LOC OBJECT CODE LINE SOURCE TEXT VALUE M ;OvrLoad M ;OverLoad ; M ; Beeper_Toggle M ; goto InitAll ; M 0003CE M MaxPoint:; ; 12 бит PWM M movlf 0xFE,PDC1L,ACCESS ; Младший модулятор 0003CE 0EFE M movlw 0xFE ; в регистр с 7р адресом на 0003D0 6E77 M movwf PDC1L,ACCESS ; текущей странице File7 M movlf 0x3F,PDC1L-1,ACCESS ; Старший модулятор 0003D2 0E3F M movlw 0x3F ; в регистр с 7р адресом на 0003D4 6E76 M movwf PDC1L-1,ACCESS ; текущей странице File7 0003D6 D??? M bra Done 0003D8 M ZeroPoint: ; Выходное значение =0, пропуск умножения и сравнения верхнего порога 0003D8 6A77 M clrf PDC1L,ACCESS ;; Младший модулятор 0003DA 6A76 M clrf PDC1L-1,ACCESS ;; Старший модулятор 0003DC M Done: M ; call DelayCuriosity ; Исследование запаса по быстродействию обработчика M