hmm.. klingt gar nicht schlecht, aber wenn man alles getrennt lässt bleibt man abwärtskompatibel. vielleicht sendest du mal ne nachricht an waste, der beschäftigt sich mit der lib, vielleicht gibt das ne neuaufnahme...
Hi!
Da unser Robo z.Zt. zwangs-inaktiv ist, habe ich mir ein wenig Eure tollen und sehr gut
dokumentierten *.h's und *.c's angeschaut; ich kann dabei noch sehr viel in Sachen C,
Asm und AVR lernen!!!
Dabei ist mir das eine oder andere aufgefallen. (Bitte nicht als Kritik verstehen, denn
das soll und will ein Newby wie ich (leider noch bin! gar nicht!
Bei der IR-Übertragung ist mir aufgefallen, dass der Sender und auch der Empfänger zwar
immer wieder eingeschaltet wird, jedoch NIE aus! (in print.c und uart.c)
Anpassungsvorschlag: UCSRB = 0x00; // Sender und Empfaenger ausschalten
Beim Senden vom Asuro aus gibt es ähnliche Programme:
void SerWrite (unsigned char *data, unsigned char length)
void UartPutc (unsigned char zeichen) mit void SerPrint (unsigned char *data)
Man könnte mit den "Sahnehäubchen" aus beiden ein Programm basteln:
z.Bsp.
aus*********
void UartPutc (unsigned char zeichen)
{
UCSRB = 0x08; // enable transmitter
UCSRA |= 0x40; // clear transmitter flag
while (!(UCSRA & 0x20)) // wait for empty transmit buffer
;
UDR = zeichen;
while (!(UCSRA & 0x40)) // Wait for transmit complete flag (TXC)
;
}
mit+++++++++
void SerPrint (unsigned char *data)
{
unsigned char i = 0;
while (data [i] != 0x00)
UartPutc (data [i++]);
}
und-------------
void SerWrite (unsigned char *data, unsigned char length)
{
unsigned char i = 0;
UCSRB = 0x08; // Sender einschalten
while (length > 0) // so lange noch Daten da sind
{
if (UCSRA & 0x20)
{ // warten, bis der Sendebuffer leer ist
UDR = data[i++];
length --;
}
}
while (!(UCSRA & 0x40)) // abwarten, bis das letzte Zeichen
; // uebertragen wurde.
for (i = 0; i < 0xFE; i++) // warten auf irgendwas; keiner weiss
for (length = 0; length < 0xFE; length++); // wofuer =>> na, dann weglassen!)
}
Prog_neu------------
void SerWrite_SerPrint_NEU (unsigned char *data, unsigned char length)
{
unsigned char i = 0;
UCSRB = 0x08; // Sender einschalten
// enable transmitter
UCSRA |= 0x40; // 'clear' transmitter flag
// TXC-flag setzen
// (TXC = transmit complete flag)
while (length && data[i]) // so lange noch Daten da sind *)
{
if (UCSRA & 0x20) // wait for empty transmit buffer
{ // warten, bis der Sendebuffer leer ist
UDR = data[i++];
length --;
}
}
while (!(UCSRA & 0x40)) // abwarten, bis das letzte Zeichen
; // uebertragen wurde.
// Wait for transmit complete flag (TXC)
UCSRB = 0x00; // Sender ausschalten
// disable transmitter
}
------------
*) 2 Fliegen mit einer Klappe schlagen!)
SerWrite_SerPrint_NEU () funktioniert (besser: SOLLTE!
- mit Null-terminierten String data[] und/oder
- mit einer Längenangabe (auch ohne 'End-Null'):
Im ersten Fall muss man (leider als Schönheitsfehler!) als Länge einfach "0xff"
oder eine Zahl angeben, die größer/gleich der tatsächlichen Länge ist,
im zweiten die korrekte Länge des Strings!
Zum Prg.-Namen machen wir einen Wettbewerb!
Prog. leider noch nicht getestet!
********************
Beim Prog. IR-Empfangen versuche ich demnächst 'mal, die Fehlererkennung mit einzubauen.
Bis bald und
cu Helmut
hmm.. klingt gar nicht schlecht, aber wenn man alles getrennt lässt bleibt man abwärtskompatibel. vielleicht sendest du mal ne nachricht an waste, der beschäftigt sich mit der lib, vielleicht gibt das ne neuaufnahme...
Hallo zusammen,
die Warteschleife am Ende der SerWrite()-Funktion ist tatsächlich sehr merkwürdig.
Als einzigen Grund für das Ding kann ich mir nur vorstellen, dass eine Syncronisation mit einem Empfänger besser funktioniert.
Wenn man permanent Daten sendet, dann kann es passieren, dass die Start-Bits in den Daten nicht mehr zum richtigen Zeitpunkt gefunden werden. Macht man ab und zu eine Pause, dann schaffen es die Empfänger wieder das nächste Start-Bit korrekt zu erkennen. Ist mir schon passiert, als ich permanet Daten der Liniensensoren gesendet habe und 'natürlich' auch diese 'Zeitverschwendung' ausgebaut hatte.
Ist waste tatsächlich der richtige Ansprechpartner? Ich würde eher m.a.r.v.i.n sehen. (Oder ich?, OK ich sehe mir das heute Abend mal in Ruhe an, und werden es dann erst hier zur Begutachtung abgeben.)
Lieber Asuro programieren als arbeiten gehen.
na ich denke ihr seid alle richtig =) nur ich halt nich...
an sich finde ich die idee nicht schlecht, evtl wirds ja was
So, an alle die richtig und nicht richtig sind P.S.: damaltor ist immer richtig!
Ich habe den Vorschlag für SerWrite_SerPrint_NEU() mal so umgeschrieben dass ich in lesen kann. (Entspricht jetzt eher den Original-Codestellen zu Vergleichszwecken)
So sieht das ganze ja recht gut aus.Code:void SerWrite_SerPrint_NEU (unsigned char *data, unsigned char length) { unsigned char i = 0; UCSRB = 0x08; // enable transmitter UCSRA |= 0x40; // clear transmitter flag while (length && data[i]) // so lange noch Daten da sind *) { while (!(UCSRA & 0x20)) // wait for empty transmit buffer ; UDR = data[i++]; length --; } while (!(UCSRA & 0x40)) // Wait for transmit complete flag (TXC) ; UCSRB = 0x00; // disable transmitter }
Es gibt aber folgendes zu bedenken:
1: Ein einzelnes Char-Zeichen ist nur noch umständlich zu senden.
--> charVariable [0] = 'x';
--> SerWrite_SerPrint_NEU (charVariable, 1);
anstatt:
--> UartPutc ('x');
2: gravierender: Ich kann nicht mehr 'alle' Daten einschliesslich 0x00 senden.
Ein Datenarray mit 0x00 als Inhalt an einer Stelle, würde genau dieses Zeichen zum Abbruch der Funktion führen. Die "while (length && data[i])"-Schleife wird ja genau hier abbrechen, ohne dieses verflixte 0x00 gesendet zu haben.
- Somit hat SerWrite() seine Daseinsberechtigung.
- SerPrint() ist fuer die C-String-Sender.
- Und UartPutc() ist nun mal für LowLevel.
Ich glaube also, dass es keine so gute Idee wäre einen Wettbewerb für den Funktionsnamen zu beginnen.
Auf alle Fälle finde ich es klasse, dass du dich so intensiv mit den einzelnen Funktionen und möglichen Sahnehäubchen, äh Optimierungen, beschäftigst. Sonst ist bestimmt nämlich noch niemandem aufgefallen, dass man Energie sparen kann durch das Ausschalten des Senders. Akku und Umwelt werden es danken. -> Wird auf den Weg in die LIB gebracht.
Was ich aber bestehen lasse, ist diese merkwürdige Warteschleife zum Schluss. Da habe ich ehrlich gesagt ein bisschen Bammel vor die auszubauen. (Beim DLR werden die sich da irgendetwas gedacht haben um so ein Rätsel einzubauen.)
Lieber Asuro programieren als arbeiten gehen.
... ich seh das mal als kompliment =)
aber warum zur hölle sollte ich ein 0x00 senden wollen? =)
Hallo Sternthaler,void SerWrite_SerPrint_NEU (unsigned char *data, unsigned char length)
könntest Du in der neuen Version den Längenparameter rauswerfen?
Buchstaben zählen können Prozessoren besser als der Mensch.
Beste Grüße ,
stochri
Hi,
Wenn man Binärdaten senden will, kommt 0x00 durchaus vor und die Längenangabe in SerWrite braucht man dann natürlich ebenso.Zitat von damaltor
Ganz so einfach geht es also nicht.
Vielleicht vereint man print.c und uart.c auf folgende Weise, indem man SerWrite umschreibt und SerPrint durch ein Define ersetzt:
Code:void SerWrite (unsigned char *data, unsigned char length) { if (length) { do { uart_putc(*data++); } while (length--); } else { while (*data) uart_putc(*data++); } } #define SerPrint SerWrite(unsigned char *data, 0);
@damaltor
Klar, ist so gemeint. Allerdings wirft dich die Frage nach der Hölle nun etwas zurück Siehe Antwort von m.a.r.v.i.n
@stochri
Da ist noch nichts eingebaut.
Mit dem Übernehmen in die LIB hatte ich nur im Sinn den Sender auch wieder auszuschalten. In meinem Beitrag hatte ich (wahrscheinlich durch blah, blah, blah verstümmelt) eigendlich für die Daseinsberechtigung aller 3 Funktions-Varianten zum senden plädiert.
Aber m.a.r.v.i.n hat wohl den Nagel auf den Kopf getroffen, und eine perfekte Lösung gefunden.
Kleine Änderung beim define:
#define SerPrint(data) SerWrite(unsigned char *data, 0);
Oder muss das "data" bei einem define auch mit Typeangabe, *-chen oder sonstigem sein?
Auch noch eine weitere Frage zu dem Code, bei der ich absolut unsicher bin was da eigendlich passieren wird.
- Ich mache ne Char-Array-Variable á la "char infos [10];"
- Daten da rein mit "strcpy (infos, "Wichtig");"
- Nun der Aufruf über SerPrint (infos) an SerWrite(infos, 0)
- In SerWrite wird mit "*data++" das zu sendende Zeichen ausgewählt UND der Zeiger auf den übergeben Datenbereich mit ++ erhöht.
Meine Frage ist:
Wenn die Funktion beendet wird, ist dann der Zeiger/Adresse in infos immer noch an der Stelle im Speicher an der ich 10 Byte speichern darf, oder wurde dieser Zeiger/Adresse nun durch das ++ auch beim Aufrufer geändert?
Wenn das der Fall wäre, dann dürfte ich als Aufrufer ja nun nicht mehr davon ausgehen, dass mir der Speicherbereich ab infos mit 10 Byte gehört.
Im Original-Code ist das Adressieren der Daten in infos mit einer eigenen Variablen gelöst: "data[i++]"
Lieber Asuro programieren als arbeiten gehen.
keine sorge:
du übergibst ja das array (welches technisch gesehen eingentlich nur ein zeiger auf dass erste element ist). dann wird damit gearbeitet, der zeicher wird etwas hin-und hergeschubst usw.
sowie du aber wieder mit dem namen des arrays arbeitest, hat sich das problem erledigt: der NAME des arrays zeigt auf das erste element. grundsätzlich. und wenn innerhalb einer funktion die adresse, auf die der zeiger zeigt, verändert wird, ist das in der aufrufenden funktion nicht geändert. sowie die fnktion verlassen wird, zegt der name wieder auf das erste element.
Lesezeichen