I'm intending to use the output of the TMP2CH0, PTF2, as the sampling frequency for an external ADC. I would like to have really accurate control over the frequency going into the ADC. What I've noticed is that as I change the MOD value, the frequency of the Output Compare changes non-linearly. Here are the values I've tested in the TPM2MODH:L:
Value Output Frequency
0x0001 375 kHz
0x00F0 3.11 kHz
0x00FF 2.93 kHz
0x0FFF 183.101 Hz
0xFFFE 11.5 Hz
And here is the code that I used to generate it:
void initializeClock(void)
{
/* Set:
* BDIV to Divide by 1 (%00)
* RANGE to 1 because it is High Frequency (%1)
* HGO to 1 for high-gain operation (%1)
* EREFS to 1 to use crystal (%1)
* ERKCLKEN to 1 to ensure the external reference clock is active(%1)
*
* 0b00110110 */
MCGC2 = 0x36;
// Wait for OSCINIT to be set;
while((MCGSC & 0x02) == 0x00);
DisableInterrupts;
/* Set:
* CLKS to select external reference clock (%10);
* RDIV to divide-by-128 (%111)
* IREFS to select external reference clock (%0);
*
* 0b10111000 */
MCGC1 = 0xB8;
// Loop until IREFST is cleared and CLKST indicates external clk src slected;
while(MCGSC_IREFST == 1);
while(MCGSC_CLKST != 2);
// Set LP bit to enter BLPE mode. This is essential when oscillator > 5 MHz;
MCGC2 = 0x3E;
// Set RDIV to divide by 8 to get 1.5 MHz reference;
MCGC1 = 0x98;
/* Set:
* PLLS to select the PLLS (%1)
* VDIV to multiply by 32 (%1000)
*
* 0b01001000 */
MCGC3 = 0x48; //Set to Multiply 1.5 reference by 32 for 48 MHz;
while(MCGSC_PLLST == 0);
MCGC2_LP = 0;
while(MCGSC_LOCK == 0);
MCGC1 = 0x18; // Set MCGC1 CLKS bits to select the output of the PLL;
while(MCGSC_CLKST != 3);
}
void initializeTPM2(void)
{
TPM2SC_TOIE = 1; // Enable the interrupt;
TPM2SC_CPWMS = 0; // Allow it to operate in output compare;
TPM2SC_CLKSB = 0; // Select Bus Rate Clock for source;
TPM2SC_CLKSA = 1;
TPM2SC_PS = 0x4; // Select divide-by-4 to give us a 12 MHz output;
TPM2C0SC_CH0IE = 1; // Enable interrupts from this channel;
TPM2C0SC_MS0B = 0; // Set the channel mode to output compare;
TPM2C0SC_MS0A = 1;
TPM2C0SC_ELS0B = 0; // Set to toggle output on compare;
TPM2C0SC_ELS0A = 1;
TPM2MODH = 0x01; // This value gets me to to my target of 2 kHz;
TPM2MODL = 0x75;
}
Quite frankly this is my first time using the 8-bit Freescale/NXP uC's so I'm not even particularly sure that my clock is running at the intended speed of 48 MHz. Is this normal operation for the Output Compare module?
If the Timer is essentially free-running, when/how do you change the mod values? Depending on the current value of the timer count register(s), changing the modulo value without taking into account the present count reg values will cause an initial problem with the period unless you either stop timer/reset the count value or add the modulo value to the count register right after it has rolls over (by checking the OF flag or through interrupt). Is this a transitional problem when changing values, or steady-state/continuous problem?
Michael Fugere wrote:
If the Timer is essentially free-running, when/how do you change the mod values?
The values which I entered for TPM2MODH:L were hard-coded when I had taken the aforementioned output values of:
Value Output Frequency
0x0001 375 kHz
0x00F0 3.11 kHz
0x00FF 2.93 kHz
0x0FFF 183.101 Hz
0xFFFE 11.5 Hz
For those respective registers. If the timer is free-running, is there a need to clear the TOF bit?
Michael Fugere wrote:
Is this a transitional problem when changing values, or steady-state/continuous problem?
As the values were hard-coded, I would call this a steady state value. I ran the program separately each time I changed the TPM2MOD values.
Is my initial bus clock configured incorrectly? I'm expecting a 48 MHz clock and, without something that I can scale properly as an output, I'm not sure how to detect that the clock is running at the appropriate frequency.
>For those respective registers. If the timer is free-running, is there a need to clear the TOF bit?
You don't have to clear it, but it provides a means to cleanly change the timer values right after the rollover point if that is important to your application.
I have mostly been using the MC9S08AC60 processors - unfortunately their clock generator module is a little bit different than in the JM for some reason, so things aren't exactly 1:1 comparable. What are you using for an external clock source? Is it a crystal or an oscillator? Are there adequate loading capacitors on the crystal (I am assuming it is a crystal with your gain setting bit above, but you don't say anything about its frequency, etc). If you are running off the internal chip oscillator and need really precise timing, you may have to do your own clock trimming (a production nusiance of significance, IMO).
I glanced through the JM60 datasheet and didn't notice that it had the same limitation or clock structure that the AC60 has - but the AC60 has a maximum busclock frequency (which is the clock that feeds its TPM timers) of 20 MHz. The AC60 CPU runs at a 2X busclk frequency, which one sets with the ICG Module, but that frequency is cut in half for running all the peripherals on the bus (IIC, SPI, TPM3, SCI, etc.) The datasheet for the JM seems like it might imply a similar functionality/requirement, but I didn't see it explicitly stated - it shows a max bus frequency of 24MHz and max CPU of 48MHz... (on the AC60 these are 20 and 40MHz). The clock module on the JM isn't quite the same, and its block diagram isn't as clear.
hopefully an NXP person can chime in to help,
Mike