Looking into the idea of having a 16 bit PWM using timer1 and I knocked up the below test code but it just keeps resetting the UNO and I don't know why (and hope someone can tell me why).
Ignore the commented out stuff I used to test different ideas.
#define ledPin 13
#define PB5 5
volatile byte Compare = 0;
volatile byte Overflow = 0;
byte OverflowOld;
void setup(){
Serial.begin(115200);
Serial.println("Setup...");
pinMode(ledPin, OUTPUT);
cli(); // Disable all interrupts
TCCR1A = 0; // Clear all flags in control register A
TCCR1B = 0; // Clear all flags in control register B
//TCCR1C = 0; // Clear all flags in control register C
TCNT1 = 0; // Zero timer 1 count
OCR1A = 32768; // Preload compare match register (50% duty cycle)
// prescaler
TCCR1B |= (1 << CS12);
//TCCR1B |= (1 << CS11);
TCCR1B |= (1 << CS10);
TIMSK1 |= (1 << OCIE1A); // Enable timer compare interrupt
TIMSK1 |= (1 << TOIE1); // Enable timer overflow interrupt
sei(); // enable all interrupts
}
void loop(){
/* if (Overflow != OverflowOld){
Serial.print("Overflow = ");
Serial.println(Overflow);
Serial.print("Compare = ");
Serial.println(Compare);
Serial.println(OverflowOld);
OverflowOld = Overflow;
}
*/
}
ISR(TIMER1_OVF_vect){ // Timer1 overflow interrupt service routine
digitalWrite(ledPin,HIGH);
//PORTB |= _BV(PB5); // Turn LED on
//Overflow++;
}
ISR(Timer1_COMPA_vect){ // Timer1 compare interrupt service routine
digitalWrite(ledPin,LOW);
//PORTB &= ~_BV(PB5); // Turn LED off
//Compare++;
}
Dr_Ugi:
This may be stupid but does the capitalisation of "Timer1_COMPA_Vect" matter? I have "TIMER1_" rather than "Timer1_".
If it did matter then you would have an unhandled interrupt which could cause no end of problems, but I would expect that it wouldn't compile.
Spot on Ugi, changed to upper case (how did I miss that) and now works as expected. Strange it compiled without error though?
Finished example without all the crap I had used to figure out what was going wrong. Fades built in LED on UNO.
// 16 bit PWM on any pin
// Example uses built in LED on pin 13 (PORTB bit 5)
void setup(){
pinMode(13, OUTPUT);
cli(); // Disable all interrupts
TCCR1A = 0; // Clear all flags in control register A
TCCR1B = 0; // Clear all flags in control register B
TCNT1 = 0; // Zero timer 1 count
OCR1A = 32768; // Preload compare match register (50% duty cycle)
// No prescaler
//TCCR1B |= _BV(CS12);
//TCCR1B |= _BV(CS11);
TCCR1B |= _BV(CS10);
TIMSK1 |= _BV(OCIE1A); // Enable timer compare interrupt
TIMSK1 |= _BV(TOIE1); // Enable timer overflow interrupt
sei(); // enable all interrupts
}
void loop(){
for(unsigned int x = 1; x < 65535; x++){
OCR1A = x;
delayMicroseconds(50);
}
}
ISR(TIMER1_OVF_vect){ // Timer1 overflow interrupt service routine
PORTB |= _BV(PORTB5); // Turn LED (pin 13) on
}
ISR(TIMER1_COMPA_vect){ // Timer1 compare interrupt service routine
PORTB &= ~_BV(PORTB5); // Turn LED off
}
One of these days someone will invent a compiler that can work out what we mean rather than what we say. Unfortunately, that will probably be the day before the SkyNet nuclear apocalypse!
It's close to impossible to see your own mistakes - if I had a penny for every "=" that should have been "=="...