以下是程序,程序运行后,发现GPIO32口,每1us翻转一次,翻转40次,然后10us执行update_compare程序。
程序目的,每50us改变一次PWM输出(全桥逆变移相控制100kHZ)。
疑惑的是:1,为什么每1us翻转,这相当于2个周期采样一次吧?哪里设置了?从ADCSOC.c 改官方程序修改。
2,全桥逆变后面接的是RLC串联电路,谐振运行,R上得到最大电压。通过移相PWM调整电流恒定。但示波器检测出来的R上的电压波形来计算电流值,会发现明明想要比较的是电流有效值,但是出来的是幅值和设定值一样。
#include "DSP28x_Project.h" // Device Headerfile and Examples Include File
#include "math.h"
typedef struct
{
volatile struct EPWM_REGS *EPwmRegHandle;
}EPWM_INFO;
#define ADC_usDELAY 5000L
// Prototype statements for functions found within this file.
void InitEPwm1Example(void);
void Gpio_select(void);
void update_compare(EPWM_INFO*);
void InitEPwm1Gpio(void);
interrupt void adc_isr(void);
// General System nets – Useful for debug
EPWM_INFO epwm1_info;
// Configure the period for each timer
#define EPWM1_TIMER_TBPRD 750 // Period register
#define EPWM1_CMPA 0
// To keep track of which way the compare value is moving
#define EPWM_CMP_UP 1
#define EPWM_CMP_DOWN 0
// ADC start parameters
#define CPU_FRQ_150MHZ 1
// #define ADC_MODCLK 0x3 // HSPCLK = SYSCLKOUT/2*ADC_MODCLK2 = 150/(2*3) = 25.0 MHz
// #define ADC_CKPS 0x0 // ADC module clock = HSPCLK/1 = 25.5MHz/(1) = 25.0 MHz
// #define ADC_SHCLK 0x1 // S/H width in ADC module periods = 2 ADC cycle
float a=0;
float kp=30;
float kiT=25;
Uint16 EPwmMaxCMPA;
Uint16 LoopCount;
Uint16 ConversionCount;
float current0[10];
float current_math[10];
float max_current;
float u[2];
float e[2];
float u_change;
float N=10;
void main(void)
{
Uint16 i;
InitSysCtrl();
Gpio_select();
EALLOW;
// Default – 150 MHz SYSCLKOUT
#define ADC_MODCLK 0x3 // HSPCLK = SYSCLKOUT/2*ADC_MODCLK2 = 150/(2*3) = 25.0 MHz
EDIS;
EALLOW;
SysCtrlRegs.HISPCP.all = ADC_MODCLK;
EDIS;
InitEPwm1Gpio();
DINT;
InitPieCtrl();
// Disable CPU interrupts and clear all CPU interrupt flags:
IER = 0x0000;
IFR = 0x0000;
InitPieVectTable();
EALLOW; // This is needed to write to EALLOW protected register
PieVectTable.ADCINT = &adc_isr;
EDIS; // This is needed to disable write to EALLOW protected registers
InitAdc();
// Enable ADCINT in PIE
PieCtrlRegs.PIEIER1.bit.INTx6 = 1;
IER |= M_INT1; // Enable CPU Interrupt 1
EINT; // Enable Global interrupt INTM
ERTM; // Enable Global realtime interrupt DBGM
LoopCount = 0;
ConversionCount = 0;
e[0]=0;
e[1]=0;
u[0]=0;
u[1]=0;
max_current=0;
GpioDataRegs.GPBSET.all =0x00000000;
GpioDataRegs.GPBCLEAR.all =0x00000001;
// For this example, only initialize the ePWM
// Step 5. User specific code, enable interrupts:
for (i=0; i<N; i++)
{
current0[i] =0;
}
EALLOW;
SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0;
EDIS;
InitEPwm1Example();
EALLOW;
SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1;
EDIS;
// Configure ADC
AdcRegs.ADCMAXCONV.all = 0x0000; // Setup 2 conv's on SEQ1
AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x0; // Setup ADCINA0 as 1st SEQ1 conv.
AdcRegs.ADCTRL2.bit.EPWM_SOCA_SEQ1 = 1;// Enable SOCA from ePWM to start SEQ1
AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 1; // Enable SEQ1 interrupt (every EOS)
// Assumes ePWM2 clock is already enabled in InitSysCtrl();
EPwm2Regs.ETSEL.bit.SOCAEN = 1; // Enable SOC on A group
EPwm2Regs.ETSEL.bit.SOCASEL = 4; // Select SOC from from CPMA on upcount
EPwm2Regs.ETPS.bit.SOCAPRD = 3; // Generate pulse on 1st event
EPwm2Regs.CMPA.half.CMPA = 10; // Set compare A value
EPwm2Regs.TBPRD =25; // Set period for ePWM1
EPwm2Regs.TBCTL.bit.CTRMODE =0; // count up and start
// Step 6. IDLE loop. Just sit and loop forever (optional):
for(;;)
{
asm(" NOP");
}
}
interrupt void adc_isr(void)
{
current0[ConversionCount] = AdcRegs.ADCRESULT0 >>4;
GpioDataRegs.GPBTOGGLE.all =0x00000001;
// If 40 conversions have been logged, start over
if(ConversionCount ==N-1 )
{
ConversionCount = 0;
LoopCount++;
}
else ConversionCount++;
if (LoopCount==4)
{update_compare(&epwm1_info);}
// Reinitialize for next ADC sequence
AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1; // Reset SEQ1
AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1; // Clear INT SEQ1 bit
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // Acknowledge interrupt to PIE
// return;
}
void InitEPwm1Example()
{
// Setup TBCLK
EPwm1Regs.TBPRD =750;
//EPwm1Regs.TBPRD=EPWM1_TIMER_TBPRD; // Set timer period 801 TBCLKs
EPwm1Regs.TBPHS.half.TBPHS = 0x0000; // Phase is 0
EPwm1Regs.TBCTR = 0x0000; // Clear counter
// Set Compare values
EPwm1Regs.CMPA.half.CMPA =40;
// EPwm1Regs.CMPA.half.CMPA =EPWM1_CMPA; // Set compare A value
EPwm1Regs.CMPB =710;
//EPwm1Regs.CMPB =EPWM1_TIMER_TBPRD-EPWM1_CMPA; // Set Compare B value
EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Symmetric
EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE; // Phase loading disabled
EPwm1Regs.TBCTL.bit.PRDLD = TB_SHADOW;
EPwm1Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE;
EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1; // TBCLK = SYSCLKOUT
EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV1;
// Setup shadowing
EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
EPwm1Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // Load on Zero
EPwm1Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;
EPwm1Regs.AQCTLA.bit.CAU = AQ_SET;
EPwm1Regs.AQCTLA.bit.CBD = AQ_CLEAR;
EPwm1Regs.AQCTLB.bit.CBU = AQ_CLEAR;
EPwm1Regs.AQCTLB.bit.CAD = AQ_SET;
// Information this example uses to keep track
// of the direction the CMPA/CMPB values are
// moving, the min and max allowed values and
// a pointer to the correct ePWM registers
epwm1_info.EPwmRegHandle = &EPwm1Regs; // Set the pointer to the ePWM module
}
void update_compare(EPWM_INFO *epwm_info)
{
int i;
max_current=0;
for (i=0; i<N; i++)
{ current_math[i]= (current0[i]-2274)/4096*3/0.2;
// 用0.01欧姆采样电流,放大20倍,输出电压共模信号1.655V,调整后可得到检测的电流值
// 放大器400KHZ的时候会-3dB,但是信号不是100KHz,每周期采样10个么?没有影响啊。
max_current=max_current+fabs(current_math[i]); // 10个电流值的绝对值进行求和
}
max_current=1.1107*max_current/N; // 求平均,然后乘以一个系数,将其转化为有效值。大约为1.1107倍。
e[1]=1-max_current;
// 转化的有效值进行求差,后面的是增量式PI算法。 目的是得到有效值为1A的电流,但是检测出来的波形为1A幅值的电流。1.1107这个系
// 数算了很多遍,没错啊。正弦波的绝对值的平均值为幅值的0.6366倍,正弦波的有效值为0.7071倍幅值,那么有效值就是1.1107倍平均值啊。
u_change=kp*(e[1]-e[0])+kiT*e[1];
u[1]=u[0]+u_change/180*750;
if (u[1]>738) { u[1]=738;}
if (u[1]<12) { u[1]=12; }
EPwmMaxCMPA=u[1]/2;
epwm_info->EPwmRegHandle->CMPA.half.CMPA=EPwmMaxCMPA;
epwm_info->EPwmRegHandle->CMPB=750-EPwmMaxCMPA;
u[0]=u[1];
e[0]=e[1];
max_current=0;
LoopCount=0;
// return;
}
void Gpio_select(void)
{
EALLOW;
GpioCtrlRegs.GPBMUX1.all = 0x00000000; // All GPIO
GpioCtrlRegs.GPBMUX2.all = 0x00000000; // All GPIO
GpioCtrlRegs.GPBDIR.all = 0x0000000F; // All outputs
EDIS;
}
//===========================================================================
// No more.
//===========================================================================