Íme egy kis karácsonyi díszvilágítás a dolgozóasztalunkra, persze nyolc lábbal. A kiválasztott mikrokontrollerünk kivételesen az ATtiny13 amiben csak 1K flash található.
Az ő mottója a "mindenből egyet".
A kapcsolás se több, se kevesebb:
Működés közben: hungarocell darabka a jobb láthatóság végett
A videó megtekintéséhez Flash lejátszó szükséges!
Már csak a forráskód hiányzik..Íme:
#include <avr/io.h>
#include <avr/interrupt.h>
//____________________________________________________
volatile unsigned char R_counter , B_counter , G_counter; // számlámó
volatile unsigned char R_duty , B_duty, G_duty; // kitöltés
unsigned char TimerCounter;
//----------------------------------------------------
void Init(void) {
//----------------------------------------------------
TCCR0B |= (0<<CS02) //64-as előosztás timer 0-re
| (0<<CS01)
| (1<<CS00);
TIMSK0 |= (1<<TOIE0) ; //enable interrupt
sei();
DDRB |= (1<<PINB0) //kimeneteink
| (1<<PINB1)
| (1<<PINB2);
}
//----------------------------------------------------
SIGNAL(SIG_OVERFLOW0) {
//----------------------------------------------------
TimerCounter--;
if(TimerCounter==0) { // Tehát F_CPU/64/255
R_counter = R_duty;
G_counter = G_duty;
B_counter = B_duty;
PORTB |= (1<<PINB0)
| (1<<PINB1)
| (1<<PINB2);
}
if(R_counter) R_counter--;
if(G_counter) G_counter--;
if(B_counter) B_counter--;
if(R_counter==0) PORTB &= ~(1<<PINB0);
if(G_counter==0) PORTB &= ~(1<<PINB1);
if(B_counter==0) PORTB &= ~(1<<PINB2);
}
//----------------------------------------------------
int main(void) {
//----------------------------------------------------
unsigned char val = 1; //belessen az 1. case-be.
Init();
R_duty = 128; //kezdoertekek
G_duty = 30;
B_duty = 200;
for(;;) { // vegtelen ciklus
switch(val) { // színek fadelése
case 1: if(R_duty<0xFF) R_duty++;
else val = 2;
break;
case 2: if(B_duty) B_duty--;
else val = 3;
break;
case 3: if(G_duty<0xFF) G_duty++;
else val = 4;
break; // break!! Különben továbbmegy..
case 4: if(R_duty) R_duty--;
else val = 5;
break;
case 5: if(B_duty<0xFF) B_duty++;
else val = 6;
break;
case 6: if(G_duty) G_duty--;
else val = 1;
break;
}
_delay_ms(50);
}
return 0;
}
A programban nem használok semmilyen nem gyári header-t. Rövid működése a következő:
Az init függvényünkben első lépésként beállítjuk az egyetlen timerünk (Timer0) előosztását 64-re, majd engedélyezzük a megfelelő regiszterben (Timsk0) a timer owerflow interruptot.
Ezt még 256-al osztjuk (256.-ra csordul túl) az overflow miatt, majd a TimerCounter változó dekrementálásával még 256-al. Tehát: F_CPU/64/256/256. F_CPU jelen esetben 9 600 000 Hz. Programozásnál is ezt az órajelet válasszuk ki (Fuses)
Ne felejtsük el, engedélyezni globálisan is az interruptokat, ezt a sei()-paranccsal tehetjük meg! A signal egy olyan függvény, ami tartalma az interrupt beesésekor hajtódik végre! Igyekezzünk, itt semmilyen nagyobb műveletet végrehajtatni processzorunkkal, hisz rendkívül időkritikus. Jelen esetben itt adjuk át a végtelen ciklusban számolt kitöltési tényezőt (az x_duty-t) az x_counterünknek. Fontos még, hogy ezek a változók volatile-ok legyenek, hisz az értékük bármelyik pillanatban változhat. Ha ezt elfelejtenénk, nem futna a software-es PWM-ünk. A végtelen ciklusunkban csak a színek fadelését végzem. Növelem az aktuális színt (azaz a kitöltési tényezőjét), ameddig el nem éri az értéke 0xFF-et. Ha eléri, akkor ugrok a következő esetre és ezeket kombinálom, így keverednek a színek. Remélem mindenki tetszését elnyeri. Sikeres után építést kívánok!
Ha kérdésetek van, szívesen segítek!
Köszönet Topinak, hogy megszerettette velem az AVR-t!
ZsirosDani
A cikk még nem ért véget, lapozz!
Értékeléshez bejelentkezés szükséges!