Having trouble setting OCR1A

I've been having trouble understanding what's happening when I try to set a value for OCR1A. Making things as simple as possible, I tried:

void setup() {
  OCR1A = 16000;
  Serial.begin(9600);
  Serial.println(OCR1A);
}
void loop() {
}

No matter what x I put for OCR1A though, it seemed to only give me x mod 256. This made it seem like it was only setting the lower register. So instead I tried

void setup() {
  OCR1AH = 0b00111110;
  OCR1AL = 0b10000000;
  Serial.begin(9600);
  Serial.println(OCR1A);
}
void loop() {
}

Again, it only printed the value in the lower register. Thinking this was maybe a problem with the print function, I replaced the println with separate commands to Serial.println(OCR1AH); Serial.println(OCR1AL); For some reason it doesn't print anything here, though when I was using Arduino-0021 earlier today (instead of the Arduino-0022 I'm using now), it printed 0 for OCR1AH and 128 for OCR1AL.

So maybe the println command is doing weird things. I tried setting up something using CTC mode with no prescaling, toggling OC1A on compare match.

void setup() {
  pinMode(9,OUTPUT);
  OCR1AH = 0b00111110;
  OCR1AL = 0b10000000;
  TCCR1A = _BV(COM1A0);
  TCCR1B = _BV(WGM12) | _BV(CS10);
}
void loop() {
}

Now using a multimeter in frequency mode, I look across ground and Digital 9 (which should be PB1 / OC1A), and get a readout of 7.998 MHz, no matter how I try to set OCR1A. This seems consistent with OCR1A being zero, so not even the low bit is being set correctly?

As a further test, I tried putting Serial.println(TCNT1); into the loop() function, and it kept printing 0, which also seems consistent with OCR1A being 0, but I'm not sure if trying to print the value interferes with it updating or something, so this might not be a good test.

Anyway, if anyone can explain what is happening here, I'd be much obliged!

The Arduino initialization code sets up timers for PWM operation (so that if you use analogWrite, the timers are already set up). The timers do certain things to their registers as they are running.

Anyhow...

If you stop the timer first, then you can see:

void setup()
{
    Serial.begin(9600);
    // Make sure the timer is really stopped
    TCCR1A = 0;
    TCCR1B = 0;
    OCR1A = 0x1234;
    Serial.print("OCR1A = 0x");
    Serial.println(OCR1A);
}

Output:


[color=blue]OCR1A = 0x1234
[/color]

Bottom line: Whenever you are going to do anything (anything at all) with any of the timers, set the mode of operation with the TCCR registers before doing anything else.

Regards,

Dave

Thanks Dave, I am now able to get the OCR1A thing set like I want to.
I wish I understood a little more how a running timer interferes with setting the registers (since it only seems to do that in some modes), but that sounds like I just need to try to make sense of the initialization code / chip documents. And in the meantime, at least I can make it work!

thork:

I wish I understood a little more how a running timer interferes with setting the registers …

The Arduino init() function (in wiring.c) sets Timer1 to 8-bit Phase Correct mode so that analogWrites to the Timer 1 pins will be consistent with analogWrite calls to other timer OCR pins. In the 8-bit mode, the OCR1 register is (automatically) updated with its upper bits equal to zero every time the timer times out.

If you are going to be using any timer for anything (anything at all) you will be reading through the ATmega data sheet and you will be initializing the TCCR registers to whatever you need them to be so you won’t have to worry about unknown states of your timer that were set up by the (invisible-to-“normal”-users) Arduino initialization code.

Regards,

Dave