This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
这段例程没有看明白,还请大家来指点迷津啊:
不明白这段例程中的C28核时钟、定时器、CMPRA、TBPRD以及GPIO71之间错综复杂的关系;根据setup_m3核中的设置C28核工作在150MHz,我用示波器测出的GPIO71脚输出的波形周期即灯的闪烁周期为328ms,我想知道是如何计算出来的,劳烦各位给小弟指条路,谢谢啦!!!
//########################################################################### // FILE: epwm_real-time_interrupts_c28.c // TITLE: ePWM Real-Time Interrupt example // //! \addtogroup control_example_list //! <h1> EPWM Real-Time Interrupt (epwm_real-time_interrupts)</h1> //! //! This example configures the ePWM1 Timer and increments //! a counter each time an interrupt is taken. ePWM interrupt can //! be configured as time critical to demonstrate real-time mode //! functionality and real-time interrupt capability //! //! PC6_GPIO70(LED7) toggled in main loop //! PC7_GPIO71(LED6) toggled in ePWM1 Timer Interrupt //! //! FREE_SOFT bits and DBGIER.INT3 bit must be set to enable ePWM1 //! interrupt to be time critical and operational in real time mode //! after halt command. Writing a 2/3 to EPwm1Regs.TBCTL[FREE_SOFT] //! allows the TBCTR to keep counting while writing a 1 to DBGIER.INT3 //! causes the interrupt to run continuously even if the processor is halted. //! \note Silicon Real-time Mode needs to be enabled to make this work. //! //! For more information see the following video //! <a href="http://focus.ti.com/general/docs/video/Portal.tsp?lang=en&entryid=0_5wd526cd">Real-Time //! Interrupts</a> //! //! As supplied: //! //! ePWM1 is initialized //! ePWM1 is cleared at period match and set at Compare-A match //! Compare A match occurs at half period //! //! Free_Soft bits and DBGIER are initially cleared. Halt the processor at //! some point and enable these bits through the watch window to see how //! real-time interrupts work. The list of watch variables needed are //! listed below //! //! An interrupt is taken on a zero event for the ePWM1 timer //! //! \b Watch \b Variables \n //! - EPwm1TimerIntCount - Timer Interrupt Count //! - EPwm1Regs.TBCTL.bit.FREE_SOFT - Free run bit //! - EPwm1Regs.TBCTR - Time Base Counter //! - DBGIER.INT3 - Time Critical Interrupt 3 Enable bit // //########################################################################### // $TI Release: F28M35x Support Library v160 $ // $Release Date: Tue Nov 6 08:48:09 CST 2012 $ //########################################################################### #include "DSP28x_Project.h" // Device Headerfile and Examples Include File // Configure if ePWM timer interrupt is enabled at the PIE level: // 1 = enabled, 0 = disabled #define PWM1_INT_ENABLE 1 // Configure the period for the timer #define PWM1_TIMER_TBPRD 0x1FFF // Prototype statements for functions found within this file. interrupt void epwm1_timer_isr(void); void InitEPwmTimer(void); // Global variables used in this example Uint32 EPwm1TimerIntCount; //counts entries into PWM1 Interrupt Uint16 LEDcount; //creates delay for LED3 toggling void main(void) { int i; // Step 1. Initialize System Control: // Enable Peripheral Clocks // This example function is found in the F28M35x_SysCtrl.c file. InitSysCtrl(); // Step 2. Initalize GPIO: // This example function is found in the F28M35x_Gpio.c file and // illustrates how to set the GPIO to it's default state. // InitGpio(); // Skipped for this example - LEDs set up in main code EALLOW; // PC6_GPIO-70 - PIN FUNCTION = LED7 on controlCARD GpioG1CtrlRegs.GPCMUX1.bit.GPIO70 = 0; // 0=GPIO GpioG1CtrlRegs.GPCDIR.bit.GPIO70 = 1; // 1=OUTput, 0=INput GpioG1DataRegs.GPCCLEAR.bit.GPIO70 = 1; // uncomment if --> Set Low // initially // GpioG1DataRegs.GPCSET.bit.GPIO70 = 1; // uncomment if --> Set High // initially // PC7_GPIO-71 - PIN FUNCTION = LED6 on controlCARD GpioG1CtrlRegs.GPCMUX1.bit.GPIO71 = 0; // 0=GPIO GpioG1CtrlRegs.GPCDIR.bit.GPIO71 = 1; // 1=OUTput, 0=INput // GpioG1DataRegs.GPCCLEAR.bit.GPIO71 = 1; // uncomment if --> Set Low // initially GpioG1DataRegs.GPCSET.bit.GPIO71 = 1; // uncomment if --> Set High // initially EDIS; // Step 3. Clear all interrupts and initialize PIE vector table: // Disable CPU interrupts DINT; // Initialize the PIE control registers to their default state. // The default state is all PIE interrupts disabled and flags // are cleared. // This function is found in the F28M35x_PieCtrl.c file. InitPieCtrl(); // Disable CPU interrupts and clear all CPU interrupt flags: IER = 0x0000; IFR = 0x0000; // Initialize the PIE vector table with pointers to the shell Interrupt // Service Routines (ISR). // This will populate the entire table, even if the interrupt // is not used in this example. This is useful for debug purposes. // The shell ISR routines are found in F28M35x_DefaultIsr.c. // This function is found in F28M35x_PieVect.c. InitPieVectTable(); // Interrupt that is used in this example is re-mapped to // ISR function found within this file. EALLOW; // This is needed to write to EALLOW protected registers PieVectTable.EPWM1_INT = &epwm1_timer_isr; EDIS; // This is needed to disable write to EALLOW protected registers // Step 4. Initialize all the Device Peripherals: // This function is found in F28M35x_InitPeripherals.c // InitPeripherals(); // Not required for this example InitEPwmTimer(); // For this example, only initialize the ePWM Timer // Step 5. User specific code, enable interrupts: // Initalize counters: EPwm1TimerIntCount = 0; LEDcount=0; // Enable CPU INT3 which is connected to EPWM1-6 INT: IER |= M_INT3; // Enable EPWM INTn in the PIE: Group 3 interrupt 1-6 PieCtrlRegs.PIEIER3.bit.INTx1 = PWM1_INT_ENABLE; // Initially disable time-critical interrupts SetDBGIER(0x0000); //PIE groups time-critical designation // Enable global Interrupts and higher priority real-time debug events: EINT; // Enable Global interrupt INTM ERTM; // Enable Global realtime interrupt DBGM // Step 6. IDLE loop. Just sit and loop forever (optional): for(;;) { asm (" NOP"); for(i=1; i<=100; i++) { //toggle LED7 on the controlCARD if(GpioG1DataRegs.GPCDAT.bit.GPIO70 == 0) { GpioG1DataRegs.GPCSET.bit.GPIO70 = 1; }else{ GpioG1DataRegs.GPCCLEAR.bit.GPIO70 = 1; } } } } void InitEPwmTimer() { EALLOW; SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0; // Stop all the TB clocks EDIS; // Disable Sync EPwm1Regs.TBCTL.bit.SYNCOSEL = 11; // Pass through // Initally disable Free/Soft Bits EPwm1Regs.TBCTL.bit.FREE_SOFT = 0; EPwm1Regs.TBPRD = PWM1_TIMER_TBPRD; // Set up PWM1 Period EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Count up mode EPwm1Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO; // Select INT on Zero event EPwm1Regs.ETSEL.bit.INTEN = PWM1_INT_ENABLE; // Enable INT EPwm1Regs.ETPS.bit.INTPRD = ET_1ST; // Generate INT on 1st event EPwm1Regs.TBCTR = 0x0000; // Clear timer counter EPwm1Regs.CMPA.half.CMPA = PWM1_TIMER_TBPRD/2; //CompareA event at half of // period EPwm1Regs.AQCTLA.all = 0x0024; // Action-qualifiers, Set on // CMPA, Clear on PRD EALLOW; SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1; // Start all the timers synced EDIS; } // Interrupt routines uses in this example: interrupt void epwm1_timer_isr(void) { EPwm1TimerIntCount++; LEDcount++; // Clear INT flag for this timer EPwm1Regs.ETCLR.bit.INT = 1; if (LEDcount==1000) { //toggle LED6 on the controlCARD if(GpioG1DataRegs.GPCDAT.bit.GPIO71 == 0) { GpioG1DataRegs.GPCSET.bit.GPIO71 = 1; }else{ GpioG1DataRegs.GPCCLEAR.bit.GPIO71 = 1; } LEDcount=0; } // Acknowledge this interrupt to receive more interrupts from group 3 PieCtrlRegs.PIEACK.all = PIEACK_GROUP3; }
你看到的GPIO的翻转周期因该是
T=PWM1_TIMER_TBPRD×1000×2/150(us)
1000从 if (LEDcount==1000) 中来
乘2是因为翻转两次IO才是一个周期。
除150是假设系统时钟是150MHz。
谢谢您的答复,还想问一下就是interrupt void epwm1_timer_isr(void)中断程序是在什么时候发生中断,计数器是在达到比较寄存器的设定值时还是在达到周期寄存器的值时发生中断呢?另外计数器是每个时钟周期加1吗?再次感谢!