// Configure PWMs to create Start of Conversion (SOC) pulses for the ADC //---------------------------------------- EPwm1Regs.ETSEL.bit.SOCASEL = ET_CTRU_CMPB; // PWM1 SOCA on CMPB event EPwm2Regs.ETSEL.bit.SOCASEL = ET_CTRU_CMPA; // PWM2 SOCA on CMPA event
EPwm1Regs.ETSEL.bit.SOCAEN = 1; // Enable PWM1 SOCA EPwm2Regs.ETSEL.bit.SOCAEN = 1; // Enable PWM2 SOCA EPwm1Regs.ETPS.bit.SOCAPRD = ET_1ST; // Trigger on every event EPwm2Regs.ETPS.bit.SOCAPRD = ET_1ST; // Trigger on every event
#endif // (INCR_BUILD == 1) EALLOW; Comp1Regs.COMPCTL.bit.SYNCSEL = 0; // asynchronous Comp1Regs.COMPCTL.bit.CMPINV = 1; // invert output Comp1Regs.COMPCTL.bit.COMPSOURCE = 0; // use internal DAC Comp1Regs.COMPCTL.bit.COMPDACEN = 1; // enable comparator Comp1Regs.DACVAL.bit.DACVAL = 764; //number is in Q5 (764=2.463V =>3A)
Comp2Regs.COMPCTL.bit.SYNCSEL = 0; // asynchronous Comp2Regs.COMPCTL.bit.CMPINV = 1; // invert output Comp2Regs.COMPCTL.bit.COMPSOURCE = 0; // use internal DAC Comp2Regs.COMPCTL.bit.COMPDACEN = 1; // enable comparator Comp2Regs.DACVAL.bit.DACVAL = 986; // number is in Q5 (986=3.18V =>48V)
EPwm1Regs.DCTRIPSEL.bit.DCAHCOMPSEL = DC_COMP1OUT; // DCAH = Comparator 1 output EPwm1Regs.DCTRIPSEL.bit.DCBHCOMPSEL = DC_COMP2OUT; // DCAL = TZ2 EPwm1Regs.TZDCSEL.bit.DCAEVT1 = TZ_DCAH_LOW; // DCAEVT1 = DCAH low(will become active as Comparator1 output goes low) EPwm1Regs.TZDCSEL.bit.DCBEVT1 = TZ_DCBH_LOW; // DCAEVT1 = DCAH low(will become active as Comparator2 output goes low) EPwm1Regs.DCACTL.bit.EVT1SRCSEL = DC_EVT1; // DCAEVT1 = DCAEVT1 (not filtered) EPwm1Regs.DCBCTL.bit.EVT1SRCSEL = DC_EVT1; // DCAEVT1 = DCAEVT1 (not filtered) EPwm1Regs.DCACTL.bit.EVT1FRCSYNCSEL = DC_EVT_ASYNC; // Take async path EPwm1Regs.DCBCTL.bit.EVT1FRCSYNCSEL = DC_EVT_ASYNC; // Take async path
EPwm1Regs.TZSEL.bit.DCAEVT1 = 1; EPwm1Regs.TZSEL.bit.DCBEVT1 = 1;
// What do we want the DCAEVT1 and DCBEVT1 events to do? - DCAEVTx events can force EPWMxA EPwm1Regs.TZCTL.bit.TZA = TZ_FORCE_LO; // EPWM1A will go low EDIS;
//================================================================================= // INTERRUPT & ISR INITIALISATION (best to run this section after other initialisation) //================================================================================= EALLOW; PieVectTable.EPWM1_INT = &ISR_Run; // Map Interrupt EDIS; PieCtrlRegs.PIEIER3.bit.INTx1 = 1; // PIE level enable, Grp3 / Int1 EPwm1Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO; // INT on Zero event EPwm1Regs.ETSEL.bit.INTEN = 1; // Enable INT EPwm1Regs.ETPS.bit.INTPRD = ET_1ST; // Generate INT on every event
// Enable Peripheral, global Ints and higher priority real-time debug events: IER |= M_INT3; // Enable CPU INT3 connected to EPWM1-6 INTs: EINT; // Enable Global interrupt INTM ERTM; // Enable Global realtime interrupt DBGM
//================================================================================= // BACKGROUND (BG) LOOP //=================================================================================
//--------------------------------- FRAMEWORK ------------------------------------- for(;;) { // State machine entry & exit point //=========================================================== (*Alpha_State_Ptr)(); // jump to an Alpha state (A0,B0,...) //===========================================================
} } //END MAIN CODE
//================================================================================= // STATE-MACHINE SEQUENCING AND SYNCRONIZATION //=================================================================================
//--------------------------------- FRAMEWORK -------------------------------------
void A0(void) { // loop rate synchronizer for A-tasks if(CpuTimer0Regs.TCR.bit.TIF == 1) { CpuTimer0Regs.TCR.bit.TIF = 1; // clear flag //----------------------------------------------------------- (*A_Task_Ptr)(); // jump to an A Task (A1,A2,A3,...) //----------------------------------------------------------- VTimer0[0]++; // virtual timer 0, instance 0 (spare } Alpha_State_Ptr = &B0; // Comment out to allow only A tasks }
void B0(void) { // loop rate synchronizer for B-tasks if(CpuTimer1Regs.TCR.bit.TIF == 1) { CpuTimer1Regs.TCR.bit.TIF = 1; // clear flag //----------------------------------------------------------- (*B_Task_Ptr)(); // jump to a B Task (B1,B2,B3,...) //----------------------------------------------------------- VTimer1[0]++; // virtual timer 1, instance 0 (used to control SPI LEDs SerialCommsTimer++; // virtual timer 1, instance 1 (used by SciCommsGui.c) } Alpha_State_Ptr = &C0; }
void C0(void) { // loop rate synchronizer for C-tasks if(CpuTimer2Regs.TCR.bit.TIF == 1) { CpuTimer2Regs.TCR.bit.TIF = 1; // clear flag //----------------------------------------------------------- (*C_Task_Ptr)(); // jump to a C Task (C1,C2,C3,...) //----------------------------------------------------------- VTimer2[0]++; // virtual timer 2, instance 0 (spare) } Alpha_State_Ptr = &A0; // Back to State A0 }
//================================================================================= // A - TASKS //================================================================================= //-------------------------------------------------------- void A1(void) // Slewrates (soft-start) of references (Sepic & LED string current 1-4) //-------------------------------------------------------- // Task runs every 2ms (CpuTimer0 period [1ms] * 2 "A" tasks active) // Slows the changing of a controller's reference by SlewStep_Sepic or SlewStep_LED { // Dmax Clamping Coef2P2Z_Sepic[5] = DmaxSepic * 67108; Coef2P2Z_LED[5] = Dmax_LED * 67108;
//--------------------------------------------------------- SlewError = (VREFsepic_slewed - Vtrgt); if (SlewError > SlewStepSepic) VREFsepic_slewed = VREFsepic_slewed - SlewStepSepic; else if (SlewError < (-SlewStepSepic) ) VREFsepic_slewed = VREFsepic_slewed + SlewStepSepic; else VREFsepic_slewed = Vtrgt; //---------------------------------------------------------
//--------------------------------------------------------- SlewError = (IREF_LED[1] - Iset_LED[1]); if (SlewError > SlewStep_LED) IREF_LED[1] = IREF_LED[1] - SlewStep_LED; else if (SlewError < (-SlewStep_LED) ) IREF_LED[1] = IREF_LED[1] + SlewStep_LED; else IREF_LED[1] = Iset_LED[1]; //--------------------------------------------------------- SlewError = (IREF_LED[2] - Iset_LED[2]); if (SlewError > SlewStep_LED) IREF_LED[2] = IREF_LED[2] - SlewStep_LED; else if (SlewError < (-SlewStep_LED) ) IREF_LED[2] = IREF_LED[2] + SlewStep_LED; else IREF_LED[2] = Iset_LED[2]; //--------------------------------------------------------- SlewError = (IREF_LED[3] - Iset_LED[3]); if (SlewError > SlewStep_LED) IREF_LED[3] = IREF_LED[3] - SlewStep_LED; else if (SlewError < (-SlewStep_LED) ) IREF_LED[3] = IREF_LED[3] + SlewStep_LED; else IREF_LED[3] = Iset_LED[3]; //--------------------------------------------------------- SlewError = (IREF_LED[4] - Iset_LED[4]); if (SlewError > SlewStep_LED) IREF_LED[4] = IREF_LED[4] - SlewStep_LED; else if (SlewError < (-SlewStep_LED) ) IREF_LED[4] = IREF_LED[4] + SlewStep_LED; else IREF_LED[4] = Iset_LED[4]; //---------------------------------------------------------
//------------------- A_Task_Ptr = &A2; //------------------- }
//----------------------------------------------------------------- void A2(void) // Slewrates (soft-start) of references (LED string current 5-8); UART comms //----------------------------------------------------------------- // Task runs every 2ms (CpuTimer0 period [1ms] * 2 "A" tasks active) // Slows the changing of a controller's reference by SlewStep_LED // SerialHostComms is a function that provides communication with a GUI host if one is connected {
if(ClearFaultFlg == 1) { UOUTsepic = 0; VREFsepic_slewed = 0;
for (i=0; i<9; i++) { IREF_LED = 0; }
EALLOW; EPwm1Regs.TZCLR.bit.OST = 1; EPwm2Regs.TZCLR.bit.OST = 1; EPwm3Regs.TZCLR.bit.OST = 1; EPwm4Regs.TZCLR.bit.OST = 1; EPwm5Regs.TZCLR.bit.OST = 1; EPwm6Regs.TZCLR.bit.OST = 1; EDIS;
ClearFaultFlg = 0; }
//--------------------------------------------------------- SlewError = (IREF_LED[5] - Iset_LED[5]); if (SlewError > SlewStep_LED) IREF_LED[5] = IREF_LED[5] - SlewStep_LED; else if (SlewError < (-SlewStep_LED) ) IREF_LED[5] = IREF_LED[5] + SlewStep_LED; else IREF_LED[5] = Iset_LED[5]; //--------------------------------------------------------- SlewError = (IREF_LED[6] - Iset_LED[6]); if (SlewError > SlewStep_LED) IREF_LED[6] = IREF_LED[6] - SlewStep_LED; else if (SlewError < (-SlewStep_LED) ) IREF_LED[6] = IREF_LED[6] + SlewStep_LED; else IREF_LED[6] = Iset_LED[6]; //--------------------------------------------------------- SlewError = (IREF_LED[7] - Iset_LED[7]); if (SlewError > SlewStep_LED) IREF_LED[7] = IREF_LED[7] - SlewStep_LED; else if (SlewError < (-SlewStep_LED) ) IREF_LED[7] = IREF_LED[7] + SlewStep_LED; else IREF_LED[7] = Iset_LED[7]; //--------------------------------------------------------- SlewError = (IREF_LED[8] - Iset_LED[8]); if (SlewError > SlewStep_LED) IREF_LED[8] = IREF_LED[8] - SlewStep_LED; else if (SlewError < (-SlewStep_LED) ) IREF_LED[8] = IREF_LED[8] + SlewStep_LED; else IREF_LED[8] = Iset_LED[8]; //---------------------------------------------------------
SerialHostComms(); //found in SciCommsGui.c
//------------------- A_Task_Ptr = &A1; // To make task A3 active, change &A1 to &A3 //------------------- }
//----------------------------------------- void A3(void) // SPARE (not active) //----------------------------------------- {
//----------------- A_Task_Ptr = &A1; // To make task A4 active, change &A1 to &A4 //----------------- }
//================================================================================= // B - TASKS //=================================================================================
//----------------------------------- USER ---------------------------------------- //---------------------------------------------------- void B1(void) // SEPIC & Vin Dashboard measurements //---------------------------------------------------- // Task runs every 10ms (CpuTimer1 period [5ms] * 2 "B" tasks active) // ADC samples are averaged over "HistPtr" samples and then scaled to real-world units // see LedCalculations.xls for how scaling was derived. { // Measurement code expandable to multiple channels, defined by "NumChannels" // Voltage measurement calculated by: // Gui_Vin = VinAvg * K_Vin, where VinAvg = sum of 8 VinR samples // Gui_Vout = VoutAvg * K_Vout, where VoutAvg = sum of 8 VoutR samples // HistPtr++; if (HistPtr >= HistorySize) HistPtr = 0;
// BoxCar Averages - Input Raw samples into BoxCar arrays //----------------------------------------------------------------
VsepicH[HistPtr] = VsepicR; IsepicH[HistPtr] = IsepicR;
VinH[HistPtr] = VinR;
// Sepic Measurements //---------------------------------------------------------------- // view following variables in Watch Window as: // Gui_Vin = Q8 // Gui_Vsepic = Q9 // Gui_Isepic = Q?
temp_Scratch=0; for(i=0; i<8; i++) temp_Scratch = temp_Scratch + VsepicH; Gui_Vsepic = ( (long) temp_Scratch * (long) K_Vsepic ) >> 15;
temp_Scratch=0; for(i=0; i<8; i++) temp_Scratch = temp_Scratch + IsepicH; Gui_Isepic = ( (long) temp_Scratch * (long) K_Isepic ) >> 15;
temp_Scratch=0; for(i=0; i<8; i++) temp_Scratch = temp_Scratch + VinH; Gui_Vin = ( (long) temp_Scratch * (long) K_Vin ) >> 15;
Vtrgt = ( (long) Gui_VsetSepic * (long) iK_Vsepic ) >> 14;
//----------------- B_Task_Ptr = &B2; //----------------- }
//------------------------------------------------------------ void B2(void) // LED Dashboard measurements //------------------------------------------------------------ // Task runs every 10ms (CpuTimer1 period [5ms] * 2 "B" tasks active) // ADC samples are averaged over "HistPtr" samples and then scaled to real-world units // see LedCalculations.xls for how scaling was derived. {
// LED String Measurements //---------------------------------------------------------------- // view following variables in Watch Window as: // Gui_ILed[j] = Q15
ILedH[1][HistPtr] = ILed2aR; ILedH[2][HistPtr] = ILed2bR; ILedH[3][HistPtr] = ILed3aR; ILedH[4][HistPtr] = ILed3bR; ILedH[5][HistPtr] = ILed4aR; ILedH[6][HistPtr] = ILed4bR; ILedH[7][HistPtr] = ILed5aR; ILedH[8][HistPtr] = ILed5bR;
for(j = 0; j<9; j++) { temp_Scratch=0; for(i=0; i<HistorySize; i++) temp_Scratch = temp_Scratch + ILedH[j]; Gui_ILed[j] = ( (long) temp_Scratch * (long) K_ILed ) >> 15;
Iset_LED[j] = ( (long) Gui_IsetLed[j] * (long) iK_ILed ) >> 14; }
//----------------- B_Task_Ptr = &B1; //----------------- }
//------------------------------------------------------------ void B3(void) // SPARE (not active) //------------------------------------------------------------ {
//----------------- B_Task_Ptr = &B1; //----------------- }
//================================================================================= // C - TASKS //=================================================================================
//----------------------------- USER ----------------------------------------------
//-------------------------------------------------------------- void C1(void) // Coefficient update / control //-------------------------------------------------------------- // Task runs every 100ms (CpuTimer2 period [50ms] * 2 "C" tasks active) // Allows user to dynamically change P, I, and D gains while the system is running. { // Coefficient Update for 1st (Ch1) Loop Coef2P2Z_Sepic[0] = Dgain_Sepic * 67108; // B2 Coef2P2Z_Sepic[1] = (Igain_Sepic - Pgain_Sepic - Dgain_Sepic - Dgain_Sepic)*67108; // B1 Coef2P2Z_Sepic[2] = (Pgain_Sepic + Igain_Sepic + Dgain_Sepic)*67108; // B0
Coef2P2Z_LED[0] = Dgain_LED * 67108; // B2 Coef2P2Z_LED[1] = (Igain_LED - Pgain_LED - Dgain_LED - Dgain_LED)*67108; // B1 Coef2P2Z_LED[2] = (Pgain_LED + Igain_LED + Dgain_LED)*67108; // B0
if (HRmode ==1) EPwm1Regs.HRCNFG.bit.EDGMODE = HR_FEP; // Enable else EPwm1Regs.HRCNFG.bit.EDGMODE = HR_DISABLE; EDIS;
//----------------- C_Task_Ptr = &C2; //----------------- }
//---------------------------------------- void C2(void) // Merging of LED controls & LED "life"-pulse //---------------------------------------- // Task runs every 100ms (CpuTimer2 period [50ms] * 2 "C" tasks active) // Blinks an LED and allows all LED controls to be controlled individually or // as a group { // toggle an LED on the controlCARD GpioDataRegs.GPBTOGGLE.bit.GPIO34 = 1; // 1/(2*100ms) = 500Hz blink rate
if (LEDs_linked == 1) { for (i=1; i<9; i++) { Gui_IsetLed = Gui_IsetLed[1]; } }
if ( (*ePWM[1]).TZFLG.bit.OST == 1 ) { FaultFlg = 1; } else { FaultFlg = 0; }
//----------------- C_Task_Ptr = &C1; //----------------- }
//-------------------------------------- void C3(void) // SPARE (not active) //-------------------------------------- {
//----------------- C_Task_Ptr = &C1; //----------------- }
[/code]
这个是代码,排除硬件的问题。单独在28035上跑这个代码的时候,28035的ADC A2输出的电压是0.5V。很奇怪为什么不是oV?作为输入管脚。当这个管脚接到模拟量的时候,程序中FaultFlag=1;这时候PWM被强制输出低电平。就是我上面说的情况。但是不我不接这个管脚 确不会出现这样的情况。 |