;Include for: PCPWM_3F_4431.asm ;PCPWM code MaxSpd_100 Extern Simples_100 Add16L PRODL,ACCESS,Simples_100 ; bra Sim_Spd_Done MaxSpd_200 Extern Simples_200 Add16L PRODL,ACCESS,Simples_200 ; bra Sim_Spd_Done ; 20/03/2020 убрал табличку - ПЗУ кончилось. ;MaxSpd_400 ; Extern Simples_400 ; Add16L PRODL,ACCESS,Simples_400 ; ; bra Sim_Spd_Done ; 19/01/2020 убрал табличку - ПЗУ кончилось. ;MaxSpd_800 ; Extern Simples_800 ; ; Add16L PRODL,ACCESS,Simples_800 ; Sim_Spd_Done movff16 PRODL,TBLPTRL ; clrf TBLPTRU,ACCESS ; для указателя таблицы TBLRD*+ movff TABLAT,PCPWM_ML_Work+0 ; TBLRD*+ movff TABLAT,PCPWM_ML_Work+1 ; TBLRD*+ movff TABLAT,PCPWM_ML_Work+2 ; bra Sim_Spd_Move SpeedCalc ; Вычисление приращения из задатчика 100 Гц ; #include Proj_Dir\PCPWM_3F\SpeedCalc.inc ; Разрослось - вынес для удобства ; movff STATUS,C_Temp ; Отладка movf PCPWM_SpeedReal,W,BANKED ; Вынес повторяемый код - Умножаем на случай mullw 0x3 ; трёхбайтные элементы таблиц ; выбора первых таблиц movf PCPWM_MaxSpdIndx,W,BANKED ; Начальные значения - по таблицам простых чисел bz MaxSpd_100 ; Нулевая - 100 Гц максимум dcfsnz WREG,W,ACCESS bra MaxSpd_200 ; Первая - 200 Гц макс ; 20/03/2020 убрал табличку - ПЗУ кончилось. ; dcfsnz WREG,W,ACCESS ; bra MaxSpd_400 ; Вторая - 400 Гц макс ; 19/01/2020 убрал табличку - ПЗУ кончилось. ; dcfsnz WREG,W,ACCESS ; bra MaxSpd_800 ; Третья - 800 Гц макс ;; Если более - то прежний алгоритм ;Tab16Load macro A_Arg,TableAdr; Загрузка указателей таблицы 16 бит Tab16Load PCPWM_MaxSpdIndx,Table_Simples; Загрузка указателей таблицы 16 бит ; movff PCPWM_SpeedReal,PCPWM_SpdCopy ; Копия для отладки FXMTab1608U PCPWM_ML_Work,BANKED,PCPWM_SpeedReal,BANKED;D_Arg,A1D,A_Arg,A1A;16 бит из таблицы на 8 бит без знака ;; Умножаем (без)знаково 8 бит скорость на 16 бит простое число из таблицы= 24 бит приращение на выходе. ;; Буфера под 32 бита приходится заготовить ; Sim_Spd_Move ; bcf INTCON,GIEL,ACCESS ; Прерывания низкий приоритет запрет movff24 PCPWM_ML_Work,BufProduct; Для использования в прерывании приращение угла накопителя фазы bsf INTCON,GIEL,ACCESS ; Прерывания низкий приоритет разрешить #ifdef PCPWM_12b ; 12 бит вычисления movf PCPWM_Amp,W,BANKED ; наклон характеристики V/F mulwf PCPWM_SpeedReal,BANKED; умножили текущую скорость на наклон характеристики V/F movff16 PRODL,PCPWM_ML_Work+2 ; Сохраняем в буферок умножение ; отладка movff C_Temp,STATUS; Восстанавливаем входной (случайный ?) перенос ;22/03/2020 входной перенос в модуль не особо случаен - пляшет ~1 Гц ; Входной перенос = пофик rlcf PRODL,W,ACCESS; Младший байт наклона movwf PCPWM_ML_Work+2,BANKED ; rlcf PRODH,W,ACCESS ;Старший байт наклона movwf PCPWM_ML_Work+3,BANKED ; bc MaxAmp12 ; При переносе - пропускаем сложение со смещением movf PCPWM_VFStart,W,BANKED ; смещение характеристики V/F mulwf PCPWM_VFStart,BANKED; возводим в квадрат или умножаем на константу смещение Add16 PCPWM_ML_Work+2,BANKED,PRODL,ACCESS bnc NoLim12 ; Перенос был ? MaxAmp12 setf PCPWM_ML_Work+2,BANKED ; Ставим setf PCPWM_ML_Work+3,BANKED ; результат NoLim12 ; Делаем из 16 бит 12 #ifdef PCPWM_DC_Corr ; 22/03/2020 добавил опцию ; movff16 PCPWM_ML_Work+2,DeBug_BufLcd+0 ; Отладочная замена ; 20/03/2020 Добавка умножения для коррекции амплитуды ; Умножаем 16*16 амплитуду на номинальное+0x7F и полученные 32 бита ; делим на 16 бит АЦП накопитель. Полученные 16 бит заменяют амплитуду. ; movlf 0x7F,PCPWM_ML_Work+4,bnk ; Мл байт номинала DC movff PcDC_VN,PCPWM_ML_Work+5 ; Ст байт множителя А ; Перед умножением PCPWM_ML_Work+2|3,bnk = вычисленная амплитуда 16 бит ; PCPWM_ML_Work+4|5,bnk = номинальное DC 16 бит ; PCPWM_ML_Work+6|7,bnk = неизвестно что, будет записан результат умножения старшие байты FXM1616U2 PCPWM_ML_Work+4,bnk ,PCPWM_ML_Work+4,bnk ,PCPWM_ML_Work+2,bnk, PCPWM_ML_Work+0,bnk ; ; movff_N PCPWM_ML_Work+4,PcDC_Amp+0,4 ; Буферируем для вывода ; FXM1680U C_Arg,BANKED ,A_Arg,BANKED ,B_Arg,BANKED;, Math_Work+3,BANKED ; ; C=А*B, А и В сохраняются неизменными ; Новый макрос могет в качестве АргС иметь АргА (приемник одинаков с источником) ; а могет и копировать в другие адреса. ; FXD3216U macro A_Arg,A1A,B_Arg,A1B,_Work,A1W; ; Подразумевается в памяти Младший-Старший байт идут ; АргументА 4 байта - 32 бита делимое и 16 бит результат в младших байтах, (+остаток в старших закоментил) ; Остаток также в _Work+0:+1 ; АргументБ 2 байта - делитель остаётся неизменным ; При переполнении 4 байта аргумента А = 0xFF ; Требуются 4 байта рабочей переменной _Work,A1W ;Unsigned Division 32bit / 16bit -> 16bit + 16bit ; Перед делением PCPWM_ML_Work+4|7,bnk = результат умножения ; PCPWM_ML_Work+0|3,bnk - ничего нужного, можно использовать как раб буфер деления FXD3216U PCPWM_ML_Work+4,bnk,PcDC_ADC+0,bnk,PCPWM_ML_Work+0,bnk; ; Подразумевается в памяти Младший-Старший байт идут ; movff_N PCPWM_ML_Work+4,PcDC_Amp+4,4 ; Буферируем для вывода ;Con16v12 MACRO Destin,AdrD,Source,AdrS ; Преобразование 16 в 12 бит Con16v12 PCPWM_ML_Work+0,BANKED,PCPWM_ML_Work+4,BANKED ; #else;#ifdef PCPWM_DC_Corr ; 22/03/2020 добавил опцию Con16v12 PCPWM_ML_Work+0,BANKED,PCPWM_ML_Work+2,BANKED ; #endif; #ifdef PCPWM_DC_Corr ; 22/03/2020 добавил опцию #ifdef PCPWM_3H ; 07/03/2020 добавил опцию ; 05/03/2020 **** отладил амплитуду 3 гармоники movf PcPwmAngInd,W,BANKED ; Амплитуда Третьей гармоники sublw d'3' ; больше нуля только при bnz ZeroAmp3H ; угле между фаз = 3 movff16 PCPWM_ML_Work+0,PCPWM_ML_Work+2; Для вычисления амплитуды 3H ; Sub16L PCPWM_ML_Work+2,BANKED,d'1638' ; Вычитаем начало роста 3 гармоники Sub16L PCPWM_ML_Work+2,BANKED,d'3180' ; 13/03/2020 начало роста 3 гармоники bc NonZeroAmp3 ; Инверсный заём ; Если основная (0|0xFFF) меньше 2/5= 1638 то амплитуда 3 гармоники = 0. ZeroAmp3H clrf PCPWM_ML_Work+4,BANKED ; Амплитуда 3й гармоники после вычислений V/F clrf PCPWM_ML_Work+5,BANKED ; Амплитуда 3й гармоники после вычислений V/F bra DoneAmp3 NonZeroAmp3 ; Иначе она равна разнице (1638|4095-1638=0|2457)*6.6943 = (0|16448). ; С фиксированной точкой 16b*16b=32/16b это будет например 6.6943*256=1713.74 множитель разницы. ; #define MultiplAmp3H d'1713' ; 13/03/2020 Иначе разница (3180|4095-3180=0|915)*14.3246 = (0|13107). ; С фиксированной точкой 16b*16b=32/16b это будет например 14.3246*256=3667,095 множитель разницы. #define MultiplAmp3H d'3667' ; Результат умножения SynMulBuf+2 : PCPWM_AmpSin3+0 : PCPWM_AmpSin3+1 младший байт только для переносов ; PCPWM_ML_Work+4 : PCPWM_ML_Work+5 movlw low(MultiplAmp3H) ; Младшие байты mulwf PCPWM_ML_Work+2,BANKED ; перемножаем ; movff PRODL,SynMulBuf+2 ; Отброшен позже movff PRODH,PCPWM_ML_Work+4; спасаем результат movlw high(MultiplAmp3H) ; старшие байты mulwf PCPWM_ML_Work+3,BANKED ; перемножаем movff PRODL,PCPWM_ML_Work+5 ; спасаем результат, старший байт будет отброшен movlw low(MultiplAmp3H) ; Младший байт со старшим mulwf PCPWM_ML_Work+3,BANKED ; перемножаем ; ArgB,A1B,ArgA,A1A ; в памяти Младший-Старший идут ; Результат будет B=B+A Add16 PCPWM_ML_Work+4,BANKED,PRODL,ACCESS; Складываем перекрёст с серединкой movlw high(MultiplAmp3H) ; старший байт с младшим mulwf PCPWM_ML_Work+2,BANKED ; перемножаем Add16 PCPWM_ML_Work+4,BANKED,PRODL,ACCESS; Складываем перекрёст с серединкой ; В PCPWM_ML_Work+4 должна быть (0|16440) величина. DoneAmp3 ; #else ;#ifdef PCPWM_3H ; ; #include Proj_Dir\PCPWM_3F\Int_PCPWM_3F_x431.inc ; фазные вычислители прежние для отладки. #endif;#ifdef PCPWM_3H ; ; Засылаем буферок в значения для фазного вычислителя с запретом прерываний bcf INTCON,GIEL,ACCESS ; Прерывания низкий приоритет запрет movff16 PCPWM_ML_Work+0,PCPWM_AmpSin; Для использования в прерывании #ifdef PCPWM_3H ; 07/03/2020 добавил опцию movff16 PCPWM_ML_Work+4,PCPWM_AmpSin3+0 ;3 гармоника Для использования в прерывании #endif;#ifdef PCPWM_3H ; bsf INTCON,GIEL,ACCESS ; Прерывания низкий приоритет разрешить #else ; 8 bit ;#ifdef PCPWM_12b movf PCPWM_Amp,W,BANKED ; наклон характеристики V/F, при замедлении для остановки делается FF mulwf PCPWM_SpeedReal,BANKED; умножили текущую скорость на наклон характеристики V/F clrf PCPWM_ML_Work+2,BANKED ; Младший байт слагаемого rrcf PCPWM_VFStart,W,BANKED ; Пара rrcf PCPWM_ML_Work+2,F,BANKED; сдвигов 16 бит rrcf WREG,W,ACCESS ; перед складыванием rrcf PCPWM_ML_Work+2,F,BANKED; начала и произведения andlw b'00111111' ; Вынужден перейти к 16 битам - глючит ; РабРег=ст байт начала, буферок=мл байт movwf PCPWM_ML_Work+3,BANKED ; ;movwf PCPWM_SpdCopy,BANKED ; Add16 PCPWM_ML_Work+2,BANKED,PRODL,ACCESS bc MaxLimit ; Перенос был ? ; bcf _C ; Перенос и так чистый rlcf PCPWM_ML_Work+2,F,BANKED ; мл байт произведения * 2 rlcf PCPWM_ML_Work+3,W,BANKED ; ст байт произведения * 2 btfsc _C; MaxLimit ; Перенос был ? - с переносом глюк, слишком большие числа не правильно. MaxLimit setf WREG,ACCESS ; ставим результат в случае переноса movwf PCPWM_AmpSin,BANKED ; засылаем РабРег в буфер результата #endif ; #ifdef PCPWM_12b ; 12 битвычисления ;movff PCPWM_AmpSin,PCPWM_AmpSinCopy ; Копия для отладки return ; Вычисление приращения из скорости - закончено.