PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Zähler der immer gleich schnell zählt



Problem
10.12.2010, 14:14
HALLO

Ich laufe meiner Progermierzeit bin ich mir draufgekommen das zähler unterschiedlich schnell zählen

Es hängt ja davon ab wie lange das Programm ist oder

#include asuro.h
.........
........
........
x++
if(x>1000)
LANG++
if(x>1000)
x=0;


//Programm(die geschwindigkeit der Zählers kommt drarauf an wie lange dieser Teil hier ist)




if(LANG>500)
LANG=0;

Jetzt wollte ich fragen ob ich einen Zähler machen kann der immer gleich schnell zählt
Es müsste quasi im hintergrund immer ein Zähler laufen
Es wärr super das zu wissen.
Lg

Richard
10.12.2010, 14:38
Ein Prozessor arbeitet sein Programm immer Schritt für Schritt ab. Jeder Schritt braucht etwas Zeit also brauchen viele Schritte mehr Zeit als wenige. Was Du da gemacht hast ist auch kein echter Zähler sondern eine Programmschleife und je öfter diese durchlaufen wird je mehr Zeit wird benötigt.

Zähler für bestimmte Zeiten werden mit Timer "Gebaut" oder wenn man externe Takte zählen will mit Counter da Hilft Dir RN Wissen weiter.

Aber auch solche Timer benötigen je nachdem wie oft sie zählen müssen eine gewisse Zeit.

Gruß Richard

Hessibaby
10.12.2010, 15:09
Egal in welcher Sprache Du programmierst wird Dein Zähler immer mehr oder weniger Zeit benötigen. Selbst wenn Du den Zähler in Silizium gießt z.B. als TTL-Sarg hast Du immer noch Gatterlaufzeiten die spätestens beim Überlauf auf die nächsthöhere Stelle bemerkbar werden.
Um konstante UP-/DOWN-Countzeiten zu bekommen kannst Du nur eine Totzeit programmieren um sicher zu stellen dass der Zähler auch gezählt hat und alle Überträge gemacht hat. Allerdings gehen Dir dann u.U. Zählereignisse verloren welche während der Totzeit eingetroffen sind.
Je nachdem wie präzise und wie schnell gezählt werden muss, solltest Du eventuell auf einen DSP oder sonstigen spezifischen Counterchip setzen.

radbruch
10.12.2010, 15:51
Hallo

In der erweiterten Lib gab es mal die Funktion Gettime(). Ich gehe davon aus, dass diese Funktion auch in der aktuellen Library vorhanden ist. Sie zählt die Millisekunden seid dem Programmstart in einer 32-Bit-Longint-Variablen. Damit kann man wunderbar einfach nichtblockierende Zeitverzögerungen basteln:


#include "asuro.h"

unsigned long umschaltpunkt, blinken;
unsigned char statusled, backled;

int main(void)
{
Init();

statusled = 1; // 1 ist grün, 2 ist rot, 3 ist gelb
umschaltpunkt = Gettime() + 5000; // nach 5 Sekunden StatusLED umschalten

BackLED(ON, OFF);
backled = 0;
blinken = Gettime() + 500; // BackLEDs mit 1Hz blinken

while(1)
{
if(Gettime() > umschaltpunkt) // Umschaltzeitpunkt überschritten?
{
umschaltpunkt = Gettime() + 3000;// neuen Umschaltzeitpunkt festlegen
statusled++;
if(statusled > 3) statusled=1;
StatusLED(statusled);
}

if(Gettime() > blinken)
{
blinken = Gettime() + 500; // Blinkintervall neu laden
backled = !backled; // bisschen schummeln :)
if(backled) BackLED(OFF, ON);
else BackLED(ON, OFF);
}
if(Gettime() & (1<<7)) FrontLED(ON);// mit 7 blinkt die FrontLED mit ca. 2Hz
else FrontLED(OFF); // 0 wäre 36kHz (theoretisch)

// Ab hier ist dann Platz für weitere Funktionen

}
return(0);
}

(ungetestet)

Gruß

mic

P.S.: Warum schreibst du eigentlich nicht in der asuro-Rubrik?

Und noch ein Edit:

Um es nicht unnötig ungenau zu machen, müsste man es wohl so formulieren:

if(Gettime() > umschaltpunkt) // Umschaltzeitpunkt überschritten?
{
umschaltpunkt += 3000; // neuen Umschaltzeitpunkt festlegen

PICture
10.12.2010, 16:06
Hallo!

So wie der Hessibaby schon geschrieben hat, ist es unmöglich einen Zähler länger als 4-bit, dessen alle Ausgänge dem Eigangsimpuls immer gleich folgen, sowohl software- als auch hardwaremässig zu kriegen.

Bei 4-bit ist es nur mit s.g. Synchronzähler hardwaremässig mit z.B. 74XX161, 74XX162, 74XX163 und 74XX164 möglich.

Man könnte es mit "Lookahead curry generator" 74XX182 probieren, habe es aber selber bisher noch nie gebraucht.

MfG

Besserwessi
10.12.2010, 17:47
Es gibt schon auch 8 Bit ( z.B: 74HC590) und auch 16 Bit Syncronzähler. Die kann man auch Kaskadieren. Ich glaube aber das geht an der ursprünglichen Frage vorbei.


Für das konstante hochzählen einer Zahl haben fast alle µCs Timer hardware dirn. Da wird ein Zähler mit 8, 16 oder ggf. auch 32 Bit Länge unabhängig von der eigentlichen CPU kontinuierlich hochgezählt.
Bei Asuro hat man 2 Timer mit 8 Bit und einen mit 16 Bit. Die Frequenz zum hochzählen kann man per Vorteiler auswählen, z.B. als µC takt / 1024 oder Takt / 8. Wenn einem die 16 Bit nicht reichen kann man das per Interrupt erweitern auf 32 Bit oder auch mehr wenn man Geduld hat. Im Wissens Bereich unter Timer steht einiges dazu.

PICture
10.12.2010, 18:02
Laut Datenblatt ist der 74HC590 kein Synchronzähler, da die Takteingänge der Flip-Flops intern nicht paralell miteinander geschaltet sind ... :(

MfG

Richard
10.12.2010, 18:35
Ich vermute jetzt einfach einmal das der Ursprungs Poster sich nur etwas ungenau ausgedrückt hat und eigentlich etwas anderes fragen wollte? Das man schlecht in gleicher Zeit bis 5 oder bis 500 zählen kann weiß jeder der schon einmal irgend etwas mit Hilfe seiner grauen Masse gezählt hat. Ich jedenfalls brauch um bis 5 (geht gerade noch), weitaus weniger Zeit als wenn ich is 500 zählen sollte. :-)

Gruß Richard

Problem
10.12.2010, 18:39
Hallo


P.S.: Warum schreibst du eigentlich nicht in der asuro-Rubrik?


[/code]

Weil ich das heute in der schule fast neben lehrer gemacht habe und irgendwie auf asuro geklickt habe aber dann waren die Themen hier

Lg

Problem
12.12.2010, 12:08
Habe da ein Problem meine Variable ist mit unsigned int z=0; deklariert

Das heißt es müsste eigentlich von 0 - 65535 zählen.

Aber.......

Hier ist mein Code

#include <stdbool.h>
#include <stdio.h>
#include <asuro.h>
int main(void)
{
Init();
char zC[2];
unsigned char umschaltpunkt = 0;
int t = 0;
unsigned int z=0;
/************************************************** *****************************************/
while( 1 )
{
if(Gettime() > umschaltpunkt) // Umschaltzeitpunkt überschritten?
{
umschaltpunkt += 10000; // neuen Umschaltzeitpunkt festlegen
z++;
}

if (umschaltpunkt > 10000)
umschaltpunkt = 0;

if (PollSwitch() == 1)
z=0;


if (PollSwitch() == 2)
z = 90;

if (PollSwitch() == 4)
z = 32750;

if (PollSwitch() == 32)
z = 990;

/************************************************** ********************/
sprintf(zC, "%d", z); //Übertragen
SerWrite(zC, 6); //Übertragen
SerWrite (" zC\n\r", 5); //Übertragen
for
(t=0; t< 40; t++) //Übertragen
{ //Übertragen
Sleep (72); //Übertragen
} //Übertragen
/************************************************** *********************/



}
return 0;
}


Hier ist die ausgabe von Hyper T.

22760 zC
32761 zC
32762 zC
32763 zC
32764 zC
32765 zC
32766 zC
32767 zC
-32768 zC
-32767 zC
-32766 zC
-32765 zC
-32764 zC
-32763 zC

Hat da jemand eienn Idee wieso er nicht bis 65... zählt

habe "z" auch schon mit int deklariert aber da ist es zählt er auch so


Lg

Besserwessi
12.12.2010, 13:20
Das Problem wird bei sprintf liegen das "%d" steht für integer Zahlen - da müsste ein "%u" hin. Die Routine sollte man schon aus Gründen der Rechenzeit und des Speichers wenn möglich vermeiden. Besser nimmt man hier utoa().

Problem
12.12.2010, 19:28
Achso

Habs vorher mit itoa probiert aber das ist nie gegangen da war die Variable immer 0


Heißt das wenn ich es mit utoa mache das ich dann das Problem mit

int und unsigned int nicht mehr habe


Mein Beitrag

Habe da ein Problem meine Variable ist mit unsigned int z=0; deklariert

Das heißt es müsste eigentlich von 0 - 65535 zählen.

Aber er zählt ab 32 000 wieder runter

Hier ist mein Code

Problem
12.12.2010, 19:28
UPS Kann mal passieren

Problem
12.12.2010, 19:39
Habs jetzt mit utoa geschaft aber da habe ich noch ein Problem:

Der Code


#include "asuro.h"
#include "stdlib.h"

int main(void)
{
unsigned int LANG = 0;
char aC[2];
int t=0,a=0;
Init();



StatusLED (GREEN);



while (1)
{
a=a+2;
if (a > 20)
LANG++; //Verzögerung des Zählers
if (a > 20)
a=0;

utoa (LANG, aC, 5); //Umwandeln von int auf char
SerWrite (aC, 2); //Übertragen ins Hyper Terminal
SerWrite ("=VAR\n\r", 6);
for (t=0; t< 40; t++) //Kurze Pause beim Übertragen
{Sleep (72);}


if ((LANG > 0) && (LANG < 5))
{BackLED(OFF,OFF);
StatusLED(RED);}
if ((LANG > 5) && (LANG < 10))
{BackLED(ON,ON);
StatusLED(GREEN);}

if (LANG > 9)
LANG = 0;

}

return 0;
}


Wenn ich utoa mit diesem Teil ersetzte

sprintf(aC, "%d", LANG);
SerWrite(aC, 2);
SerWrite (" aC\n\r", 5);

funktioniert alles.
Wenn ich utoa nehme nicht


Das sehe ich im Hyper Terminal


3=VAR
3=VAR
4=VAR
4=VAR
4=VAR
4=VAR
4=VAR
4=VAR
4=VAR
4=VAR
4=VAR
4=VAR
4=VAR //Wieso?
10=VAR //Wieso von 4 auf 10
10=VAR


keine Ahnung wieso er von 4 auf 10 springt

Lg

Problem
12.12.2010, 19:51
Hier habe mal beides gemacht

Code



#include "asuro.h"
#include "stdlib.h"

int main(void)
{
unsigned int LANG = 0;
char aC[2];
int t=0,a=0;
Init();

StatusLED (GREEN);

while (1)
{
a=a+2;
if (a > 20)
LANG++; //Verzögerung des Zählers
if (a > 20)
a=0;

sprintf(aC, "%d", LANG);
SerWrite(aC, 2);
SerWrite (" aC\n\r", 5);


utoa (LANG, aC, 5); //Umwandeln von int auf char
SerWrite (aC, 2); //Übertragen ins Hyper Terminal
SerWrite ("=VAR\n\r", 6);
for (t=0; t< 130; t++) //Kurze Pause beim Übertragen
{Sleep (72);}


if ((LANG > 0) && (LANG < 5))
{BackLED(OFF,OFF);
StatusLED(RED);}
if ((LANG > 5) && (LANG < 10))
{BackLED(ON,ON);
StatusLED(GREEN);}

if (LANG > 9)
LANG = 0;

}

return 0;
}


Hier Hyper Terminal



4 aC
4=VAR
4 aC
4=VAR
4 aC
4=VAR
5 aC
10=VAR
5 aC
10=VAR
5 aC
10=VAR
5 aC
10=VAR
5 aC
10=VAR
5 aC
10=VAR

Mir wärs auch lieber wenns mit utoa funktioniert weil da ist viel weniger zum flashen

Lg

Besserwessi
12.12.2010, 20:05
Der letzte Parameter bei utoa() sollte in der Regel eine 10 sein. Wenn da eine 5 steht, wird das 5er System benutzt, und da bedeuten dann "10" halt fünf.

Wie es so schön heißt: Beim Binärsystem gibt es 10 Möglichkeiten, man versteht es, oder halt nicht.

Problem
12.12.2010, 20:10
Wow danke ihr seid die besten

Ich werde jetzt mal das mit dem Timer testen ob er jetzt bin 65000 zählt

Lg

Problem
12.12.2010, 20:26
Ganz zufrieden bin ich noch nicht

Hier mein Programm

#include <stdbool.h>
#include <stdio.h>
#include <asuro.h>
int main(void)
{
Init();
char zC[2];
unsigned char umschaltpunkt;
int t = 0;
unsigned int z = 0;
/************************************************** *****************************************/
while( 1 )
{
if(Gettime() > umschaltpunkt) // Umschaltzeitpunkt überschritten?
{
umschaltpunkt += 1000; // neuen Umschaltzeitpunkt festlegen
z++;
}

if (PollSwitch() == 1)
z=80;

if (PollSwitch() == 2)
z=65500;

if (PollSwitch() == 4)
z=32740;

if (PollSwitch() == 16)
z=0;

/************************************************** ********************/
//sprintf(zC, "%d", z); //Übertragen
utoa (z, zC, 10);

SerWrite(zC, 5); //Übertragen
SerWrite (" zC\n\r", 6); //Übertragen
for (t=0; t< 40; t++) //Übertragen
{ //Übertragen
Sleep (72); //Übertragen
} //Übertragen
/************************************************** *********************/




if (z > 200)
z=0;
}
return 0;
}


/* sprintf(aC, "%d", LANG);
SerWrite(aC, 2);
SerWrite (" aC\n\r", 5);




utoa (LANG, aC, 10); sprintf(aC, "%d", LANG);
SerWrite (aC, 2);

SerWrite ("=VAR\n\r", 6);


for (t=0; t< 130; t++)
{Sleep (72);}*/

Er zählt irgendwie so eigenartig wenn ich irgend einen Taster drück



32740 zC
32740 zC
32740 zC //if (PollSwitch() == 2) habe ich gedrückt
1740 zC // wieso zählt er nicht weiter bis auf 65635?
2740 zC
3740 zC
4740 zC
5740 zC
6740 zC


Lg

Besserwessi
12.12.2010, 21:01
if (z > 200) z=0; könnte die Sache etwas durcheinander bringen.
Außerdem ist da wohl noch ein Problem mit dem Puffer oder serwrite(), da bleiben irgendwie noch die 740 drin stehen.

Problem
13.12.2010, 19:40
Hallo

Ok das mit den 200 ist klar danke (blöde frage von mir eigentlich)


Meinst du das

SerWrite(zC, 5); Aber da können 5 stellen übertragen werden

65000 sind genau 5

Werde das morgen testen muss noch lernen!!
Leider


Lg

Besserwessi
13.12.2010, 20:06
Bei utoa ist der String wie sonst bei C üblich mit einer "o" als Ende markiert. Die Routine SerWirte() scheint immer stur 5 zeichen zu schreiben. Da kommt dann eine Mischung mit dem alten Pufferinhalt raus. Die oben gezeigte 1740 sind wohl eine 1 , dann das Trennzeichen (ASCII code 0 -> wird nicht gezeigt) und dann 740 als Rest aus dem Puffer (von 32740).

Problem
13.12.2010, 20:32
Ok

Das heißt er zählt richtig und wenn er von 4 auf 1 Stelle springt sind die letzten 3 einfach wegzudenken

Oder

Problem
13.12.2010, 20:44
Habe jetzt nochmal zusammengefasst (Weil etwas funktioniert)

Hier mein Code


#include <stdbool.h>
#include <stdio.h>
#include <asuro.h>
int main(void)
{
Init();
char zC[2];
unsigned char umschaltpunkt;
int t = 0,z = 0;
/************************************************** *****************************************/
while( 1 )
{
if(Gettime() > umschaltpunkt) // Umschaltzeitpunkt überschritten?
{
umschaltpunkt += 1000; // neuen Umschaltzeitpunkt festlegen
z++;
}

if (PollSwitch() == 1)
z=80;

if (PollSwitch() == 2)
z=65500;

if (PollSwitch() == 4)
z=32740;

if (PollSwitch() == 16)
z=0;

/************************************************** ********************/
//sprintf(zC, "%d", z); //Übertragen
utoa (z, zC, 10);

SerWrite(zC, 5); //Übertragen
SerWrite (" zC\n\r", 6); //Übertragen
for (t=0; t< 40; t++) //Übertragen
{ //Übertragen
Sleep (72); //Übertragen
} //Übertragen
/************************************************** *********************/




if (z > 200)
z=0;
}
return 0;
}


Hier HT ausgabe

65528 zC
65529 zC
65530 zC
65531 zC
65532 zC
65533 zC
65534 zC
65535 zC //So stimmt es Da ich oben z mit int deklarieert habe
0535 zC
1535 zC
2535 zC
3535 zC
4535 zC
5535 zC
6535 zC


Wenn ich z mit unsigned int deklariere:

Init();
char zC[2];
unsigned char umschaltpunkt;
int t = 0;
unsigned int z = 0;




10 zC
11 zC
12 zC
13 zC
14 zC
15 zC //Taster gedrückt
30000 zC // fangt er immer wieder bei null an
1000 zC
2000 zC
3000 zC
4000 zC
5000 zC
6000 zC
7000 zC
8000 zC
9000 zC
1000 zC
1100 zC


Wieso?

Besserwessi
13.12.2010, 21:59
Das Problem ist immer noch die Ausgabe aus dem Puffer. Genau wie vermutet kommt das Problem, wenn die Zahl der Ziffern abnimmt.
Die komischen Kästchen sind ein schönes Beispiel dazu.

Problem
14.12.2010, 13:23
Das oben genannte Programm stimmt eigentlich nicht


Weil:
int t = 0,z = 0; (z müsste eigentlich bis 32768 zählen)

es zählt aber bis 65535

Wieso

Keine Ahnung bitte helft mir wenn ihr eine Idee habt

Lg

Besserwessi
14.12.2010, 15:19
Für die Addition, Subtraktion und halt auch das z++ macht es keinen Unterschied ob die variable als int oder uint deklariert ist. Da wird einfach der selbe ASM-code erzeugt. Der Unterschied kommt nur dadurch wie die Zahlen ab 32768 interpretiert werden. Das selbe Bitmuster kann z.B. als 32768 (uint16) oder -32768 (int) interpretiert werden.

Was ausgegeben wird wird entsprechend festgelegt durch den Formatstring beim printf oder halt die Wahl ob man utoa oder itoa nimmt. Eine strenge Prüfung ob das zur Variablendeklaration passt findet nicht statt. Eine Warnung wäre schön - kommt aber wohl nicht.

Problem
14.12.2010, 15:32
doch

Diese 3

test.c:35: warning: pointer targets in passing argument 1 of 'SerWrite' differ in signedness
test.c:36: warning: pointer targets in passing argument 1 of 'SerWrite' differ in signedness
test.c:8: warning: 'umschaltpunkt' may be used uninitialized in this function


Lg

Besserwessi
14.12.2010, 16:28
Die Warnungen verstehe ich nicht ganz. Die haben auch nichts mit der Umwandlung zu tun, sondern erst mit der Ausgabe und der Funktion SerWrite(), wohl aus "Asuro.h".

Die Hoffnung wäre eventuell eine solche Warnung zu bekommen wenn man utoa() mit einer Integer Variable aufruft.

Da ist noch ein Problem: zC ist mit als 2 Zeichen langer Puffer definiert - der sollten wenigstens 7 Zeichen lang sein ( für "-12345" und eine 0 als Abschluss).

Problem
14.12.2010, 21:17
Hallo

Ich habe es jetzt auf 7 geändert und habe das gleiche Ergebniss