From: Pat Thoyts Date: Wed, 12 Aug 2015 11:16:49 +0000 (+0100) Subject: Demo configuration of AVR timer and PWM. X-Git-Url: http://privyetmir.co.uk/gitweb?a=commitdiff_plain;h=870644515ce5db0a51de564fa27100b9b0aafc6a;p=avr%2Ftimer-demo.git Demo configuration of AVR timer and PWM. Demonostrates the initialization of a timer for 1ms resolution interrupts and also shows the control of PWM frequency using timer 1. Signed-off-by: Pat Thoyts --- 870644515ce5db0a51de564fa27100b9b0aafc6a diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d6c2e45 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.elf +*.hex diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..1c0410f --- /dev/null +++ b/Makefile @@ -0,0 +1,27 @@ +# -*- Makefile -*- + +PROJECT=timer-demo +DEVICE =atmega328p +F_CPU =16000000UL +INC =-I. +AVRDUDE=avrdude -c usbasp -p $(DEVICE) -C $(AVR_DIR)\etc\avrdude.conf + +CC=avr-gcc +LD=avr-gcc +OBJCOPY=avr-objcopy +CFLAGS =-Wall -Os -mcall-prologues -mmcu=$(DEVICE) -DF_CPU=$(F_CPU) +LDFLAGS=-Wall -mmcu=$(DEVICE) + +all: $(PROJECT).hex + +%.hex: %.elf + $(OBJCOPY) -j .text -j .data -O ihex $< $@ + +%.elf: %.o + $(LD) $(LDFLAGS) $< -o $@ + +%.o: %.c + $(CC) $(CFLAGS) $(INC) -c $< + +flash: $(PROJECT).hex + $(AVRDUDE) -U flash:w:$<:i \ No newline at end of file diff --git a/timer-demo.c b/timer-demo.c new file mode 100644 index 0000000..83fe5e6 --- /dev/null +++ b/timer-demo.c @@ -0,0 +1,136 @@ +/* Copyright (c) 2015 Pat Thoyts + * + * Demonstrate the use of AVR timer 2 to precisely control a pin. + * Test board has LEDs connected to pin 5 and 9 (PD5 and PB1) on an + * Arduino Nano board. Pin 5 is connected to timer2 and demonstrates + * control of the timer interval while pin 9 is connected to timer1 + * and shows the PWM frequency control. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* + * timer2: + * Using a /64 prescaler with 1 16MHz clock and counting from + * 6 we get an interval of 1ms exactly between interrupts: + * (64.0 / 16e6) * (256 - 6) = 0.001s + * + * timer1: + * Using Phase/Freq correct mode we can control the PWM freq precisely. + * f = 16e6 / (2 * mul * TOP) + * TOP = 0xf000 yields 125 Hz + * TOP = 64 yields 125 kHz + * TOP = 16 yields 500 kHz + * TOP = 2 yields max of 4 MHz + * For IR: 36kHz use 222; 38kHz use 212 + */ +const uint8_t TIMER_INIT = 6; +const uint16_t PWM_TOP = 212; +const uint16_t PWM_MATCH = 212/2; /* square wave, 50% */ + +volatile uint16_t counter = 0; + +ISR(TIMER2_OVF_vect) +{ + cli(); + TCNT2 = TIMER_INIT; /* reset the timer */ + if (++counter >= 250) + { + PORTD ^= _BV(PD5); + OCR1A = (OCR1A == 0) ? PWM_MATCH : 0; + counter = 0; + } + sei(); +} + +static void init_timer2() +{ + cli(); + /* 18.9: Disable the timer2 overflow interrupt for configuration */ + TIMSK2 &= ~(1 << TOIE2); + /* 18.9b: Select clock source as internal i/o clock */ + ASSR &= ~(1<