主题中讨论的其他器件: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); }