; PDC_3H_Macro.inc Include for Filename: Int_PCPWM_3H_x431.inc * ; #include Proj_Dir\PCPWM_3F\PDC_3H_Macro.inc;Макросы повторяющегося кода вынес ;Angle_8 equ Angle_1+2 Con16v12b MACRO Destin,AdrD,Source,AdrS ; Начало Преобразования 16 в 12 бит ;; Формируем 12 бит указатель из 16 бит адреса - 9 команд с пересылкой в указатель таблицы. ; Добавлено буферирование для 3й гармоники в SynAdrH Старший байт адреса таблицы синусов swapf Source+0,W,AdrS ; Младший нибл стал младшим в Акб andlw 0x0F ; чистим старший нибл Акб movwf Destin,AdrD ; Буферизуем результат младшего нибла swapf Source+1,W,AdrS ; Старший байт адреса с поменянными ниблами в Акб andlw 0xF0 ; чистим младший нибл Акб iorwf Destin,F,AdrD ; Средний нибл в младшем байте указателя swapf Source+1,W,AdrS ; Старший байт адреса с поменянными ниблами в Акб movwf SynAdrH,BANKED; Старший байт адреса таблицы синусов и 3 гармоники тоже andlw 0x03;0x0F ; чистим старший нибл Акб для 1/4 периода movwf TBLPTRH,ACCESS ; Старший нибл в старшем байте указателя. ; swapf Angle_8-1,W,BANKED ; Младший нибл стал младшим в Акб ; andlw 0x0F ; чистим старший нибл Акб ; movwf TBLPTRL,ACCESS ; Буферизуем результат младшего нибла ; swapf Angle_8+0,W,BANKED ; Старший байт адреса с поменянными ниблами в Акб ; andlw 0xF0 ; чистим младший нибл Акб ; iorwf TBLPTRL,F,ACCESS ; Средний нибл в младшем байте указателя ; swapf Angle_8+0,W,BANKED ; Старший байт адреса с поменянными ниблами в Акб ; ENDM ; Новый макрос для устранения повторно вводимого кода и дублирования меток ; Повторяющийся код оформлен макросом. ; На входе - смещение таблицы уже в TBLPTRL, выход - засылаем в ШИМ указанного адреса Sin2PdcLoad macro PDC_16L ; Выборка из таблицы и засылка в PWM local ExitMul,Done,ZeroPoint, MaxPoint,Reverse,DoneAdress local OvrLoad,OvrLoad1,TopWithoutCharge,BotWithoutPWM local SubFromMiddle ; код выборки таблицы синусов, умножения на амплитуду,складывания/вычитания с накопителем, ; нормализации до необходимого значение для PCPWM, вывода в модулятор. ; Выполняется часто - каждая команда дорога. ; **** Где-то здесь будет вход в новый макрос фазного вычислителя. ;6. **** Вычисление опорной/первой фазы ; bcf TBLPTRL,0,ACCESS ; Таблица синусов - ОДНО байтные положительные числа btfsc SynAdrH,2,BANKED ; 1/4 = Почти Старший бит 12 бит угла bra Reverse ; Вычитаем Add16L TBLPTRL,ACCESS,Table_Sinus ; Начальный адрес таблицы синусов основной частоты ;#ifdef PCPWM_CoSinus; Yes ; Экономия ~2 Кб ПЗУ ценой усложнения фазного вычислителя на ~10 циклов bra DoneAdress Reverse ; Обратное движение с другого конца половины/четверти синусоиды ; bcf TBLPTRH,3,ACCESS ; Старший бит 12 бит угла movf TBLPTRL,W,ACCESS ; sublw low(Table_Sinus+0x400) ; Из Конца таблицы movwf TBLPTRL,ACCESS ; movf TBLPTRH,W,ACCESS ; Старший байт btfss _C ; Если в прошлом вычитании Заем incfsz WREG,W,ACCESS ; Увеличим Старший БАЙТ Вычитаемого на 1, sublw high(Table_Sinus+0x400); Из Конца таблицы movwf TBLPTRH,ACCESS ; DoneAdress ; ***** Конец вычисления 1/2 либо 1/4 адреса таблицы ;7. ****** Перемножение основного синуса на основную амплитуду с накоплением в ; 1) Перемножаем младшие байты: tblrd*+ ; Читаем единственный байт синуса из таблицы movf TABLAT,W,ACCESS ; Единственный байт 8+1 бит синуса mullw 0x08 ; Превращаем синус 8+1 в 12 бит movff16 PRODL,SynMulBuf+6; буферируем - будет нужно ниже movf PRODL,W,ACCESS ; Младший байт 16 бит синуса mulwf PCPWM_AmpSin+0,BANKED; Буфер Амплитуды синусоиды после вычислений V/F младший байт movf PRODL,W,ACCESS ; Средние байты множим, прибавляем btfsc SynAdrH,3,BANKED ; 1/4 = Почти Старший бит 12 бит угла bra SubFromMiddle ; Вычитаем addwf SynMulBuf+0,f,BANKED ; Add movf PRODH,W,ACCESS ; products addwfc SynMulBuf+1,f,BANKED ; к накопителю результата btfsc _C ; Без порчи РабРега учёт переноса incf SynMulBuf+2,f,BANKED ; Самый старший байт результата ; tblrd*+ ; Читаем старший байт синуса ;7. ****** 2) Перемножаем старшие байты: movf SynMulBuf+7,W,BANKED ; Старший байт 16 бит синуса <0x10 mulwf PCPWM_AmpSin+1,BANKED; Буфер Амплитуды синусоиды старший байт <0x10 movf PRODL,W,ACCESS ; Средние байты множим, прибавляем addwf SynMulBuf+2,f,BANKED ; Add ; movf PRODH,W,ACCESS ; products ; Старший ; addwfc SynMulBuf+1,f,BANKED ; к накопителю результата ; байт ; btfsc _C ; Без порчи РабРега учёт переноса ; позже ; incf SynMulBuf+2,f,BANKED ; Самый старший байт ; отброшен ; складываем в серединку. ;7. ****** 3) старший Sin на младший Amp, прибавляем к середине результата movf SynMulBuf+7,W,BANKED ; Старший байт 16 бит синуса <0x10 mulwf PCPWM_AmpSin+0,BANKED; Буфер Амплитуды синусоиды после вычислений V/F младший байт movf PRODL,W,ACCESS ; Средние байты множим, прибавляем addwf SynMulBuf+1,f,BANKED ; Add movf PRODH,W,ACCESS ; products addwfc SynMulBuf+2,f,BANKED ; к накопителю результата ; btfsc _C ; Без порчи РабРега учёт переноса ; позже ; incf SynMulBuf+3,f,BANKED ; Самый старший байт ; отброшен ;7. ****** 4) Младший Sin на старший Amp, прибавляем к середине результата movf SynMulBuf+6,W,BANKED; буфер Sin младшего ;movf TABLAT,W,ACCESS ; Единственный байт 8+1 бит синуса mulwf PCPWM_AmpSin+1,BANKED; Буфер Амплитуды синусоиды старшой байт movf PRODL,W,ACCESS ; Средние байты множим, прибавляем addwf SynMulBuf+1,f,BANKED ; Add movf PRODH,W,ACCESS ; products addwfc SynMulBuf+2,f,BANKED ; к накопителю результата ; btfsc _C ; Без порчи РабРега учёт переноса ; позже ; incf SynMulBuf+3,f,BANKED ; Самый старший байт ; отброшен bra ExitMul SubFromMiddle ; Вычитаем из накопителя subwf SynMulBuf+0,f,BANKED ; Subtract WREG from f movf PRODH,W,ACCESS ; products subwfb SynMulBuf+1,f,BANKED ; из накопителя результата btfss _C ; Инверсный Заём, Без порчи РабРега учёт переноса decf SynMulBuf+2,f,BANKED ; Самый старший байт результата ; tblrd*+ ; Читаем старший байт синуса ;7. ****** 2-2) Перемножаем старшие байты: movf SynMulBuf+7,W,BANKED ; Старший байт 16 бит синуса <0x10 mulwf PCPWM_AmpSin+1,BANKED; Буфер Амплитуды синусоиды старший байт <0x10 movf PRODL,W,ACCESS ; Старшие байты множим, вычитаем subwf SynMulBuf+2,f,BANKED ; Subtract WREG from f ; movf PRODH,W,ACCESS ; products ; Старший ; subwfc SynMulBuf+1,f,BANKED ; к накопителю результата ; байт ; btfss _C ;Инверсный Заём, Без порчи РабРега учёт переноса; позже ; decf SynMulBuf+2,f,BANKED ; Самый старший байт ; отброшен ; вычитаем из серединки перекрёстные умножения. ;7. ****** 3-2) старший Sin на младший Amp, вычитаем из середки результата movf SynMulBuf+7,W,BANKED ; Старший байт 16 бит синуса <0x10 mulwf PCPWM_AmpSin+0,BANKED; Буфер Амплитуды синусоиды после вычислений V/F младший байт movf PRODL,W,ACCESS ; Средние байты множим, вычитаем subwf SynMulBuf+1,f,BANKED ; Subtract WREG from f movf PRODH,W,ACCESS ; products subwfb SynMulBuf+2,f,BANKED ; из накопителю результата ; btfsc _C ; Без порчи РабРега учёт переноса ; позже ; incf SynMulBuf+3,f,BANKED ; Самый старший байт ; отброшен ;7. ****** 4-2) Младший Sin на старший Amp, прибавляем к середине результата movf SynMulBuf+6,W,BANKED; буфер Sin младшего ;movf TABLAT,W,ACCESS ; Единственный байт 8+1 бит синуса mulwf PCPWM_AmpSin+1,BANKED; Буфер Амплитуды синусоиды старшой байт movf PRODL,W,ACCESS ; Средние байты множим, вычитаем subwf SynMulBuf+1,f,BANKED ; Subtract WREG from f movf PRODH,W,ACCESS ; products subwfb SynMulBuf+2,f,BANKED ; из накопителя результата ExitMul ; Тут в SynMulBuf должно быть положительное число макс амплитудой 23 бит ;8. ****** ; 16 бит выходного значения сравниваем с верхним и нижним порогом ограничителей, ; присваиваем пороги при пересечении. ; вычитаем нижний порог для смещения точки 0. ; Ограниченные 16 бит для превращения в 11-12 бит ШИМ - умножаем на коэффициент 16 бит, ; результат 32 бита усекаем до 11-12 бит ; Вычитание нижнего порога 1/10 с обнулением при заёме movlw low(0xFFFF/0xA);,W ,A1A ; Младший байт 10% от 0xFFFF subwf SynMulBuf+1,F,BANKED ; Вычитаем А из В, результат в: В=B-A movlw high(0xFFFF/0xA);,W,A1A ; Старший байт, 10% от 0xFFFF ; btfss _C ; Если в прошлом вычитании Заем ; incfsz ArgA+1,W,A1A ; Увеличим Старший БАЙТ Вычитаемого на 1, subwfb SynMulBuf+2,F,BANKED ; и вычтем старшие байты - результат в В #ifdef PCPWM_Board; Yes ; Плата настольная без периферии/контроля условий запуска bnc ZeroPoint ;При заёме - выход на минимум для синхро учебной платы #else bnc BotWithoutPWM;При заёме - обнуление выхода в боевой плате #endif ; Вычитание удвоенного порога 1/5 с присвоением Макс при отсутствии заёма movlw low(0xFFFF-0xFFFF/0x5);,W ,A1A ; Младший байт 10% от 0xFFFF subwf SynMulBuf+1,W,BANKED ; Вычитаем А из В для сравнения movlw high(0xFFFF-0xFFFF/0x5);,W,A1A ; Старший байт, 10% от 0xFFFF subwfb SynMulBuf+2,W,BANKED ; и вычтем старшие байты - результат в В bc MaxPoint ;При отсутствии заёма - Максимальное значение ;9, ***** ; Выходное значение зажато между границами, теперь его надо отмасштабировать из ХХХХ в строго 11 бит например FXM1680U2 SynMulBuf+4, bnk, SynMulBuf+1, bnk, PCPWM_MK1+0, bnk;, SynMulBuf+0, bnk; Умножаем на коэфф movff PRODL,PDC_16L ; Младший модулятор movff PRODH,PDC_16L-1 ; Старший модулятор ; movff SynMulBuf+6,PDC_16L ; Младший модулятор ; movff SynMulBuf+7,PDC_16L-1 ; Старший модулятор bra Done MaxPoint: ;10. ***** Верхнее ограничение ;PcPwmPdcMax :2;F,BANKED; Значение PDC верхней полки - не портим ; movf DTCON,W,ACCESS ; Вычитаемое #1 - Dead Time Unit movf PcPwmTopDT,W,BANKED; Вычитаемое #2 = Интервал времени для заряда конденсаторов при верхней полке bz TopWithoutCharge ; При нулевом времени - ничего не вычитаем movff PcPwmPdcMax+1,SynMulBuf+0 ; Буферок старшего байта для заёмов subwf PcPwmPdcMax+0,W,BANKED ; Уменьшаемое, результат в АКБ btfss _C ; Инверсный заём decf SynMulBuf+0,F,BANKED ; Отработка заёма bsf _C ; Чистим инверсный заём subfwb DTCON,W,ACCESS ; Вычитаемое #1 - Dead Time Unit ; Инверсный заём формируем btfss _C ; Инверсный заём decf SynMulBuf+0,F,BANKED ; Отработка заёма movwf PDC_16L,ACCESS ; Мл.модулятор верхней полки movff SynMulBuf+0,PDC_16L-1;,ACCESS ; Ст.модулятор верхней полки bra Done TopWithoutCharge movff PcPwmPdcMax+0,PDC_16L;,ACCESS; Мл.модулятор верхней полки movff PcPwmPdcMax+1,PDC_16L-1;,ACCESS; Ст.модулятор верхней полки bra Done ;11. **** Нижнее ограничение ZeroPoint: ; Выходное значение =0, пропуск умножения и сравнения верхнего порога ; Двойной защитный интервал времени PDC - численно равен значению DTCON - по причине вдвое более ; высокой тактовой генератора DT. ; В момент равенства PDC=DTCon - наблюдается глюк формирователя DT - одновременное ; открытие транзисторов на малое время ~ 0.1 мкСек. ; ***** При этом равенстве глюк модуля формирования DT - *** отсутствие *** защитного интервала.***** ; Для преодоления глюка - надо программно обеспечить минимальное значение модулятора ВЫШЕ счётчика DT. ; clrf SynMulBuf+0,BANKED ; Буферок старшего байта для переноса movf PcPwmTopDT,W,BANKED; Слагаемое #1 = Интервал времени для заряда конденсаторов при верхней полке bz BotWithoutPWM ; При нулевом времени - ничего не складываем addwf DTCON,W,ACCESS ; Слагаемое №2 btfsc _C ; incf SynMulBuf+0,F,BANKED ; Буферок старшего байта для переноса movwf PDC_16L,ACCESS ; Младший модулятор movff SynMulBuf+0,PDC_16L-1;,ACCESS; Ст.модулятор ; movlf 0x19,PDC_16L,ACCESS ;Отладка Младший модулятор bra Done BotWithoutPWM clrf PDC_16L,ACCESS ; Младший модулятор clrf PDC_16L-1,ACCESS ;; Старший модулятор ;12 **** Конец нового 02/02/2020 макроса Done: endm ; Конец описания одинакового кода. Для быстроты и простоты - в макро а не в саб проге.