Dim LED with Timer1 Interrupt and Binary manipulation of registers?


Used this in my previous Atmega life (i’m born again in the SAMD21 life)

;initialize 16-bit timer1

// fast PWM mode on OC1A
TCCR1A = (1<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (1<<WGM11) | (0<<WGM10)

// define TOP value for Fast PWM OC1A (1 Hz)
ICR1 = 15625

// compare counter (50ms pulse generation on OC1A)
OCR1A = 781

// timer1 overflow interrupt (disabled)
TIMSK1 = (0<<OCIE1B) | (0<<OCIE1A) | (0<<TOIE1)

// 1024 prescaler, start timer1 in fast PWM
TCCR1B = (0<<ICNC1) | (0<<ICES1) | (1<<WGM13) | (1<<WGM12) | (1<<CS12) | (0<<CS11) | (1<<CS10)

ICR1, OCR1A, and CS1x works together to get the period and duty cycle you need.

It doesn't use interrupt to dim the output, it uses the duty cycle


In your code, you are trying to set the pin output using the compare interrupt routine. You don't have too since the hardware timer can do it for you (using PWM mode).

If you want to control the pins yourself, you have to use normal timer mode and use the compare or overflow interrupts to set the pins.


if using PWM timer mode, DONT touch the PORTx registers, the hardware does it for you
if using normal timer mode, then you have complete control of the PORTx registers, you can manipulate them inside the compare/overflow ISR

The SAMD21 is a lot more capable than the 328 found on the UNO. Lots of timers (has 7 compared to 2 on the 328) and lots more serial port. Its more complicated to program but that's what the datasheets are for.