Stromversorgung

Implementierung eines digitalen Schaltreglers

22. Februar 2013, 13:51 Uhr | Von Dr. Ali Shirsavar
Diesen Artikel anhören

Fortsetzung des Artikels von Teil 3

Quellcode für ControlSuite von Texas Instruments

/******************************************************************************
* (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;
}

Anbieter zum Thema

zu Matchmaker+

  1. Implementierung eines digitalen Schaltreglers
  2. Verstärkungsfaktor bestimmen
  3. Literatur
  4. Quellcode für ControlSuite von Texas Instruments
  5. Quellcode für CSL von Biricha Digital Power

Lesen Sie mehr zum Thema


Das könnte Sie auch interessieren

Jetzt kostenfreie Newsletter bestellen!

Weitere Artikel zu DC/DC-Wandler