Bandau programint ATTINY2313

Bandau programint ATTINY2313

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 Laughing out loud
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< //(cia, tipo, suteikiam 0 ir turim turet iejima)

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;
}


Komentarų rodymo nustatymai

Pasirinkite patinkantį komentarų vaizdavimo būdą ir paspauskite "Išsaugoti nustatymus", kad pakeitimas įsigaliotų.

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. Eye-wink

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
void Laikas (void);
int main (void)
{
DDRB = 252;
DDRD = (0< while (1)
{
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.

Quote:
#include
void Laikas (void);
int main (void)
{
DDRB = 252;
DDRD = (0< while (1)
{
if (2)
{
while (bit_is_set(PIND,0));
}
else
{
return 1 ;
}
PORTB=4;
Laikas(); //cia nepripazysta sio nurodymo:" svarka.c:23: undefined reference to `Laikas' "
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;
}

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 Evil

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 Smiling

#include  
#include "avr/iotn2313.h"
void Laikas (void); 
int main (void) 
{ 
DDRB = 252; 
DDRD = (0<

Programavimo etikos reiketu prisilaikyti, kad programa butu lengviau skaitoma ne tik kitiems bet ir sau paciam.

Alfreds wrote:
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:

Quote:
#include "io2313.h"

void Laikas();

void main() // Prasideda pagrindinė procedūra
{

// Tai yra registras nustatntis duomenų kryptį
// tai reikalinga diodams įjungti,
// 255 atitinka dvejetainį 1111 1111.
DDRB = 255;

// Am˛iną ciklą naudosim diodų junginėjimui
while(1){

// Įjungiami visi diodai
PORTB=255;

// Kreipiamės į vėlinimo funkciją
// u˛laikome įjungtus šviesos diodus
Laikas();

// išjungiame visus šviesos diodus
PORTB=0;

// Kreipiamės į vėlinimo funkciją
// u˛laikome išjungtus šviesos diodus
Laikas();

}

} ----- sitoj vietoj kaip ir uzsidare pagrindine procedura, o toliau void Laikas() liko "ant ledo" ?

void Laikas() // vėlinimo funkcijos prad˛ia
{
// Tuščio ciklo vykdymas 100 000 kartų
long i=0; for (i=0; i<100000; i++){}

}

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 ?

sauliucka wrote:
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 ?

Quote:
Delay loop using an 8-bit counter \c __count, so up to 256
iterations are possible. (The value 256 would have to be passed
as 0.) The loop executes three CPU cycles per iteration, not
including the overhead the compiler needs to setup the counter
register.

Thus, at a CPU speed of 1 MHz, delays of up to 768 microseconds
can be achieved.
*/
void
_delay_loop_1(uint8_t __count)

Dar vienas cirkas is "delay.h":

Quote:
\ingroup util_delay

Perform a delay of \c __ms milliseconds, using _delay_loop_2().

The macro F_CPU is supposed to be defined to a
constant defining the CPU clock frequency (in Hertz).

The maximal possible delay is 262.14 ms / F_CPU in MHz.

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:
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. Puzzled Paprastesnio kelio nera ?

Pala, kazko dar neisikirtau:

Quote:
5.22.2.4 void _delay_us (double __us)
Perform a delay of __us microseconds, using _delay_loop_1().
The macro F_CPU is supposed to be defined to a constant defining the CPU clock
frequency (in Hertz).
The maximal possible delay is 768 us / F_CPU in MHz.

Cia gi 768 mikrosekundziu ? Tai butu lygu 0.768 milisekundes. Vat tai velnias: ziuriu i datasheta, o matau tik s... Laughing out loud

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 ? Laughing out loud Ar tikrai pakanka tokio redagavimo su salyga, kad pavyks pakeisti ka reikia ir kur reikia ? Puzzled

sauliucka wrote:
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 ? Laughing out loud Ar tikrai pakanka tokio redagavimo su salyga, kad pavyks pakeisti ka reikia ir kur reikia ? Puzzled

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:

Quote:
void Laikas(void)
{
counter = 0;
while(counter != 35) //jei tiksliau, tai reikejo 34.72 daliklio, bet patrauks
{
_delay_us(1); //turetu buti 768us / 8 MHz = 96 us = 0.096 ms
counter++;
}
{
} ;
//return 1;
}

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 Laughing out loud 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 ? :

Quote:
{
DDRB = 252;
DDRD = (0< while (1)
{
PIND=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;
}

Vo, blyn, net ir DDRB = 252 nurodyt nereika, kad cia bus sesi isejimai Puzzled .
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 Laughing out loud .
O sita
DDRD = (0<
ismetu visai, likusia programos dali nusiunciu i valdikli - ir tas iejimas dirba kaip niekur nieko. Vat tas man ir keisciausia Puzzled . Gal as cia klaidingai nurodau, kad D porto PD6 (11 koja) man bus kaip iejimas ?

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ą

Šio laukelio turinys bus laikomas privatus ir nerodomas viešai.
CAPTCHA
Apsauga nuo spamo. Įveskite žemiau esantį kodą.
Image CAPTCHA
Copy the characters (respecting upper/lower case) from the image.