This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Hi,
I have weird problem with shadowing.
1) I set CMPCTL.SHDWAMODE = 0. Now I can change CMPA value - this is fine.
2) I set CMPA value for example to 1234, then change CMPCTL.SHDWAMODE from 0 to 1, I can not change CMPA value beaceuse value will immeditly restore to previous CMPA value.
3) I'm changing back to CMPCTL.SHDWAMODE to 0, now I can change CMPA value. I change LOADAMODE from 00b to 11b (freeze mode), but I still can change value for CMPA even when LOADAMODE is in freeze mode.
4) All tests I'm doing from CCS but code behave same
5) Also changing LOADAMODE with SHDWAMODE == 0 doesn't change anything.
Register startup code:
EPwmxRegs->CMPCTL.bit.SHDWAMODE = CC_SHADOW; // tryb shadow dla rejestrów EPWMxA jest aktywny EPwmxRegs->CMPCTL.bit.SHDWBMODE = CC_SHADOW; // tryb shadow dla rejestrów EPWMxB jest aktywny EPwmxRegs->CMPCTL.bit.LOADAMODE = CC_CTR_PRD; // nowa wartość wypełnienia A będzie ładowana, gdy główny licznik będzie równy PRD EPwmxRegs->CMPCTL.bit.LOADBMODE = CC_CTR_PRD; // nowa wartość wypełnienia B będzie ładowana, gdy główny licznik będzie równy PRD // ładowanie przy PRD jest wynikiem tego, że PWM pracuje na odwrót, tj. wyjścia są zanegowane SetEPwmxPeriod(EPwmxRegs, GRID_FREQUENCY); // częstotliwość pracy tranzystorów IGBT dla fgrid == 50.000Hz EPwmxRegs->TBPHS.all = 0x00; // wartość ładowana do licznika podczas synchronizacji EPwmxRegs->TBCTR = 0x00; // zerowanie licznika PWM EPwmxRegs->CMPA.bit.CMPA = 0x00; // zerowe wypełnienie PWM EPwmxRegs->TBCTL.bit.FREE_SOFT = 0b11; // sygnał aktywny w trybie debugowania EPwmxRegs->TBCTL.bit.PHSDIR = TB_UP; // liczy w górę przy synchronizacji EPwmxRegs->TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // tryb licznika up-down EPwmxRegs->TBCTL.bit.SYNCOSEL = TB_SYNC_IN; // wyjście synchronizacji, jest wejściem EPwmxRegs->TBCTL.bit.PHSEN = TB_ENABLE; // synchronizacja modułu z sygnałem SYNCI EPwmxRegs->TBCTL.bit.CLKDIV = TB_DIV1; EPwmxRegs->TBCTL.bit.HSPCLKDIV = TB_DIV1; // taktowanie TBCLK = EPWMCLK / (1 * 1) EPwmxRegs->AQCTLA.bit.CAU = AQ_SET; // ustaw wyjście A, gdy licznik A dojdzie do zadanej wartości oraz licznik główny liczy w górę EPwmxRegs->AQCTLA.bit.CAD = AQ_CLEAR; // wyzeruj wyjście A, gdy licznika A dojdzie do zadanej wartości oraz licznik główny liczy w dół EPwmxRegs->DBCTL.bit.OUT_MODE = DB_FULL_ENABLE; // aktywujemy moduł sterowania komplementarnego z czasem martwym EPwmxRegs->DBCTL.bit.POLSEL = DB_ACTV_HIC; // wyjście komplementarne B jest negacją wyjścia A, wyjścia są aktywne jako plus EPwmxRegs->DBCTL.bit.OUTSWAP = 0b11; // wyjście zamienione, co umożliwia ustawienie wartości wypełnienia 0 == 0% oraz PERIOD == 100% EPwmxRegs->DBCTL.bit.HALFCYCLE = 1; // moduł komplementarny pracuje z podwójną częstotliwością modułu PWM EPwmxRegs->DBFED.bit.DBFED = IGBT_FALLING_EDGE_DBFED; // czas opóźnienia dla zbocza opadającego EPwmxRegs->DBRED.bit.DBRED = IGBT_RISING_EDGE_DBRED; // czas opóźnienia dla zbocza narastającego EPwmxRegs->EPWMXLINK.bit.TBPRDLINK = 1; // linkujemy nastawę TBPRD z EPwm2.TBPRD EALLOW; EPwmxRegs->DCTRIPSEL.bit.DCAHCOMPSEL = 3; // wejście DCAH jako TRIPIN4 z ePWM X-BAR [konfiguracja w GPIO.c] EPwmxRegs->DCACTL.bit.EVT1SRCSEL = 0; // DCAEVT1 źródło bezpośrednio bez filtracji EPwmxRegs->DCACTL.bit.EVT1FRCSYNCSEL = 1; // DCAEVT1 źródło jest asynchroniczne EPwmxRegs->TZCTL.bit.TZA = TZ_FORCE_LO; // wyjście EPWMxA ma być zero jak jest aktywny TZ EPwmxRegs->TZCTL.bit.TZB = TZ_FORCE_LO; // wyjście EPWMxB ma być zero jak jest aktywny TZ EPwmxRegs->TZFRC.bit.OST = 1; // na starcie wymuszamy OST jako softwarowe wyłączenie PWMów EPwmxRegs->TZSEL.bit.DCAEVT1 = 1; // DCAEVT1 jako one-shot-trip EPwmxRegs->TZDCSEL.bit.DCAEVT1 = 2; // DCAEVT1 generujemy, gdy DCAH = 1; DCAL = X // *** Konfiguracja trybu High Resolution EPwmxRegs->HRCNFG.bit.EDGMODE = HR_BEP; // MEP kontroluje obydwa zbocza sygnału EPwmxRegs->HRCNFG.bit.CTLMODE = HR_CMP; // MEP kontrolowany jest przez wypełnienie EPwmxRegs->HRCNFG.bit.HRLOAD = 0; // nowe wartości CMPAHR ładowane są gdy TBCTR == 0x0000 EPwmxRegs->HRCNFG.bit.SELOUTB = 0; // negacja wyjścia B przez moduł HRPWM wyłączona EPwmxRegs->HRCNFG.bit.AUTOCONV = 1; // automatyczne skalowanie HRMSTEP EPwmxRegs->HRCNFG.bit.SWAPAB = 0; // wyjścia A i B nie są zamienione EPwmxRegs->HRCNFG.bit.EDGMODEB = HR_DISABLE; // MEP wyłączony na CMPB EPwmxRegs->HRPCTL.bit.TBPHSHRLOADE = 1; // aktywowanie synchronizacji liczników up/down z sygnałem HR EPwmxRegs->HRPCTL.bit.HRPE = 1; // aktywowanie HRPWM EDIS;
Full info from CCS about this EPwm register
EPwm7Regs struct EPWM_REGS {TBCTL={all=57350,bit={CTRMODE=2,PHSEN=1,PRDLD=0,SYNCOSEL=0,SWFSYNC=0...}},TBCTL2=... 0x00004600@Data TBCTL union TBCTL_REG {all=57350,bit={CTRMODE=2,PHSEN=1,PRDLD=0,SYNCOSEL=0,SWFSYNC=0...}} 0x00004600@Data TBCTL2 union TBCTL2_REG {all=0,bit={rsvd1=0,rsvd2=0,OSHTSYNCMODE=0,OSHTSYNC=0,rsvd3=0...}} 0x00004601@Data rsvd1 unsigned int[2] [0,0] 0x00004602@Data TBCTR unsigned int 1633 0x00004604@Data TBSTS union TBSTS_REG {all=3,bit={CTRDIR=1,SYNCI=1,CTRMAX=0,rsvd1=0}} 0x00004605@Data rsvd2 unsigned int[2] [0,0] 0x00004606@Data CMPCTL union CMPCTL_REG {all=323,bit={LOADAMODE=3,LOADBMODE=0,SHDWAMODE=0,rsvd1=0,SHDWBMODE=1...}} 0x00004608@Data CMPCTL2 union CMPCTL2_REG {all=0,bit={LOADCMODE=0,LOADDMODE=0,SHDWCMODE=0,rsvd1=0,SHDWDMODE=0...}} 0x00004609@Data rsvd3 unsigned int[2] [0,0] 0x0000460A@Data DBCTL union DBCTL_REG {all=45067,bit={OUT_MODE=3,POLSEL=2,IN_MODE=0,LOADREDMODE=0,LOADFEDMODE=0...}} 0x0000460C@Data DBCTL2 union DBCTL2_REG {all=0,bit={LOADDBCTLMODE=0,SHDWDBCTLMODE=0,rsvd1=0}} 0x0000460D@Data rsvd4 unsigned int[2] [0,0] 0x0000460E@Data AQCTL union AQCTL_REG {all=0,bit={LDAQAMODE=0,LDAQBMODE=0,SHDWAQAMODE=0,rsvd1=0,SHDWAQBMODE=0...}} 0x00004610@Data AQTSRCSEL union AQTSRCSEL_REG {all=0,bit={T1SEL=0,T2SEL=0,rsvd1=0}} 0x00004611@Data rsvd5 unsigned int[2] [0,0] 0x00004612@Data PCCTL union PCCTL_REG {all=0,bit={CHPEN=0,OSHTWTH=0,CHPFREQ=0,CHPDUTY=0,rsvd1=0}} 0x00004614@Data rsvd6 unsigned int[3] [0,0,0] 0x00004615@Data VCAPCTL union VCAPCTL_REG {all=0,bit={VCAPE=0,VCAPSTART=0,TRIGSEL=0,rsvd1=0,VDELAYDIV=0...}} 0x00004618@Data VCNTCFG union VCNTCFG_REG {all=0,bit={STARTEDGE=0,rsvd1=0,STARTEDGESTS=0,STOPEDGE=0,rsvd2=0...}} 0x00004619@Data rsvd7 unsigned int[6] [0,0,0,0,0...] 0x0000461A@Data HRCNFG union HRCNFG_REG {all=64,bit={EDGMODE=0,CTLMODE=0,HRLOAD=0,SELOUTB=0,AUTOCONV=1...}} 0x00004620@Data HRPWR union HRPWR_REG {all=0,bit={rsvd1=0,rsvd2=0,rsvd3=0,rsvd4=0,rsvd5=0...}} 0x00004621@Data rsvd8 unsigned int[4] [0,0,0,0] 0x00004622@Data HRMSTEP union HRMSTEP_REG {all=0,bit={HRMSTEP=0,rsvd1=0}} 0x00004626@Data HRCNFG2 union HRCNFG2_REG {all=0,bit={EDGMODEDB=0,CTLMODEDBRED=0,CTLMODEDBFED=0,rsvd1=0,rsvd2=0...}} 0x00004627@Data rsvd9 unsigned int[5] [0,0,0,0,0] 0x00004628@Data HRPCTL union HRPCTL_REG {all=5,bit={HRPE=1,PWMSYNCSEL=0,TBPHSHRLOADE=1,rsvd1=0,PWMSYNCSELX=0...}} 0x0000462D@Data TRREM union TRREM_REG {all=256,bit={TRREM=256,rsvd1=0}} 0x0000462E@Data rsvd10 unsigned int[5] [0,0,0,0,0] 0x0000462F@Data GLDCTL union GLDCTL_REG {all=0,bit={GLD=0,GLDMODE=0,OSHTMODE=0,rsvd1=0,GLDPRD=0...}} 0x00004634@Data GLDCFG union GLDCFG_REG {all=0,bit={TBPRD_TBPRDHR=0,CMPA_CMPAHR=0,CMPB_CMPBHR=0,CMPC=0,CMPD=0...}} 0x00004635@Data rsvd11 unsigned int[2] [0,0] 0x00004636@Data EPWMXLINK union EPWMXLINK_REG {all=1611032161,bit={TBPRDLINK=1,CMPALINK=6,CMPBLINK=6,CMPCLINK=6,CMPDLINK=6...}} 0x00004638@Data rsvd12 unsigned int[4] [0,0,0,1] 0x0000463A@Data EPWMREV union EPWMREV_REG {all=1024,bit={REV=0,TYPE=4}} 0x0000463E@Data rsvd13 unsigned int 768 0x0000463F@Data AQCTLA union AQCTLA_REG {all=96,bit={ZRO=0,PRD=0,CAU=2,CAD=1,CBU=0...}} 0x00004640@Data AQCTLA2 union AQCTLA2_REG {all=0,bit={T1U=0,T1D=0,T2U=0,T2D=0,rsvd1=0}} 0x00004641@Data AQCTLB union AQCTLB_REG {all=0,bit={ZRO=0,PRD=0,CAU=0,CAD=0,CBU=0...}} 0x00004642@Data AQCTLB2 union AQCTLB2_REG {all=0,bit={T1U=0,T1D=0,T2U=0,T2D=0,rsvd1=0}} 0x00004643@Data rsvd14 unsigned int[3] [0,0,0] 0x00004644@Data AQSFRC union AQSFRC_REG {all=0,bit={ACTSFA=0,OTSFA=0,ACTSFB=0,OTSFB=0,RLDCSF=0...}} 0x00004647@Data rsvd15 unsigned int 0 0x00004648@Data AQCSFRC union AQCSFRC_REG {all=0,bit={CSFA=0,CSFB=0,rsvd1=0}} 0x00004649@Data rsvd16 unsigned int[6] [0,0,0,0,0...] 0x0000464A@Data DBREDHR union DBREDHR_REG {all=0,bit={rsvd1=0,rsvd2=0,rsvd3=0,DBREDHR=0}} 0x00004650@Data DBRED union DBRED_REG {all=239,bit={DBRED=239,rsvd1=0}} 0x00004651@Data DBFEDHR union DBFEDHR_REG {all=0,bit={rsvd1=0,rsvd2=0,rsvd3=0,DBFEDHR=0}} 0x00004652@Data DBFED union DBFED_REG {all=239,bit={DBFED=239,rsvd1=0}} 0x00004653@Data rsvd17 unsigned int[12] [0,0,0,0,0...] 0x00004654@Data TBPHS union TBPHS_REG {all=0,bit={TBPHSHR=0,TBPHS=0}} 0x00004660@Data TBPRDHR unsigned int 0 0x00004662@Data TBPRD unsigned int 3888 0x00004663@Data rsvd18 unsigned int[6] [0,0,0,0,0...] 0x00004664@Data CMPA union CMPA_REG {all=131072000,bit={CMPAHR=0,CMPA=2000}} 0x0000466A@Data CMPB union CMPB_REG {all=0,bit={CMPBHR=0,CMPB=0}} 0x0000466C@Data rsvd19 unsigned int 0 0x0000466E@Data CMPC unsigned int 0 0x0000466F@Data rsvd20 unsigned int 0 0x00004670@Data CMPD unsigned int 0 0x00004671@Data rsvd21 unsigned int[2] [0,0] 0x00004672@Data GLDCTL2 union GLDCTL2_REG {all=0,bit={OSHTLD=0,GFRCLD=0,rsvd1=0}} 0x00004674@Data rsvd22 unsigned int[2] [0,0] 0x00004675@Data SWVDELVAL unsigned int 0 0x00004677@Data rsvd23 unsigned int[8] [0,0,0,0,0...] 0x00004678@Data TZSEL union TZSEL_REG {all=16384,bit={CBC1=0,CBC2=0,CBC3=0,CBC4=0,CBC5=0...}} 0x00004680@Data rsvd24 unsigned int 0 0x00004681@Data TZDCSEL union TZDCSEL_REG {all=2,bit={DCAEVT1=2,DCAEVT2=0,DCBEVT1=0,DCBEVT2=0,rsvd1=0}} 0x00004682@Data rsvd25 unsigned int 0 0x00004683@Data TZCTL union TZCTL_REG {all=10,bit={TZA=2,TZB=2,DCAEVT1=0,DCAEVT2=0,DCBEVT1=0...}} 0x00004684@Data TZCTL2 union TZCTL2_REG {all=0,bit={TZAU=0,TZAD=0,TZBU=0,TZBD=0,rsvd1=0...}} 0x00004685@Data TZCTLDCA union TZCTLDCA_REG {all=0,bit={DCAEVT1U=0,DCAEVT1D=0,DCAEVT2U=0,DCAEVT2D=0,rsvd1=0}} 0x00004686@Data TZCTLDCB union TZCTLDCB_REG {all=0,bit={DCBEVT1U=0,DCBEVT1D=0,DCBEVT2U=0,DCBEVT2D=0,rsvd1=0}} 0x00004687@Data rsvd26 unsigned int[5] [0,0,0,0,0] 0x00004688@Data TZEINT union TZEINT_REG {all=0,bit={rsvd1=0,CBC=0,OST=0,DCAEVT1=0,DCAEVT2=0...}} 0x0000468D@Data rsvd27 unsigned int[5] [0,0,0,0,0] 0x0000468E@Data TZFLG union TZFLG_REG {all=0,bit={INT=0,CBC=0,OST=0,DCAEVT1=0,DCAEVT2=0...}} 0x00004693@Data TZCBCFLG union TZCBCFLG_REG {all=0,bit={CBC1=0,CBC2=0,CBC3=0,CBC4=0,CBC5=0...}} 0x00004694@Data TZOSTFLG union TZOSTFLG_REG {all=64,bit={OST1=0,OST2=0,OST3=0,OST4=0,OST5=0...}} 0x00004695@Data rsvd28 unsigned int 0 0x00004696@Data TZCLR union TZCLR_REG {all=0,bit={INT=0,CBC=0,OST=0,DCAEVT1=0,DCAEVT2=0...}} 0x00004697@Data TZCBCCLR union TZCBCCLR_REG {all=0,bit={CBC1=0,CBC2=0,CBC3=0,CBC4=0,CBC5=0...}} 0x00004698@Data TZOSTCLR union TZOSTCLR_REG {all=0,bit={OST1=0,OST2=0,OST3=0,OST4=0,OST5=0...}} 0x00004699@Data rsvd29 unsigned int 0 0x0000469A@Data TZFRC union TZFRC_REG {all=0,bit={rsvd1=0,CBC=0,OST=0,DCAEVT1=0,DCAEVT2=0...}} 0x0000469B@Data rsvd30 unsigned int[8] [0,0,0,0,0...] 0x0000469C@Data ETSEL union ETSEL_REG {all=0,bit={INTSEL=0,INTEN=0,SOCASELCMP=0,SOCBSELCMP=0,INTSELCMP=0...}} 0x000046A4@Data rsvd31 unsigned int 0 0x000046A5@Data ETPS union ETPS_REG {all=0,bit={INTPRD=0,INTCNT=0,INTPSSEL=0,SOCPSSEL=0,rsvd1=0...}} 0x000046A6@Data rsvd32 unsigned int 0 0x000046A7@Data ETFLG union ETFLG_REG {all=0,bit={INT=0,rsvd1=0,SOCA=0,SOCB=0,rsvd2=0}} 0x000046A8@Data rsvd33 unsigned int 0 0x000046A9@Data ETCLR union ETCLR_REG {all=0,bit={INT=0,rsvd1=0,SOCA=0,SOCB=0,rsvd2=0}} 0x000046AA@Data rsvd34 unsigned int 0 0x000046AB@Data ETFRC union ETFRC_REG {all=0,bit={INT=0,rsvd1=0,SOCA=0,SOCB=0,rsvd2=0}} 0x000046AC@Data rsvd35 unsigned int 0 0x000046AD@Data ETINTPS union ETINTPS_REG {all=0,bit={INTPRD2=0,INTCNT2=0,rsvd1=0}} 0x000046AE@Data rsvd36 unsigned int 0 0x000046AF@Data ETSOCPS union ETSOCPS_REG {all=0,bit={SOCAPRD2=0,SOCACNT2=0,SOCBPRD2=0,SOCBCNT2=0}} 0x000046B0@Data rsvd37 unsigned int 0 0x000046B1@Data ETCNTINITCTL union ETCNTINITCTL_REG {all=0,bit={rsvd1=0,INTINITFRC=0,SOCAINITFRC=0,SOCBINITFRC=0,INTINITEN=0...}} 0x000046B2@Data rsvd38 unsigned int 0 0x000046B3@Data ETCNTINIT union ETCNTINIT_REG {all=0,bit={INTINIT=0,SOCAINIT=0,SOCBINIT=0,rsvd1=0}} 0x000046B4@Data rsvd39 unsigned int[11] [0,0,0,0,0...] 0x000046B5@Data DCTRIPSEL union DCTRIPSEL_REG {all=3,bit={DCAHCOMPSEL=3,DCALCOMPSEL=0,DCBHCOMPSEL=0,DCBLCOMPSEL=0}} 0x000046C0@Data rsvd40 unsigned int[2] [0,0] 0x000046C1@Data DCACTL union DCACTL_REG {all=2,bit={EVT1SRCSEL=0,EVT1FRCSYNCSEL=1,EVT1SOCE=0,EVT1SYNCE=0,rsvd1=0...}} 0x000046C3@Data DCBCTL union DCBCTL_REG {all=0,bit={EVT1SRCSEL=0,EVT1FRCSYNCSEL=0,EVT1SOCE=0,EVT1SYNCE=0,rsvd1=0...}} 0x000046C4@Data rsvd41 unsigned int[2] [0,0] 0x000046C5@Data DCFCTL union DCFCTL_REG {all=0,bit={SRCSEL=0,BLANKE=0,BLANKINV=0,PULSESEL=0,EDGEFILTSEL=0...}} 0x000046C7@Data DCCAPCTL union DCCAPCTL_REG {all=0,bit={CAPE=0,SHDWMODE=0,rsvd1=0,CAPSTS=0,CAPCLR=0...}} 0x000046C8@Data DCFOFFSET unsigned int 0 0x000046C9@Data DCFOFFSETCNT unsigned int 0 0x000046CA@Data DCFWINDOW unsigned int 0 0x000046CB@Data DCFWINDOWCNT unsigned int 0 0x000046CC@Data rsvd42 unsigned int[2] [0,0] 0x000046CD@Data DCCAP unsigned int 0 0x000046CF@Data rsvd43 unsigned int[2] [0,0] 0x000046D0@Data DCAHTRIPSEL union DCAHTRIPSEL_REG {all=0,bit={TRIPINPUT1=0,TRIPINPUT2=0,TRIPINPUT3=0,TRIPINPUT4=0,TRIPINPUT5=0...}} 0x000046D2@Data DCALTRIPSEL union DCALTRIPSEL_REG {all=0,bit={TRIPINPUT1=0,TRIPINPUT2=0,TRIPINPUT3=0,TRIPINPUT4=0,TRIPINPUT5=0...}} 0x000046D3@Data DCBHTRIPSEL union DCBHTRIPSEL_REG {all=0,bit={TRIPINPUT1=0,TRIPINPUT2=0,TRIPINPUT3=0,TRIPINPUT4=0,TRIPINPUT5=0...}} 0x000046D4@Data DCBLTRIPSEL union DCBLTRIPSEL_REG {all=0,bit={TRIPINPUT1=0,TRIPINPUT2=0,TRIPINPUT3=0,TRIPINPUT4=0,TRIPINPUT5=0...}} 0x000046D5@Data rsvd44 unsigned int[39] [0,0,0,0,0...] 0x000046D6@Data HWVDELVAL unsigned int 0 0x000046FD@Data VCNTVAL unsigned int 0 0x000046FE@Data rsvd45 unsigned int 0 0x000046FF@Data
It seems to be problem with HRPWM. When I set bit HRPCTL.HRPE to 0 all come back to normal, but when enabled HRPE it makes weird things.
Another weird thing: self-changing CMPA value from 1500 to 1501 and again from 1501 to 1500 without possibility to change it by hand :)
So - i'm still looking for error.
OK, so there is more information:
I have main EPwm1 that is used to clock two ADC converters on channel EPWM1A and EPWM1B. EPwm1 register is working with two times of frequency of EPwm2, 3, 4, 6, 7 and 8 (named as EPwmSET). This 6 PWMs are for three-level three phase IGBTs.
I was able to properly synchronize EPwmSET with EPwm1 only when I disable HRPWM on EPwmSET (bit HRPCTL.HRPE == 0). Unofrtunetly I also disabled CMPAHR/TBPRDHR registry settings. I used workaround - EPwmSET is synchronized with EPwm1 using OSHTSYNC. Also EPwmSET must be phase corrected with EPwm1 so I'm using OSHTSYNC with CMPC EPWM1 register.
This is my full setup:
// ADC EPwm1 setup: ADCClockRegs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; // tryb shadow na rejestry CMPA ADCClockRegs.CMPCTL.bit.SHDWBMODE = CC_SHADOW; // tryb shadow na rejestry CMPB ADCClockRegs.CMPCTL2.bit.SHDWCMODE = CC_SHADOW; // tryb shadow na rejestry CMPC SetADCClockPeriod(GRID_FREQUENCY); // częstotliwość pracy przetwornika ADC dla fgrid == 50.000Hz ADCClockRegs.TBPHS.all = 0x00; // przesunięcie fazowe wyłączone ADCClockRegs.TBCTR = 0x00; // zerowanie licznika PWM ADCClockRegs.TBCTL.bit.PRDLD = 0; // rejestr TBPRD jest ładowany gdy TBCTR == 0x0000 ADCClockRegs.TBCTL.bit.FREE_SOFT = 0b11; // sygnał aktywny w trybie debugowania ADCClockRegs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // tryb licznika up-down ADCClockRegs.TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE; // wyjście synchronizacji, gdy licznik będzie mieć wartość CMPC ADCClockRegs.TBCTL.bit.PHSEN = TB_DISABLE; // wejście synchronizacji wyłączone ADCClockRegs.TBCTL.bit.CLKDIV = TB_DIV1; // taktowanie TBCLK = EPWMCLK / (1 * 1) ADCClockRegs.TBCTL.bit.HSPCLKDIV = TB_DIV1; // taktowanie TBCLK = EPWMCLK / (1 * 1) ADCClockRegs.TBCTL2.bit.OSHTSYNCMODE = 1; // aktywowanie trybu pojedynczej synchronizacji ADCClockRegs.TBCTL2.bit.SYNCOSELX = 1; // wyjście synchronizacji, gdy licznik będzie mieć wartość CMPC ADCClockRegs.AQCTLA.bit.CAU = AQ_SET; // ustaw wyjście gdy licznik dojdzie do CMPA jak liczy w górę ADCClockRegs.AQCTLA.bit.CAD = AQ_CLEAR; // zeruj wyjście gdy licznik dojdzie do CMPA jak liczy w dół ADCClockRegs.AQCTLA.bit.PRD = AQ_NO_ACTION; // brak reakcji gdy licznik dojdzie do PERIOD ADCClockRegs.AQCTLA.bit.ZRO = AQ_NO_ACTION; // brak reakcji gdy licznik dojdzie do zera ADCClockRegs.AQCTLB.bit.CAU = AQ_SET; // ustaw wyjście gdy licznik dojdzie do CMPB jak liczy w górę ADCClockRegs.AQCTLB.bit.CAD = AQ_CLEAR; // zeruj wyjście gdy licznik dojdzie do CMPB jak liczy w dół ADCClockRegs.AQCTLB.bit.PRD = AQ_NO_ACTION; // brak reakcji gdy licznik dojdzie do PERIOD ADCClockRegs.AQCTLB.bit.ZRO = AQ_NO_ACTION; // brak reakcji gdy licznik dojdzie do zera ADCClockRegs.ETSEL.bit.INTSEL = ET_CTRU_CMPA; // przerwanie INT generowane gdy licznik dojdzie do CMPA licząc w górę EPwm1Regs_ETSEL_Shadow = ADCClockRegs.ETSEL.all; // kopiowanie ETSEL dla CPU2 ADCClockRegs.ETPS.bit.INTPSSEL = 0; ADCClockRegs.ETPS.bit.INTPRD = 1; // przerwanie co każdy event // Funkcjonalność wyłączenia softwarowego sygnału taktującego jest realizowane przez TripZone 6. // Procesor ustawiając programowy TZ6 wyłącza generowanie sygnału taktującego przetworniki ADC. EALLOW; ADCClockRegs.TZCTL.bit.TZA = TZ_FORCE_LO; // wyjście EPWM1A ma być zero jak jest aktywny TZ ADCClockRegs.TZCTL.bit.TZB = TZ_FORCE_LO; // wyjście EPWM1B ma być zero jak jest aktywny TZ ADCClockRegs.TZFRC.bit.OST = 1; // przy konfiguracji wymuszamy już TripZone // Konfiguracja trybu High Resolution ADCClockRegs.HRCNFG.bit.EDGMODE = HR_BEP; // MEP kontroluje obydwa zbocza sygnału ADCClockRegs.HRCNFG.bit.CTLMODE = HR_CMP; // MEP kontrolowany jest przez wypełnienie ADCClockRegs.HRCNFG.bit.HRLOAD = 0; // nowe wartości CMPAHR ładowane są gdy TBCTR == 0x0000 ADCClockRegs.HRCNFG.bit.SELOUTB = 0; // wyjście B jest zwykłym wyjściem PWM ADCClockRegs.HRCNFG.bit.AUTOCONV = 1; // automatyczne skalowanie HRMSTEP ADCClockRegs.HRCNFG.bit.SWAPAB = 0; // wyjścia A i B nie są zamienione ADCClockRegs.HRCNFG.bit.EDGMODEB = HR_BEP; // MEP kontroluje obydwa zbocza sygnału na wyjściu B ADCClockRegs.HRCNFG.bit.CTLMODEB = HR_CMP; // MEP kontrolowany jest przez wypełnienie na wyjściu B ADCClockRegs.HRCNFG.bit.HRLOADB = 0; // nowe wartości CMPBHR ładowane są gdy TBCTR == 0x0000 //ADCClockRegs.HRPCTL.bit.TBPHSHRLOADE = 1; // aktywowanie synchronizacji liczników up/down z sygnałem HR ADCClockRegs.HRPCTL.bit.HRPE = 1; // aktywowanie HRPWM EDIS; // IGBT Setup: void InitializeEPwmxRegs(volatile struct EPWM_REGS* EPwmxRegs) { // TODO: ustawienie trip zone // Najpierw należy zmienić tryb Shadow Mode, bo zmiana podowuje wyzerowanie rejestrów CMPA oraz CMPB EPwmxRegs->CMPCTL.bit.SHDWAMODE = CC_SHADOW; // tryb shadow dla rejestrów EPWMxA jest aktywny EPwmxRegs->CMPCTL.bit.SHDWBMODE = CC_SHADOW; // tryb shadow dla rejestrów EPWMxB jest aktywny EPwmxRegs->CMPCTL.bit.LOADAMODE = CC_CTR_PRD; // nowa wartość wypełnienia A będzie ładowana, gdy główny licznik będzie równy PRD EPwmxRegs->CMPCTL.bit.LOADBMODE = CC_CTR_PRD; // nowa wartość wypełnienia B będzie ładowana, gdy główny licznik będzie równy PRD // ładowanie przy PRD jest wynikiem tego, że PWM pracuje na odwrót, tj. wyjścia są zanegowane SetEPwmxPeriod(EPwmxRegs, GRID_FREQUENCY); // częstotliwość pracy tranzystorów IGBT dla fgrid == 50.000Hz EPwmxRegs->TBPHS.all = 0x00; // wartość ładowana do licznika podczas synchronizacji EPwmxRegs->TBCTR = 0x00; // zerowanie licznika PWM EPwmxRegs->CMPA.bit.CMPA = 0x00; // zerowe wypełnienie PWM EPwmxRegs->TBCTL.bit.FREE_SOFT = 0b11; // sygnał aktywny w trybie debugowania EPwmxRegs->TBCTL.bit.PHSDIR = TB_UP; // liczy w górę przy synchronizacji EPwmxRegs->TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // tryb licznika up-down EPwmxRegs->TBCTL.bit.SYNCOSEL = TB_SYNC_IN; // wyjście synchronizacji, jest wejściem EPwmxRegs->TBCTL.bit.PHSEN = TB_ENABLE; // synchronizacja modułu z sygnałem SYNCI EPwmxRegs->TBCTL.bit.CLKDIV = TB_DIV1; EPwmxRegs->TBCTL.bit.HSPCLKDIV = TB_DIV1; // taktowanie TBCLK = EPWMCLK / (1 * 1) EPwmxRegs->AQCTLA.bit.CAU = AQ_SET; // ustaw wyjście A, gdy licznik A dojdzie do zadanej wartości oraz licznik główny liczy w górę EPwmxRegs->AQCTLA.bit.CAD = AQ_CLEAR; // wyzeruj wyjście A, gdy licznika A dojdzie do zadanej wartości oraz licznik główny liczy w dół EPwmxRegs->DBCTL.bit.OUT_MODE = DB_FULL_ENABLE; // aktywujemy moduł sterowania komplementarnego z czasem martwym EPwmxRegs->DBCTL.bit.POLSEL = DB_ACTV_HIC; // wyjście komplementarne B jest negacją wyjścia A, wyjścia są aktywne jako plus EPwmxRegs->DBCTL.bit.OUTSWAP = 0b11; // wyjście zamienione, co umożliwia ustawienie wartości wypełnienia 0 == 0% oraz PERIOD == 100% EPwmxRegs->DBCTL.bit.HALFCYCLE = 1; // moduł komplementarny pracuje z podwójną częstotliwością modułu PWM EPwmxRegs->DBFED.bit.DBFED = IGBT_FALLING_EDGE_DBFED; // czas opóźnienia dla zbocza opadającego EPwmxRegs->DBRED.bit.DBRED = IGBT_RISING_EDGE_DBRED; // czas opóźnienia dla zbocza narastającego EPwmxRegs->EPWMXLINK.bit.TBPRDLINK = 1; // linkujemy nastawę TBPRD z EPwm2.TBPRD EALLOW; EPwmxRegs->DCTRIPSEL.bit.DCAHCOMPSEL = 3; // wejście DCAH jako TRIPIN4 z ePWM X-BAR [konfiguracja w GPIO.c] EPwmxRegs->DCACTL.bit.EVT1SRCSEL = 0; // DCAEVT1 źródło bezpośrednio bez filtracji EPwmxRegs->DCACTL.bit.EVT1FRCSYNCSEL = 1; // DCAEVT1 źródło jest asynchroniczne EPwmxRegs->TZCTL.bit.TZA = TZ_FORCE_LO; // wyjście EPWMxA ma być zero jak jest aktywny TZ EPwmxRegs->TZCTL.bit.TZB = TZ_FORCE_LO; // wyjście EPWMxB ma być zero jak jest aktywny TZ EPwmxRegs->TZFRC.bit.OST = 1; // na starcie wymuszamy OST jako softwarowe wyłączenie PWMów EPwmxRegs->TZSEL.bit.DCAEVT1 = 1; // DCAEVT1 jako one-shot-trip EPwmxRegs->TZDCSEL.bit.DCAEVT1 = 2; // DCAEVT1 generujemy, gdy DCAH = 1; DCAL = X // *** Konfiguracja trybu High Resolution EPwmxRegs->HRCNFG.bit.EDGMODE = HR_BEP; // MEP kontroluje obydwa zbocza sygnału EPwmxRegs->HRCNFG.bit.CTLMODE = HR_CMP; // MEP kontrolowany jest przez wypełnienie EPwmxRegs->HRCNFG.bit.HRLOAD = 0; // nowe wartości CMPAHR ładowane są gdy TBCTR == 0x0000 EPwmxRegs->HRCNFG.bit.SELOUTB = 0; // negacja wyjścia B przez moduł HRPWM wyłączona EPwmxRegs->HRCNFG.bit.AUTOCONV = 1; // automatyczne skalowanie HRMSTEP EPwmxRegs->HRCNFG.bit.SWAPAB = 0; // wyjścia A i B nie są zamienione EPwmxRegs->HRCNFG.bit.EDGMODEB = HR_DISABLE; // MEP wyłączony na CMPB EPwmxRegs->HRPCTL.bit.TBPHSHRLOADE = 1; // aktywowanie synchronizacji liczników up/down z sygnałem HR EPwmxRegs->HRPCTL.bit.HRPE = 0; // deaktywowanie HRPWM (jakiś problem w procku??) EDIS; } //╔════════════════════════════════════════════════════════════════════════════════════════════╗ //║ PUBLICZNE FUNKCJE I PROCEDURY ║ //╚════════════════════════════════════════════════════════════════════════════════════════════╝ void SetupIGBTModule() { /*** Konfigurujemy synchronizację PWMów ***/ SyncSocRegs.SYNCSELECT.bit.EPWM4SYNCIN = 0; // Synchronizujemy z EPWM1SYNCOUT SyncSocRegs.SYNCSELECT.bit.EPWM7SYNCIN = 0; // Synchronizujemy z EPWM1SYNCOUT SyncSocRegs.SYNCSOCLOCK.bit.SYNCSELECT = 1; // Blokujemy rejestr SYNCSELECT // Moduł ePWM generuje sygnały tranzystorów wyjściowych (po prawej stronie aktualny stan na PCB ze względu na błąd w ścieżkach): // GPWM14 = ePWM2A = U:UDC0 = !GPWM12 | GPWM14 = ePWM2A = U:UDC0 = !GPWM12 // GPWM12 = ePWM2B = U:UDC- | GPWM13 = ePWM2B = U:UDC0 = !GPWM11 // GPWM22 = ePWM3A = V:UDC- | GPWM22 // GPWM24 = ePWM3B = V:UDC0 = !GPWM22 | GPWM24 // GPWM32 = ePWM4A = W:UDC- | GPWM32 // GPWM34 = ePWM4B = W:UDC0 = !GPWM32 | GPWM34 // GPWM13 = ePWM6A = U:UDC0 = !GPWM11 | GPWM12 = ePWM6A = U:UDC- // GPWM11 = ePWM6B = U:UDC+ | GPWM11 = ePWM6B = U:UDC+ // GPWM21 = ePWM7A = V:UDC+ | GPWM21 // GPWM23 = ePWM7B = V:UDC0 = !GPWM21 | GPWM23 // GPWM31 = ePWM8A = W:UDC+ | GPWM31 // GPWM33 = ePWM8B = W:UDC0 = !GPWM31 | GPWM33 InitializeEPwmxRegs(&EPwm2Regs); InitializeEPwmxRegs(&EPwm3Regs); InitializeEPwmxRegs(&EPwm4Regs); InitializeEPwmxRegs(&EPwm6Regs); InitializeEPwmxRegs(&EPwm7Regs); InitializeEPwmxRegs(&EPwm8Regs); /*** ustawienia PIE dla TripZone ***/ PieCtrlRegs.PIEIFR2.bit.INTx2 = 0; // zerowanie ewentualnie oznaczonego przerwania INT2.2 PieCtrlRegs.PIEIER2.bit.INTx2 = 1; // aktywowanie przerwania INT2.2 = EPWM2_TZ IER |= M_INT2; // aktywacja grupy INT2.x }
Also time diagram of PWM setup (blue lines are: lowest is EPwm1, very light two big triangles are EPwmSET, one big triangle is EPwmSET after inversion only for easy use):
Screens from analyzer:
1. HRPE is OFF. On I11.03.1 you see pulse - this pulse is wrtie new CMPA value and after two CONV U pulses CMPA value is restored back by program (PWM1 and PWM2 data). So on this - one pulse shot test is valid.
2. HRPE is ON - there is only change. You see that update of CMPA value is not on CC_CTR_PRD but on CC_CTR_ZERO and eventually I have not one pulse but two with half of duty - so this is terrible for me.
Hi,
yes already I found same solution - when HRPWM is enabled you don't have ability to control when to load values from shadow registers, because controlling of this takes HRCNFG.HRLOAD bits and this bist must be configured same as EDGMODE - and only with this configuration HRPWM works correctly. This is little confusing and description of HRPWM in datasheet isn;t clear about some nuances.
Also second nuance that I found not related to HRPWM - when trip zone set outputs to low, action qualifier output pin state isn't changed. So for example - when we have output set to HI, TZ sets output to LO and we clear TZ - output sets immediate to HI. Afcourse you can set what to do with outputs if TZ occurs in AQ module, but this nuance isn't clear elaborated in datasheet.
I suggest to add this three small tips (HRLOAD control overtake; EDGMODE must be same as HRLOAD; TZ dont change AQ output) in descriptions of ePWM and HRPWM.