Tikslas: pasirasyti valdymo programa mikroprocesoriui ATtiny2313 del 6 tristoriu valdymo.
Programos rasymui naudoju PN[WinAVR], WinAVR simuliatoriu. Ziniu bagazas nulinis, jei negalima zinias vertinti neigiamu skaiciu israiska
Beda ta, kad "normalios" programos pradedamos "void main ()", o manoji meta klaidas:
svarka.c:5: warning: return type of 'main' is not `int'
svarka.c: In function `main':
svarka.c:5: error: syntax error before '{' token
Zinoma, veikia ir netaisus. Taciau pagal A.Kylienes metodines priemones operatorius "int" skirtas kintamojo tipui aprasyt, o ne pagrindinei programai. O norisi tvarkingai pradzia parasyt, kad po to butu galima velinimo funkcija iterpt ir nesigautu kokiu nors papildomu nesamoniu.
Pasiulymu kokiu bus ?
#include
void main(void)
int {
DDRB = 252;//nustato sesis isejimus (cia kai suteikiam 1, tai
//gaunasi isejimas)
DDRD = (0<
while (2)
{
//darom sustabdyma, jei neaktyvuotas PD6 (11 koja)
if (3)
{
while (bit_is_set(PIND,0));
}
else
{
return 2;
}
PORTB=4;
PORTB=8;
PORTB=16;
PORTB=32;
PORTB=64;
PORTB=128;
PORTB=0;
PIND=1;//cia isiraso 1 i 11 mikres koja (PD6), ir stato procesa i ,
//pirmine busena, kol svarkos sinchronizacinis paleidimo impulselis
//(tipo log0) nepasirodo ant sios 11 mikres (PD6) kojos
}
return;
}
Del void ir int tipo main funkcijoje. Pagal C C99 standarta vietoj void main() reikia naudoti int main(), nes ši funkcija turi grazinti reikšmę. Taigi cia yra grynai standarto nurodymas ir geriausia jo laikytis. Aisku su void irgi veiks. Ale kam gilintis labiau. Rasyk int tipair viskas.
Bandau ikisti velinimo funkcija, taciau kazko nepripazysta tos funkcijos: svarka.c:23: undefined reference to `Laikas' Kur as cia klaida darau ?
Programa dabar atrodo taip:
#include
while (1)
void Laikas (void);
int main (void)
{
DDRB = 252;
DDRD = (0<
{
if (2)
{
while (bit_is_set(PIND,0));
}
else
{
return 1 ;
}
PORTB=4;
Laikas(); //cia nepripazysta sio nurodymo
PORTB=8;
PORTB=16;
PORTB=32;
PORTB=64;
PORTB=128;
PORTB=0;
PIND=1;
void Laikas (void)
{
long i=0;
for(i=0;i<10;i++);
}
}
return 1;
}
bent pavyzdyje matau kad po Laikas yra tarpas pries skliausteli. Tarpo neturi buti.
Imesk kokia klaida gauni, gal daugiau padesiu.
kitokiu klaidu nera, nepriklausomai, void Laikas(void) ar void Laikas (void) su tarpu patasyta, isskyrus ta 23 klaida prie Laikas()
#include
void Laikas (void); <- o cia yra tarpas? Turetu nebuti.
int main (void)
Ar darau tarpa, ar nedarau - tas pats velnias- klaida meta linkinant, o ir simuliatoriuje velinimas neveikia
Na velinimas kodel neveikia tai daug maz zinau kodel. Patarciau paskaityti straipsni apie C programavima kaip tik mano puslapyje. O jeigu trumpiau, tai kompiliatirius ta tuscia cikla suoptimizuoja nes jame niekas nevyksta. Todel cikle patariu ideti bent assemblerio "nop" komanda.
Va cia sutvarkyta. Buvai praleides pora skliaustu, del ko main funkcija nebuvo apgaubta skliaustais, tai kompiliatorius buvo durninamas
Programavimo etikos reiketu prisilaikyti, kad programa butu lengviau skaitoma ne tik kitiems bet ir sau paciam.
Cia as nesilaikau etikos ? Ui, as tai rankom, kojom ir dantim isikandes i ja, bet ta etikmat pasinaudoja mano patirtim ir issisuka is mano gniauztu.
Iskilo keletas klausimeliu:
1.
for(i=0;i<10;i++)
{
} ;
cia "{" ir "}" skliaustai reikalingi tam, kad funkcija "for" turetu vieta, kur jai vykdyti salyga (i=0;i<10;i++) ? Kazkaip kvailai atrodo: nurodai, ka daryti, tai dar turi nurodyti, kad po saves dar ir padarytu.
2.
Kaip suprantu, yra viena "main" programa, kurioje sukasi "while (1)", "if (2)" ir "void Laikas (void)". Ir mano beda buvo ta, kad nukopijavus nuo "mirksinciu diodu" is elektronikos.lt programele, kuri atrode lyg taip, kad buvo dvi lygiagrecios programos: "void main()" ir "void Laikas()". Cia "void Laikas()" nepakliuvo i "void main()" skliaustu galia:
1. Tie skliaustai reikalingi apgaubti sakiniu grupe kurie sukasi cikle. jeigu sakiniu nera, tai tu skliaustu berods galima ir nerasyti. Bet kaip sakau, geriausia laikytis bendros tvarkos.
2. main ir Laikas yra atskiros funkcijos. main taita funkcija, kuri vykdoma po reset. O Laikas() yra aprasoma atskirai ir gali buti iskvieciama pagrindines main funkcijos arba kitos funkcijos. Taipkad atskiras funkcija reikia aprasineti uz main funkcijos ribu.
O kaip isskaiciuot, koks laikas gaunasi tarp portu persijungimo, jei teorinis vidinio generatoriaus daznis apie 8 MHz ? Programos didumas kaip nors itakoja tam "Laikas()" vykdymui ar ne ?
Hmm. Tiksliam laikui gauti geriausia naudoti gatavas bibliotekas arba valdyti taimeri. Nes paprastai parasius cikla, laiko vykdymas priklauso nuo kompiliatoriaus geranoriskumo, t.y. optimizavimo, ir kitu niuansu. Yra delay.h biblioteka kuria gali naudotis tiksliam laikui nurodyti.
Tai cia reikia kazka kurti su "_delay_loop_" ? Cia reikia suprast, kad kazkoks laiko tarpelis bus grieztai priristas kazkokiu santykiu procesoriaus dazniui, nepriklausomai nuo programos storumo, kompiliatoriaus nuotaikos ar isoriniu kintamuju isikisimo i programa darbo metu ?
Dar vienas cirkas is "delay.h":
Tai reiskia, kad jei mano naudojamas procesorius yra 8 MHz daznio, tai maksimalia dalyba arba maziausia laika gausiu 262.14 / 8 = 32,7675 ms ? Cia reikia suprast, kad gaunu impulseli apytiksliai kas 32.8 ms ?
Ar as klystu ?
Taip. WinAvr standartinese bibliotekose berods neratokiu funkciju, kur galetum nurodyti kiek nori laiko uzlaikyma. Jeigu reikia pavyzdziui kokios 1 sekundes ar daugiau, tai reikia kombinuoti tuos mazus velinimus, arba paciam rasytis bibliotekele, kurioje valdant taimerius pasidarai kiek nori velinima. CodeVision kiek pamenu, buvo galima nurodyti kiek nori ms.
Vach, vach, kokia nelaime :cry:
Paprastesnio kelio nera ?
Man siaip reikalinga 3.33333 ms, o cia pasiule maziausiai 32.7 ms. Kad juos kur ...
Kadangi zalio supratimo neturiu del biblioteku perdarymo, tai net nezinau, kaip dabar pasielgt.
Pala, kazko dar neisikirtau:
Cia gi 768 mikrosekundziu ? Tai butu lygu 0.768 milisekundes. Vat tai velnias: ziuriu i datasheta, o matau tik s...
Na tai dek _delay_us (double __us) komandas i koki cikla. Aisku tikslumas gal kazkiek ir nukentes. Siaip protingiausia tada rasytis paciam arba modifikuoti. Jeigu nori gali net su ASM pasirasyti. Yra kazkur kodo generatorius, kur irasai kiek reikia uzvelinimo ir jis sugeneruoja asm koda.
Tas bibliotekeles pasirasymas galimas paprasciausias "delay.h" failiuko redagavimas su kokia nors programa (pvz.: Programmers Notepad), po redagavimo issaugojant tame paciame formate .h ? Nejaugi taip paprasta redaguoti, isskyrus tai, ka reikia kurioj vietoj ir ka irasyti ?
Ar tikrai pakanka tokio redagavimo su salyga, kad pavyks pakeisti ka reikia ir kur reikia ? 
Tai aisku pakanka. Tuom atviro kodo sistemos ir zavi, kad gali redaguotis kaip nori. Va koki Codevision, ar IAR tianelabai paredaguosi, nes ten jau yra sukompiliuotos bibliotekos.
Na, pradziai pakeiciau gabaliuka programos, ikisdamas ta delay:
Teoriskai turetu dirbti stabiliau, nei ankstesneje programoje ? Ar ka nusigrybavau ? Siaip ant simuliatoriaus tai veikia...
Jeigu tikslumas tenkina tai ir gerai. kazka mandriau su tuom ir neisspausi. O del tikslesnio rezultato manau reiktu su taimeriais zaisti it tt.
Viskas pasimatys derinimo metu, kada reiks programa pririst prie gaminio. Tikiuosi, kad mano lukesciai pasitvirtins
Dabar vyksta tik teoriniai pasapaliojimai, kad nenusigybaut i pievas: viso darbo pabaigoje labai nemalonu butu suprasti, kad is principo nesigaus to, ko noriu.
Keista, pasirodo, visiskai nereikia nurodyti iejimo/isejimo krypties. Cia turima omenyje DDRD (PD6, tipo 11 kojos) nustatyma. Ar su DDRD=(0 Tai cia nereikia nurodyti, kad tai bus kaip iejimas ? :
Vo, blyn, net ir DDRB = 252 nurodyt nereika, kad cia bus sesi isejimai
.
O tai kaip butu gudriausia padaryti, kad is eiles persijunginedami isejimai dar spetu keleta tukstanciu kartu sumirkseti ? Cia turima omenyje, aktyvuodamiesi isejimai vienas nuo kito, pvz kas 3333us, dar sugebetu tik aktyvus isejimas sumirkseti kas pvz. 10us pulsiukais ir 20us pauze tarp pulsiuku ?
Tai kad pas taves blogai parasyta. Kaip tau nebus visada iejime vienas. jeigu tu pirma irasai PIND64 o paskui tikrini ar PIND=64. PIrmiausia Reikia parasyti PORTD=64; Nes ta komanda enablina vidini pullUp rezistoriu.
Ir ar nepaprasciau skaityti tokia struktura. Dabar kol sugaudai kur cia baigias kur prasideda sakinys.
{ DDRB = 252; DDRD = (0<
while (1)
{
PORTD=64; //cia turi buti portd=64!!
if (2)
{
while (bit_is_set(PIND,6));
}
else
{
return 1 ;
}
PORTB=4;
Laikas();
PORTB=8;
Laikas();
PORTB=16;
Laikas();
PORTB=32;
Laikas();
PORTB=64;
Laikas();
PORTB=128;
Laikas();
PORTB=0;
}
}
Ui, tas PIND=64 man reikalingas tam, kad ijungus maitinima, ciklas is kart sustotu ir lauktu, kada as padarysiu isorini paleidima, t.y. ant 11 kojos (PD6) paduosiu zema lygi. O po to ir darbo eigoje turi laukti, kol atleliaus tas zemo lygio impulselis ir tik tada prasisukti ciklas. Viskas sitai veikia praktiskai ant valdiklio, tik laikus padidinus, kad matyciau, kaip sviesdiodziai mirksi. Beje, irasiau PORTD=64 ir supratau, kas pasidare
.
. Gal as cia klaidingai nurodau, kad D porto PD6 (11 koja) man bus kaip iejimas ?
O sita
DDRD = (0<
ismetu visai, likusia programos dali nusiunciu i valdikli - ir tas iejimas dirba kaip niekur nieko. Vat tas man ir keisciausia
Na dabar nesigincysiu, bet portai po resetu visi pasidaro kaip iejimai kiek zinau. Taip kad tas nustatymas DDRD = (0<
jeigu nustatysi DDRD = (1<
Aha, pagal default'-a reik suprast kad visi iejimai. Na jo, yra logikos...
Skelbti naują komentarą