主题中讨论的其他器件:PMP23338、 PMP23069
工具与软件:
大家好、我一直在尝试使用数字 SDK 库中的库来实现单相 PLL、而我一直在努力使其工作。 我正在提供频率为60Hz 的(0至2V)正弦波信号。 我使用我的 ADC 引脚并在其上运行 PLL 算法来检测这一点。 出于某种原因、我需要将 AC_FREQ 加倍、以使其生成频率相似但未完全锁定的正弦波。 请查看我的代码和程序中的图像。 我正在使用 DAC 读取输出信号、这些信号是我通过 ADC 检测到的正弦波、我还显示了正弦波输出。
注意:我以30kHz 的频率触发 ePWM、这与我用于 PLL 的频率相同。 出于某种原因、当我显示正弦波时、它是同相的、但余弦波是90异相的。
请提供任何帮助以使其正常工作?


第一张图显示了 PLL 余弦(蓝色)和黄色(输入电压)。
第二张图显示了 PLL 正弦(蓝色)和黄色(输入电压)
#include "driverlib.h"
#include "device.h"
#include "board.h"
#include "c2000ware_libraries.h"
#include "spll_1ph_notch.h"
#include "spll_1ph_sogi.h"
#include "spll_1ph_sogi_fll.h"
#include "dlog_4ch.h"
#include <math.h>
#define AC_FREQ 120
//#define Grid_freq 60
#define ISR_FREQUENCY 30000 //min is 20kHz
#define DBUFF_SIZE 2
SPLL_1PH_SOGI spll1;
float32_t spll_sine;
float32_t spll_cosine;
float32_t spll_theta;
float32_t spll_fo;
float32_t dacVal;
float32_t dacValB;
uint16_t myADC0Results;
float32_t actualDCVoltage;
float32_t currentDCVoltage;
void initEPWM(void);
//
// Main
//
void main(void)
{
//
// Initialize device clock and peripherals
//
Device_init();
//
// Disable pin locks and enable internal pull-ups.
//
Device_initGPIO();
//
// Initialize PIE and clear PIE registers. Disables CPU interrupts.
//
Interrupt_initModule();
//
// Initialize the PIE vector table with pointers to the shell Interrupt
// Service Routines (ISR).
//
Interrupt_initVectorTable();
//
// PinMux and Peripheral Initialization
//
Board_init();
SPLL_1PH_SOGI_reset(&spll1);
SPLL_1PH_SOGI_config(&spll1, AC_FREQ, ISR_FREQUENCY, (float32_t)(222.2862), (float32_t)(-222.034));
initEPWM();
//
// C2000Ware Library initialization
//
C2000Ware_libraries_init();
//
// Enable Global Interrupt (INTM) and real time interrupt (DBGM)
//
EINT;
ERTM;
while(1)
{
EPWM_enableADCTrigger(EPWM1_BASE, EPWM_SOC_A);
EPWM_setTimeBaseCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_UP);
EPWM_disableADCTrigger(EPWM1_BASE, EPWM_SOC_A);
EPWM_setTimeBaseCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_STOP_FREEZE);
}
}
void initEPWM(void)
{
//
// Disable SOCA
//
EPWM_disableADCTrigger(EPWM1_BASE, EPWM_SOC_A);
//
// Configure the SOC to occur on the first up-count event
//
EPWM_setADCTriggerSource(EPWM1_BASE, EPWM_SOC_A, EPWM_SOC_TBCTR_U_CMPA);
EPWM_setADCTriggerEventPrescale(EPWM1_BASE, EPWM_SOC_A, 1);
//
// Set the compare A value to 1000 and the period to 1999
// Assuming ePWM clock is 100MHz, this would give 50kHz sampling
// 50MHz ePWM clock would give 25kHz sampling, etc.
// The sample rate can also be modulated by changing the ePWM period
// directly (ensure that the compare A value is less than the period).
//
EPWM_setCounterCompareValue(EPWM1_BASE, EPWM_COUNTER_COMPARE_A, 1000);
EPWM_setTimeBasePeriod(EPWM1_BASE, 1667);
//
// Set the local ePWM module clock divider to /1
//
EPWM_setClockPrescaler(EPWM1_BASE,
EPWM_CLOCK_DIVIDER_2,
EPWM_HSCLOCK_DIVIDER_1);
//
// Freeze the counter
//
EPWM_setTimeBaseCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_STOP_FREEZE);
}
__interrupt void adcB1ISR(void)
{
//
// Add the latest result to the buffer
myADC0Results = ADC_readResult(ADCBRESULT_BASE, ADC_SOC_NUMBER0) +
ADC_readResult(ADCBRESULT_BASE, ADC_SOC_NUMBER1) +
ADC_readResult(ADCBRESULT_BASE, ADC_SOC_NUMBER2) +
ADC_readResult(ADCBRESULT_BASE, ADC_SOC_NUMBER3) >> 2;
actualDCVoltage = (myADC0Results/4095.0)*3.3;
currentDCVoltage = (myADC0Results)/4095.0; //pucalc
SPLL_1PH_SOGI_run(&spll1, currentDCVoltage);
spll_sine=spll1.sine;
spll_cosine=spll1.cosine;
spll_theta=spll1.theta;
dacVal = myADC0Results;
DAC_setShadowValue(myDAC0_BASE, dacVal);
DEVICE_DELAY_US(2);
dacValB = ((spll_sine+1)/3.3)*4095;
DAC_setShadowValue(myDAC1_BASE, dacValB);
DEVICE_DELAY_US(2);
//
// Clear the interrupt flag
//
ADC_clearInterruptStatus(myADC0_BASE, ADC_INT_NUMBER1);
//
// Check if overflow has occurred
//
if(true == ADC_getInterruptOverflowStatus(myADC0_BASE, ADC_INT_NUMBER1))
{
ADC_clearInterruptOverflowStatus(myADC0_BASE, ADC_INT_NUMBER1);
ADC_clearInterruptStatus(myADC0_BASE, ADC_INT_NUMBER1);
}
//
// Acknowledge the interrupt
//
Interrupt_clearACKGroup(INT_myADC0_1_INTERRUPT_ACK_GROUP);
}