1

I am stuck on this for a while, I am trying to generate a 100 hz square wave with 50% duty cycle in pin 3 and trying to verify it with wire at pin 4; I am getting 64000 but not 100 in serial monitor.


#define LEDPIN 3

uint16_t val2= pulseIn(4, HIGH);

ISR(TIMER1_COMPA_vect) { digitalWrite(LEDPIN, !digitalRead(LEDPIN)); }
void setup() {
Serial.begin(9600);
pinMode(LEDPIN, OUTPUT);
// initialize Timer1 (the 16-bit timer) using channel A output compare
noInterrupts(); // disable global interrupts
// TIMER 1 for interrupt frequency 100 Hz:
cli(); // stop interrupts
TCCR1A = 0; // set entire TCCR1A register to 0
TCCR1B = 0; // same for TCCR1B
TCNT1 = 0; // initialize counter value to 0
// set compare match register for 100 Hz increments
OCR1A = 19999; // = 16000000 / (8 * 100) - 1 (must be <65536)
// turn on CTC mode
TCCR1B |= (1 << WGM12);
// Set CS12, CS11 and CS10 bits for 8 prescaler
TCCR1B |= (0 << CS12) | (1 << CS11) | (0 << CS10);
// enable timer compare interrupt
TIMSK1 |= (1 << OCIE1A);
sei(); // allow interrupts
//TCCR1A = 0; // Timer/Counter Control Register 1A
//TCCR1B = 0; // (both control registers need to be configured)
//// set compare match register to desired timer count:
//OCR1A = 15624; // Output Compare Register 1A (i.e., for channel A)
//TCCR1B |= (1 << WGM12); // CTC (Clear Timer on Compare Match) mode
//TCCR1B |= (1 << CS10); // for 1,024 prescaler; UNO has a 16 MHz clock
//TCCR1B |= (1 << CS12);
//TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt
interrupts(); // enable global interrupts:
}
void loop() {
uint16_t val = OCR1A/8;

ICR1 = val -1;
OCR1A = val/2 - 1 ; // 50% duty cycle for pin 3
//OCR1B = val/2 - 1 ; // 50% duty cycle for pin 4
//uint16_t val2= pulseIn(4, HIGH);
Serial.print(val2);
delay(1000);
Serial.print("\n");

}

0

You wrote:

uint16_t val2 = pulseIn(4, HIGH);

It makes no sense to call this here, as the timer has not been initialized. You probably cannot expect anything but a timeout in this context.

noInterrupts();
cli();

These two are synonyms. No need to repeat yourself. Actually, no need to block interrupts at all.

sei();
interrupts();

Ditto.

OCR1A = 19999; // = 16000000 / (8 * 100) - 1

This is supposed to fire interrupts at 100 Hz. But if you want a 100 Hz output signal, you should fire the interrupts at 200 Hz (two interrupts per cycle). Thus:

OCR1A = 9999; // = (16 MHz / 8) / (2 * 100 Hz) - 1

Then,

// Set CS12, CS11 and CS10 bits for 8 prescaler
TCCR1B |= (0 << CS12) | (1 << CS11) | (0 << CS10);

This is configuring Timer 1 for an external clock source. If you want ÷8 prescaler, you should only set bit CS11. Check the datasheet.

uint16_t val = OCR1A/8;
ICR1 = val -1;
OCR1A = val/2 - 1 ; // 50% duty cycle for pin 3

This doesn't make any sense to me. Why are you setting ICR1? Why are you changing OCR1A although it was already configured in setup()? You can remove all this. Here is the loop() I used for testing:

void loop() {
    Serial.println(pulseIn(3, HIGH));
    delay(1000);
}

And it repeatedly printed 4955, which is quite close to the expected value (namely 5000).

1
  • Thanks for your help.
    – ram patel
    Feb 13 at 18:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.