Problem writing to TCCR1A

Hello all, I have spent some time now trying to create an interrupt at 5ms but after awhile I realized my code does not seem to be writing to the TCCR1A. I am not sure where in my code there is a problem so if you could take a look I would really appreciate it! Almost forgot the serial monitor produces a 0 value for this code.

int valueTCCR1B = 0;
int valueTCCR1A = 0;
int valueOCR1A = 0;
int valueTIMSK1 = 0;
unsigned int valueTCNT1 = TCNT1;

void setup()
{
  pinMode(13, OUTPUT);
  Serial.begin(9600);
  cli();
  TCCR1A = 0;
  TCCR1B = 0;
  // initialize counter
  TCNT1 = 0;
  // initialize compare value
  OCR1A = 0;
  // set up timer with prescaler 256 and CTC mode
  TCCR1B |= (1 << CS12);
  TCCR1A |= (1 << WGM12);
  // enable overflow interrupt
  TIMSK1 |= (1 << TOIE1);
  // set all interrupts on
  sei();
}

void loop()
{
  valueTCCR1B = TCCR1B;
  valueTCCR1A = TCCR1A;
  valueOCR1A = OCR1A;
  valueTIMSK1 = TIMSK1;
  valueTCNT1 = TCNT1;

  Serial.println(valueTCCR1A);
  delay(250);
}

ISR(TIMER1_OVF_vect)
{
  digitalWrite(13, digitalRead(13) ^ 1);
}

If you want a specific value in a register, do NOT use the OR ("|") operation, write to it directly.

I changed to the below and I get 0 for TCCR1A and 4 for TCCR1B. I know TCCR1B is still |= and I did this as a test but not to defy you. I will take your advice on setting with the = operator regardless but what is so bad about using OR ( | )?

void setup()
{
  Serial.begin(9600);
  TCCR1A = 0;
  TCCR1B = 0;
  TIMSK1 = 0;
  pinMode(13, OUTPUT);
  // initialize counter
  TCNT1 = 0;
  // initialize compare value
  OCR1A = 15000;
  // set up timer with prescaler 256 and CTC mode
  TCCR1A = 4;
  TCCR1B |= (1 << CS12);

  // enable overflow interrupt
  TIMSK1 |= (1 << 1);
  // set all interrupts on
  sei();
}

void loop()
{
  delay(100);
  Serial.println(TCCR1A);
  Serial.println(TCCR1B);
}

ISR(TIMER1_COMPA_vect)
{
  digitalWrite(13, digitalRead(13) ^ 1);
}

steve13579: but what is so bad about using OR ( | )?

There's nothing bad about using |= if you only want to change one bit or another. But if you want to set the value of the whole register it won't work since it leaves all the other bits unchanged.

I think I figured it out, I believe my problem is in the understanding of the registers and their respective modes for these timers. First I can not write a 4 to TCCR1A because that writes to a locations I do not have access to. And I can not write a 1 either as it puts it in a PWM mode which I assume has some issue with the other settings since I am trying to do a compare match interrupt. However I can write a 16 to TCCR1A and everything will work.

Moral of the story I need to read the datasheet section on these registers a few more times... Hopefully this will help someone in the future. If you know what I was doing and agree with my analysis please let me know! Thanks again.

TCCR1A |= (1 << WGM12);

The WGM12 bit lives on TCCR1B.

I’m sure there was some architectural reason (backwards compatibility?) in the past where Atmel decided to split the waveform mode bits (WGM) into two registers rather than to use bits 3 and 2 on TCCR1A to put all three or four WGM bits on the same register.

And I can not write a 1 either as it puts it in a PWM mode which I assume has some issue with the other settings since I am trying to do a compare match interrupt.

Not true.

Moral of the story I need to read the datasheet section on these registers a few more times…

Amen.