www.mikrocontroller.net

Forum: Compiler & IDEs Timer genaue Zeit und entprellen


Autor: Christoph G. (booty3009)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: STK500-Besitzer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>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?

Autor: Christoph G. (booty3009)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie schreibe ich den Code um damit eine LED am PORTA im Sekundentakt 
blinkt? Ich sehe bei dem Code noch nicht so richtig durch.

Autor: xyz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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:
for(;;){
    if( second == 60 )
      second = 0;
    if(second%2)
      PORTA &= ~(1<<PINA0); //LED aus
    else
      PORTA |= (1<<PINA0);  // LED an
  }
Also statt nun binär wie im Code acht LEDs gleichzeitig zu schalten, 
wird nur eine getoggelt.
Oder meinst Du etwas anderes ?

Autor: Christoph G. (booty3009)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: Fred S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?
int8_t sekunde;
sekunde=atoi(string_mit_Sekundenwert);

Gruß

Fred

Autor: Christoph G. (booty3009)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Variable Sekunde benötige ich aber als unsigned char und nicht als 
integer. Wie wandle ich das um?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Fred S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Christoph G. (booty3009)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: Fred S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Christoph,

Du gibst die Sekunde an "LED_DIR" aus, und das ist DDRA. Wahrscheinlich 
willst Du aber an PORTA o.ä. ausgeben!

Der Befehl
  
  DDRA  |= (1 << PA6);
 im Anschluss an
  LED_DIR = 0xFF;

bewirkt auch nichts, da schon alle Bits gesetzt sind.

Welche Warnung gibt Dir denn der Compiler?

Gruß

Fred

Autor: Christoph G. (booty3009)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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...

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> ../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>.

Autor: Fred S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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:
static uint8_t position=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

Autor: Christoph G. (booty3009)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: Fred S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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__...
Und das ganze als PDF: 
http://download.savannah.gnu.org/releases/avr-libc...

Viele Grüße

Fred

Autor: Christoph G. (booty3009)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: Fred S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,
itoa((int)second, second2, 10);
uart_puts(second2);

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

Autor: Christoph G. (booty3009)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: Fred S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Christoph G. (booty3009)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Fred S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.
 char Zeitstring[]="  :  :  "; 
) und schreibst die Zeitwerte so in diesen String (Vorsicht, fiese 
Falle!):
itoa(stundeninteger, Zeitstring, 10);
itoa(minuteninteger, &Zeitstring[3], 10);
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

Autor: Christoph G. (booty3009)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke!
Ich werde es versuchen!

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.