187 lines
6.9 KiB
C
187 lines
6.9 KiB
C
// 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
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|