Apple-stil pulserande LED genom att använda en $1,30 MCU (5 / 6 steg)
Steg 5: Koden
/ * LED pulsera med PWM
*/
#include < avr/io.h >
#include < avr/interrupt.h >
#include < util/delay.h >
#include < avr/sleep.h >
int main)
{
Slå på LED utgångsstiftet
DDRB | = _BV(DDB0);
Tydliga OC0A på match
TCCR0A | = _BV(COM0A1);
Ställ in timern att räkna med F_CPU / 64
TCCR0B | = _BV(CS10); F_CPU
TCCR0B | = _BV(CS01) | _BV(CS00); / 64 prescale
Använda snabb PWM, OCRA topp
TCCR0A | = _BV(WGM00);
TCCR0A | = _BV(WGM01);
TCCR0B | = _BV(WGM02);
Startvärdet för vår bredd för synkpuls är 0
OCR0A = 0X00;
uint8_t dir = 1; Riktning
uint16_t div = 500. # av klockor per inc/Sänk
uint16_t stall = 0; Inledande stall counter
uint16_t stall_time = 500. # av klockor till stall på översta/nedersta
for(;;) {
Vi vill bara uppdatera varje div räknas
om (TCNT0% div! = 0) fortsätta;
Stall på toppen och botten, och ändrar riktning
om (OCR0A == 255 || OCR0A == 0) {
Switch directon överst
IF(OCR0A == 255) dir = -1;
annat
{/ / Inaktivera LED längst ner
Och byta riktning
DDRB & = ~(_BV(DDB0));
dir = 1;
}
While(stall < stall_time)
{
++ stall;
_delay_ms(10);
}
Vända utgång på vid behov
IF(OCR0A == 0) DDRB | = _BV(DDB0);
stall = 0;
}
Det allmänna fallet - increment riktning Hursomhelst
OCR0A += dir;
}
Return 0;
}
Förhoppningsvis, denna kod är självdokumenterande. I grunden ändrar vi pulse bredd varje några hundra klockor i ena eller andra. Vi har ett specialfall för när vi kommer till toppen eller botten (ändra riktning och dröja kvar), precis som Apple grejer gör. Det finns ett annat specialfall när vi vill att helt stänga av lampan i botten - om vi inte gör detta, fortfarande har en (1/256) % intermittens, och du kan se den. Koden bör annars vara ganska kortfattad. Konstruktiv kritik uppmuntras.