Teensy 3.2 output 16MHz clock?

Status
Not open for further replies.

neltnerb

Well-known member
What is the best method to get the Teensy 3.2 to produce a 16MHz clock output for another chip?

My guess is that PWM output at 50% dutycycle is the best way, but please let me know if there is a better solution.

Code:
pinMode(5, OUTPUT); // Configure pin 5 as output.
analogWriteFrequency(5, 16000000); // Set PWM frequency to 16M
analogWriteResolution(1); // Set PWM resolution to 1 bit
analogWrite(5,0); // On from start until counter reaches 0, then shuts off until counter reaches 1 and then loops back?

I think this might not quite be right, particularly the resolution and value I use analogWrite to set, but is this about what I need?

In this application I'm not using any other PWM pins, thankfully, though it would be nice to know if there's a way to generate a high frequency clock while still being able to use 16-bit PWM on other pins at lower PWM frequency.
 
The Teensy 3.2 has a bus clock of 48MHz when the CPU runs at 96MHz, and 36MHz when the CPU clock is 72MHz. Since all Timers work from the bus clock, you can’t get a 50/50 16MHz signal, because there is no even integer ratio between the bus clock and 16MHz. But why not simply build a separate 16MHz oscillator with one CMOS inverter, a resistor, 2 capacitors and a Xtal?
 
Thanks for the information!

Yes, building my own clock is my alternative, I just prefer to use fewer parts when I can and it's a compact board and I'm not doing much else with the Teensy here. Sounds like a freerunning oscillator is the best route!
 
Maybe you could get a copy of the 16 MHz crystal signal to come out a pin. I haven't personally done this, but my guess is you'd need 3 steps.

1: Set the ERCLKEN bit in OSC_CR. See page 528 in the MK20DX256 reference manual for details. Be careful not to disturb the other 7 bits in this register!

2: Configure SIM_SOPT2's CLKOUT field for OSCERCLK0. See page 241 for details. Be careful not to disturb the other 29 bits in this register!

3: Configure pin PTC3 (which is Arduino pin 9) for ALT5 mux setting, which is "CLKOUT". Details on page 209 (look for the PTC3 line in the huge table). Perhaps use CORE_PIN9_CONFIG = PORT_PCR_MUX(5); Or look up the register details in chapter 11.

Please let everyone know if this actually works? This is one of the more obscure little features in the chip....

If it does work, a resistor in series with the signal, located close to the Teensy pin 9 would be a good idea if you connect a wire longer than about an inch. Even with the resistor, this is a high speed signal with fast edges which can emit RF energy if your wiring acts like an antenna. Running a ground wire close to the signal wire is a good practice.
 
Thanks Paul!

My read of page 528 is that ERCLKEN is telling it to expect an external clock rather than an oscillator (function described on page 526). But the table 5-1 on page 158 does say that if ERCLKEN is cleared it's disabled, so... yeah, I'll probably have to wait until I get my oscilliscope set back up for me to give it a try. But I will see how it goes and let everyone know!

For this particular board, I have an external chip (http://www.ti.com/product/TPS92661-Q1) which requires a clock to control it's internal counter which is also used to set the UART transmission rate. I have to admit surprise that they used an asynchronous protocol for this, but I want the counter running as fast as I can manage and 16MHz is the upper limit it allows. The TPS92661-Q1 has a mandatory prescaler on the timer of at least 2, so that gives me a 125ns minimum pulse length with a 16MHz clock and my circuit can actually switch current that fast, so I'd just like to get it as high as I can.

But this actually imposes another constraint that Theremingenieur noted which is that I need to be able to configure the Teensy 3.2 UART to run at the same speed. As such I think I need to ensure that the clock to that chip is set at whatever the maximum UART frequency I can exactly select is which is less than 16MHz but otherwise as high as possible. This seems likely to suffer from the limitations in the clock divider being an integer multiple of the bus frequency.

Is this right? What is the maximum frequency I can run the UART at and be confident that the clocking is quite close to the target frequency? It appears that this might be 4608000 based on https://www.pjrc.com/teensy/td_uart.html but is this the actual maximum possible? It seems like a funny value with a bus clock of 48MHz assuming a 2x divider from the system clock. Are there any issues with simply using Serial1.begin(12000000)?

In that situation, I would simply use a 12MHz clock for the UART and also use that to output a clock signal using PWM set at 50%.

If I did this, how should I best configure the PWM output? I know I can't have the resolution very high if I need high PWM frequencies. Would setting a resolution of 2 bits, and setting the OCR (or whatever they call it on ARM) to 2 get me where I want to be? I'm not sure on the exact specification for the OCR and TOP timing, but I think this gets a 1:1 ratio between on and off times?
 
What is the maximum frequency I can run the UART

On Serial1 & Serial2, the max baud rate is F_CPU / 16. Serial3 max is F_BUS / 16.

If I did this, how should I best configure the PWM output? I know I can't have the resolution very high if I need high PWM frequencies. Would setting a resolution of 2 bits, and setting the OCR (or whatever they call it on ARM) to 2 get me where I want to be? I'm not sure on the exact specification for the OCR and TOP timing, but I think this gets a 1:1 ratio between on and off times?

PWM speeds and resolutions are documented here:

https://www.pjrc.com/teensy/td_pulse.html

The basic formula is F_BUS / (2^n), where n is the number of bits.

The F_BUS speeds used can be found in kinetis.h.

https://github.com/PaulStoffregen/cores/blob/master/teensy3/kinetis.h#L765

F_BUS is always an integer division of F_CPU. Teensy 3.2 is rated for up to 50 MHz on F_BUS, and Teensy 3.5 & 3.6 are rated for up to 60 MHz. The smallest integer division of F_CPU that meets these limits is used.

Some people have reported success with substantial F_BUS overclocking. You can edit that file if you want to try faster-the-specified F_BUS speeds.
 
Thanks Paul!

If I understand what you're saying, I can set a UART clock of 6MHz since F_CPU is 96MHz (overclocked mode) and this is a precise upper limit with:

Serial1.begin(6000000);

And then I can set the PWM output to a precise frequency of 6MHz with:

analogWriteFrequency(12000000);
analogWriteResolution(2);
analogWrite(5, 2);

to get a 12MHz total PWM frequency and on for 0-1 and off for 2-3 to give an output synthesized clock of 6MHz on pin 5.

Should this work as is, or do I need to mess with kinetis.h?
 
Yes, but is that really correct?

I looked quickly at the TPS92661-Q1 datasheet. On page 20 is says:

Code:
[B]7.4.1.6 Receive (RX Pin)[/B]
The RX pin is the TPS92661 UART input. It should be connected to the UART Tx pin of the MCU, as well as the
other TPS92661 RX pins on the network. The [COLOR="#FF0000"]bit rate of data transmitted on this pin should be at CLOCK / 16[/COLOR],
and is fixed at that bit rate.

So if you're sending a 6 MHz clock, wouldn't you set the baud rate at 375000?
 
Thanks, great catch. You are absolutely correct.

In that case, can I use the PWM generator in 1-bit mode to generate a 12MHz clock:

analogWriteFrequency(24000000);
analogWriteResolution(1);
analogWrite(5, 1);

or will that confuse the chip?

Then I'll need a baud rate of 750kHz which is just a 128x divider of F_CPU so hopefully can be set exactly with:

Serial1.begin(750000);

Look good to you? I've never tried running a PWM generator in 1-bit mode, not sure if that confuses the system too much, but on for count 0 and off for count 1 seems like in principle it should work.
 
Status
Not open for further replies.
Back
Top