/******************************************************************************
* (c) Copyright 2011 Biricha Digital Power Limited
* DATEI : main.c
* AUTOR : Dr. A. Shirsavar / Dr. C. Hossack
* PROJEKT : Piccolo A DPCM
* Zielsystem : DSP C2802x
* ERSTELLUNGSDATUM : 24.11.2011
* COPYRIGHT : Copyright Biricha Digital Power Limited 2011
* Alle Rechte vorbehalten. Eine vollständige oder teilweise Vervielfältigung
* ist untersagt, sofern keine ausdrückliche schriftliche
* Genehmigung des Inhabers der Urheberrechte vorliegt.
* BESCHREIBUNG :
*
* In diesem Projekt wird die spitzenstromgeführte Regelung eines BDP-105-Abwärtswandler-Boards
* mit einem Mikrocontroller Piccolo A von Texas Instruments und
* controlSUITE-Dateien vorgeführt.
*
* Auf der MCU wird ein 2p2z-Controller (2 Pole, 2 Nullstellen) ausgeführt und es wird ein Anstiegsausgleich
* zur Beseitigung von subharmonischen Schwingungen realisiert. Der Komparator 2 der Piccolo-MCU wird zur Erkennung
* des Spitzenstrom-Sollwerts verwendet.
*
* WICHTIG:
* Strommesskontakt wird an A4 angeschlossen – nicht-invertierender Eingang von Komparator 2.
* Ausgangsspannungs-Messkontakt wird an B2 angeschlossen.
*
******************************************************************************/
/****************************** ABSCHNITT MIT #include-DIREKTIVEN *****************************/
typedef unsigned int Uint16;
typedef unsigned long Uint32;
#include "DSP2802x_Comp.h"
#include "DSP2802x_EPwm.h"
#include "DSP28x_Project.h"
#include "IQmathLib.h"
/**************************** ABSCHNITT MIT DEKLARATIONEN ***************************/
/* Einrichten der Koeffizienten für den 2p2z-Controller eines Abwärtswandlers
* mit einer Schaltfrequenz von 200 kHz und einer Durchtrittsfrequenz von 10 kHz
*/
#define period 300 /* 200 kHz, wenn PLL auf 0xC (60 MHz) gesetzt ist */
#define slopeval 8 /* Erforderlicher Anstiegsausgleich */
#define K (54.3563)
#define REF (_IQ15toF(2048))
#define MIN_DUTY 0
#define MAX_DUTY 65535
#define A1 +1.8069498069
#define A2 -0.8069498069
#define B0 +1.1409584360
#define B1 +0.0695049698
#define B2 -1.0714534663
// Define iq31 type
typedef long _iq31;
typedef union CNTRL_ARG CNTRL_ARG;
typedef struct CNTRL_2p2zData CNTRL_2p2zData;
// Access to int and IQ
union CNTRL_ARG
{
_iq15 m_IQ;
int m_Int;
};
// Controller
struct CNTRL_2p2zData
{
CNTRL_ARG Ref; /* +0 Dies ist ein Bereich von +1*/
CNTRL_ARG Fdbk; /* +2 Dies ist ein Bereich von +1*/
CNTRL_ARG Out; /* +4 Dies ist ein Bereich von +1*/
long temp; /* +6 */
_iq24 m_U1; /* +8 */
_iq24 m_U2; /* +10 */
_iq31 m_E0; /* +12 */
_iq31 m_E1; /* +14 */
_iq31 m_E2; /* +16 */
_iq26 m_B2; /* +18 */
_iq26 m_B1; /* +20 */
_iq26 m_B0; /* +22 */
_iq26 m_A2; /* +24 */
_iq26 m_A1; /* +26 */
_iq23 m_K; /* +28 */
_iq15 m_max; /* +30 */
_iq15 m_min; /* +32 */
};
/************************** ABSCHNITT NACH DEKLARATIONEN ************************/
interrupt void adc_isr(void);
/* Datenabgleich mit Speicher vor Instanziierung eines 2p2z-Controllers. */
#pragma DATA_ALIGN ( CNTRL_2p2z , 64 );
CNTRL_2p2zData CNTRL_2p2z;
CNTRL_2p2zData* CNTRL_ptr;
main()
{
/* DSP2803x_SysCtrl.c*/
InitSysCtrl();
/* DSP2802x_EPwm.c*/
InitEPwm1Gpio();
/* Deaktivieren von CPU-Interrupts*/
DINT;
/* DSP2802x_PieCtrl.c*/
InitPieCtrl();
/* Löschen aller CPU-Interrupt-Flags*/
IER = 0x0000;
IFR = 0x0000;
/* DSP2802x_PieVect.c*/
InitPieVectTable();
/* Interrupt neu zu ISR-Funktion zugewiesen*/
EALLOW;
PieVectTable.ADCINT1 = &adc_isr;
EDIS;
/* DSP2802x_InitPeripherals.c*/
InitAdc();
/* Aktivierung ADCINT1 in PIE*/
PieCtrlRegs.PIEIER1.bit.INTx1 = 1;/* Aktivierung INT 1.1 in PIE*/
IER |= M_INT1;/* Aktivierung CPU-Interrupt 1*/
EINT;/* Aktivierung globales Interrupt INTM*/
ERTM;/* Aktivierung globales Echtzeit-Interrupt DBGM*/
/* Konfigurieren des A/D-Wandlers*/
EALLOW;
AdcRegs.INTSEL1N2.bit.INT1E = 1;/* ADCINT1 aktiviert*/
AdcRegs.INTSEL1N2.bit.INT1CONT = 0;/* Deaktivierung kontinuierlicher Modus ADCINT1*/
AdcRegs.INTSEL1N2.bit.INT1SEL = 0;/* Einrichten von EOC0 zum Auslösen von ADCINT1*/
AdcRegs.ADCSOC0CTL.bit.CHSEL = 0xA;/* Setzen von SOC0-Kanalauswahl auf ADCINB2*/
AdcRegs.ADCSOC0CTL.bit.TRIGSEL = 6;/* Setzen von SOC0-Startauslöser auf EPWM1B, aufgrund des Umlaufs wandelt zuerst SOC0 und dann SOC1*/
AdcRegs.ADCSOC0CTL.bit.ACQPS = 6;/* Setzen von SOC0 Abtast-/Haltefenster auf 7 A/D-Wandler-Takte (6 ACQPS plus 1)*/
AdcRegs.ADCCTL1.bit.INTPULSEPOS = 0;/* Konfigurieren früher Interrupts*/
EDIS;
/* Geht davon aus, das ePWM1-Takt bereits in InitSysCtrl(); aktiviert ist*/
EPwm1Regs.ETSEL.bit.SOCBEN = 1;/* Aktivierung SOC an B-Gruppe*/
EPwm1Regs.ETSEL.bit.SOCBSEL = 6;/* Auswahl SOC aus CPMB bei Hochzählen*/
EPwm1Regs.ETPS.bit.SOCBPRD = 1;/* Generieren von Impuls bei 1. Ereignis*/
/* Setzen der Periodendauer / Last / Zählmodus*/
EPwm1Regs.TBPHS.half.TBPHS = 0;/* Setzen des Phasenregisters auf null*/
EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE;/* Phasenlast deaktiviert*/
EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;/* Taktrate auf SYSCLKOUT*/
EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV1;
EPwm1Regs.TBCTL.bit.PRDLD = TB_SHADOW;
EPwm1Regs.AQCTLA.bit.ZRO = AQ_SET;/* Setzen von PWM1A auf null*/
EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR;/* Löschen von PWM1A bei Übereinstimmung bei Hochzählen von A*/
EPwm1Regs.AQCTLB.bit.ZRO = AQ_SET;/* Setzen von PWM1B auf null*/
EPwm1Regs.AQCTLB.bit.CBU = AQ_CLEAR;/* Löschen von PWM1B bei Übereinstimmung bei Hochzählen von B*/
EPwm1Regs.CMPB = 180;/* Setzen des Vergleichswerts für B*/
EPwm1Regs.CMPA.half.CMPA = 250;/* Setzen des Vergleichswerts für A*/
EPwm1Regs.TBPRD = period;/* Setzen der Periodendauer für ePWM1*/
EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP;/* Hochzählen und starten*/
/* Konfigurieren des Auslösebereichs basierend auf Ausgang von Komparator 2 und Konfigurieren des Austastens*/
EALLOW;
EPwm1Regs.TZSEL.bit.DCAEVT2 = 1;/* Digitaler Compare, Ausgang A, zyklisch*/
EPwm1Regs.TZCTL.bit.TZA = TZ_FORCE_LO;/* EPWM1A wechselt zu Low-Pegel*/
EPwm1Regs.TZCTL.bit.TZB = TZ_NO_CHANGE;/* EPWM1B im Leerlauf*/
EPwm1Regs.TZDCSEL.bit.DCAEVT2 = TZ_DCAH_HI;/* DCAEVT2 = DCAH hoch (wird aktiviert, wenn Komparatorausgang High-Pegel annimmt)*/
EPwm1Regs.DCTRIPSEL.bit.DCAHCOMPSEL = DC_COMP2OUT;/* DCAH = Ausgang Komparator 2*/
EPwm1Regs.DCACTL.bit.EVT2SRCSEL = DC_EVT2;/* DCAEVT2 = DCAEVT2 (ungefiltert)*/
EPwm1Regs.DCACTL.bit.EVT2FRCSYNCSEL = DC_EVT_ASYNC;/* Verwendung asynchroner Pfad*/
EPwm1Regs.DCFCTL.bit.PULSESEL = 0;/* Timebase-Zähler gleich Periodendauer (TBCTR = TBPRD)*/
EPwm1Regs.DCFCTL.bit.BLANKINV = 0;/* Austastfenster invertiert*/
EPwm1Regs.DCFCTL.bit.BLANKE = 1;/* Aktivierung Austastfenster*/
EPwm1Regs.DCFCTL.bit.SRCSEL = 0;/* Quelle ist DCAEVT1-Signal*/
EDIS;
EPwm1Regs.DCFWINDOW = 0;/* Austastfenster = 0*/
EPwm1Regs.DCFOFFSET = 25;/* Austastfenster-Offset von 420 ns, dann Beginn Austastfenster*/
/*Konfigurieren von Komparator 2*/
EALLOW;
SysCtrlRegs.PCLKCR3.bit.COMP2ENCLK = 1;/* Aktivierung Komparatortakt*/
Comp2Regs.COMPCTL.bit.SYNCSEL = 0;/* Asynchroner Ausgang*/
Comp2Regs.COMPCTL.bit.QUALSEL = 0;/* Keine Qualifizierung*/
Comp2Regs.COMPCTL.bit.CMPINV = 0;/* Nicht-invertiert*/
Comp2Regs.COMPCTL.bit.COMPSOURCE = 0;/* Interne D/A-Wandler-Verbindung*/
Comp2Regs.COMPCTL.bit.COMPDACEN = 1;/* Aktivierung*/
EDIS;
/* Konfigurieren von D/A-Wandler und Anstiegsausgleich*/
Comp2Regs.DACVAL.all = 0;
EALLOW;
Comp2Regs.DACCTL.bit.FREE_SOFT = 0;/* Emulationsmodusverhalten, sofort stoppen*/
Comp2Regs.DACCTL.bit.DACSOURCE = 1;/* Aktivierung Anstieg*/
Comp2Regs.DACCTL.bit.RAMPSOURCE = 0;/* ePWM1 ist Synchronisierungsquelle*/
EDIS;
Comp2Regs.RAMPDECVAL_SHDW = slopeval;/* Setzen der Anstiegsverminderung*/
/* Konfigurieren von GPIO12-Pin zum Umschalten*/
EALLOW;
GpioCtrlRegs.GPAPUD.bit.GPIO0 = 1;/* Deaktivierung der Erhöhung an GPIO12*/
GpioCtrlRegs.GPAMUX1.bit.GPIO12 = 0;/* Konfigurieren von GPIO0 als GPIO*/
GpioCtrlRegs.GPADIR.bit.GPIO12 = 1;/* Konfigurieren als Ausgang*/
EDIS;
/* Initialisieren des Controllers*/
CNTRL_2p2z.Ref.m_IQ = _IQ15(REF);
CNTRL_2p2z.m_U1 = _IQ24(0.0);
CNTRL_2p2z.m_U2 = _IQ24(0.0);
CNTRL_2p2z.m_E1 = _IQ30(0.0);
CNTRL_2p2z.m_E2 = _IQ30(0.0);
CNTRL_2p2z.m_B2 = _IQ26(B2);
CNTRL_2p2z.m_B1 = _IQ26(B1);
CNTRL_2p2z.m_B0 = _IQ26(B0);
CNTRL_2p2z.m_A2 = _IQ26(A2);
CNTRL_2p2z.m_A1 = _IQ26(A1);
CNTRL_2p2z.m_K = _IQ24(K);
CNTRL_2p2z.m_max = _IQ15(MAX_DUTY);
CNTRL_2p2z.m_min = _IQ15(MIN_DUTY);
CNTRL_ptr = &CNTRL_2p2z;
while(1)
{
}
}
interrupt void adc_isr(void)
{
GpioDataRegs.GPADAT.bit.GPIO12 = 1;/* Setzen von GPIO12 (für Timing-Zwecke)*/
AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;/* Löschen der ADCINT1-Flag für nächsten SOC*/
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;/* Bestätigung Interrupt für PIE*/
/* Abrufen des Rückführwerts*/
CNTRL_2p2z.Fdbk.m_Int = AdcResult.ADCRESULT0;
/* Im Folgenden finden Sie eine integrierte Umwandlungsfunktion, mit der der
* 2p2z-Controller (2 Pole, 2 Nullstellen) ausgeführt wird. Sie wurde von Biricha fest programmiert,
* um den Controller in der kürzestmöglichen Zeit ausführen zu können.
*/
asm(""
"\t\n PUSH XAR7 "
"\t\n PUSH XT "
"\t\n PUSH ACC "
"\n\t.global _CNTRL_2p2z "
"\n_CNTRLstart: "
"\t\n MOVW DP, #_CNTRL_2p2z+0 "
"\t\n MOVL XAR7,#_CNTRL_2p2z+18 "
"\t\n SETC SXM,OVM"
"\t\n MOV ACC,@_CNTRL_2p2z+0 "
"\t\n SUB ACC,@_CNTRL_2p2z+2 "
"\t\n LSL ACC,#16 "
"\t\n ; Diff equation"
"\t\n MOVL @_CNTRL_2p2z+8+4,ACC "
"\t\n MOVL XT,@_CNTRL_2p2z+8+8 "
"\t\n QMPYL ACC,XT,*XAR7++ "
"\t\n MOVDL XT,@_CNTRL_2p2z+8+6 "
"\t\n QMPYL P,XT,*XAR7++ "
"\t\n ADDL ACC,P "
"\t\n MOVDL XT,@_CNTRL_2p2z+8+4 "
"\t\n QMPYL P,XT,*XAR7++ "
"\t\n ADDL ACC,P "
"\t\n SFR ACC,#1"
"\t\n MOVL @_CNTRL_2p2z+6,ACC "
"\t\n MOVL XT,@_CNTRL_2p2z+8+2 "
"\t\n QMPYL ACC,XT,*XAR7++ "
"\t\n MOVDL XT,@_CNTRL_2p2z+8+0 "
"\t\n QMPYL P,XT,*XAR7++ "
"\t\n "
"\t\n ADDL ACC,P "
"\t\n LSL ACC,#5 "
"\t\n ADDL ACC,ACC "
"\t\n ADDL ACC,@_CNTRL_2p2z+6 "
"\t\n MOVL @_CNTRL_2p2z+8+0,ACC "
"\t\n MOVL XT,ACC "
"\t\n QMPYL ACC,XT,*XAR7++ "
"\t\n MINL ACC,*XAR7++ "
"\t\n MAXL ACC,*XAR7++ "
"\t\n MOV @_CNTRL_2p2z+4, AL "
"\t\n POP ACC "
"\t\n POP XT "
"\t\n POP XAR7 ");
Comp2Regs.RAMPMAXREF_SHDW = CNTRL_2p2z.Out.m_Int;/* Setzen der Stromreferenz des D/A-Wandlers*/
GpioDataRegs.GPADAT.bit.GPIO12 = 0;/* Löschen von GPIO12 (für Timing-Zwecke)*/
return;
}