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?
Gast
#870425
>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?
Wie schreibe ich den Code um damit eine LED am PORTA im Sekundentakt blinkt? Ich sehe bei dem Code noch nicht so richtig durch.
Gast
#870637
Wo liegt denn Dein Problem ? Man nehme den TimerIRQ, zähle darin die Sekunden hoch und schalte die LED im main je nach Sekunde an oder aus:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
Also statt nun binär wie im Code acht LEDs gleichzeitig zu schalten, wird nur eine getoggelt. Oder meinst Du etwas anderes ?
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?
Gast
#870878
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?
1 | |
2 | |
Gruß Fred
Die Variable Sekunde benötige ich aber als unsigned char und nicht als integer. Wie wandle ich das um?
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.
Gast
#872977
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?
Gast
#874936
Hallo Christoph, Du gibst die Sekunde an "LED_DIR" aus, und das ist DDRA. Wahrscheinlich willst Du aber an PORTA o.ä. ausgeben! Der Befehl
1 | |
2 | |
im Anschluss an
1 | |
bewirkt auch nichts, da schon alle Bits gesetzt sind. Welche Warnung gibt Dir denn der Compiler? Gruß Fred
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...
Gast
#875157
> ../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>.
Gast
#875159
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 | |
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?
Gast
#875660
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?
Gast
#876256
Hi,
1 | |
2 | |
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?
Gast
#876341
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.
Gast
#876403
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 | |
) und schreibst die Zeitwerte so in diesen String (Vorsicht, fiese Falle!):
1 | |
2 | |
3 | |
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
Danke! Ich werde es versuchen!
Antwort schreiben
Bitte melde dich an, um einen Beitrag zu schreiben.