; DeBug 12 bit ; Код из Help отладки симулятор USART ; bcf TRISC,6 ; Make RC6 an output ; movlw 19h ; 9600 baud @4MHz movlw 0x01 ; Много/Максимум baud @ 48 MHz для симулятора movwf SPBRG,ACCESS ; bsf TXSTA,TXEN,ACCESS ; Enable transmit bsf TXSTA,BRGH,ACCESS ; Select high baud rate bsf BAUDCTL,BRG16,ACCESS; Select 16 бит режим генератора baud rate ; Примерно 400-500 кбит при тактовой 50 МГц bsf RCSTA,SPEN,ACCESS ; Enable Serial Port bsf RCSTA,CREN,ACCESS ; Enable continuous reception ; Extern Table_Sinus PCPWM_Page ; BSR for PCPWM Task movlf 0x3A,DeBug_BufLcd+9,BANKED; Порог перехода от 9 к А в знакогенераторе. movlf 0x0,PCPWM_MK1+0,BANKED; Мл. Байт Множителя масштабирования для 12 бит movlf 0x14,PCPWM_MK1+1,BANKED; Ст. Байт Множителя масштабирования для 12 бит clrf PCPWM_AmpSin+0,BANKED ; Буфер Амплитуды синусоиды после вычислений V/F младший байт clrf PCPWM_AmpSin+1,BANKED ; bra DeBugLoopAmp ; Ненавязчивая добавка 0x0D к каждому 0x0A в выходном потоке - заставила передавать текстом ; вместо двоичных значений. HexNibSend andlw 0x0F ; чистим старший нибл Акб addlw 0x30 ; cpfsgt DeBug_BufLcd+9,BANKED; Пропуск если Порог9 > WREG addlw 0x7 ; иначе Прибавляем смещение до А ByteSend movwf TXREG,ACCESS ; nop ; Время для установки флагов USART ; btfss PIR1,TXIF,ACCESS ; Флаг прерывания от USART btfss TXSTA,TRMT,ACCESS ; Флаг пустого буфера передачи bra $-2 ; return SendHexWord macro ArgA,Adr1,Lit1 ; 23/01/2020 вроде не должен портить аргумент - портит лишь РабРег. movlw Lit1 ; Разделитель полей в выходном файле rcall ByteSend ; разделитель swapf ArgA+1,W,Adr1 ; Порядок выдачи - rcall HexNibSend ; первыми старшие разряды movf ArgA+1,W,Adr1 ; rcall HexNibSend ; второй старший разряд swapf ArgA+0,W,Adr1 ; rcall HexNibSend ; третий разряд movf ArgA+0,W,Adr1 ; rcall HexNibSend ; младший разряд endm DeBugLoopAmp: EXTERN PDC_TableLoad ; call PDC_TableLoad ; clrf DeBug_BufLcd+0,BANKED ; Отладочный переполняющийся clrf DeBug_BufLcd+1,BANKED ; 16 бит счетчик ; movlw 0x0D ; Разделитель полей в выходном файле ; rcall ByteSend ; разделитель movlw 0x0A ; Разделитель полей в выходном файле rcall ByteSend ; разделитель SendHexWord PCPWM_AmpSin+0,BANKED,"%" ; =====0====== PCPWM_AmpSin+0,BANKED ; Буфер Амплитуды синусоиды после вычислений V/F младший байт DeBugLoop: movlw ";";0x0D ; Разделитель полей в выходном файле rcall ByteSend ; разделитель movlw 0x0A ; Разделитель полей в выходном файле rcall ByteSend ; разделитель ; ============ Присваивание полей макроса реальным именам ============= PDC_16L equ PDC0L ; PDC_16H equ PDC0H ; Angle_8 equ DeBug_BufLcd+1 ; BSF EECON1, EEPGD,ACCESS ; Point to PROGRAM memory NotSendSinus ; Сразу по 2 штуки увеличиваем ; Inc16 DeBug_BufLcd+0,BANKED ; Отладочный переполняющийся Add16L DeBug_BufLcd+0,BANKED,0x20 ; Из накопителя угла берём старшие 16 бит ; movf DeBug_BufLcd+1,W,BANKED ; 12 бит счетчик ; andlw 0xF0 ; чистим младший нибл Акб ; bz $+6 ; Через GoTo bnc $+6 ; Через GoTo goto EndDeBugLoop ; ; movf DeBug_BufLcd+1,W,BANKED ; 12 бит счетчик ; andlw 0x0F ; чистим старший нибл Акб ; movwf DeBug_BufLcd+1,BANKED ; для выборки синуса ; movwf TBLPTRH,ACCESS ; при отладке ; movff DeBug_BufLcd+0,TBLPTRL ; ; ; btfss TBLPTRL,0,ACCESS ; Таблица синусов - двух байтные числа ; bra NotSendSinus ; =========== Код кусков макроса начинается здесь (всё кроме отладочного вывода в УСАРТ) ;; Формируем 12 бит указатель из 16 бит адреса - 9 команд с пересылкой в указатель таблицы. 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 ; Старший байт адреса с поменянными ниблами в Акб andlw 0x0F ; чистим старший нибл Акб movwf TBLPTRH,ACCESS ; Старший нибл в старшем байте указателя. ;--- ; btfss TBLPTRL,0,ACCESS ; Таблица синусов - двух байтные числа ; bra NotSendSinus ; Отладочные строки - в макросе их нет ;--- bcf TBLPTRL,0,ACCESS ; Таблица синусов - двух байтные числа ;**************************************************************************************** ; SendHexWord DeBug_BufLcd+0,BANKED,"#";=====1====== Номер таблицы синуса старый SendHexWord TBLPTRL+0,ACCESS,"#"; Номер таблицы синуса новый с проверкой конвертатора ;**************************************************************************************** btfsc TBLPTRH,3,ACCESS ; Старший бит 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+0x802) ; Из Конца таблицы movwf TBLPTRL,ACCESS ; movf TBLPTRH,W,ACCESS ; Старший байт btfss _C ; Если в прошлом вычитании Заем incfsz WREG,W,ACCESS ; Увеличим Старший БАЙТ Вычитаемого на 1, sublw high(Table_Sinus+0x802); Из Конца таблицы movwf TBLPTRH,ACCESS ; DoneAdress ; ***** Конец попытки укоротить таблицу вдвое ;1) Перемножаем младшие байты: tblrd*+ ; Читаем младший байт синуса из таблицы синусов movf TABLAT,W,ACCESS ; Младший байт 16 бит синуса movwf SynMulBuf+7,BANKED; буферируем - будет нужен ниже ;**************************************************************************************** movwf DeBug_BufLcd+6,BANKED; ******** Отладка USART ;**************************************************************************************** mulwf PCPWM_AmpSin+0,BANKED; Буфер Амплитуды синусоиды после вычислений V/F младший байт movff16 PRODL,SynMulBuf+0 ; спасаем результат tblrd*+ ; Читаем старший байт синуса movf TABLAT,W,ACCESS ; Старший байт 16 бит синуса ;**************************************************************************************** movwf DeBug_BufLcd+7,BANKED; ******** Отладка USART SendHexWord DeBug_BufLcd+6,BANKED,"=" ;=====2====== Значение синуса из таблицы movf TABLAT,W,ACCESS ; ******Восстановил АКБ ********* Старший байт 16 бит синуса ;**************************************************************************************** ;2) Перемножаем старшие байты: mulwf PCPWM_AmpSin+1,BANKED; Буфер Амплитуды синусоиды старший байт <0x10 ; movff16 PRODL,SynMulBuf+2 ; спасаем результат в старшую половину movff PRODL,SynMulBuf+2 ; спасаем результат в старшую половину ; Все 4 байта результата инициализированы - можно складывать в серединку. ;3) старший Sin на младший Amp, прибавляем к середине результата mulwf PCPWM_AmpSin+0,BANKED; Буфер Амплитуды синусоиды после вычислений V/F младший байт ; ArgB,A1B,ArgA,A1A ; в памяти Младший-Старший идут ; Результат будет B=B+A Add16 SynMulBuf+1,BANKED,PRODL,ACCESS; Складываем перекрёст с серединкой ;4) Младший Sin на старший Amp, прибавляем к середине результата movf SynMulBuf+7,W,BANKED; буфер Sin младшего mulwf PCPWM_AmpSin+1,BANKED; Буфер Амплитуды синусоиды старшой байт ; ArgB,A1B,ArgA,A1A ; в памяти Младший-Старший идут ; Результат будет B=B+A Add16 SynMulBuf+1,BANKED,PRODL,ACCESS; Складываем перекрёст с серединкой btfss TABLAT,7,ACCESS ; Знак Старший байт 16 бит синуса bra ExitMul ;Sub16 ArgB,A1B,ArgA,A1A ; в памяти Младший-Старший идут ; Результат B=B-A Sub16 SynMulBuf+2,BANKED,PCPWM_AmpSin+0,BANKED; в соответствии с кодом FXM1616S ExitMul ; Отладка показала что здесь имеем знаковое число размаха от 8 355 585/0x7f7f01 до -8 355 585/0x8080FF #ifdef __DEBUG;******* отладчик АКБ покажет movf SynMulBuf+0,W,BANKED; Результат вычислений младший байт movf SynMulBuf+1,W,BANKED; Результат средний0 байт movf SynMulBuf+2,W,BANKED; Результат средний1 байт movf SynMulBuf+3,W,BANKED; старший байт всегда = 0 должен быть #endif ; Для возврата к беззнаковому - надо прибавить эти пол диапазона к результату ;Края диапазона при максимальной амплитуде должны соответствовать 0 и 2048 регистра PDC, середина, которая = 0 = 1024 PDC. ;0=0гр=0000=00000000==средняя точка пвм ;64=90гр=7fff=007f7f01=максимум ПВМ, удвоенный буде FEFE02, после сдвигов - 7F7 ;128=180гр=0000=00000000=средняя точка пвм, после коррекции FEFE02 ;192=270гр=8001=ff8080ff=минимум ПВМ=после коррекции = 00000000000 ;255=359гр=fcdc=fffcdf24=почти ноль, после коррекции = 7c5e25 - почти средняя точка movlw 0x01; ; Складывание 32 бит результата с константой 0x7f7f01 ADDWF SynMulBuf+0,F,BANKED; младший movlw 0x7F; ; Складывание 32 бит результата с константой 0x7f7f01 ADDWFC SynMulBuf+1,F,BANKED; средний-1 movlw 0x7F; ; Складывание 32 бит результата с константой 0x7f7f01 ADDWFC SynMulBuf+2,F,BANKED; средний-2 ;**************************************************************************************** SendHexWord SynMulBuf+1,BANKED,"*" ; =====3====== Значение синус * Амплитуду без знака ;**************************************************************************************** ; 16 бит синуса * 8 бит амплитуды = 24 бита, прибавляем точку нуля, усекаем до 16 бит. ; 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 ;При отсутствии заёма - Максимальное значение ;**************************************************************************************** SendHexWord SynMulBuf+1,BANKED,"+" ; =====4====== Зажатое / ограниченног Значение синус * Амплитуду без знака ;**************************************************************************************** ; Выходное значение зажато между границами, теперь его надо отмасштабировать из ХХХХ в строго 11 бит например ; PCPWM_MK1+0 присваивается в \Init_PCPWM_3F.inc:217 ;FXM1616U2 macro D_Arg,A1D,A_Arg,A1A,B_Arg,A1B,_Work,A1W; ; Подразумевается в памяти Младший-Старший байт идут ; FXM1616U2 SynMulBuf+4, bnk, SynMulBuf+1, bnk, PCPWM_MK1+0, bnk, SynMulBuf+0, bnk; Умножаем на коэфф ; FXM1680U SynMulBuf+4, bnk, SynMulBuf+1, bnk, PCPWM_MK1+0, bnk;, SynMulBuf+0, bnk; Умножаем на коэфф 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 ; Старший модулятор ;**************************************************************************************** movff PRODL,DeBug_BufLcd+4 ; Младший модулятор movff PRODH,DeBug_BufLcd+5 ; Старший модулятор ;**************************************************************************************** bra Done MaxPoint: ; 05/01/2019 отлаживал верхнюю полку на осциллограммах подробно ; В момент равенства PDC=4*PTPer-DTCon - наблюдается глюк формирователя DT - одновременное ; открытие транзисторов на малое время ~ 0.1 мкСек. ;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 ; Ст.модулятор верхней полки ;**************************************************************************************** movwf DeBug_BufLcd+4,BANKED; Мл.модулятор верхней полки в УСАРТ movff SynMulBuf+0,DeBug_BufLcd+5;,BANKED; Ст.модулятор верхней полки в УСАРТ ;**************************************************************************************** bra Done TopWithoutCharge movff PcPwmPdcMax+0,PDC_16L;,ACCESS; Мл.модулятор верхней полки movff PcPwmPdcMax+1,PDC_16L-1;,ACCESS; Ст.модулятор верхней полки ;**************************************************************************************** movff PcPwmPdcMax+0,DeBug_BufLcd+4;,BANKED; Мл.модулятор верхней полки в УСАРТ movff PcPwmPdcMax+1,DeBug_BufLcd+5;,BANKED; Ст.модулятор верхней полки в УСАРТ ;**************************************************************************************** bra Done 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; Ст.модулятор ;**************************************************************************************** movwf DeBug_BufLcd+4,BANKED; Мл.модулятор ZeroPoint в УСАРТ movff SynMulBuf+0,DeBug_BufLcd+5;,BANKED; Ст.модулятор ZeroPoint в УСАРТ ;**************************************************************************************** ; movlf 0x19,PDC_16L,ACCESS ;Отладка Младший модулятор bra Done BotWithoutPWM clrf PDC_16L,ACCESS ; Младший модулятор clrf PDC_16L-1,ACCESS ;; Старший модулятор ;**************************************************************************************** clrf DeBug_BufLcd+4,BANKED ; Младший модулятор clrf DeBug_BufLcd+5,BANKED ; Старший модулятор ;**************************************************************************************** Done: ;**************************************************************************************** ; 23/01/2020 Есть мнение что при чтении модулятора в симуляторе МпЛаб - байты меняются местами ; movff PDC_16L,DeBug_BufLcd+4 ; Младший модулятор ; movff PDC_16L-1,DeBug_BufLcd+5 ; Старший модулятор SendHexWord DeBug_BufLcd+4,BANKED,"$";=====5====== Значение в PDC ;**************************************************************************************** goto DeBugLoop ; SinTabLdDbg Angle_1+2,PDC0L ; номер элемента и адрес куда заслать EndDeBugLoop ; Inc16 PCPWM_AmpSin+0,BANKED ; ; Буфер Амплитуды синусоиды Add16L PCPWM_AmpSin+0,BANKED,0xD ; Буфер Амплитуды синусоиды movf PCPWM_AmpSin+1,W,BANKED ; старшой байт andlw 0xF0 ; чистим младший нибл Акб bnz $+6 goto DeBugLoopAmp nop nop halt sleep bra $-2