|
www.elektronik.si Forum o elektrotehniki in računalništvu
|
Poglej prejšnjo temo :: Poglej naslednjo temo |
Avtor |
Sporočilo |
chaos Član
Pridružen-a: Sob 16 Sep 2006 22:12 Prispevkov: 1063 Aktiv.: 4.96 Kraj: Zagorje ob Savi
|
Objavljeno: Ned Feb 21, 2010 6:01 pm Naslov sporočila: |
|
|
sortaj je napisal/a: |
Koda: |
for(int i = 128; i >1; i -= i/2)
|
|
Če sem prav razbral, je problem v tej vrstici. Poskusi tako:
Koda: |
for(int i = 128; i >=1; i -= i/2)
|
LP! |
|
Nazaj na vrh |
|
|
Samo87 Član
Pridružen-a: Pet 25 Jan 2008 2:14 Prispevkov: 462 Aktiv.: 2.34 Kraj: Kamnik
|
Objavljeno: Ned Feb 21, 2010 8:54 pm Naslov sporočila: |
|
|
Naredil sem kodno ključavnico, ki sicer pravilnio deluje, vendar sem eno stvar programsko zelo nerodno rešil. Vrednosti tipk shranjujem v char geslo[], in ko se vpiše prava koda (štirje pravilni znaki), se na LCD izpiše "ODKLENJENO", v nasprotnem primeru pa "ZAKLENJENO". Problem je, da ne znam v enem if stavku pravilno postavit pogoja, da bi se celotni znakovni niz primerjal, ampak znam primerjati le posamezno spremenljivko v nizu.
Tako imam za primer pravilne kode "1234" napisano kodo:
Koda: |
if (geslo[0]=='1')
{
if (geslo[1]=='2')
{
if (geslo[2]=='3')
{
if (geslo[3]=='4')
{
lcd_gotoxy(0,0);
LCDputs("ODKLENJENO");
}
else
{
lcd_gotoxy(0,0);
LCDputs("ZAKLENJENO");
}
}
else
{
lcd_gotoxy(0,0);
LCDputs("ZAKLENJENO");
}
}
else
{
lcd_gotoxy(0,0);
LCDputs("ZAKLENJENO");
}
}
else
{
lcd_gotoxy(0,0);
LCDputs("ZAKLENJENO");
}
|
Kako bi to izvedel v enem if stavku?
Hvala! |
|
Nazaj na vrh |
|
|
silvo_v Član
Pridružen-a: Pon 11 Jul 2005 22:00 Prispevkov: 146 Aktiv.: 0.66 Kraj: Domžale
|
Objavljeno: Ned Feb 21, 2010 9:14 pm Naslov sporočila: |
|
|
Mogoče takole:
Koda: |
if (geslo[0]=='1' && geslo[1]=='2' && geslo[2]=='3' && geslo[3]=='4')
{ ... |
Lp |
|
Nazaj na vrh |
|
|
Samo87 Član
Pridružen-a: Pet 25 Jan 2008 2:14 Prispevkov: 462 Aktiv.: 2.34 Kraj: Kamnik
|
Objavljeno: Ned Feb 21, 2010 9:41 pm Naslov sporočila: |
|
|
Sem prepričan, da sem točno takole tudi že preizkusil, pa takrat ni delovalo... No, sedaj sem še enkrat tako poizkusil, pa začuda deluje! Izgleda, da sem prejšnjič pozabil enojne narekovaje, ali pa kaj drugega...
Hvala Silvo!
No, pa vseeno me zanima, če se da tudi cel niz primerjat? Nekaj v tem stilu if(geslo[]=="1234")? |
|
Nazaj na vrh |
|
|
chaos Član
Pridružen-a: Sob 16 Sep 2006 22:12 Prispevkov: 1063 Aktiv.: 4.96 Kraj: Zagorje ob Savi
|
Objavljeno: Pon Feb 22, 2010 4:51 am Naslov sporočila: |
|
|
strcmp.
LP! |
|
Nazaj na vrh |
|
|
gumby Član
Pridružen-a: Sob 28 Apr 2007 12:32 Prispevkov: 4066 Aktiv.: 19.67
|
Objavljeno: Pon Feb 22, 2010 8:03 am Naslov sporočila: |
|
|
Za strcmp() ne pozabi dodat na koncu niza še znak '\0'. Niz mora bit dolg vsaj 5 znakov, torej "char geslo[5];".
Sicer pa geslo lahko že pri branju pretvoriš v integer (ali BCD) in se na ta način izogneš uporabi char[]. _________________ Tule nisem več aktiven. |
|
Nazaj na vrh |
|
|
Samo87 Član
Pridružen-a: Pet 25 Jan 2008 2:14 Prispevkov: 462 Aktiv.: 2.34 Kraj: Kamnik
|
Objavljeno: Pon Feb 22, 2010 8:19 pm Naslov sporočila: |
|
|
Eto, sem naredil s strcmp(). Hvala! |
|
Nazaj na vrh |
|
|
Samo87 Član
Pridružen-a: Pet 25 Jan 2008 2:14 Prispevkov: 462 Aktiv.: 2.34 Kraj: Kamnik
|
Objavljeno: Sob Mar 13, 2010 7:18 pm Naslov sporočila: |
|
|
Živ! Imam vprašanje. Na EasyAVR5 imam Atmega16, uporabljen je zunanji kristal 10.240 MHz in sprogramiral sem uro z alarmom. Vse deluje kot mora, le natančnost je zelo slaba. V enem dnevu prehiti za približno 16 sekund!! Zdaj pa me zanima, kaj bi bil lahko vzrok za tako veliko napako. Ali je možno, da je kristal tako nenatančen? V programu mi timer2 skrbi samo za sekundni interval:
Koda: |
ISR(TIMER2_OVF_vect)
{
TCNT2 = 6;
overflow_counter_sec++; //na vsake 0.025s se poveča
if(overflow_counter_sec==40) //40 * 0.025s = 1s
{
overflow_counter_sec=0; //reset števca
sec++; //povečanje sekund
if(sec==60) {sec=0; min++; if(min==60) {min=0; hour++; if(hour==24) hour=0;}}
}
}
|
Preescaler je 1024, torej bi po moje moralo vse štimat. Imate kak nasvet? |
|
Nazaj na vrh |
|
|
gumby Član
Pridružen-a: Sob 28 Apr 2007 12:32 Prispevkov: 4066 Aktiv.: 19.67
|
Objavljeno: Sob Mar 13, 2010 8:37 pm Naslov sporočila: |
|
|
Navadni kristali imajo točnost nekje 50ppm, kar na dan znese nekaj čez 4 sekunde. 16 sekund na dan je pa 185ppm - dvomim, da je kristal tako netočen.
Poglej v sumulatorju, na koliko ciklov se ti sproži prekinitv in potem preračunaj... _________________ Tule nisem več aktiven. |
|
Nazaj na vrh |
|
|
int47 Član
Pridružen-a: Pon 15 Dec 2003 0:10 Prispevkov: 2066 Aktiv.: 9.28 Kraj: Ljubljana
|
Objavljeno: Sob Mar 13, 2010 8:47 pm Naslov sporočila: |
|
|
Problem je čas od postavitve prekinitvene zastavice timerja, do (programskega) vpisa nove vrednosti v timer2.
Min. potreben čas lahko oceniš in popraviš program. Vendar na odzivni čas vpliva tudi program, ki ga uC izvaja.
Bolje bi bilo, če bi vpis nove vrednosti v timer izvedel hardver (CTC). |
|
Nazaj na vrh |
|
|
Samo87 Član
Pridružen-a: Pet 25 Jan 2008 2:14 Prispevkov: 462 Aktiv.: 2.34 Kraj: Kamnik
|
Objavljeno: Ned Mar 14, 2010 1:52 pm Naslov sporočila: |
|
|
@gumby
Torej ni kristal. Hm, simulatorja pa še nisem nikoli uporabljal. Se bom poglobil v zadevo.
@int47
Če prav razumem: Zastavica se postavi točno ob preskoku TCNT2 iz 255 na 0. Problem pa naj bi bil čas od te točke, pa dokler se v prekinitveni rutini ne vpiše začetna vrednost 6 v TCNT2?
Kako pa naj ocenim ta čas? Se ta čas tudi lahko ugotovi s simulacijo?
Ta projekt je sicer le učenje C-ja in spoznavanje AVR-jev, ampak vseeno bi rad, da stvar deluje brez napak.
int47 je napisal/a: |
Bolje bi bilo, če bi vpis nove vrednosti v timer izvedel hardver (CTC). |
Lahko predlagaš kako konkretno rešitev? |
|
Nazaj na vrh |
|
|
int47 Član
Pridružen-a: Pon 15 Dec 2003 0:10 Prispevkov: 2066 Aktiv.: 9.28 Kraj: Ljubljana
|
Objavljeno: Ned Mar 14, 2010 3:04 pm Naslov sporočila: |
|
|
Čas lahko ugotoviš s simulacijo, ali štetjem ukazov in ciklov.
Problem je, da ta čas ni nujno vedno enak:
uC mora najprej zaključiti ukaz, ki se trenutno izvaja (ne trajajo vsi ukazi enako dolgo).
Če v prekinitveni rutini nisi (ponovno) omogočil prekinitev, so le te onemogočene do zaključka prekinitvene rutine.
Če sta hkrati aktivni dve prekinitveni zastavici, se bo izvršila tista, ki ima večjo prioriteto.
CTC = način delovanja timerja: (8 bit timer/counter2 with... -> Modes of operation -> Clear timer on compare match.
Svoj del napake lahko prispeva tudi netočnost kristala. |
|
Nazaj na vrh |
|
|
Samo87 Član
Pridružen-a: Pet 25 Jan 2008 2:14 Prispevkov: 462 Aktiv.: 2.34 Kraj: Kamnik
|
Objavljeno: Ned Mar 14, 2010 5:41 pm Naslov sporočila: |
|
|
Aha. No, rad bi razčistil še nekaj stvari: Torej, program se izvaja. In ko se izpolni pogoj za prekinitev, se postavi zastavica za to prekinitev. Program potem takoj po zaključenem ukazu, ki ga je takrat izvajal, skoči v prekinitveno rutino. Takrat se ta zastavica tudi pobriše, program pa ne glede na karkoli, najprej izvede celo prekinitveno rutino in se potem vrne v glavni program, če vmes ni bila postavljena kaka zastavica. Če pa je že vmes spet izpolnjen pogoj za prekinitev (taisto, ali kako drugo), se zastavica spet postavi, torej se takoj po izvedeni prekinitvi spet izvede prekinitev (taista ali katerakoli druga). Če pride do tega, da se med prekinitvijo izpolnita pogoja za dve različni prekinitvi, se torej postavita dve zastavici. Potem pa se najprej izvede tista prekinitev, ki ima večjo prioriteto, potem pa takoj še druga. Potem se naprej izvaja glavni program. Ali je tako, kot sem napisal, ali kaj narobe razumem?
Citiram: |
Če v prekinitveni rutini nisi (ponovno) omogočil prekinitev, so le te onemogočene do zaključka prekinitvene rutine. |
Tega sedaj ne razumem čisto. Za kakšno omogočenje gre tukaj? Ali je to mišljeno tako, da se tudi sama prekinitev lahko zaustavi, če je izpolnjen pogoj za kako drugo prekinitev?
Citiram: |
Če sta hkrati aktivni dve prekinitveni zastavici, se bo izvršila tista, ki ima večjo prioriteto. |
Torej, kot sem zgoraj napisal, se po prvi prekinitvi, ki ima večjo prioriteto, izvede še druga prekinitvena rutina?
Saj vem, da mora to tudi v datasheetu pisat, ampak včasih je težko točno razumet, za kaj gre. In ko ne veš točno, kako se program izvaja, prihaja do takih napak.
Sem pa še malo gledal po forumu in sem zasledil rešitev v čipu PCF8385, kateri odpravi še težave z izpadom napajanja, saj se ti čas ohrani. |
|
Nazaj na vrh |
|
|
int47 Član
Pridružen-a: Pon 15 Dec 2003 0:10 Prispevkov: 2066 Aktiv.: 9.28 Kraj: Ljubljana
|
Objavljeno: Ned Mar 14, 2010 9:54 pm Naslov sporočila: |
|
|
Citiram: |
Ali je tako, kot sem napisal, ali kaj narobe razumem? |
Mislim, da bo kar prav.
Citiram: |
Ali je to mišljeno tako, da se tudi sama prekinitev lahko zaustavi, če je izpolnjen pogoj za kako drugo prekinitev? |
Ja. Za čas trajanja prekinitve uC globalno onemogiči prekinitve (bit I v SREG).
Če v prekinitveni rutini ponovno omogočiš prekinitve, se lahko izvrši druga prekinitev v času trajanja prve prekinitvene rutine.
Na žalost 8 bit AVR ne pozna prioritet prekinitev v stilu: Izvajanje prekinitve z nižjo prioriteto lahko prekine le prekinitev z višjo.
Citiram: |
Torej, kot sem zgoraj napisal, se po prvi prekinitvi, ki ima večjo prioriteto, izvede še druga prekinitvena rutina? |
Ja, če je ustrezna prekinitvena zastavica/bit še aktivna.
Prekinitev se bo izvedla samo 1x. uC si zapomni samo, da je bila prekinitvena zastavica postavljena, ne pa kolikokrat je bila postavljena. |
|
Nazaj na vrh |
|
|
Samo87 Član
Pridružen-a: Pet 25 Jan 2008 2:14 Prispevkov: 462 Aktiv.: 2.34 Kraj: Kamnik
|
Objavljeno: Ned Mar 14, 2010 11:21 pm Naslov sporočila: |
|
|
Hvala int47, sedaj razumem situacijo
Še nekaj mi je padlo na pamet. V tej aplikaciji trenutno 16 bitni timer1 uporabljam le za indikacijo dolžine pritiska na tipko, ker se mi je to zdelo z njim najenostavejše izvest. Če bi timer1 prevzel vlogo za "sekunde++", bi enostavno naredil eno prekinitev na sekundo, brez kakega overflow števca, ker je na razpolago 16 bitov.
Koda: |
ISR(TIMER1_OVF_vect) //kristal 10.240 MHz, preescaler 1024
{
TCNT1 = 65536 - 10000;
sec++;
}
|
V tem primeru bi bilo "tako čez prst" 40x manjša napaka, saj se je moralo s timerjem2 pravočasno izvest 40 prekinitev, da je bila ena sekunda točna, tu pa se mora le ena sama prekinitev točno izvest. Pa če še med vsemi ostalimi prekinitvami ponovno omogočim prekinitve, mislim da bom rešil zadevo.
Ko bo čas, bom izvedel tako, kot sem napisal, pa potem poročam rezultat.
LP |
|
Nazaj na vrh |
|
|
|
|
Ne, ne moreš dodajati novih tem v tem forumu Ne, ne moreš odgovarjati na teme v tem forumu Ne, ne moreš urejati svojih prispevkov v tem forumu Ne, ne moreš brisati svojih prispevkov v tem forumu Ne ne moreš glasovati v anketi v tem forumu Ne, ne moreš pripeti datotek v tem forumu Ne, ne moreš povleči datotek v tem forumu
|
Uptime: 68 dni
Powered by phpBB © 2001, 2005 phpBB Group
|