Add a program that demonstrates PWM and interrupts

This commit is contained in:
Savanni D'Gerinel 2022-04-27 22:28:54 -04:00
parent 5487c27c50
commit 02716cc58b
2 changed files with 81 additions and 3 deletions

View File

@ -30,21 +30,24 @@
pkgs = import nixpkgs { system = "x86_64-linux"; };
avr = pkgs.pkgsCross.avr.buildPackages;
in pkgs.stdenv.mkDerivation rec {
name = "hello";
name = "pwm";
src = ./.;
buildInputs = [ pkgs.simavr ];
MCU = "attiny85";
CHIP_SELECT = "AVR_ATtiny85";
F_CPU = "8000000";
CFLAGS = ''-O -finline-functions -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -DF_CPU=${F_CPU} -std=gnu99 -D__${CHIP_SELECT}__=1 -mmcu=${MCU}'';
buildPhase = ''
set -x
${avr.gcc}/bin/avr-gcc ${CFLAGS} -I${src}/base/include/ -o main.elf ${src}/prototype/src/main.c
${avr.gcc}/bin/avr-gcc ${CFLAGS} -I${src}/base/include/ -E -o main.post-cc ${src}/pwm/src/main.c
${avr.gcc}/bin/avr-gcc ${CFLAGS} -I${src}/base/include/ -o main.elf ${src}/pwm/src/main.c
$OBJCOPY -O ihex main.elf main.hex
'';
installPhase = ''
mkdir $out
cp main.post-cc $out
cp main.elf main.hex $out
'';
};
@ -56,6 +59,7 @@
binutils
gcc
avrdude
simavr
];
in
pkgs.mkShell {

74
pwm/src/main.c Normal file
View File

@ -0,0 +1,74 @@
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <base.h>
#define FIVE_SECOND_TICK (8000000 * 10) / 256
volatile uint32_t iteration = 0;
void set_up_pwm(void);
void start_pwm(void);
ISR(TIMER0_OVF_vect) {
if (iteration >= FIVE_SECOND_TICK) {
GTCCR |= _BV(TSM);
/*
PORTB &= ~(_BV(2));
PORTB |= _BV(1);
*/
PORTB = _BV(1);
} else {
iteration += 1;
}
}
void set_up_pwm(void) {
// Stop the clock
GTCCR = _BV(TSM) | _BV(PSR0);
TCCR0B = _BV(CS00);
// Set normal mode
TCCR0A = _BV(COM0A1) | _BV(WGM01) | _BV(WGM00);
// Enable the overflow interrupt
TIMSK = _BV(TOIE0);
}
void start_pwm(void) {
GTCCR &= ~(_BV(TSM));
}
int main (void) {
int8_t step = 1;
uint8_t target = 0;
set_up_pwm();
OCR0A = 0;
PORTB = 0;
DDRB = _BV(2) | _BV(1) | _BV(0);
_delay_ms(50);
PORTB |= _BV(2);
sei();
start_pwm();
while (iteration != FIVE_SECOND_TICK) {
OCR0A = target;
target += step;
if (target == 255) {
step = -1;
} else if (target == 0) {
step = 1;
}
_delay_ms(10);
}
while (1) {}
}