I am trying to understand timer1 but I cant work it out.[Solved]

Hi
I have been experimenting with timer 1 on a UNO 3.
I am trying to print out the difference when I delay my code for 2ms.
The code below prints out 501, which to me doesn't make sense.

My thinking is, that the difference should be a lot larger E.g. 16000 as it takes the 16 bit timer 4ms to complete.

void setup() {
  Serial.begin(115200);           
  
  TCCR1A = 0x00;                // Normal mode, just as a Timer/Counter
    TCNT1 = 0;
}

void loop() {
  int first = TCNT1;
  delay(2);  
  int timer = TCNT1 - first;

  Serial.print("TCNT1: ");  
  Serial.println(timer);
 
}
  int first = TCNT1;
  delay(2); 
  int timer = TCNT1 - first;

Using ints?

I did try unsigned ints.. got the same result.
as it 16bits, I assumed an int should surface. Should it be something else?

Should it be something else?

Well, millis() returns an unsigned long…

There are two Timer/Counter Control Registers:
TCCR1A and TCCR1B

Since you are not setting TCCR1B it contains whatever the firmware set it for! If you want a clock that runs at 16 MHz you have to configure everything:

  TCCR1A = 0;  // Timer/Counter1 Control Register A
  TCCR1B = 0;  // Timer/Counter1 Control Register B
  TIMSK1 = 0;   // Timer/Counter1 Interrupt Mask Register
  // Set clock prescale to 1 for maximum PWM frequency
  TCCR1B |= (1 << CS10);
// Leave WGM2:0 set to 0 for "Normal" mode

Note: The datasheet says you should turn off interrupts while reading 16-bit timer registers:

unsigned int TIM16_ReadTCNT1( void ) {
unsigned char sreg;
 unsigned int i;
sreg = SREG; // Save global interrupt flag
noInterrupts();
 /* Read TCNT1 into i */
count = TCNT1;
SREG = sreg;  // Restore global interrupt flag

}

On my UNO I get 32142 to 32147. That’s about 0.002009 seconds or about 2.009 milliseconds. Pretty good!

void setup() {
  Serial.begin(115200);

  TCCR1A = 0;                // Normal mode, just as a Timer/Counter
  TCCR1B = 0;
  TCNT1 = 0;
    // Set clock prescale to 1 for maximum PWM frequency
  TCCR1B |= (1 << CS10);
}

void loop() {
  byte sreg;

  sreg = SREG; // Save global interrupt flag
  noInterrupts();
  unsigned first = TCNT1;
  SREG = sreg;  // Restore global interrupt flag

  delay(2);

  sreg = SREG; // Save global interrupt flag
  noInterrupts();
  unsigned second = TCNT1;
  SREG = sreg;  // Restore global interrupt flag

  Serial.print("TCNT1: ");
  Serial.println(second - first);
  delay(5000);
}

thank you johnwasser, it is now working as expected.

the most important missing line was TCCR1B |= (1 << CS10);

Ill also disable the interrupts when reading the registers.

I think something had set the Clock Select bits to 0b011 (divide by 64) instead of 0b001 (divide by 1).

I think something had set the Clock Select bits to 0b011 (divide by 64) instead of 0b001 (divide by 1).

The prescaler of 64 is the default timer 1 set up by the IDE with wiring.c This is what gives the pwm frequency 490 in 8 bit phase correct mode.