Flex timer problem

Status
Not open for further replies.

grease_lighting

Well-known member
I'm planning on using the FTM as an event counter. Starting with this previous posting I've gotten some promising results. However I notice that I cannot change the count modulus with the FTM1_MOD command. It always seems to be stuck at 0x8FFF (36863 decimal). When I run the attached code it will function as expected, counting in increments of 1023, but when it gets to a count of 36828 it will roll over to a count of 987 which is probably what should happen. Is there a problem, or maybe I'm using the wrong code, in setting the count modulus to maximum 65535? or any value really? I get same results with another Teensy that I have.

If you try this remember to jumper pin 13 to pin 3.

Code:
//
//  Code for Teensy 3.x to read Flex Timer quadrature counters 
//
//  use flex timer on pins 3 & 4
//
//    reference
//    https://forum.pjrc.com/threads/30822-Teensy-3-1-and-Flextimer(s)-Counting-external-pulses-accurately
//    https://forum.pjrc.com/threads/26803-Hardware-Quadrature-Code-for-Teensy-3-x
//
//    code mostly from reference #1
//
//    Jumper LED_PIN (13) to pin 3 (clock)
//    Pin #4 controls count direction.  HIGH = up   LOW = down
//    
//


int p1;
int x;

#define LED_PIN 13

//(1) Setup statements
void setup() {
//  pinMode(3, INPUT_PULLUP);     //  signal to count       gets taken care of by PORT_PCA  statements
  pinMode(4, INPUT_PULLUP);     //  tied high to set count direction
  pinMode(16, OUTPUT);          //  some kind of pulse output -- for debug
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, LOW);
  

  Serial.begin(0); 
  while (!Serial);
                                  //configure Flextimer 1
  FTM1_MODE = FTM_MODE_WPDIS | FTM_MODE_FTMEN;          //set write-protect disable (WPDIS) bit to modify other registers
  Serial.print("FTM1_MODE: ");  Serial.println(FTM1_MODE, BIN);
                                  
  FTM1_FILTER = 0x00; // no filtering                                
  Serial.print("FTM1_SC: ");  Serial.println(FTM1_SC, BIN);   //  read then set to eliminate Timer Overflow Flag
  FTM1_SC = 0x00;                 //set status/control to zero = disable all internal clock sources
  Serial.print("FTM1_SC: ");  Serial.println(FTM1_SC, BIN);   //  SC=0 does not disable quadrature mode
  FTM1_QDCTRL = FTM_QDCTRL_QUADMODE |  FTM_QDCTRL_QUADEN; // comes in on pin 3 
  Serial.print("FTM1_QDCTRL: ");  Serial.println(FTM1_QDCTRL, BIN);                                
  FTM1_CNTIN=0x0030;              //  counter preset value
  Serial.print("FTM1_CNTIN: ");  Serial.println(FTM1_CNTIN, BIN);   
  FTM1_CNT = 0x0000;              //preset count to 'CNTIN' value by writing to the register
  Serial.print("FTM1_CNT: ");  Serial.println(FTM1_CNT, BIN);     //  show counter value gets 'preset'
  FTM1_CNTIN=0x0000;              //  different preset value
  FTM1_CNT = 0x0000;
  FTM1_MOD = 0xFFFF;              //max modulus = 65535 (gives count = 65535 on roll-over)
  Serial.print("FTM1_MOD: ");  Serial.println(FTM1_MOD, BIN); 
  // FTM1_C0SC = 0x04;               // CHF=0, CHIE=0 (disable interrupt, use software polling), MSB=0 MSA=0, ELSB=0 ELSA=1 (input capture - rising edge), 0, DMA=0
  Serial.print("FTM1_C0SC: ");  Serial.println(FTM1_C0SC, BIN);     //  status register ? ?
  Serial.print("FTM1_C0V: ");  Serial.println(FTM1_C0V, BIN);       //  aparently the counter values can be pipelined ? ?
  Serial.print("FTM1_C1SC: ");  Serial.println(FTM1_C1SC, BIN);

                                  //configure Teensy port pins
  PORTA_PCR12 |= 0x700;           //MUX = alternative function 7 on Chip Pin 28 (FTM1_QD_PHA) = Teensy Pin 3
  PORTA_PCR13 |= 0x700;           //MUX = alternative function 7 on Chip Pin 29 (FTM1_QD_PHB) = Teensy Pin 4
                                  //  remove this ^^^ causes counter to decrement.
  PORTB_PCR0 |= 0x300;            //MUX = alternative function 3 on Chip Pin 35 (FTM1_CH0) = Teensy Pin 16



}

//(3) main loop statements
void loop() {
    
    for (x=0; x<1023; x++)  {             //  use 'blink' example to make clock pulses
      digitalWrite(LED_PIN, HIGH);      //  this routine makes 25 pulses
      delay(5); 
      digitalWrite(LED_PIN,LOW);
      delay(5);
    }
                                    //read FTM1 Ch0 value  -- just read it to see if value present
        p1=FTM1_CNT;    //read CH0 COUNTER value


  Serial.print("FTM1_CNT: ");
  Serial.print(p1, BIN); Serial.print("   ");
  Serial.println(p1);
  Serial.println();
  
}

This is my output.


Code:
FTM1_MODE: 101
FTM1_SC: 10001001
FTM1_SC: 0
FTM1_QDCTRL: 1001
FTM1_CNTIN: 110000
FTM1_CNT: 110000
FTM1_MOD: 1000111111111111
FTM1_C0SC: 101000
FTM1_C0V: 0
FTM1_C1SC: 101000
FTM1_CNT: 1111111111   1023

FTM1_CNT: 11111111110   2046

FTM1_CNT: 101111111101   3069

FTM1_CNT: 111111111100   4092

FTM1_CNT: 1001111111011   5115

FTM1_CNT: 1011111111010   6138

FTM1_CNT: 1101111111001   7161

FTM1_CNT: 1111111111000   8184

FTM1_CNT: 10001111110111   9207

FTM1_CNT: 10011111110110   10230

FTM1_CNT: 10101111110101   11253

FTM1_CNT: 10111111110100   12276

FTM1_CNT: 11001111110011   13299

FTM1_CNT: 11011111110010   14322

FTM1_CNT: 11101111110001   15345

FTM1_CNT: 11111111110000   16368

FTM1_CNT: 100001111101111   17391

FTM1_CNT: 100011111101110   18414

FTM1_CNT: 100101111101101   19437

FTM1_CNT: 100111111101100   20460

FTM1_CNT: 101001111101011   21483

FTM1_CNT: 101011111101010   22506

FTM1_CNT: 101101111101001   23529

FTM1_CNT: 101111111101000   24552

FTM1_CNT: 110001111100111   25575

FTM1_CNT: 110011111100110   26598

FTM1_CNT: 110101111100101   27621

FTM1_CNT: 110111111100100   28644

FTM1_CNT: 111001111100011   29667

FTM1_CNT: 111011111100010   30690

FTM1_CNT: 111101111100001   31713

FTM1_CNT: 111111111100000   32736

FTM1_CNT: 1000001111011111   33759

FTM1_CNT: 1000011111011110   34782

FTM1_CNT: 1000101111011101   35805

FTM1_CNT: 1000111111011100   36828

FTM1_CNT: 1111011011   987

FTM1_CNT: 11111011010   2010

FTM1_CNT: 101111011001   3033

FTM1_CNT: 111111011000   4056
 
Some additional information.

I can set the preset value to 0xFFFF with FTM1_CTIN and the counter will assume this value when FTM1_CNT is executed. This still does not change my ability to set the counter modulus to 0xFFFF.

BTW I am am using Arduino 1.6.5 with Teensyduino 1.27.

Thanks.
 
Thanks for the lead, defragster.

It was not explicitly stated in the post nor the K20 manual, but it appears there is an order to which FTM parameters must be set.

Unlock the mode registers FTMx_MODE
Set the status and control FTMx_SC
Set the preset value FTMx_CNTIN
Preset the register FTMx_CNT
Set the modulus FTMx_MOD

Once the quadrature register (FTMx_QDCTRL) is set it appears hopeless to set the modulus register. Must be some un-documented info as one would think these are just registers that should be read/write at random by a user.
 
Once the quadrature register (FTMx_QDCTRL) is set it appears hopeless to set the modulus register. Must be some un-documented info as one would think these are just registers that should be read/write at random by a user.

Look at section 36.4.10.2 "MOD register update" on page 847. Whenever the CLKS bits aren't both zero (the timer is stopped), there's complex rules about when this register can be updated. It only works as "read/write at random by a user" when the timer is not running.
 
Status
Not open for further replies.
Back
Top