Skip to main content
Arduino

Return to Answer

+ clarification.
Source Link
Edgar Bonet
  • 45.1k
  • 4
  • 42
  • 81

You must write the clock-select bits to the correct value. The simplest way to do it is to write the proper configuration into the TCCR1B register:

TCCR1B = (1<<CS12)|(1<<CS10);

In your program, you used |= instead of =. This doesn't write the bits appropriately: it only sets (writes to 1) the bits CS12 and CS10 but doesn't clear CS11. Since the Arduino core library sets the prescaler to 64 (CS11 and CS10 set), you end up with all the clock-select bits sets, in which case the timer is clocked by an external signal on the T1 pin. Not what you want.


Edit: Judging from the comments, it appears that at least dannyf did not understand my answer, I am therefore adding a clarification. There are two scenarios when you may want to tweak the control registers of a peripheral:

  1. The peripheral is normally controlled by the Arduino core library, and you want to use it through that library. Typical case: you want to use a timer to analogWrite(), or the ADC to analogRead(), but you want to clock the peripheral at a frequency which is not the core's default.

  2. You want to use a peripheral directly rather than through the Arduino core. Either you are going to "take it over" from the core, or it's a peripheral the core doesn't use in the first place.

In the first case, you should only touch those bits of the control registers that you must change. The other bits should be left alone, at whatever values the core has set them to. This is the approach of dannyf's answer.

In the second case, it is wiser to not rely on the core's default setting, and instead write every single bit of the control registers to the values appropriate for your application. This is the scenario of the original question, and the solution proposed in my answer.

For the particular case of this question, the TCCR1B register would be set to: ICNC1 = 0, ICES1 = 0, reserved bit = 0, WGM13 = 0, WGM12 = 0, CS12 = 1, CS11 = 0 and CS10 = 1. Combining those bits together gives the setting TCCR1B = 0x05;. However, for readability reasons, I prefer to write that value (1<<CS12)|(1<<CS10), as in the question and in my original answer. Some people may prefer to explicitly write every bit, like

TCCR1B = (0<<ICNC1) | (0<<ICES1) | (0<<5) | (0<<WGM13)
 | (0<<WGM12) | (1<<CS12) | (0<<CS11) | (1<<CS10);

Whichever version you prefer is up to you. I personally don't find this latter version any easier to read.

: The values of ICNC1 and ICES1 are actually irrelevant in this case.

You must write the clock-select bits to the correct value. The simplest way to do it is to write the proper configuration into the TCCR1B register:

TCCR1B = (1<<CS12)|(1<<CS10);

In your program, you used |= instead of =. This doesn't write the bits appropriately: it only sets (writes to 1) the bits CS12 and CS10 but doesn't clear CS11. Since the Arduino core library sets the prescaler to 64 (CS11 and CS10 set), you end up with all the clock-select bits sets, in which case the timer is clocked by an external signal on the T1 pin. Not what you want.

You must write the clock-select bits to the correct value. The simplest way to do it is to write the proper configuration into the TCCR1B register:

TCCR1B = (1<<CS12)|(1<<CS10);

In your program, you used |= instead of =. This doesn't write the bits appropriately: it only sets (writes to 1) the bits CS12 and CS10 but doesn't clear CS11. Since the Arduino core library sets the prescaler to 64 (CS11 and CS10 set), you end up with all the clock-select bits sets, in which case the timer is clocked by an external signal on the T1 pin. Not what you want.


Edit: Judging from the comments, it appears that at least dannyf did not understand my answer, I am therefore adding a clarification. There are two scenarios when you may want to tweak the control registers of a peripheral:

  1. The peripheral is normally controlled by the Arduino core library, and you want to use it through that library. Typical case: you want to use a timer to analogWrite(), or the ADC to analogRead(), but you want to clock the peripheral at a frequency which is not the core's default.

  2. You want to use a peripheral directly rather than through the Arduino core. Either you are going to "take it over" from the core, or it's a peripheral the core doesn't use in the first place.

In the first case, you should only touch those bits of the control registers that you must change. The other bits should be left alone, at whatever values the core has set them to. This is the approach of dannyf's answer.

In the second case, it is wiser to not rely on the core's default setting, and instead write every single bit of the control registers to the values appropriate for your application. This is the scenario of the original question, and the solution proposed in my answer.

For the particular case of this question, the TCCR1B register would be set to: ICNC1 = 0, ICES1 = 0, reserved bit = 0, WGM13 = 0, WGM12 = 0, CS12 = 1, CS11 = 0 and CS10 = 1. Combining those bits together gives the setting TCCR1B = 0x05;. However, for readability reasons, I prefer to write that value (1<<CS12)|(1<<CS10), as in the question and in my original answer. Some people may prefer to explicitly write every bit, like

TCCR1B = (0<<ICNC1) | (0<<ICES1) | (0<<5) | (0<<WGM13)
 | (0<<WGM12) | (1<<CS12) | (0<<CS11) | (1<<CS10);

Whichever version you prefer is up to you. I personally don't find this latter version any easier to read.

: The values of ICNC1 and ICES1 are actually irrelevant in this case.

Source Link
Edgar Bonet
  • 45.1k
  • 4
  • 42
  • 81

You must write the clock-select bits to the correct value. The simplest way to do it is to write the proper configuration into the TCCR1B register:

TCCR1B = (1<<CS12)|(1<<CS10);

In your program, you used |= instead of =. This doesn't write the bits appropriately: it only sets (writes to 1) the bits CS12 and CS10 but doesn't clear CS11. Since the Arduino core library sets the prescaler to 64 (CS11 and CS10 set), you end up with all the clock-select bits sets, in which case the timer is clocked by an external signal on the T1 pin. Not what you want.

lang-cpp

AltStyle によって変換されたページ (->オリジナル) /