你好!
我在使用280049输出PWM的时候,发现当控制PWM为0输出的时候,PWM的输出会有间歇性的脉冲出现。查找程序一直找到不问题,也没有一个思路,想请教一下这是什么问题?
有关PWM的控制程序如下:
void initEPWM1() {//// Set_up TBCLK//EPWM_setTimeBasePeriod(EPWM1_BASE, EPWM1_TIMER_TBPRD);EPWM_setPhaseShift(EPWM1_BASE, 0U);EPWM_setTimeBaseCounter(EPWM1_BASE, 0U);// Set up counter modeEPWM_setTimeBaseCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_UP_DOWN);EPWM_disablePhaseShiftLoad(EPWM1_BASE);//// Set ePWM clock pre-scaler//EPWM_setClockPrescaler(EPWM1_BASE,EPWM_CLOCK_DIVIDER_4,EPWM_HSCLOCK_DIVIDER_4);//// Set up shadowing//EPWM_setCounterCompareShadowLoadMode(EPWM1_BASE,EPWM_COUNTER_COMPARE_A,EPWM_COMP_LOAD_ON_CNTR_ZERO);EPWM_setCounterCompareShadowLoadMode(EPWM1_BASE,EPWM_COUNTER_COMPARE_B,EPWM_COMP_LOAD_ON_CNTR_ZERO);//// Set-up compare//EPWM_setCounterCompareValue(EPWM1_BASE,EPWM_COUNTER_COMPARE_A,EPWM1_MIN_CMPA);EPWM_setCounterCompareValue(EPWM1_BASE,EPWM_COUNTER_COMPARE_B,EPWM1_MIN_CMPB);//// Set actions//EPWM_setActionQualifierAction(EPWM1_BASE,EPWM_AQ_OUTPUT_A,EPWM_AQ_OUTPUT_HIGH,EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);EPWM_setActionQualifierAction(EPWM1_BASE,EPWM_AQ_OUTPUT_A,EPWM_AQ_OUTPUT_LOW,EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);EPWM_setActionQualifierAction(EPWM1_BASE,EPWM_AQ_OUTPUT_B,EPWM_AQ_OUTPUT_HIGH,EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB);EPWM_setActionQualifierAction(EPWM1_BASE,EPWM_AQ_OUTPUT_B,EPWM_AQ_OUTPUT_LOW,EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPB); } void pump_ctrl(uint16_t pump, uint16_t freq, float32_t ratio) {EPWM_SignalParams *signalParams;uint32_t base;float32_t tbClkInHz = 0.0F;uint16_t tbPrdVal = 0U, cmpAVal = 0U, cmpBVal = 0U;switch (pump){case 0:base = EPWM1_BASE;signalParams = &pwmSignal1;signalParams->dutyValA = ratio;if(ratio != 0.0)neg_pump1_status = 1;elseneg_pump1_status = 0;break;case 1:base = EPWM1_BASE;signalParams = &pwmSignal1;signalParams->dutyValB = ratio;if(ratio != 0.0)neg_pump2_status = 1;elseneg_pump2_status = 0;break;case 2:base = EPWM2_BASE;signalParams = &pwmSignal2;signalParams->dutyValA = ratio;if(ratio != 0.0)pos_pump_status = 1;elsepos_pump_status = 0;break;}signalParams->freqInHz = freq;//// Calculate TBCLK, TBPRD and CMPx values to be configured for// achieving desired signal//tbClkInHz = ((float32_t)signalParams->sysClkInHz /(1U << (uint16_t)signalParams->tbClkDiv));if(signalParams->tbCtrMode == EPWM_COUNTER_MODE_UP){tbPrdVal = (uint16_t)((tbClkInHz / signalParams->freqInHz) - 1.0f);cmpAVal = (uint16_t)((float32_t)signalParams->dutyValA *(tbPrdVal + 1U));cmpBVal = (uint16_t)((float32_t)signalParams->dutyValB *(tbPrdVal + 1U));}else if(signalParams->tbCtrMode == EPWM_COUNTER_MODE_DOWN){tbPrdVal = (uint16_t)((tbClkInHz / signalParams->freqInHz) - 1.0f);cmpAVal = (uint16_t)((tbPrdVal + 1U) -((float32_t)signalParams->dutyValA * (tbPrdVal + 1U)));cmpBVal = (uint16_t)((tbPrdVal + 1U) -((float32_t)signalParams->dutyValB * (tbPrdVal + 1U)));}else if((signalParams->tbCtrMode == EPWM_COUNTER_MODE_UP_DOWN)){tbPrdVal = (uint16_t)(tbClkInHz / (2.0f * signalParams->freqInHz));cmpBVal = (uint16_t)(((float32_t)tbPrdVal -((float32_t)(signalParams->dutyValB *tbPrdVal))) + 0.5f);cmpAVal = (uint16_t)(((float32_t)tbPrdVal -((float32_t)(signalParams->dutyValA *tbPrdVal))) + 0.5f);}//// Configure TBPRD value//EPWM_setTimeBasePeriod(base, tbPrdVal);//// Set Compare values//EPWM_setCounterCompareValue(base, EPWM_COUNTER_COMPARE_A,cmpAVal);EPWM_setCounterCompareValue(base, EPWM_COUNTER_COMPARE_B,cmpBVal); //++counterA; //if(counterA < epwm1Info.epwmMaxCompA) //{ //epwm1Info.epwmCompA = counterA; //} //else //{ //counterA = epwm1Info.epwmMinCompA; //} // //++counterB; //if(counterB < epwm1Info.epwmMaxCompB) //{ //epwm1Info.epwmCompB = counterB; //} //else //{ //counterB = epwm1Info.epwmMinCompB; //} //updataCompare(&epwm1Info); } void main() {//// Disable sync(Freeze clock to PWM as well)//SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);//// Initialize device clock and peripherals//Device_init();DINT;//// 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();//// Enable sync and clock to PWM//SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);//// Enable Global Interrupt (INTM) and realtime interrupt (DBGM)//EINT;// Disable pin locks and enable internal pullups.Device_initGPIO();// Set up GPIOssetupGPIO();//// Configuring ePWM module for desired frequency and duty//EPWM_configureSignal(EPWM1_BASE, &pwmSignal1);EPWM_configureSignal(EPWM2_BASE, &pwmSignal2);pump_ctrl(POS_PUMP, 0, 0); }
xiao kelvin:
对了,要再说一下,这个脉冲的特征跟我们CPUtimer1设置的定时时长有关系,定时器时长越长,脉冲的宽度越大。定时器的程序如下
void initTimerInterrupt(void) {// ISRs for each CPU Timer interrupt// Timer0 for led// Timer1 for PPG ADCInterrupt_register(INT_TIMER0, &cpuTimer0ISR);Interrupt_register(INT_TIMER1, &cpuTimer1ISR);// Initializes the cpu timersinitCPUTimers(); //SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TIMER0);// Configure CPU-Timer0 to interrupt every second: 1 second period(1 uSeconds)// Configure CPU-Timer1 to interrupt every msecondconfigCPUTimer(CPUTIMER0_BASE, DEVICE_SYSCLK_FREQ, 1000000);configCPUTimer(CPUTIMER1_BASE, DEVICE_SYSCLK_FREQ, 100);// To ensure precise timing, use write-only instruction to write to the// entire register, Therefore, if any of the configuration bits are changed// in configCPUTimer and initCPUTimers, the below settings must also be updated.CPUTimer_enableInterrupt(CPUTIMER0_BASE);CPUTimer_enableInterrupt(CPUTIMER1_BASE);// Enables CPU int1.// Enable TINT0 in the PIE: Group 1 interrupt 7Interrupt_enable(INT_TIMER0);Interrupt_enable(INT_TIMER1);//Starts CPU-Timer 0CPUTimer_startTimer(CPUTIMER0_BASE);CPUTimer_startTimer(CPUTIMER1_BASE);}// // initCPUTimers - This function initializes all three CPU timers // to a known state. // void initCPUTimers(void) {// Initialize timer period to maximumCPUTimer_setPeriod(CPUTIMER0_BASE, 0XFFFFFFFF);CPUTimer_setPeriod(CPUTIMER1_BASE, 0XFFFFFFFF);// Initialize pre-scale counter to divide by 1(SYSCLKOUT)CPUTimer_setPreScaler(CPUTIMER0_BASE, 0);CPUTimer_setPreScaler(CPUTIMER1_BASE, 0);// Make sure timer is stoppedCPUTimer_stopTimer(CPUTIMER0_BASE);CPUTimer_stopTimer(CPUTIMER1_BASE);// Reload all counter register with period valueCPUTimer_reloadTimerCounter(CPUTIMER0_BASE);CPUTimer_reloadTimerCounter(CPUTIMER1_BASE);// Reset interrupt countercpuTimer0IntCount = 0;cpuTimer1IntCount = 0;}// // configCPUTimer - This function initializes the selected timer to the // period specified by the "freq" and "period" parameters. The "freq" is // entered as Hz and the period in uSeconds. The timer is held in the stopped // state after configuration. // void configCPUTimer(uint32_t cpuTimer, float freq, float period) {uint32_t temp;// Initialize timer periodtemp = (uint32_t)(freq / 1000000 * period);CPUTimer_setPeriod(cpuTimer, temp);// Set pre-scale counter to divide by 1 (SYSCLKOUT)CPUTimer_setPreScaler(cpuTimer, 0);// Initializes timer control register. The timer is stopped, reloaded,// free run disabled, and interrupt enabled.// Additionally, the free and soft bits are setCPUTimer_stopTimer(cpuTimer);CPUTimer_reloadTimerCounter(cpuTimer);CPUTimer_setEmulationMode(cpuTimer, CPUTIMER_EMULATIONMODE_STOPAFTERNEXTDECREMENT);CPUTimer_enableInterrupt(cpuTimer);// Resets interrupt counters for the cpuTimerif(cpuTimer == CPUTIMER0_BASE){cpuTimer0IntCount = 0;}else if(cpuTimer == CPUTIMER1_BASE){cpuTimer1IntCount = 0;} } // // cpuTimer1ISR - Counter for CpuTimer1 // __interrupt void cpuTimer1ISR(void) {// Save IER register on stack //volatile uint16_t tempPIEIER = HWREGH(PIECTRL_BASE + PIE_O_IER1);// Set the global and group priority to allow CPU interrupts// with higher priority //IER |= M_INT2; //IER &= MINT2; //HWREGH(PIECTRL_BASE + PIE_O_IER1);// Enable InterruptsInterrupt_clearACKGroup(0xFFFFU); //__asm(" NOP"); //EINT;cpuTimer1IntCount++;// Insert ISR code hereif(IRLED_flip == 0){IRLED_flip = 1;if(init_count<5000)//按照1000us定时,2000次相当于4s长度的数据{++init_count;} ////使IRLED关闭 //SPI_transmit(mySPI0_BASE, 0X0000); //SPI_transmit(mySPI0_BASE, 0X3000);// 测试DAC输出与阀输出的关系DAC_VALVE_RELATIVE_TEST();}else{IRLED_flip = 0; ////使IRLED打开 //SPI_transmit(mySPI0_BASE, 0X0800); //SPI_transmit(mySPI0_BASE, 0X3800);}//ADC_flag = 1;// Disable interrupts and restore register saved; //DINT; //HWREGH(PIECTRL_BASE + PIE_O_IER1) = tempPIEIER;//// Add ISR to Trace //traceISR[traceISRIndex % TRACE_SIZE] = 0x00D0; //traceISRIndex++; }
,
Susan Yang:
我们会在确认后给您回复
,
xiao kelvin:
Susan,你好
不知道问题讨论有结果了吗?
祝好!
,
Susan Yang:
请问这个脉冲pulse是只有当 CMPA/CMPB=PRD时发生?
,
xiao kelvin:
应该不是,这个脉冲出现的时间点比较随机
,
Susan Yang:
在发送的代码中,您没有使用死区/ HRPWM或除CMPA / B之外可能修改PWM输出的其他任何方式。您编辑了TBPRD。那么您是什么时候调用pump_ctrl呢(除main函数之外)?
,
xiao kelvin:
我本来是在cputimer1的中断函数中调用的,pump_ctrl()在函数DAC_VALVE_RELATIVE_TEST()内,后来我为了测试,就把pump_ctrl()单独拎出来放在main里面,观察显现,同时把DAC_VALVE_RELATIVE_TEST()内的pump_ctrl()注释掉。目前就只有在main中有调用这个函数。
,
xiao kelvin:
我刚刚发现一个现象,我设置pump_ctrl(POS_PUMP, 0, 0),但是用示波器抓取波形,发现一直有一个50%占空比,频率1k的PWM输出,感觉像是没有配置上。
,
xiao kelvin:
susan,
我自己再研究一下,估计按照我现在提供的信息,你们看不出来什么,我再进一步研究一下,到时候再做进一步交流。我现在有点怀疑的是中断优先级的问题。
,
Susan Yang:
好的,谢谢理解。期待您的反馈