Hallo!
Ich möchte gerne eine Uhr programmieren. Dazu habe ich mir im Forum die
Routine von Peter Dannegger angeschaut. Ich nutze einen Atmega8535 und
das Programmierboard STK500. Ich habe diesen externen Quarz noch nicht,
sondern nutze den internen vom STK500 8Mhz. Kann ich das auch mit diesem
Programm machen? Ich will es ja erstmal testen! Die Entprellroutine von
Peter Dannegger nutze ich schon und die funktioniert auch sehr gut. Die
Uhr läuft aber auch mit dem Timer. Funktioniert das denn? Wenn ich zum
Beispiel einen Taster drücke und eine LED damit an und aus schalte, soll
sich ja an der Uhrzeit nichts ändern. Wie realisiere ich das? Später,
wenn ich die Uhr hinbekommen habe möchte ich eine Zeit als String vom PC
auf dem uC senden. Die Zeit soll dann mit der Uhrzeit des uC verglichen
werden. Wenn die Zeiten gleich sind, soll z.B. eine LED einegeschaltet
werden.
Jetzt möchte ich aber erstmal die Uhrzeit realisieren. Kann ich das im
Anhang aufgeführte Programm so übernehmen oder was muss ich noch
abändern? Bleibt die Berechnung gleich, wenn ich statt des externen
Quarzes den interne Frequenz des STK500 von 8Mhz einstelle?
>internen vom STK500 8Mhz
Der interne "Quarz" ist ein Oszillator, der mit 3,686 MHz läuft.
Aus dem STK-500-Userguide:
"The frequency of the software generated clock can be set from 0 to
3.68Mhz. The default value is 3.68Mhz. Section "Oscillator" explains how
to set the clock frequency from AVR Studio."
Wenn du 8KHz hast, dann sind die controllerintern per RC-Oszillator
erzeugt, welcher relativ ungenau ist...
Die STK500-Frequenz ist da genauer...
Im Programm ist noch die von PeDa verwendete Quarzfrequenz angegeben.
Ansosnten könnte es funktionieren. Aber waum gibts du die Sekunden per
DDR aus und nicht per PORT?
Danke für die Antwort. Ich habe es schon selber hinbekommen.
Ich möchte gerne noch über die RS232 Schnittstelle vom Rechner einen
String senden z.B. eine "12". Wenn der String am uC ankomt dann soll die
Sekunde auf 12 gestellt werden und weiterlaufen. Wie ich einen String
mit dem uC empfange weiß ich, aber wie setze ich dann die Zeit?
Hi Christoph,
>... eine "12". Wenn der String am uC ankomt dann soll die> Sekunde auf 12 gestellt werden und weiterlaufen. Wie ich einen String> mit dem uC empfange weiß ich, aber wie setze ich dann die Zeit?
Christoph G. wrote:
> Die Variable Sekunde benötige ich aber als unsigned char und nicht als> integer. Wie wandle ich das um?
du kannst genauso atoi dafür benutzen.
Hallo Christoph,
> Die Variable Sekunde benötige ich aber als unsigned char und nicht als> integer. Wie wandle ich das um?
Karl Heinz hat Dir die Antwort schon gegeben. Denk mal nach: "Sekunde"
kann maximal welchen Wert annehmen? Ja, 60. Wie viele Bits sind dafür in
einer int8_t Variablen erforderlich? Wird dabei das Vorzeichen-Bit
gesetzt? Nein? Dann gibt es auch keine Komplikationen bei der Umwandlung
in unsigned! Falls Du dies nicht nachvollziehen kannst, empfielt sich
ein Tutorial zu Datentypen.
Gruß
Fred
Hallo!
Ich habe im Anhang meinen Quellcode geändert bereitgestellt. Beim
compilieren kommen zwei Warnungen. Eine betrifft "atoi". Es kommt auch
nichts an auf über RS232. Was habe ich falsch gemacht?
Warnung:
avr-gcc.exe -mmcu=atmega8535 -Wall -gdwarf-2 -O0 -MD -MP -MT uhr.o -MF
dep/uhr.o.d -c ../uhr.c
../uhr.c: In function `main':
../uhr.c:130: warning: passing arg 1 of `uart_puts' makes pointer from
integer without a cast
../uhr.c:139: warning: implicit declaration of function `atoi'
Build succeeded with 2 Warnings...
Ich habe oben einmal F_CPU definiert und dann XTAL. Darf man das
überhaupt?
Christoph G. wrote:
> ../uhr.c:130: warning: passing arg 1 of `uart_puts' makes pointer from> integer without a cast
uart_puts will einen Pointer (und zwar genaugenommen einen Pointer auf
ein Array von const char mit einem darin befindlichen nullterminierten
String) übergeben bekommen, second ist aber eine einfache Variable und
kein Pointer. Mit dem was Du da machst, kann alles Mögliche passieren,
nur wahrscheinlich nicht das, was Du willst.
> ../uhr.c:139: warning: implicit declaration of function `atoi'
Du hast die stdlib.h nicht eingebunden.
> Ich habe oben einmal F_CPU definiert und dann XTAL. Darf man das> überhaupt?
Du kannst definieren soviel Du willst. Ein "#define EINS 1" bedeutet
nur, dass an allen Stellen im Code, an denen "EINS" steht, eine 1
eingefügt wird. Wenn Du noch ein #define ONE 1 dahinterschreibst, werden
eben alle "ONE"s auch durch 1en ersetzt...
> ../uhr.c:130: warning: passing arg 1 of `uart_puts' makes pointer from> integer without a cast
uart_puts erwartet einen Zeiger (auf den Anfang eines Arrays aus char).
Stattdessen übergibst du ihm einen unsigned char. Das paßt überhaupt
nicht.
> ../uhr.c:139: warning: implicit declaration of function `atoi'
Dir fehlt der Header <stdlib.h>.
Hallo Christoph,
> Ich habe oben einmal F_CPU definiert und dann XTAL. Darf man das> überhaupt?
Normalerweise wird F_CPU aus den voreingestellten Parametern (beim
AVRStudio: "Project"|"Configuration Options") übernommen. Wie es bei
reiner Verwendung eines "makefile" geht, weiß ich nicht. Welche
"toolchain" benutzt Du?
Was Johannes zu uart_puts() sagt, stimmt. Wenn Du die Sekunde wieder in
einen String zurückwandeln möchtest, könntest Du "itoa()" verwenden.
Oder Du nimmst einfach Deinen "buffer" -- oder setzt Du atoi() auch ein,
um führende Leerzeichen im übertragenen String zu unterdrücken?
"position" wird nicht so funktionieren, wie Du es Dir wünschst, denn es
müsste mindestens als "volatile" deklariert sein. Da Du diese Variable
nur innerhalb der ISR benötigst, wäre es noch besser, "position"
innerhalb *der* ISR als "static" zu deklarieren und zu
initialisieren:
1
staticuint8_tposition=0;
Ich habe nur ganz grob über Deinen Code geschaut, es können durchaus
noch weitere Probleme drin sein. Versuche mal, die Vorschläge von
Johannes und mir zu implementieren.
Viele Grüße
Fred
Ich habe jetzt die <stdlib.h> implementiert. Jetzt kommen keine
Warnungen mehr.
Die Variablen "second" und "buffer" habe ich wie unten aufgeführt
deklariert. Ist die aufgeführte Zuweisung so richtig?
unsigned char volatile second;
char buffer[10];
second = atoi(buffer);
Ich möchte es über RS232 wieder zurückschicken. Da habe ich folgende
zusätzliche Variable deklariert:
char second2[10];
Das mit der Zuweisung stimmt glaube ich nicht, denn ich bekomme zwei
Fehlermeldungen beim compilieren.
second2 = itoa(second);
Fehlermeldungen:
../uhr.c:133: error: too few arguments to function `itoa'
../uhr.c:133: error: incompatible types in assignment
Wie muss ich es richtig machen?
Hallo Christoph,
versuche doch erst einmal, ein Problem (das mit der Binärausgabe) zu
lösen, ehe Du die serielle Ausgabe probierst. Sonst suchst Du immer
Fehler an mehreren Stellen gleichzeitig. Das ist ein wichtiges Element
jeder Fehlereingrenzung. Die serielle Eingabe (siehe Beitrag oben zu
"position") muss zuerst noch in Ordnung gebracht werden.
Ich empfehle Dir dringlich, Dich mit den Bibliotheksfunktionen vertraut
zu machen, damit Du Dir Fragen wie die zur Warnung bei Deiner itoa()
selbst beantworten kannst. Hier eine gute Adresse:
http://www.nongnu.org/avr-libc/user-manual/group__avr__stdlib.html#g4f6b3dd51c1f8519d5b8fce1dbf7a665
Und das ganze als PDF:
http://download.savannah.gnu.org/releases/avr-libc/avr-libc-user-manual-1.4.4.pdf
Viele Grüße
Fred
Hallo!
Ich habe jetzt nochmal das Programm umgeschrieben. Nach 10 Sekunden soll
die LED kurz angehen. Das macht sie auch. Wenn ich über RS232 vom
Rechner z.B. eine 9 schicke geht sie nach einer Sekunde an. Die RS232
Kommunikation funktioniert also auch. Jetzt möchte ich aber vom yC die
Sekunde auf den Rechner ausgeben. Dazu muss ich die Variable "second",
die als "unsigned char volatile second" deklariert ist in einen String
umwandeln und dann in eine andere Variable z.B. "buffer" schreiben. Die
Umwandlung soll glaub ich mit "itoa" funktionieren. Ich bekomme es aber
nicht hin. Wie muss ich den Quelltext im Anhang abändern, dass auch das
funktioniert?
Was genau hast Du daran nicht hinbekommen? Was ist an der Dokumentation,
auf die ich Dich im letzten Posting hingewiesen habe, nicht zu
verstehen?
Lies noch einmal nach, wie man Variable mit "volatile" deklariert.
"position" ist immer noch nicht richtig deklariert (siehe 2 Beiträge von
mir weiter oben). Ich gebe es auf, Dir hier Tipps zu geben.
Gruß
Fred
Danke für deine Auskunft.
Ich habe auch jetzt die Variable "position" geändert, dass hatte ich
total vergessen.
Ich habe es ja vorhin so ausprobiert wie du es geschrieben hast, doch
ich habe das int vor second vergessen. Trotzdem nochmal danke!
Wie mache ich es denn, das die Sekunde nur einmal zum Rechner geschickt
wird und nicht viele male hintereinander?
Hi Christoph,
> Ich habe auch jetzt die Variable "position" geändert, dass hatte ich> total vergessen.
OK
> Wie mache ich es denn, das die Sekunde nur einmal zum Rechner geschickt> wird und nicht viele male hintereinander?
Die Daten sollten (wegen des Flags "habekommando") nur 1x für jeden
empfangenen String gesendet werden.
Gruß
Fred
Ja das ist richtig, aber das ist doch nur für den Empfang auf den yC.
Ich möchte ja vom yC zum PC die Zeit senden. Ich habe das Programm noch
für Stunden, Minuten und Sekunden erweitert. Der yC sendet zwar die
Sekunden raus aber immer zu hintereinander. Ich möchte das er die
Stunden und Minuten in formatierter Uhrzeitform sendet. Wie mache ich
das?
Im Anhang findest du das Programm.
Hi,
> Ich möchte das er die Stunden und Minuten in formatierter Uhrzeitform> sendet. Wie mache ich das?
Dein Programm habe ich mir nicht noch einmal angesehen.
Du stellst eigentlich zwei Fragen. Dazu gleich. Die beste Vorgehensweise
ist, sich so etwas genau zu überlegen, ehe man Code schreibt. Man
fragt sich, was wie, wann, unter welchen Umständen, usw. passieren soll
und welcher Prozess von welchen anderen Prozessen abhängig sein soll.
Sind diese Fragen beantwortet, kann man ans Kodieren denken.
Erstens fragst Du, wie man die Zeit nur einmal sendet. Dafür schlage ich
vor, Du detektierst, wann ein neuer Zeitwert (zu testen wäre ja nur der
Sekundenwert!) vorliegt. Ist das gegeben, sendest Du die Zeit einmal.
Zweitens fragst Du, wie man die Zeit formatieren kann. Vermutlich denkst
Du an etwas wie HH:MM:SS. Dazu musst Du lernen, wie man Strings
formatiert. Alternativ kannst Du ja HH schicken, dann den Doppelpunkt,
dann die Minuten, usw. Die "echten" Befehle zur String-Formatierung
fressen manchmal viel Speicher (z.B. sprintf(), das mag aber trotzdem
eine gute Lösung sein!). Da Deine Daten aber in einem festen Format
(Stunden, Minuten und Sekunden zweistellig) vorliegen, kannst Du auch
einfacher vorgehen: Du nimmst einen String (z.B.
1
charZeitstring[]=" : : ";
) und schreibst die Zeitwerte so in diesen String (Vorsicht, fiese
Falle!):
1
itoa(stundeninteger,Zeitstring,10);
2
itoa(minuteninteger,&Zeitstring[3],10);
3
itoa(sekundeninteger,&Zeitstring[6],10);
Jetzt habe ich Dich absichtlich aufs Glatteis geführt. Hast Du's
gemerkt? Das geht zwar, aber es gibt einen Haken: itoa() schreibt '\0'
an das Ende eines jeden Strings, überschreibt Dir also die Doppelpunkte!
Die musst Du dann erneut setzen.
Wichtige Stringfunktionen, die Du lernen solltest, sind u.a.: strcpy(),
strcat(), strlen(), strstr().
Das alles nur zur Anregung -- es gibt viele andere mögliche Wege. Die
Implementierung bleibt "eine Öbung föör den Schööler".
Viel Erfolg,
Fred