// TI File $Revision: /main/10 $ // Checkin $Date: April 21, 2008 15:42:07 $ //########################################################################### // // FILE: Example_freqcal.c // // TITLE: Frequency measurement using EQEP peripheral // // DESCRIPTION: // // This file includes the EQEP initialization and frequency calcuation // functions called by Example_2833xEqep_freqcal.c. The frequency calculation // steps performed by FREQCAL_Calc()at SYSCLKOUT = 150 MHz and 100 MHz are // described below: // // For 150 MHz Operation: // ---------------------- // // 1. This program calculates: **freqhz_fr** // freqhz_fr or v = (x2-x1)/T - Equation 1 // // If max/base freq = 10kHz: 10kHz = (x2-x1)/(2/100Hz) - Equation 2 // max (x2-x1) = 200 counts = freqScaler_fr // Note: T = 2/100Hz. 2 is from (x2-x1)/2 - because QPOSCNT counts 2 edges per cycle // (rising and falling) // // If both sides of Equation 2 are divided by 10 kHz, then: // 1 = (x2-x1)/[10kHz*(2/100Hz)] where [10kHz* (2/100Hz)] = 200 // Because (x2-x1) must be <200 (max), // (x2-x1)/200 < 1 for all frequencies less than max // freq_fr = (x2-x1)/200 or (x2-x1)/[10kHz*(2/100Hz)] - Equation 3 // // To get back to original velocity equation, Equation 1, multiply Equation 3 by 10 kHz // freqhz_fr (or velocity) = 10kHz*(x2-x1)/[10kHz*(2/100Hz)] // = (x2-x1)/(2/100Hz) - Final equation // // 2. min freq = 1 count/(2/100Hz) = 50 Hz // // 3. **freqhz_pr** // freqhz_pr or v = X/(t2-t1) - Equation 4 // // If max/base freq = 10kHz: 10kHz = (4/2)/T = 4/2T // where 4 = QCAPCTL [UPPS] (Unit timeout - once every 4 edges) // 2 = divide by 2 because QPOSCNT counts 2 edges per cycle (rising and falling) // T = time in seconds // = t2-t1/(150MHz/128), t2-t1= # of QCAPCLK cycles, and // 1 QCAPCLK cycle = 1/(150MHz/128) // = QCPRDLAT // // So: 10 kHz = 4(150MHz/128)/2(t2-t1) // t2-t1 = 4(150MHz/128)/(10kHz*2) = (150MHz/128)/(2*10kHz/4) - Equation 5 // = 234 QCAPCLK cycles = maximum (t2-t1) = freqScaler_pr // // Divide both sides by (t2-t1), and: // 1 = 234/(t2-t1) = [150MHz/128)/(2*10kHz/4)]/(t2-t1) // Because (t2-t1) must be <234 (max). // 234/(t2-t1) < 1 for all frequencies less than max // freq_pr = 234/(t2-t1) or [150MHz/128)/(2*10kHz/4)]/(t2-t1) - Equation 6 // Now within velocity limits, to get back to original velocity equation, Equation 1, // multiply Equation 6 by 10 kHz: // freqhz_fr (or velocity) = 10kHz*[150MHz/128)/(2*10kHz/4)]/(t2-t1) // = (105MHz/128)*4/[2(t2-t1)] // or 4/[2*(t2-t1)(QCPRDLAT)] - Final Equation // // // For 100 MHz Operation: // ---------------------- // // The same calculations as above are performed, but with 100 MHz // instead of 150MHz when calculating freqhz_pr, and at UPPS of 8 instead of 4. // The value for freqScaler_pr becomes: (100MHz/128)/(2*10kHz/8) = 313 // More detailed calculation results can be found in the Example_freqcal.xls // spreadsheet included in the example folder. // // // This file contains source for the freq calculation module // //########################################################################### // Original Author: SD // // $TI Release: DSP2833x/DSP2823x Header Files V1.20 $ // $Release Date: August 1, 2008 $ //########################################################################### #include "DSP28x_Project.h" // Device Headerfile and Examples Include File #include "Example_freqcal.h" // Example specific include file void FREQCAL_Init(void) { #if (CPU_FRQ_150MHZ) EQep1Regs.QUPRD=1500000; // Unit Timer for 100Hz at 150MHz SYSCLKOUT #endif #if (CPU_FRQ_100MHZ) EQep1Regs.QUPRD=1000000; // Unit Timer for 100Hz at 100MHz SYSCLKOUT #endif EQep1Regs.QDECCTL.bit.QSRC=2; // Up count mode (freq. measurement) EQep1Regs.QDECCTL.bit.XCR=0; // 2x resolution (cnt falling and rising edges) EQep1Regs.QEPCTL.bit.FREE_SOFT=2; EQep1Regs.QEPCTL.bit.PCRM=00; // QPOSCNT reset on index evnt EQep1Regs.QEPCTL.bit.UTE=1; // Unit Timer Enable EQep1Regs.QEPCTL.bit.QCLM=1; // Latch on unit time out EQep1Regs.QPOSMAX=0xffffffff; EQep1Regs.QEPCTL.bit.QPEN=1; // QEP enable #if (CPU_FRQ_150MHZ) EQep1Regs.QCAPCTL.bit.UPPS=2; // 1/4 for unit position at 150MHz SYSCLKOUT #endif #if (CPU_FRQ_100MHZ) EQep1Regs.QCAPCTL.bit.UPPS=3; // 1/8 for unit position at 100MHz SYSCLKOUT #endif EQep1Regs.QCAPCTL.bit.CCPS=7; // 1/128 for CAP clock EQep1Regs.QCAPCTL.bit.CEN=1; // QEP Capture Enable } void FREQCAL_Calc(FREQCAL *p) { unsigned long tmp; _iq newp,oldp; //**** Freq Calcultation using QEP position counter ****// // Check unit Time out-event for speed calculation: // Unit Timer is configured for 100Hz in INIT function // For a more detailed explanation of the calculation, read // the description at the top of this file if(EQep1Regs.QFLG.bit.UTO==1) // Unit Timeout event { /** Differentiator **/ newp=EQep1Regs.QPOSLAT; // Latched POSCNT value oldp=p->oldpos; if (newp>oldp) tmp = newp - oldp; // x2-x1 in v=(x2-x1)/T equation else tmp = (0xFFFFFFFF-oldp)+newp; p->freq_fr = _IQdiv(tmp,p->freqScaler_fr); // p->freq_fr = (x2-x1)/(T*10KHz) tmp=p->freq_fr; if (tmp>=_IQ(1)) // is freq greater than max freq (10KHz for this example)? p->freq_fr = _IQ(1); else p->freq_fr = tmp; p->freqhz_fr = _IQmpy(p->BaseFreq,p->freq_fr); // Q0 = Q0*GLOBAL_Q => _IQXmpy(), X = GLOBAL_Q // p->freqhz_fr = (p->freq_fr)*10kHz = (x2-x1)/T // Update position counter p->oldpos = newp; //======================================= EQep1Regs.QCLR.bit.UTO=1; // Clear interrupt flag } //**** Freq Calcultation using QEP capture counter ****// if(EQep1Regs.QEPSTS.bit.UPEVNT==1) // Unit Position Event { if(EQep1Regs.QEPSTS.bit.COEF==0) // No Capture overflow tmp=(unsigned long)EQep1Regs.QCPRDLAT; else // Capture overflow, saturate the result tmp=0xFFFF; p->freq_pr = _IQdiv(p->freqScaler_pr,tmp); // p->freq_pr = X/[(t2-t1)*10KHz] tmp=p->freq_pr; if (tmp>_IQ(1)) p->freq_pr = _IQ(1); else p->freq_pr = tmp; p->freqhz_pr = _IQmpy(p->BaseFreq,p->freq_pr); // Q0 = Q0*GLOBAL_Q => _IQXmpy(), X = GLOBAL_Q // p->freqhz_pr =( p->freq_pr)*10kHz = X/(t2-t1) EQep1Regs.QEPSTS.all=0x88; // Clear Unit position event flag // Clear overflow error flag } }