TelephoneBill
Well-known member
I was delighted yesterday when I stumbled upon a new feature that you can implement with Teensy 3.6 (K66) that you could not easily do with Teensy 3.1 (K20). This is to use an External Clock Signal with any of the FTM timers.
For example, suppose you have a 10 MHz sq wave from another electronic module (OCXO or similar), and you want to divide that signal by an integer value such as 10,000 to produce a 1 KHz sq wave (or any other integer up to 65,536). Or maybe you wish to accurately count the number of pulses from an external source using one of the FTM timers. This is now very simple to achieve with the enhanced port/pins multiplexing features available within T3.6.
If you study the table in para 11.3.1 (page 184) of the K66 Reference Manual, you may note a number of entries for two signals named FTM_CLKIN0 and FTM_CLKIN1 (e.g. PTB16 and PTB17). These same signals were also present with the K20 Reference Manual but only at PTA18 and PTA19, and because these same chip signal pins were also used for the external 16 MHz clock module, then they were NOT available for the end user. The K66 chip with Teensy 3.6 still uses PTA18 and PTA19 for the 16 MHz clock module, but now the signals FTM_CLKIN0 and FTM_CLKIN1 are repeated elsewhere in the table, so that they are available.
The following code gives a working practical example of dividing 10 MHz by 10,000 to produce 1 KHz. It uses FTM1 and outputs on CH0. If you choose to use some other external clock frequency, the reference manual warns you to ensure that the frequency does not exceed one quarter of the "System Clock" by which is meant the Peripheral Bus Clock of 60 MHz.
Note that the choice of FTM_CLKIN0 or FTM_CLKIN1 is made within the SIM_SOPT4 register (para 13.2.5, page 241). My example uses FTM_CLKIN0. If you run this code, you will see the LED blink 4 times as the Setup routine is executed, then each pass of the Main Loop will simply blink the LED twice in quick succession. The FTM timers operate without any intervention from the Main Loop, once configured and enabled in the Setup code.
For example, suppose you have a 10 MHz sq wave from another electronic module (OCXO or similar), and you want to divide that signal by an integer value such as 10,000 to produce a 1 KHz sq wave (or any other integer up to 65,536). Or maybe you wish to accurately count the number of pulses from an external source using one of the FTM timers. This is now very simple to achieve with the enhanced port/pins multiplexing features available within T3.6.
If you study the table in para 11.3.1 (page 184) of the K66 Reference Manual, you may note a number of entries for two signals named FTM_CLKIN0 and FTM_CLKIN1 (e.g. PTB16 and PTB17). These same signals were also present with the K20 Reference Manual but only at PTA18 and PTA19, and because these same chip signal pins were also used for the external 16 MHz clock module, then they were NOT available for the end user. The K66 chip with Teensy 3.6 still uses PTA18 and PTA19 for the 16 MHz clock module, but now the signals FTM_CLKIN0 and FTM_CLKIN1 are repeated elsewhere in the table, so that they are available.
The following code gives a working practical example of dividing 10 MHz by 10,000 to produce 1 KHz. It uses FTM1 and outputs on CH0. If you choose to use some other external clock frequency, the reference manual warns you to ensure that the frequency does not exceed one quarter of the "System Clock" by which is meant the Peripheral Bus Clock of 60 MHz.
Note that the choice of FTM_CLKIN0 or FTM_CLKIN1 is made within the SIM_SOPT4 register (para 13.2.5, page 241). My example uses FTM_CLKIN0. If you run this code, you will see the LED blink 4 times as the Setup routine is executed, then each pass of the Main Loop will simply blink the LED twice in quick succession. The FTM timers operate without any intervention from the Main Loop, once configured and enabled in the Setup code.
Code:
//Teensy36 - Test Count of External Pulses
//========================================
// Author: TelephoneBill
// Date: 14 DEC 2016 - This T36 program counts 3 volt clock pulses from an external source (e.g. 10 MHz OCXO).
// Notes: The program uses the FTM_CLKIN0 signal input pin available on PTB16 (Teensy Pin 0) when configured for ALT4. This pin
// can accept external input pulses to be used by any of the FTM timers as a clock signal. FTM channels can then be used in the
// normal way to either measure a count value at a defined instant or to output a digital signal on attaining a count value. In
// this example, the 10 MHz input pulses are divided by a factor of 10,000 to give a 1 KHz square wave output on FTM1_CH0.
//
// Pins: Teensy Pin 0 (PTB16 ALT4) = FTM_CLKIN0 = 10 MHz from OCXO.
// Teensy Pin 16 (PTB0 ALT3) = FTM1_CH0 = 1 KHz sq wave output (toggled).
//
//declarations
#include <stdint.h>
#define LED_ON GPIOC_PSOR=(1<<5)
#define LED_OFF GPIOC_PCOR=(1<<5)
int FTM1MODCount, LoopCount;
void setup() {
// put your setup code here, to run once:
//initialise general hardware
PORTC_PCR5 = PORT_PCR_MUX(0x1); // LED PC5 pin 13, config GPIO ALT1
GPIOC_PDDR = (1<<5); // make this an output pin
LED_OFF; // start with LED off
//initialise variables
FTM1MODCount = 4999; //4999 modulus for each output half cycle (toggle)
//initialise FTM_CLKIN0 and Flextimer 1 CH0
FTM1_MODE = 0x05; //set write-protect disable (WPDIS) bit to modify other registers
//FAULTIE=0, FAULTM=00, CAPTEST=0, PWMSYNC=0, WPDIS=1, INIT=0, FTMEN=1(no restriction FTM)
FTM1_SC = 0x00; //set FTM1 Status/Control to zero = disabled (enabled later in setup)
FTM1_CNT = 0x0000; //reset count to zero
FTM1_MOD = FTM1MODCount;
FTM1_C0SC = 0x14; // CHF=0, CHIE=0 (disable interrupt, use software polling), MSB=0 MSA=1, ELSB=0 ELSA=1 (output compare - toggle), 0, DMA=0
//enable FTM1 interrupt within NVIC table
NVIC_ENABLE_IRQ(IRQ_FTM1);
//configure Teensy port pins
PORTB_PCR16 |= 0x400; //MUX = FTM_CLKIN0 ALT4 on Chip Pin 95 (FTM1_CH0) = Teensy Pin 0
PORTB_PCR0 |= 0x300; //MUX = FTM1_CH0 ALT3 on Chip Pin 81 (FTM1_CH0) = Teensy Pin 16
//initialise SIM_SOPT4
SIM_SOPT4 = 0x00000000; //uses FTM_CLKIN0 for external clock signals
//enable external clock (10 MHz), no prescale
FTM1_C0V = 0; //compare value = 0
FTM1_SC = 0x58; //(Note - FTM1_SC [TOF=0 TOIE=1 CPWMS=0 CLKS=11 (external clocks enabled) PS=000 [no prescale divide])
//blink 4 times
Blink();
delay(400);
Blink();
delay(400);
Blink();
delay(400);
Blink();
delay(400);
} //end of setup
// ISR routine for FlexTimer1 Module
extern "C" void ftm1_isr(void) {
if ((FTM1_SC & FTM_SC_TOF) != 0) { //read the timer overflow flag (TOF in FTM1_SC)
FTM1_SC &= ~FTM_SC_TOF; //if set, clear overflow flag
}
}
void loop() {
// put your main code here, to run repeatedly:
LoopCount++;
if (LoopCount == 1000000) {
LoopCount = 0;
Blink();
delay(200);
Blink();
}
}
//SUBROUTINES
//===========
//Blink Routine
void Blink() {
//blink the LED
LED_ON;
delay(10);
LED_OFF;
delay(10);
}