bearislive
Published © MIT

Enable PWM on an ATtiny by programming its registers

Let's find out how to recreate Arduino's Fade example by manually manipulating an ATtiny's registers with C and avr-libc.

BeginnerFull instructions provided7,899
Enable PWM on an ATtiny by programming its registers

Things used in this project

Story

Read more

Schematics

Schematics

Layout

Code

blink.c

C/C++
/*
  Fade for ATtiny85 using only avr-libc
  Copyright (c) 2022 Hans Peter Müller

  This code recreates Arduino's Fade example on an ATtiny85 using only avr-libc
  functionality. Without having access to Ardunio's syntactic sugaring, we need
  to recreate Arduino's "analogWrite()" function. Under the hood this function
  enables Pulse-width-modulation (PWM) by setting the necessary registers on the
  ATtiny85. For more information on how PWM works, see these fantastic
  tutorials:

  - https://www.re-innovation.co.uk/docs/fast-pwm-on-attiny85/
  - http://matt16060936.blogspot.com/2012/04/attiny-pwm.html

  You'll also need Atmel's data sheet to understand how the registers are named
  and which functions are controlled by them (see read me document).
*/

#include <avr/io.h>
#include <util/delay.h>

int fadeAmount = 5;
int brightness = 0;

/*
  We enable PWM by setting some registers. This code assumes that a LED is
  attached to the lower right pin of the ATtiny85 (pin 0). See schematics.png
  for further details on how to setup the circuit.

  DDRB (Data Direction Register Port B):
  - DDBO (Data Direction Port B Pin 0) to 1 (output)

  TCCR0A (Timer/Counter Control Register A):
  - COM0A1 (Compare Match Output A Mode) to 1 (non-inverting mode)
  - WGM0[0,1] (Waveform Generation Mode Register 0 and 1) to 1 (fast PWM)

  TCCR0B (Timer/Counter Control Register B):
  - CS00 (Clock Select Register 0) to 1 (no prescaling)

  Instead of calling "analogWrite()", we set the ATtiny's Output Compare
  Register A (OCR0A) to the current brightness value. The rest is similar to the
  original Fade.ino sketch.
*/
int main()
{
  DDRB = 1 << DDB0;                       
  TCCR0A = 1 << COM0A1 | 1 << WGM01 | 1 << WGM00;
  TCCR0B = 1 << CS00;

  while (1) {
    brightness = brightness + fadeAmount;
    if (brightness <= 0 || brightness >= 255) {
      fadeAmount = -fadeAmount;
    }
    OCR0A = brightness;
    _delay_ms(30);
  }
  return 0;
}

Credits

bearislive

bearislive

0 projects • 0 followers

Comments