Forum: Compiler & IDEs AVRStudio6.1 Compiler meckert (warnt) bei Struct-Pointer-Übergabe


von Alex V. (bastel_alex) Benutzerseite


Lesenswert?

Hallo, ich wundere mich jetzt bereits eine Weile über diverse Warnungen 
des AVR-Studio6.1 Compilers. Da ich nun aber mal wieder beim debuggen 
festhänge, komme ich wohl nun um die Warnungen nicht mehr herum.

Zum einen bekomme ich bei einer Übergabe eines Pointers auf ein 
deklariertes Struct eine Warnung:

"Warning  1  'struct circular_buffer' declared inside parameter list 
[enabled by default]"

Dabei ist mein struct ein ringpuffer (mit Redundanzen):
1
typedef struct circular_buffer {
2
    char volatile *data;
3
    int size;
4
    char volatile fillcount;
5
    char head;
6
    char tail;
7
}TCircBuf;

und die Funktion(en) z.B. so deklariert:
1
uint8_t uart_ReceiveByte(struct circular_buffer *buf );

Wo liegt denn da das problem?


Dann ein zweites Problem (mit entsprechend vielen Warnungen):
Die Übergabe eines Struct-Pointers, der in der Funktion wiederum 
übergeben wird, z.B.
1
send_ADC_raw(struct circular_buffer *buf, uint32_t adcreceive)
2
{
3
  uint8_t sendbuf;
4
  
5
  sendbuf = 0xFF;
6
  uart_TransmitByte(buf, sendbuf);
7
...}

gibt mir die Warnung

Warning  8  passing argument 1 of 'uart_TransmitByte' from incompatible 
pointer type [enabled by default]

Kann mir da jemand zu helfen? Viele Grüße

: Verschoben durch User
von Peter II (Gast)


Lesenswert?

Alex v. L. schrieb:
> Wo liegt denn da das problem?

das ein typedef hier falsch bzw. unnötig ist.

von Verne (Gast)


Lesenswert?

Du kommst mir langsam vor wie der Bastel-Thomas hier.
Die Meldung sind doch klar verständlich. Wo ist da das Problem?

Lies mal ein C-Buch. Da wird Dir geholft.

von Alex V. (bastel_alex) Benutzerseite


Lesenswert?

Peter II schrieb:
> das ein typedef hier falsch bzw. unnötig ist.

ich habe einfach die Ringpufferfiles aus der Dipl.Arbeit eines mir 
bekannten Informatikers eingebunden und war davon ausgegangen dass der 
weiß was er getan hat! Also nicht?

Verne schrieb:
> Du kommst mir langsam vor wie der Bastel-Thomas hier.
> Die Meldung sind doch klar verständlich. Wo ist da das Problem?
>
> Lies mal ein C-Buch. Da wird Dir geholft.

Das Problem ist, dass ich es nicht verstehe. Aber auch, dass ich keine 
Zeit habe ein C-Buch zu lesen, weil die ganze Arbeit auf dem µC zu 
meiner Masterthesis gehört, die sich EIGENTLICH um etwas ganz anderes 
(Entwurf eines Infrarot-Spektroskopiegerätes) dreht. Weil das Institut 
(besagte Informatiker) an dem ich die arbeit mache aber weniger 
Elektronikzubehör hat als ich zu hause, geschweige denn eine 
labviewkarte, muss ich hier eben ein Analog-Digitalwandlerboard mit UART 
MAL EBEN ENTWICKELN (und das als SPI/UART neuling) um meine hardware 
überhaupt evaluieren zu können - und das während mir der Arsch brennt 
weil es gerade bei der Hardware noch wichtigere dinge gibt, die ich aber 
nur bearbeiten kann, wenn ich sie evaluiert bekomme.

Ich würde mich also wirklich freuen nicht noch ein C-Buch lesen zu 
müssen, auch wenn die Fragen euch reichlich dämlich vorkommen. Das 
natürlich auch, weil ich hier nur reinschreibe wenn was nicht klappt - 
dass ich aber innerhalb von 3 monaten bisher nach Rückmeldungen aller 
Profs und Betreuer die mich kennen ungefähr das dreifache an Leistung 
vollbracht habe wie normal lasse ich hier eben nicht dauernd raushängen.
Das nur, weil: BITTE stempelt mich hier nicht als zu faul ab, ich 
arbeite hier von morgens bis abends - nur ist die µC programmierung eben 
nicht mein Fachgebiet, so wie bei vielen von euch!!

von Cyblord -. (cyblord)


Lesenswert?

> uart_TransmitByte(buf, sendbuf)

Wo ist der Kopf dieser Funktion? Der fehlt.

Dann sieht diese doch eher so aus, als erwarte die EIN Byte. Rein vom 
Namen her. Aber kein Struct. Nur wir wissen es nicht. Weil wir die 
Funktion nicht sehen.

: Bearbeitet durch User
von Alex V. (bastel_alex) Benutzerseite


Lesenswert?

cyblord ---- schrieb:
> Weil wir die Funktion nicht sehen.

ja, sorry.
1
void uart_TransmitByte(struct circular_buffer *buf, uint8_t data );

von Karl H. (kbuchegg)


Lesenswert?

Alex v. L. schrieb:

> Das Problem ist, dass ich es nicht verstehe. Aber auch, dass ich keine
> Zeit habe ein C-Buch zu lesen, weil die ganze Arbeit auf dem µC zu
> meiner Masterthesis gehört, die sich EIGENTLICH um etwas ganz anderes


Eigentlich sollte man ein C-Buch bereits gelesen haben, bevor man eine 
Mastherthesis anfängt, bzw. man fängt keine Masterthesis an in der man C 
programmieren soll, wenn man keines gelesen hat.


Zeig mal mehr Code. So eindeutig ist der Wortlaut der Fehlermeldungen 
nämlich meiner Meinung nach nicht. Für mich klingt das eher nach einem 
vergessenen Strichpunkt da oder dort und die konkrete Fehlermeldung ist 
ein Folgefehler davon.
Tippe den Code NICHT ab, sondern hänge die Files an.

: Bearbeitet durch User
von Alex V. (bastel_alex) Benutzerseite


Lesenswert?

Also um es nochmal anders aufzudröseln:
Ich habe die Funktion
1
void uart_TransmitByte(struct circular_buffer *buf, uint8_t data );
, die mir ein byte "data" in den Ringpuffer schreiben lässt , aus dem 
der UART sendet:
1
void uart_TransmitByte(struct circular_buffer *buf, uint8_t data ) {
2
  while ( circbuf_isfull(buf) );
3
  circbuf_add(buf,data);    /* store data in buffer */
4
  
5
  UCSR0B |= (1<<UDRIE0);      // Enable UDRIE- UART Data Register empty Interrupt - UDRE-ISR is going to put data in UDR
6
}

Die aufgerufene Funktion circbuff_add(buf,data) schreibt das byte 
tatsächlich in den Puffer:
1
  void circbuf_add(struct circular_buffer *buf, char value) {
2
  buf->data[buf->head] = value;
3
    buf->head++;
4
    buf->fillcount++;
5
  }

Nun übergebe ich also von "oben" nach "unten" immer den selben Pointer 
auf den Ringpuffer durch. Wie würde man das denn richtig machen?

von Cyblord -. (cyblord)


Lesenswert?

Alex v. L. schrieb:
> cyblord ---- schrieb:
>> Weil wir die Funktion nicht sehen.
>
> ja, sorry.
>
>
1
> void uart_TransmitByte(struct circular_buffer *buf, uint8_t data );
2
>

Ok schon klarer. Die Übergabe an sich passt.

Woran sich Peter II stört ist, die Tatsache dass du mit typedef einen 
Datentyp definierst, in den Funktionen allerdings weiterhin das nackte 
Struct benutzt. Wozu? Du kannst direkt den Datentyp "TCircBuf" ohne das 
Schlüsselwort "struct" nutzen.

von Alex V. (bastel_alex) Benutzerseite


Angehängte Dateien:

Lesenswert?

Karl Heinz schrieb:
> Tippe den Code NICHT ab, sondern hänge die Files an.

Gerne, hier das volle Paket.

von Alex V. (bastel_alex) Benutzerseite


Lesenswert?

cyblord ---- schrieb:
> Woran sich Peter II stört ist, die Tatsache dass du mit typedef einen
> Datentyp definierst, in den Funktionen allerdings weiterhin das nackte
> Struct benutzt. Wozu? Du kannst direkt den Datentyp "TCircBuf" ohne das
> Schlüsselwort "struct" nutzen.

Danke für die klare Ansage cyblord!!!
Die Deklaration von zwei eigenen Ringpuffern UART_rx_buffer und 
UART_tx_buffer habe ich in der main gemacht, die werden dann auch immer 
referenziert. Das TCircBuf war ein Überbleibsel aus der Headerfile, das 
ich von jemandem bekommen habe. Der verwendet es interessanterweise in 
seinem code auch nicht (eben mal nachgeschaut) sondern deklariert auch 
seine eigenen structs in der main.

Karl Heinz schrieb:
> Eigentlich sollte man ein C-Buch bereits gelesen haben, bevor man eine
> Mastherthesis anfängt, bzw. man fängt keine Masterthesis an in der man C
> programmieren soll, wenn man keines gelesen hat.

Da gebe ich dir recht. Ich kann auch eure Vorbehalte gegen Frager wie 
mich wirklich verstehen.
Nun ist es aber eben so, dass ich in der Regel bei kleineren Projekten 
auch immer zurandegekommen bin mit meinem C-Wissen aus eigener Bastelei 
(die es recht viel gab bisher) und meinem C++ Wissen aus Uni und HiWi 
jobs (und eigenen Programmen). Ein C-Buch habe ich tatsächlich mal 
durchgearbeitet vor jahren - aber französisch habe ich auch mal sprechen 
gekonnt, nur ist die schule schon so lange her. Mein Problem ist nun 
eher der eigene Anspruch denke ich, der dafür gesorgt hat, dass es eine 
wirklich fette Masterarbeit wird. Dazu gehört dann aber (inzwischen eben 
leider auch zwingend) die komplexere Programmierung als mal geplant war. 
Es hat mir aber schon jetzt unglaublich viel gebracht: In UART und SPI 
eingearbeitet und weitgehend auch erfolgreiche kommunikation 
zustandebekommen, das kann ja nun in alle weiteren Bastelprojekte von 
mir einfließen, macht mich also happy! ;)

von Yalu X. (yalu) (Moderator)


Lesenswert?

Die Reihenfolge deiner Deklarationen und Definitionen muss folgende
sein:
1
1.   typedef struct circular_buffer { ...
2
3
2.   uint8_t uart_ReceiveByte(struct circular_buffer *buf );
4
     void uart_TransmitByte(struct circular_buffer *buf, uint8_t data );
5
6
3.   void send_ADC_raw(struct circular_buffer *buf, uint32_t adcreceive) { ...

Bei dir sieht die Reihenfolge aber möglicherweise so aus:
1
1.   uint8_t uart_ReceiveByte(struct circular_buffer *buf );
2
     void uart_TransmitByte(struct circular_buffer *buf, uint8_t data );
3
4
2.   typedef struct circular_buffer { ...
5
6
3.   void send_ADC_raw(struct circular_buffer *buf, uint32_t adcreceive) { ...

Das würde zumindest die Compiler-Meldungen erklären.

Schau noch einmal nach, ob die Reihenfolge der Deklarationen bzw. der
#include-Direktiven der entsprechenden Header-Files stimmt.

von M, nicht Q (Gast)


Lesenswert?

Ohne in den Code zu sehen:

Alex v. L. schrieb:
> und die Funktion(en) z.B. so deklariert:uint8_t uart_ReceiveByte(struct
> circular_buffer *buf );


Der Compiler hat an dieser Stelle noch keine Deklaration von "struct 
circular_buffer" gesehen. Da der Parameter aber "nur" ein Pointer auf 
eine struct ist, kann der Compiler sich den Parameter grundsätzlich 
zusammenreimen, nämlich Pointer-auf-einen-irgendwie-geartete-Struktur. 
Passt scho, wie der Bayer sagen würde.

Deshalb nur eine Warnung, der Compiler kommt schon irgendwie klar.

Gleichzeitig, da er "struct circular_buffer" zum ersten Mal sieht, nimmt 
er das als (unvollständige) Deklaration der Struktur und verkündet das 
in der Warnung.

von Alex V. (bastel_alex) Benutzerseite


Lesenswert?

Nur weil die  geringe hoffnung besteht, dass jemand meinen Code 
tatsächlich mal aufspielt und laufen lässt (da steckt jetzt schon 
ziemlich viel arbeit drin):

Die Probleme die ich EIGENTLICH mit dem Code noch habe - und die die 
Ursache dafür sind, dass ihc mich jetzt näher um die Warnungen kümmern 
wollte sind zweierlei (vielleicht sieht ja jemand die ursache für eins 
von beiden):

1. Sende ich nach Eingang des Kontrollbytes 0xAA über UART einen 
20-Byte-Block mit Konfigurations- und ADC Daten, passiert es immer 
wieder, dass diese irgendwann "verwürfeln". Im Beispiel über das Br@y 
Terminal:

M0;C0;S0;301F;1032
M0;C0;S0;301F;00B3
0B
M0
0;S0;0CA1;0112
0;S0;0CA1;01M0
0;S0;0CA0;01M0;C0;S0;0CA3;0112
M0;C0;S0;0CA3;01F1
M0;C0;S0;0CA1;1ABE

Hierbei sind die ersten beiden und letzten Beiden Zeilen so, wie man es 
erwarten würde, nachdem man einmal 0xAA an den Controller schickt. 
Dazwischen wurde das selbe geschickt, kommt aber Gewurschtel an. Ich 
dachte erst dass das evtl an meinen Interrupts liegt, da bin ich mir 
aber inzwischen nicht mehr sicher - denn mit ausgeschaltetem 
TimerInterrupt und auch mit der Interruptfreien SPI Kommunikation (die 
ich mal eigentlich mit I.s umgesetzt hatte) sieht es genauso aus.

2. bekomme ich vom ADC (LTC2486) seltsame Werte und das liegt nicht an 
der SPI-Schnittstelle. Wenn ich nämlich die Temperatur abfrage, stimmt 
diese. Die Eingänge sind (inzwischen) alle auf masse oder an einem 
spannungsteiler - und der ausgegebene ADC wert stimmt nur in der nähe 
von ca. 0,6V. aber das wird sich hier nicht lösen lassen...

von Karl H. (kbuchegg)


Lesenswert?

Hmm. Das ist ein seltsamer Fehler. Ich denke er kommt daher, dass du ein 
wesentliches Prinzip nicht beachtet hast:
Man inkludiert nur das was man wirklich braucht!

Du hast hier zb circbuf.h
1
#ifndef CIRCBUF_H_
2
#define CIRCBUF_H_
3
4
#include <stdbool.h>
5
#include <avr/interrupt.h>
6
#include "SPI_functions.h"
7
#include "UART_functions.h"
8
#include "Mainboard_UART_functions.h"
9
10
//circular buffer data structure
11
struct circular_buffer {
12
    char volatile *data;
13
    int size;
14
    char volatile fillcount;
15
    char head;
16
    char tail;
17
};
18
19
//function declarations
20
char circbuf_get(struct circular_buffer *buf);
21
void circbuf_add(struct circular_buffer *buf, char value);
22
bool circbuf_isempty(struct circular_buffer *buf);
23
bool circbuf_isfull(struct circular_buffer *buf);
24
void circbuf_clear(struct circular_buffer *buf);
25
26
27
  
28
#endif /*CIRCBUF_H_*/

Braucht dieses Header File irgendwas aus SPI_functions.h? Nein! Warum 
ist dann da ein include drinnen? Wird in diesem Header File irgendwas 
benötigt, was in UART_functions.h steht? Nein! Was ist mit den anderen 
includes? Kein einziger davon ist notwendig. Was also machen die da 
drinnen.

Das Problem ist nämlich, dass du ganz schnell in zirkulären includes 
landest. Denn UART_functions.h includiert seinerseits wieder die 
circbuf.h usw. usw.
Und das ist nicht gut!

Löse das alles mal ordentlich auf. Jedes Header File, jedes C-File 
includiert nur das, was es tatsächlich braucht.
Du hast in deinem Code offenbar eine Hierarchie. Ganz unten in der 
Hierarchie stehen die Funktionen für Ringbuffer. Die sind von nichts 
anderem abhängig. Also braucht es auch keinen Include, ausser den einen 
oder anderen System-Header und natürlich im C-File das eigene 
Header-File.
Darüber sitzen in der Hierarchie die UART Funktionen. Die brauchen die 
Unterstützung durch einen Ringbuffer. Also ist es für die in Ordnung 
circbuf.h zu inkludieren. Aber umgekehrt nicht. circbuf ist in keinster 
Weise davon abhängig, dass er zusammen mit einer UART eingesetzt wird. 
Also warum soll er dann den Header für UART Funktionen includieren?

Halte Ordnung in deinem Code, respektiere Hierarchien und du wirst 
weniger von seltsamen Fehlermeldungen geplagt.

(Richte das mal her und dann schaun wir mal weiter, ob und wenn ja 
welche Warnungen verschwinden)

: Bearbeitet durch User
von Alex V. (bastel_alex) Benutzerseite


Lesenswert?

Yalu X. schrieb:
> Schau noch einmal nach, ob die Reihenfolge der Deklarationen bzw. der
> #include-Direktiven der entsprechenden Header-Files stimmt.

Danke für deine Hilfe Yalu!
Die Reihenfolge in der Main hatte nicht gestimmt, da hat dein Punkt 
exakt zugetroffen. Ich hatte aber (aus noob-vorsichtigkeit?) die 
circbuf.h in allen headerfiles nochmal über ifdef eingebunden, wo der 
struct verwendet wird. Dein Tip (d.h. einbinden der circbuf.h ganz zu 
beginn) hat einige der Warnungen weniger werden lassen (insbesondere zum 
pointer-type), dafür sind tatsächlich aber ein paar mehr

Warning  1  'struct circular_buffer' declared inside parameter list 
[enabled by default]

aufgetaucht..

von Alex V. (bastel_alex) Benutzerseite


Lesenswert?

Karl Heinz schrieb:
> (Richte das mal her und dann schaun wir mal weiter, ob und wenn ja
> welche Warnungen verschwinden)

Danke Karl-Heinz! Mache ich.
Die includes im circbuf.h sind ein Überbleibsel meiner heutigen 
Programmierarbeit: Ich hatte vorher die anderen files includiert um 
während der Ringpufferzugriffe Interrupts ausschalten zu können (die 
funktionen dazu im jeweiligen file).

von Karl H. (kbuchegg)


Lesenswert?

Aber mach das in allen Files!

Hier zb die UART_functions.h
1
/*
2
 * Mainboard_UART_functions.h
3
 *
4
 * Created: 14.01.2014 10:32:13
5
 *  Author: Alex
6
 */ 
7
8
9
  
10
  #ifndef _UART_functions_h_
11
  #define _UART_functions_h_
12
  
13
  #define F_CPU 20E6 //Systemtakt in Hz
14
  #include <util/delay.h>
15
  
16
  #include "circbuf.h"
17
18
  // FUNCTIONS
19
  void UART_Init();
20
  uint8_t uart_ReceiveByte(struct circular_buffer *buf );
21
  void uart_TransmitByte(struct circular_buffer *buf, uint8_t data );
22
  void UART_enable_interrupts();
23
  void UART_disable_interrupts();
24
25
  #endif /*_UART_functions_h_*/

was macht da F_CPU bzw. der include von util/delay.h da drinnen? Braucht 
das irgendwer in DIESEM Header File?
Nein, kein Mensch braucht das in diesem Header File. Also weg damit!

Und so gehst du jedes einzelne C-File, jedes einzelne Header-File durch 
und fragst dich bei jedem #include 'Brauch ich den da drinnen?', 'Wird 
hier, in diesem File, irgendetwas verwendet, was diesen #include 
notwendig machen würde?'. Wenn die Antwort 'Nein, nichts' lautet, dann 
-> weg damit.

von Karl H. (kbuchegg)


Lesenswert?

Alex v. L. schrieb:

> Die includes im circbuf.h sind ein Überbleibsel meiner heutigen
> Programmierarbeit: Ich hatte vorher die anderen files includiert um
> während der Ringpufferzugriffe Interrupts ausschalten zu können (die
> funktionen dazu im jeweiligen file).

Das würde maximal einen entsprechenden Include in den jeweiligen C-Files 
erklären, aber nicht in den Header-Files.

im Ernst: du musst es dir zur Regel machen, jedes File für sich zu 
betrachten. Ein Header File wird als in sich abgeschlossen betrachtet. 
Es enthält nur die #include, die im Header-File notwendig sind, um 
Begriffe zu definieren (wie zb Strukturnamen, die woanders herkommen). 
Das Header File nimmt aber keine Rücksicht darauf, dass 'sein' C-File 
vielleicht irgendwelche Dinge benötigen würde. Wenn dem so ist, dann 
soll gefälligst das C- File den #include machen, aber das Header File 
wird einen Teufel tun und für 'sein' C-File etwas inkludieren.

: Bearbeitet durch User
von Alex V. (bastel_alex) Benutzerseite


Lesenswert?

Karl Heinz schrieb:
> Ein Header File wird als in sich abgeschlossen betrachtet.
> Es enthält nur die #include, die im Header-File notwendig sind, um
> Begriffe zu definieren (wie zb Strukturnamen, die woanders herkommen).
> Das Header File nimmt aber keine Rücksicht darauf, dass 'sein' C-File
> vielleicht irgendwelche Dinge benötigen würde. Wenn dem so ist, dann
> soll gefälligst das C- File den #include machen, aber das Header File
> wird einen Teufel tun und für 'sein' C-File etwas inkludieren.

Danke, so war mir das noch nicht klar. ich dachte immer: Wenn das c-file 
ohnehin seine headerfile includiert, dann kann ich ja alle weiteren 
includes auch in den header tun. Das werde ich in zukunft dann wohl 
lassen ;)

Das Aufräumen nach deinen Anweisungen hat enorm etwas gebracht - es sind 
nur noch zwei x zwei Warnungen übrig: jeweils hinter den zwei typedef 
struct-deklarationen ohne variablendeklaration
1
typedef struct circular_buffer {
2
    char volatile *data;
3
    int size;
4
    char volatile fillcount;
5
    char head;
6
    char tail;
7
};
Bekomme ich einen "useless storage class specifier in empty 
declaration".

Der kommt mir bekannt vor, ich hatte damals nämlich auch die nicht 
verwendete TCircBuf deklaration gelöscht, dann aber wegen der warnung 
wieder hingeschrieben... kann man die warnung verhindern, wenn man eben 
trotzdem in einem anderen file deklarieren will?

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Die Warnung hier
1
Warning 1 'struct circular_buffer' declared inside parameter list [enabled by default]
spricht davon, dass da per default etwas enbled (also eingeschaltet) 
wurde. Ich kann mir auch schon vorstellen, was das ist, und es ist IMHO 
keine gute Idee dieses zuzulassen.

In C gibt es eine Grundregel, die da lautet:
Der Compiler liest den Code von oben nach unten und er liest ihn genau 
ein einziges mal.
Weiters gilt: verwendet werden kann nur, was auch bekannt ist.

Wenn du also eine Funktion hast
1
void doIt( struct xyz* abc);
und der Compiler hat an dieser Stelle vorher nicht erfahren, dass es 
eine 'struct xyz' überhaupt gibt, dann ist das ein Fehler im Code! Die 
Strukturdeklaration muss vor der ersten Verwendung erfolgt im zu 
compilierenden File erfolgt sein.

Scheinbar gibt es da aber im Compiler eine Erweiterung, die zulässt, 
dass der Compiler so etwas akzeptiert: Die Verwendung eines Datentyps 
von dem im Code davor nicht klar gestellt wurde, dass er existiert. 
Daher der Wortlaut in der Warnung "declared inside parameter list". Das 
ist nichts anderes als eine implizite Deklaration basierend darauf, dass 
dieser Strukturname in der Funktionsdeklaration benutzt wird.

Meiner Meinung nach ist das keine gute Idee. Eines der größten Probleme 
im alten Kernighan&Ritchie C waren genau derartige impliziten Annahmen 
und Zulassungen des Compilers. Eine der großen Errungenschaften von C++ 
war es, dass diese impliziten Annahmen und Zulassungen mehr oder weniger 
alle gestrichen wurden. Im Laufe der Jahre hat sich nämlich 
rausgestellt, dass eine Menge Fehler auf deren Konto gingen. Die jetzt 
zumindest teilweise wieder über die Hintertür zuzulassen ist IMHO ein 
Schritt in die falsche Richtung.

von Cyblord -. (cyblord)


Lesenswert?

Karl Heinz schrieb:
> Die Warnung hier
>
1
> Warning 1 'struct circular_buffer' declared inside parameter list 
2
> [enabled by default]
3
>
> spricht davon, dass da per default etwas enbled (also eingeschaltet)
> wurde. Ich kann mir auch schon vorstellen, was das ist, und es ist IMHO
> keine gute Idee dieses zuzulassen.

Das bedeutet IMO eigentlich nur, dass die Warnung per default an ist. 
Seit einiger Zeit, gibt der GCC bei jeder Warnung noch an, wegen welchem 
Flag diese Warnung enabled ist.

von Karl H. (kbuchegg)


Lesenswert?

Alex v. L. schrieb:

> nur noch zwei x zwei Warnungen übrig: jeweils hinter den zwei typedef
> struct-deklarationen ohne variablendeklaration

:-)
Da gehört auch keine Variablendefinition hin
:-)

(Jetzt sind wir wieder an dem Punkt mit dem C-Buch)

In C definiert man so eine Struktur
1
struct xyz
2
{
3
  int member;
4
};

So weit so gut.
Um diese Struktur zu verwenden, musst du überall schreiben
1
void foo( struct xyz argument )
also immer das 'struct ...' ausschreiben. Eine Struktur definiert keinen 
neuen Typ, der nur aus dem Namen der STruktur bestehen würde.

Aber: dagegen kann man was tun. Mit einem typedef kann man sich einen 
echten neuen Namen für einen Datentyp definieren, der als Alias für 
diesen Datentyp gilt.
Man kann also machen
1
struct xyz
2
{
3
  int member;
4
};
5
6
typedef struct xyz neuerNameXYZ;

die Typedef-Syntax ist recht einfach. Stell dir einfach die Definition 
einer entsprechenden Variablen vor
1
struct xyz variableA;
, schreib ein typedef davor und der Variablenname wird zum Namen dieses 
neuen Datentyps.

Damit hast du dir einen echten neuen Datentyp geschaffen, der auf den 
Namen 'neuerNameXYZ' hört, und der ein Alias (ein Stellvertreter) für 
'struct xyz' ist.

Damit kannst du aber schreiben
1
void foo( neuerNameXYZ argument )
und bist das ewige schreiben von 'struct' los.

Man kann auch weitergehen. Anstelle von 2 getrennten Dingen
1
struct xyz
2
{
3
  int member;
4
};
5
6
typedef struct xyz neuerNameXYZ;

kann man auch die Strukturdfintion direkt in den typedef einbinden. 
Quasi wie eine Text-Einsetzung ...
1
typedef struct xyz
2
{
3
  int member;
4
} neuerNameXYZ;
... und so Strukturdefinition und typedef miteinander verbinden.
Logischerweise macht es aber überhaupt keinen Sinn, einen typedef zu 
machen und dann für diesen typedef keinen Aliasnamen anzugeben!

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

Zu "struct S ..." vs "typedef struct ... T":

Üblich ist es heute, mit den typedef Namen zu arbeiten. Die alte "struct 
S" Variante wird kaum noch verwendet - es sei denn der Code stammt noch 
aus grauer Vorzeit (Unix-API). Die typedefs gab es anfangs nämlich 
nicht.

Nur bei Vorwärtsdeklarationen kommt man nicht gänzlich ohne aus:
   typedef struct S T;
   struct S {
      T *next;
      ...
   };
oder
   typedef struct S {
      struct S *next;
      ...
   } T;

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

cyblord ---- schrieb:

> Das bedeutet IMO eigentlich nur, dass die Warnung per default an ist.

Der springende Punkt ist aber, dass das laut C-Regeln keine Warnung sein 
sollte, sondern tatsächlich ein waschechter Fehler sein müsste.
Und dafür muss es eine Option geben, die eingeschaltet ist.

von Alex V. (bastel_alex) Benutzerseite


Lesenswert?

Ich danke euch für eure Zeit! Zumindest in meinem Fall soll sie nicht 
vergeudet gewesen sein ich schreibe mir so viel wie möglich davon hinter 
die ohren!

Leider hat sich durch die Warnungsbehebung nicht der Fehler behoben 
(kein Compilefehler), der mich gerade davon abhält hinter einem weiteren 
großen Schritt einen haken setzen zu können.
Der Code ist inzwischen soweit gewachsen, dass ich nach einer Eingabe 
eines Kontrollbytes die Werte eines SPI ADC abfragen und diesen 
konfigurieren kann, die daten werden dann im ASCII mit timestamp ans 
terminal geschickt.
Offen ist noch, an welcher Stelle (bei Ringpufferzugriffen?) das Senden 
gestört wird.

Es ist an sich ganz leicht: Ich sende derzeit wiederholt ein 0xAA als 
Request für einen Datenblock mit dem Format (in Bytes)
1
// Send ASCII DataBlock: [M|#|;|C|#|;|S|0/1|;|ADCVAL(Hex,dargestellt in 4ASCIIBytes)|;| |TIMERVAL(Hex,dargestellt in 4ASCIIBytes)|CR|LF]

Wobei M# eine Modulnummer, C# die aktive Channelnummer, S0/1 den 
Speedmode des ADC und darauf für das CSV-Format mit Semikolon getrennt 
der 16Bit ADC-Wert und Timestamp kommen.

Was ich also erwarte und in 50% der Fälle erhalte:
z.B.
1
 M0;C0;S0;113D;3131

Was ich bekomme (nach hier 11 Requests):
1
M0;C0;S0;113D;3131
2
M0;C0;S0;113E;3101
3
;113E;31D0
4
M113E;31M0;C0;S0;113D;322A
5
M1;C0;S0;0000;0210
6
M1;C0;S0;113F;023B
7
M1;C0;S0;113F;02F1
8
;0000;002B
9
M0000;00M1;C0;S0;113E;0000
10
;113E;00DA
11
M113E;00;113F;0121

Ich möchte hier nicht überstrapazieren, deshalb die Frage: Neues Thema 
aufmachen? Alle hier in Ruhe lassen? Oder hier ausbreiten?

von Alex V. (bastel_alex) Benutzerseite


Lesenswert?

Karl Heinz schrieb:
> Logischerweise macht es aber überhaupt keinen Sinn, einen typedef zu
> machen und dann für diesen typedef keinen Aliasnamen anzugeben!

Lichtaufgeh
Karl Heinz, ich danke dir!

von Alex V. (bastel_alex) Benutzerseite


Angehängte Dateien:

Lesenswert?

Angehängt die aufgeräumte(re - man weiß ja nie) Version unter Befolgung 
aller Tips von Karl-Heinz. Tatsächlich ohne Warnung compilierbar ;-)

von Cyblord -. (cyblord)


Lesenswert?

Alex v. L. schrieb:
> Angehängt die aufgeräumte(re - man weiß ja nie) Version unter Befolgung
> aller Tips von Karl-Heinz. Tatsächlich ohne Warnung compilierbar ;-)

Tja, kaum macht man es richtig, schon gehts ;-)

von Karl H. (kbuchegg)


Lesenswert?

> Leider hat sich durch die Warnungsbehebung nicht der Fehler behoben

Tja.

Das hier
1
void circbuf_add(struct circular_buffer *buf, char value) {
2
  buf->data[buf->head] = value;
3
    buf->head++;
4
    buf->fillcount++;
5
  }
ist ja auch kein Ringbuffer.

Eigentlich ein Wunder, dass dein Programm nicht mehr Amok läuft.

: Bearbeitet durch User
von Alex V. (bastel_alex) Benutzerseite


Lesenswert?

Karl Heinz schrieb:
>> Leider hat sich durch die Warnungsbehebung nicht der Fehler
> behoben
>
> Tja.
>
> Das hiervoid circbuf_add(struct circular_buffer *buf, char value) {
>   buf->data[buf->head] = value;
>     buf->head++;
>     buf->fillcount++;
>   }
> ist ja auch kein Ringbuffer.

Irgendwie one-way, nicht?

von Karl H. (kbuchegg)


Lesenswert?

Alex v. L. schrieb:
> Karl Heinz schrieb:
>>> Leider hat sich durch die Warnungsbehebung nicht der Fehler
>> behoben
>>
>> Tja.
>>
>> Das hiervoid circbuf_add(struct circular_buffer *buf, char value) {
>>   buf->data[buf->head] = value;
>>     buf->head++;
>>     buf->fillcount++;
>>   }
>> ist ja auch kein Ringbuffer.
>
> Irgendwie one-way, nicht?

Ich würd mal sagen:

Irgendwie 'mir doch scheissegal wie gross der Speicher ist, ich knall 
das nächste Byte einfach hinten drann'.

Und von einem 'Ring' ist schon gleich gar nichts zu sehen.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Alex v. L. schrieb:
> Das Aufräumen nach deinen Anweisungen hat enorm etwas gebracht - es sind
> nur noch zwei x zwei Warnungen übrig: jeweils hinter den zwei typedef
> struct-deklarationen ohne variablendeklaration
>
> typedef struct
> circular_buffer {
>     char volatile *data;
>     int size;
>     char volatile fillcount;
>     char head;
>     char tail;
> };
>
> Bekomme ich einen "useless storage class specifier in empty
> declaration".

Lass einfach das typedef weg.

Du verwendest die Strukturtypen doch sowieso unter Angabe von
struct circular_buffer, dann ist das typedef unnötig.

Im oben zitierten Fall ist das typedef sogar unvollständig - Du gibst 
zwar an, welcher Typ definiert werden soll (Dein struct), lässt aber 
weg, als was (das ist das, was Du als "ohne Variablendeklaration" 
bezeichnest).

So ein typedef hat folgende Syntax:
1
typedef [Kram, der als neuer Datentyp definiert werden soll] Name für neuen Typ

Also beispielsweise
1
typedef int bla;

Das erzeugt einen neuen Datentyp namens "bla", der fortan genauso 
verwendet werden kann wie int:
1
  bla x;
2
3
  x = 4;

etc.

Bei einer Struktur und einem typedef davon sieht das genauso aus:
1
typedef 
2
  // --- ab hier folgt der "Kram, der als neuer Datentyp definiert werden soll"
3
  struct circular_buffer {
4
     char volatile *data;
5
     int size;
6
     char volatile fillcount;
7
     char head;
8
     char tail;
9
  }
10
  // --- das ist das Ende vom "Kram, der als neuer Datentyp definiert werden 
11
  TCircBuf;  // das ist der Name unseres neuen Datentyps

Damit kannst Du fortan anstelle von "struct circular_buffer" einfach 
"TCircBuf" schreiben:
1
uint8_t uart_ReceiveByte(TCircBuf *buf );
2
void uart_TransmitByte(TCircBuf *buf, uint8_t data );

von Alex V. (bastel_alex) Benutzerseite


Lesenswert?

Ja, ich glaube das reicht als hinweis. "wenn man nicht alles selber 
macht" ist wohl in dem sinne falsch: Wenn man sich nicht die mühe macht 
alles selber zu durchschauen. Ich habe ja als erstes selber einen 
UART-puffer bauen wollen, worauf ich (richtigerweise) hier im forum 
hingewiesen wurde doch nicht das rad neu zu erfinden. Und wenn man dann 
den "Ringpuffer" von wem anders einfach einbaut ist man selber schuld.
Danke für die Geduld!

von Alex V. (bastel_alex) Benutzerseite


Lesenswert?

Rufus Τ. Firefly schrieb:
> Damit kannst Du fortan anstelle von "struct circular_buffer" einfach
> "TCircBuf" schreiben:

Danke Rufus! Ja, so hatte ich Karl Heinz vorhin auch verstanden - und 
habe (weils schöner ist) jetzt überall im Code (auch in der aufgeräumten 
version oben)
1
CircBuf *buf
 stehen! ich bin ja echt überrascht und beeindruckt von eurem Feedback! 
:)

von Karl H. (kbuchegg)


Lesenswert?

Ich weiß ja nicht, wo du den her hast. Aber ich weiß mit Sicherheit, 
dass das kein Ringbuffer ist :-)
Das ist selbst für einen normalen linearen Buffer ein bischen zu 
schlampig geschrieben. Werte in ein Array schreiben, ohne zu prüfen ob 
man nicht mit dem Index das Array überläuft, ist bei einer so unviersell 
einsetzbaren Basiskomponente nicht tolerierbar. Das ist Mist, und zwar 
einer von der großen Sorte.

: Bearbeitet durch User
von Alex V. (bastel_alex) Benutzerseite


Lesenswert?

Karl Heinz schrieb:
> Das
> ist Mist, und zwar einer von der großen Sorte.

Ich bin jetzt auch überrascht. Ist schließlich mist aus einer 
diplomarbeit. Eventuell habe ich auch den unglaublich tollpatschigen 
fehler begangen bei dem header/c-namen "circbuf" von "circular buffer" 
und damit ringpuffer auszugehen. Ach nee, steht ja sogar im kommentar 
oben. :D
Nun denn, zurück zu meiner eigenen version.

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz schrieb:
> Ich weiß ja nicht, wo du den her hast. Aber ich weiß mit Sicherheit,
> dass das kein Ringbuffer ist :-)
> Das ist selbst für einen normalen linearen Buffer ein bischen zu
> schlampig geschrieben. Werte in ein Array schreiben, ohne zu prüfen ob
> man nicht mit dem Index das Array überläuft, ist bei einer so unviersell
> einsetzbaren Basiskomponente nicht tolerierbar. Das ist Mist, und zwar
> einer von der großen Sorte.



Jetzt mal davon abgesehen, dass es sich hier nicht um einen Ringbuffer 
handelt. Denn so ein Ringbuffer ist ja im Grunde nicht so schwer.
Er funktioniert wie das Zifferblatt einer Uhr, mit 60 Abstellplätzen und 
wo der "Sekunden"-zeiger anzeigt, wo das nächste Element abzulegen ist 
(und dann um 1 Stelle vorrückt). Logischerweise ist der Sekundenzeiger 
aber irgendwann mal rum, und die 60 Plätze sind benutzt worden, der 
Sekundenzeiger rückt ja immer nur vor und nicht zurück. Und so wie beim 
Sekundenzeiger geht es dann wieder bei 0 weiter. Und weil das 
Zifferblatt einer Uhr so schön rund ist und sich der Zeiger im Kreis 
dreht, nennt man das einen 'RingBuffer', weil man sich das verwendete 
Array wie zu einem Ring zusammengeklebt vorstellen kann. So wie die 
Markierungen auf einem Uhrblatt. Ist man "am Ende" angelangt, geht es 
"vorne" wieder weiter.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Alex v. L. schrieb:

> Ich bin jetzt auch überrascht. Ist schließlich mist aus einer
> diplomarbeit.

Jetzt wollen wir mal nicht unfair sein. Denn es gibt tatsächlich einen 
speziellen Fall, in dem dieser Coed tatsächlich als Ringbuffer arbeitet. 
Aber dazu müssen ein paar Voraussetzungen erfüllt sein
* char muss ein unsigned Datentyp sein
* die Länge des Arrays muss der 2-er Potenz der Bitzahl von char 
entsprechen. Auf Deutsch: beim wohl häufigsten Fall, dass ein char 8 Bit 
hat, muss das Array 256 Elemente gross sein.

Dann und nur dann ist das tatsächlich ein Ringbuffer, weil das 
Rücksetzen des head auf 0 dann implizit im Inkrement mit enthalten ist.

Das natürlich die Strukturdefinition da etwas ganz anderes suggeriert 
und nichts davon dokumentiert ist, ist allerdings eine ganz andere 
Geschichte.

von Alex V. (bastel_alex) Benutzerseite


Angehängte Dateien:

Lesenswert?

Ja, das Prinzip meinte ich auch schon verstanden zu haben. Ich hatte mir 
nämlich damals unter Verwendung des hiesigen FiFo Eintrags 
http://www.mikrocontroller.net/articles/FIFO meinen eigenen geschrieben.

Nur muss ich jetzt leider folgendes verkünden: Trotz verwendung des 
"richtigen" Ringpuffers (will zumindest heißen meines eigenen auf basis 
des µC.net eintrags) habe ich das selbe Verhalten am Terminal.

Wieder mal angehängt der aktuelle Satz files, jetzt mit dem eigenen 
Ringpuffer.

von Alex V. (bastel_alex) Benutzerseite


Lesenswert?

Karl Heinz schrieb:
> Auf Deutsch: beim wohl häufigsten Fall, dass ein char 8 Bit
> hat, muss das Array 256 Elemente gross sein.

Karl Heinz schrieb:
> Dann und nur dann ist das tatsächlich ein Ringbuffer, weil das
> Rücksetzen des head auf 0 dann implizit im Inkrement mit enthalten ist.

Ah das erklärt was, die länge war auf 256 Bytes definiert im 
Originalfile.

Nunja, leider erklärt das dann das Problem (auch bei Verwendung des 
anderen Buffers) nicht...

von Karl H. (kbuchegg)


Lesenswert?

Mal eine andere Frage.
Musst du die UART Funktionen bzw. den Ringbuffer selber schreiben oder 
darfst du auch auf externe Komponenten zurückgreifen?

Denn beim P.Fleury gibt es ein fix fertiges UART/Ringbuffer Modul, 
welches erstklassig funktioniert und all die kleinen Fallen auch schon 
umschifft hat. Es ist zwar nicht so schön universell in UART und Buffer 
getrennt, hat dafür aber den Vorteil aus dem Stand heraus zu 
funktionieren. Denn der Teufel steckt im Detail, dass sich der 
Ringbuffer nicht selbst überholt, bzw. dass die Interrupts korrekt und 
zum richtigen Zeitpunkt ein bzw. ausgeschaltet werden.

: Bearbeitet durch User
von Alex V. (bastel_alex) Benutzerseite


Lesenswert?

Karl Heinz schrieb:
> Musst du die UART Funktionen bzw. den Ringbuffer selber schreiben oder
> darfst du auch auf externe Komponenten zurückgreifen?

Müsste ich nicht. Das Fleury Package habe ich auch schon mal angeguckt, 
ich muss aber zugeben dass es mich in seiner komplexität (wahrscheinlich 
der allgemeingültigkeit geschuldet) etwas überfordert hat - und ich dann 
auch nicht sicher gewusst habe wie ich es in mein bestehendes interface 
einfüge.
Und dem Gefühl nach bin ich ja nur noch ganz dicht davor dass es einfach 
läuft! Naja, vielleicht trügt es ja. :(

von Alex V. (bastel_alex) Benutzerseite


Lesenswert?

Karl Heinz schrieb:
> Denn der Teufel steckt im Detail, dass sich der
> Ringbuffer nicht selbst überholt, bzw. dass die Interrupts korrekt und
> zum richtigen Zeitpunkt ein bzw. ausgeschaltet werden.

Ja, die Interrupts habe ich auch schon länger im Verdacht. Auch aus 
diesem Grund bin ich von Interruptgesteuerter SPI zu einer schlichten 
Funktion mit warten übergegangen. Der einzige Interrupt neben den UART 
Interrupts, den es gibt, ist nun noch der von Timer1, den ich für 
Timestamps verwenden will. Leider muss ich (soweit ich das bisher 
überschaut habe) den Output Compare Interrupt nutzen, damit ich bei 16 
bit und maximalem Clockdivider (1024) bei 20 MHz überhaupt auf einen 
10ms Counter komme. D.h. aber: alle 10ms gibts einen interrupt.

Aber: Wenn ich den timer zu testzwecken einfach ausmache, ist das 
problem auch nicht gelöst.

Wie könnte denn sich selbst überholen gehen?

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Alex v. L. schrieb:

> Müsste ich nicht. Das Fleury Package habe ich auch schon mal angeguckt,
> ich muss aber zugeben dass es mich in seiner komplexität (wahrscheinlich
> der allgemeingültigkeit geschuldet) etwas überfordert hat

alles halb so wild.
Die Grundfunktion ist auch nicht anders als das, was du gerade baust.

> auch nicht sicher gewusst habe wie ich es in mein bestehendes interface
> einfüge.

Das sollte aber nicht wirklich ein Problem sein.
Am Anfang ist es etwas gewöhnungsbedürftig, die get FUnktion so zu 
benutzen
1
int c;
2
3
  c = uart_getc();
4
5
  if( !( c & UART_NODATA ) )
6
  {
7
    // Juhu, da ist was vorrätig, verarbeite c
8
  }

aber so schlimm ist das auch wieder nicht. Du machst ja im Grunde auch 
nichts anderes, wenn du den Ringbuffer befragst, ob er empty ist oder 
nicht. Peter hat halt beide Informationen zusammen in einen int 
gesteckt: Ist ein Zeichen im UART-Modul vorrätig und wenn ja, welches 
Zeichen ist das?

Soooo groß ist der Unterschied nicht. Es ist anders, eine andere Idee 
der Realisierung. Aber bei genauerem Hinsehen ist es dieselbe 
Funktionalität.

Der Sendecode hingegen unterscheidet sich kaum. Du rufst eine der 
vorgefertigten Sendefunktionen auf und bist das zu sendende Zeichen 
(oder den String) los.

Was beim Fleury Code hinzukommt ist, dass der Code auf mehreren 
AVR-Typen einsetzbar ist und da Atmel die Dinge da unterschiedlich 
macht, sind da ein paar #define bzw. #ifdef drinnen um die Anpassung zu 
machen. Das dreht sich hauptsächlich um unterschiedliche Register- bzw. 
Bitnamen bzw. ISR-Namen, die Atmel leider nicht einheitlich nach einem 
Schema vergibt. Die kann man aber auch alle ausbauen bzw. entfernen, 
wenn man das Gefühl hat, dass sie stören.

: Bearbeitet durch User
von Alex V. (bastel_alex) Benutzerseite


Lesenswert?

Na dann schaue ich mir das jetzt nochmal an, inzwischen bin ich zu allem 
bereit! ;) (vielleicht verstehe ich es jetzt auch besser, die fleury 
dateien habe ich am anfang meiner einarbeitung angesehen)

von Karl H. (kbuchegg)


Lesenswert?

Im Zip-File ist ein Demobeispiel.

WEnn das compiliert und sauber funktioniert, dann hast du schon 
gewonnen. Dann wird dein AVR-Typ unterstützt (wegen der 
Registerbezeichnungen) und du kannst die Internals des Codes gleich mal 
ignorieren. (wobei: so schwer sind die auch wieder nicht zu verstehen. 
Peter kocht auch nur mit Wasser)

Der Code ist halt schon ein wenig älter. D.h. bei neueren Prozessoren 
müsste man unter Umständen die Register bzw. Interrupt Bezeichnungen 
nachtragen. Die hast du aber mit deinen 'Vorstudien' mitlerweile aber 
sowieso intus :-)

: Bearbeitet durch User
von Alex V. (bastel_alex) Benutzerseite


Lesenswert?

Danke für deine Hilfe! Ich grab mich rein. Ich werd schon rumschreien im 
Notfall ;)

von Karl H. (kbuchegg)


Lesenswert?

Alex v. L. schrieb:
> Danke für deine Hilfe! Ich grab mich rein. Ich werd schon rumschreien im
> Notfall ;)

Ist kein Problem. Wirst sehen, das geht in 0-komma-nix. Und wenn nicht, 
dann tragen wir deinen AVR einfach im Code nach und dann gehts in 
0-komma-nix

von Alex V. (bastel_alex) Benutzerseite


Lesenswert?

Der AtMega644 ist in der uart.c zumindest mitdefiniert. Nur welcher 
controller der zu verwendende ist ist mir unklar: Muss ich den angeben 
oder wird der vom Compiler "erkannt" (ist ja im Projekt angegeben)? 
(Gäbe es da einen Unterschied zwischen AVRGCC und AVRStudio6.1?)

von Karl H. (kbuchegg)


Lesenswert?

AVRStudio verwendet auch den AVR-Gcc, wenn auch eine neuere Version 
davon.

wird erkannt.
Für dich ist erst mal (bis zum Beweis des Gegenteils :_) nur das Header 
File interessant. Alles was dort mit einem #define einstellbar ist, 
darüber machst du dir Gedanken. Das C-File interessiert dich momentan 
überhaupt nicht (ausser es gibt irgendwann mal Fehler oder man will im 
Detail wissen, wie die Dinge funktionieren).

Denn genau so soll ja auch die Trennung C-File und Header-File sein: Das 
Header-File ist die Schnittstelle nach aussen. Zum verwendenden Code. 
Alles was der, bzw. der Programmierer desselben, wissen muss, findet er 
im Header File. Das C-File braucht er im Idealfall nie angreifen. Das 
wird einfach zum Projekt hinzugefügt, mitkompiliert und implementiert 
das, was das Header File verspricht.

: Bearbeitet durch User
von Alex V. (bastel_alex) Benutzerseite


Lesenswert?

Danke. Also erstmal compiliert er das noch nicht:
"Error  19  #error "no UART definition for MCU available"

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz schrieb:

> File interessant. Alles was dort mit einem #define einstellbar ist,
> darüber machst du dir Gedanken.

Wobei man natürlich darauf achten muss, was denn eigentlich wirklich 
einstellbar ist und welche #define so eine Art Vereinbarung von 
Benachrichtigungen sind. Aus dem Zusammenhang ist das aber normalerweise 
recht eindeutig. Das hier
1
#define UART_FRAME_ERROR      0x1000              /* Framing Error by UART       */
2
#define UART_OVERRUN_ERROR    0x0800              /* Overrun condition by UART   */
3
#define UART_PARITY_ERROR     0x0400              /* Parity Error by UART        */ 
4
#define UART_BUFFER_OVERFLOW  0x0200              /* receive ringbuffer overflow */
5
#define UART_NO_DATA          0x0100              /* no receive data available   */
ist ganz klar nichts, was du verändern kannst, sondern das sind Werte, 
die du in deinem Programm benutzen kannst um die Returnwerte von den 
Funktionen auszuwerten.

von Alex V. (bastel_alex) Benutzerseite


Lesenswert?

Aber es gibt ja den abschnitt
1
#elif defined(__AVR_ATmega644__)
2
 /* ATmega with one USART */
3
 #define ATMEGA_USART0
4
 #define UART0_RECEIVE_INTERRUPT   USART0_RX_vect
5
 #define UART0_TRANSMIT_INTERRUPT  USART0_UDRE_vect
6
 #define UART0_STATUS   UCSR0A
7
 #define UART0_CONTROL  UCSR0B
8
 #define UART0_DATA     UDR0
9
 #define UART0_UDRIE    UDRIE0

nur sehe ich im header keine möglichkeit die MCU als ATmega644 zu 
definieren... bin ich nur blind?

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Alex v. L. schrieb:
> Danke. Also erstmal compiliert er das noch nicht:
> "Error  19  #error "no UART definition for MCU available"

Dann ist das Symbol
_AVR_ATmega644_
doch nicht definiert.

Wundert mich, sollte es eigentlich. Dem Compiler wird auf der Command 
Line, beim Aufruf der Typ des µC mitgegeben. Je nachdem wird dann in 
avr/io.h das zu diesem Prozessor passende spezielle Include File 
includiert und das definiert dann diese Konstante.

Kannst du den Compiler Aufruf in der IDE sehen? (Output Fenster oder so)
Wie sieht der Aufruf aus?

von Karl H. (kbuchegg)


Lesenswert?

Ah warte mal.

Es gibt den 644 und den 644P

welchen hast du eingestellt?

von Alex V. (bastel_alex) Benutzerseite


Lesenswert?

Sorry für den kompletten text hier aber bevor ich jetzt irgendwas 
unverstandenes von mir gebe: Das ist der Output vom Compiler
1
------ Build started: Project: MainBoard_UART, Configuration: Debug AVR ------
2
Build started.
3
Project "MainBoard_UART.cproj" (default targets):
4
Target "PreBuildEvent" skipped, due to false condition; ('$(PreBuildEvent)'!='') was evaluated as (''!='').
5
Target "CoreBuild" in file "D:\Program Files (x86)\Atmel\Atmel Studio 6.1\Vs\Compiler.targets" from project "D:\Eigene Dateien\Office\UNI\Studium\11. Semester (Masterarbeit)\Hardware\Code\MainBoard_UART\MainBoard_UART\MainBoard_UART.cproj" (target "Build" depends on it):
6
  Task "RunCompilerTask"
7
    D:\Program Files (x86)\Atmel\Atmel Studio 6.1\shellUtils\make.exe all 
8
    Building file: .././uart.c
9
    Invoking: AVR/GNU C Compiler : 3.4.2
10
    "D:\Program Files (x86)\Atmel\Atmel Toolchain\AVR8 GCC\Native\3.4.2.1002\avr8-gnu-toolchain\bin\avr-gcc.exe"  -funsigned-char -funsigned-bitfields -DDEBUG  -O1 -ffunction-sections -fdata-sections -fpack-struct -fshort-enums -g2 -Wall -mmcu=atmega644a -c -std=gnu99 -MD -MP -MF "uart.d" -MT"uart.d" -MT"uart.o"   -o "uart.o" ".././uart.c"
11
D:\Eigene Dateien\Office\UNI\Studium\11. Semester (Masterarbeit)\Hardware\Code\MainBoard_UART\MainBoard_UART\uart.c(233,3): #error "no UART definition for MCU available"
12
    .././uart.c: In function 'UART0_RECEIVE_INTERRUPT':
13
D:\Eigene Dateien\Office\UNI\Studium\11. Semester (Masterarbeit)\Hardware\Code\MainBoard_UART\MainBoard_UART\uart.c(260,1): 'UART0_RECEIVE_INTERRUPT' appears to be a misspelled signal handler [enabled by default]
14
D:\Eigene Dateien\Office\UNI\Studium\11. Semester (Masterarbeit)\Hardware\Code\MainBoard_UART\MainBoard_UART\uart.c(273,12): 'UART0_STATUS' undeclared (first use in this function)
15
D:\Eigene Dateien\Office\UNI\Studium\11. Semester (Masterarbeit)\Hardware\Code\MainBoard_UART\MainBoard_UART\uart.c(273,12): each undeclared identifier is reported only once for each function it appears in
16
D:\Eigene Dateien\Office\UNI\Studium\11. Semester (Masterarbeit)\Hardware\Code\MainBoard_UART\MainBoard_UART\uart.c(274,12): 'UART0_DATA' undeclared (first use in this function)
17
D:\Eigene Dateien\Office\UNI\Studium\11. Semester (Masterarbeit)\Hardware\Code\MainBoard_UART\MainBoard_UART\uart.c(268,19): variable 'usr' set but not used [-Wunused-but-set-variable]
18
    .././uart.c: In function 'UART0_TRANSMIT_INTERRUPT':
19
D:\Eigene Dateien\Office\UNI\Studium\11. Semester (Masterarbeit)\Hardware\Code\MainBoard_UART\MainBoard_UART\uart.c(305,1): 'UART0_TRANSMIT_INTERRUPT' appears to be a misspelled signal handler [enabled by default]
20
D:\Eigene Dateien\Office\UNI\Studium\11. Semester (Masterarbeit)\Hardware\Code\MainBoard_UART\MainBoard_UART\uart.c(319,9): 'UART0_DATA' undeclared (first use in this function)
21
D:\Eigene Dateien\Office\UNI\Studium\11. Semester (Masterarbeit)\Hardware\Code\MainBoard_UART\MainBoard_UART\uart.c(322,9): 'UART0_CONTROL' undeclared (first use in this function)
22
D:\Eigene Dateien\Office\UNI\Studium\11. Semester (Masterarbeit)\Hardware\Code\MainBoard_UART\MainBoard_UART\uart.c(322,27): 'UART0_UDRIE' undeclared (first use in this function)
23
    .././uart.c: In function 'uart_putc':
24
D:\Eigene Dateien\Office\UNI\Studium\11. Semester (Masterarbeit)\Hardware\Code\MainBoard_UART\MainBoard_UART\uart.c(471,5): 'UART0_CONTROL' undeclared (first use in this function)
25
D:\Eigene Dateien\Office\UNI\Studium\11. Semester (Masterarbeit)\Hardware\Code\MainBoard_UART\MainBoard_UART\uart.c(471,25): 'UART0_UDRIE' undeclared (first use in this function)
26
    make: *** [uart.o] Error 1
27
  Done executing task "RunCompilerTask" -- FAILED.
28
Done building target "CoreBuild" in project "MainBoard_UART.cproj" -- FAILED.
29
Done building project "MainBoard_UART.cproj" -- FAILED.
30
31
Build FAILED.
32
========== Build: 0 succeeded or up-to-date, 1 failed, 0 skipped ==========

von Alex V. (bastel_alex) Benutzerseite


Lesenswert?

644. Aber beide sind von Fleury definiert

von Karl H. (kbuchegg)


Lesenswert?

Da, in der Command Line
1
.... -mmcu=atmega644a ...

mit dem wird das geregelt.

Jetzt weiß ich aber nicht, wie die entsprechende _AVR..... Konstante 
dazu heißt, bzw. was der Unterschied zwischen einem 644A und dem 
normalen 644 ist.

von Karl H. (kbuchegg)


Lesenswert?

Eine Möglichkeit wäre (so hab ich auch gefunden, dass der P Typ 
unterschieden wird):

Schau in die avr/io.h rein.
Bei mir findet sich da (ich hab hier noch eine ganz alte Version vom 
avr-gcc)
1
....
2
#elif defined (__AVR_ATmega644__)
3
#  include <avr/iom644.h>
4
#elif defined (__AVR_ATmega644P__)
5
#  include <avr/iom644.h>
6
....

da sind also 2 verschiedene 644 eingetragen. Der normale und der P Typ. 
Beide führen aber in jeweils dasselbe iom644.h, so dass man davon 
ausgehen kann, dass die beiden softwaretechnisch identisch zu behandeln 
sind.

Ich schätze mal, das wird beim 644A auch nicht anders sein.
Aber schau ins io.h. Wenn ich richtig liege, dann gibt es dort dann auch 
noch ein #elif für den _AVR_ATmega644A_, welcher ebenfalls in iom644.h 
weiter gibt.

: Bearbeitet durch User
von Alex V. (bastel_alex) Benutzerseite


Lesenswert?

Womit du mich darauf gebracht hast dass ich zu beginn des Projektes den 
644A angegeben habe (register sind in meinem fall gleich) - habe jetzt 
auf 644 umgestellt (das ist auch der tatsächliche controller):

Jetzt bekomme ich nur noch "undefined reference to PSTR" drei mal sowie 
"ld returned 1 exit status"

Wobei ich wenn ic hdem fehler folge zur uart_puts_P("  ") Funktion in 
der main komme..

: Bearbeitet durch User
von Alex V. (bastel_alex) Benutzerseite


Lesenswert?

Ok habs. compiliert ist.

von Karl H. (kbuchegg)


Lesenswert?

Alex v. L. schrieb:
> Womit du mich darauf gebracht hast dass ich zu beginn des Projektes den
> 644A angegeben habe (register sind in meinem fall gleich) - habe jetzt
> auf 644 umgestellt (das ist auch der tatsächliche controller):
>
> Jetzt bekomme ich nur noch "undefined reference to PSTR" drei mal sowie
> "ld returned 1 exit status"
>
> Wobei ich wenn ic hdem fehler folge zur uart_puts_P("  ") Funktion in
> der main komme..


:-)
Da hat der Peter das nicht gemacht, was ich dir oben gepredigt habe.

PSTR ist ein Makro aus
1
#include <avr/pgmspace.h>

das Header File verwendet PSTR, also müsste das Header File diesen 
Header inkludieren. Tut es aber nicht, statt dessen macht es die 
test_uart.c, also das verwendende Programm.

: Bearbeitet durch User
von Alex V. (bastel_alex) Benutzerseite


Lesenswert?

jup, habe eben auch gesehen dass ich die pgmspace nicht includiert 
hatte.

Gut, ich denke damit kann ich umrüsten, das terminal gibt mir meinen 
input wieder aus, so wie der code es vorhersagt ;)

Die zwei funktionen, die für mich nun interessant sind, sind ja wohl
1
 = uart_getc();
und
1
uart_putc( (unsigned char)c );

Wie ich getc verarbeite ist ja durch den kommentar im code klar: das 
lower byte ist mein datenbyte.
putc ist ja dann eigentlich analog, ich gehe davon aus dass das higher 
byte automatisch gefüllt wird oder leer bleibt - d.h. ich kann beide 
funktionen nutzen wie meine alten write_byte und read_bytes korrekt? :)

von Alex V. (bastel_alex) Benutzerseite


Lesenswert?

Ach super, läuft. Dann werde ich diesen Abend mal nutzen um die 
bestehenden Funktionen umzuschreiben und dann habe ich seelenfrieden! ;D
Danke!!

von Karl H. (kbuchegg)


Lesenswert?

Alex v. L. schrieb:
> jup, habe eben auch gesehen dass ich die pgmspace nicht includiert
> hatte.
>
> Gut, ich denke damit kann ich umrüsten, das terminal gibt mir meinen
> input wieder aus, so wie der code es vorhersagt ;)
>
> Die zwei funktionen, die für mich nun interessant sind, sind ja wohl
>
>
1
 = uart_getc();
> und
>
1
uart_putc( (unsigned char)c );
>
> Wie ich getc verarbeite ist ja durch den kommentar im code klar: das
> lower byte ist mein datenbyte.

Exakt.
Daher auch der Return Typ von int.

Das macht aber nichts, du kannst das in weiterer Folge genauso 
verwenden, wie wenn es ein char wäre. Wenn kein Fehler vorliegt und ein 
Zeichen da ist, dann ist das High-Byte 0x00 und damit funktionieren alle 
Vergleiche
1
  if ( c == 'a' )
wie bisher. Du kannst natürlich das High-Byte auch (nach Fehlerprüfung) 
loswerden, indem du auf einen echten char umkopierst. Aus C Sicht ist es 
aber nicht notwendig.

von Alex V. (bastel_alex) Benutzerseite


Lesenswert?

Danke Karl Heinz. Ich stehe in deiner Schuld. Wenn du mal was kleines 
3D-gedruckt brauchst gib mir bescheid! ;-)

von Alex V. (bastel_alex) Benutzerseite


Lesenswert?

Noch wegen der Reinlichkeit: wenn ich z.B.
1
uart_puts_P("TEMP: ");

schreibe bekomme ich eine warnung
"passing argument 1 of 'uart_puts_p' makes pointer from integer without 
a cast [enabled by default]"

Wie werde ich die los? Ich weiß, dass ich casten könnte - aber so war 
die funktion ja eigentlich nicht gedacht (und wird ja auch im beispiel 
so verwendet)..

von Alex V. (bastel_alex) Benutzerseite


Angehängte Dateien:

Lesenswert?

So. Jetzt habe ich das alles übertragen und durchgeprügelt und freue 
mich erst und könnte dann schreien. Denn:
Nach ca. 20 erfolgreichen Übertragungen bekomme ich den selben (sorry) 
SCHEISS wieder, dann renkt es sich wieder ein, dann spinnts wieder:
1
M1;C0;S0;1B12;003A
2
M1;C0;S0;1B12;00AC
3
M1;C0;S0;1B12;00DE
4
M1;C0;S0;1B12;0110
5
M1;C0;S0;1B12;0101
6
M1;C0;S0;1B12;0133
7
M1;C0;S0;1B12;01A1
8
M1;C0;S0;1B12;01D3
9
M1;C0;S0;1B12;0201
10
M1;C0;S0;1B12;023B
11
M1;C0;S0;1B12;022D
12
1E
13
M1
14
0;S0;1B12;02D0
15
0;S0;1B12;02M0
16
0;S0;1B11;02M1;C0;S0;1B12;0302
17
30
18
M1
19
0;S0;1B12;03M1;C0;S0;1B12;0322
20
;1B12;0310
21
M1B12;03M1;C0;S0;1B11;03CA
22
FB
23
M1
24
0;S0;1B12;03;1B12;002D
25
0;S0;1B12;03M1B12;00M1;C0;S0;1B12;001F
26
M1;C0;S0;1B12;0011
27
;1B12;00C3
28
M1B12;00;1B12;00F1
29
M1B12;00M1B12;00M1;C0;S0;1B12;0122
30
;1B12;0110
31
M1B12;01M1;C0;S0;1B12;010A
32
M1;C0;S0;1B12;01BC
33
M1;C0;S0;1B12;01EE
34
M1;C0;S0;1B12;0A20

Woran kann das bitte liegen? Nun nicht mehr am Ringpuffer oder der 
UART-Umsetzung, da habe ich ja jetzt zu 100% Peter Fleury's library 
genommen.
Der Timer-Interrupt war beim ersten versuch auch aus (macht keinen 
Unterschied), das heißt aktiv waren im ersten Testfall nur Peters 
interrupts.

Ich mache jetzt schluss für heute, ich sitze seit knapp 10 stunden ohne 
pause dran. Wenn hier noch irgendjemand hilfe weiß bin ich ihm mehr als 
nur einen 3D Druck (oder zumindest den) schuldig.
Immerhin kann ich jetzt strings über UART schicken, ging vorher nicht. 
War die Umstellung auf Fleury's library also nicht umsonst... Ha....

von Alex V. (bastel_alex) Benutzerseite


Lesenswert?

Kann es irgendwie noch an den Baudrateneinstellungen liegen?

Ich nutze einen 20MHz externen NX5032GA SMD Quarz mit C=12pF beschaltet.

Bei 9600 bps mit Baudratenregisterwert 130 gibt das nach µC-net Rechnung 
(http://www.mikrocontroller.net/articles/AVR-Tutorial:_UART) 0,22% 
fehler
Bei 38400 bps mit Registerwert 32 (-)0,157%.
Das sollte also eigentlich gehen oder nicht?!

von Karl H. (kbuchegg)


Lesenswert?

Vielleicht hab ichs auch übersehen, aber
1
  TIMSK1 |= (1<<OCIE1A);                  // Timer/Counter1 Output Compare Interrupt Request

du gibst hier einen Interrupt frei. Ich finde aber keine zugehörige ISR.
WEnn du tatsächlich keine ISR dafür hast, dann machts peng, sobald der 
erste Compare Match vorliegt.

von Karl H. (kbuchegg)


Lesenswert?

Hat das eigentlich einen Grund warum die send_ADC_Data so dermassen 
komplex aufgebaut ist.
(Ist das gewollt, dass die interne Kanalnummer nicht mit der per UART 
übertragenen übereinstimmt?)

Denn so ging das doch viel einfacher, wenn ich das richtig sehe
1
void send_ADC_data (uint8_t active_module, uint8_t active_channel, bool Speedmode, uint16_t adc_value, uint16_t timestamp) {
2
  char buffer[40];
3
4
  sprintf( buffer, "M%d;C%d;S%d;%04X;%04X\r\n", active_module,
5
                                                active_channel,
6
                                                (int)Speedmode,
7
                                                adc_value,
8
                                                timestamp );
9
  uart_puts( buffer );
10
}

und selbst wenn du sprintf nicht benutzen willst, durch die Einführung 
von ein paar Hilfsfunktionen könntest du dir da eine Menge Arbeit 
ersparen.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Zu dem PSTR Problem.
Ich weiß nicht, wo die Warnung herkommt.
Ich hab sie bei mir nicht und ich sehe in den Headerfiles auf meinem 
System auch keinen Grund, warum die kommen würde.

Ich kann sie aber, wenn ich 'Gewalt anwende' forcieren. Aber da muss ich 
die _p Funktion schon vergewaltigen.

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz schrieb:

>
1
>   TIMSK1 |= (1<<OCIE1A);                  // Timer/Counter1 Output 
2
> Compare Interrupt Request
3
>

Ach nein, da
1
// Timer Compare Match A Interrupt (each ~10ms)
2
ISR(TIMER1_COMPA_vect) {
3
  timer_ms_counter++;
4
}
ist sie ja.

Jetzt wirds aber wirklich spannend, wo da das Problem liegt. Ich nehm 
mir nochmal die originale Ausgabefunktion vor.

von Karl H. (kbuchegg)


Lesenswert?

Nope.
Ich seh nix mehr.

Da hilft nur noch eines: abspecken und das Pgm nochmal in Schritten neu 
aufbauen.
1
...
2
3
volatile uint16_t timer_ms_counter;                
4
5
int main(void)
6
{
7
  bool speedmode = false;
8
  bool tempmeas = false;
9
  uint8_t active_channel= 0;
10
  uint8_t active_module= 1;
11
  uint16_t adc_value =0;              
12
  unsigned int c;
13
14
  uart_init(UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU));          
15
16
  sei();
17
18
  while(1) {  
19
    send_ADC_data(active_module, active_channel,
20
                  speedmode, adc_value, timer_ms_counter);
21
    _delay_ms(500);
22
  }
23
}

damit gehts los
und dann wird sukzessive ein Teil nach dem anderen wieder eingebaut.
Wenn die Ausgabe problemlos funktioniert (wovon ich ausgehe), ist als 
nächstes der Timer drann, der die Millisekunden hochzählt.
Dann SPI initialisieren
dann ADC abfragen
dann Abfrage auf Benutzerwunsch.

Nach jeder Erweiterung exzessiv testen. Lieber einmal zuviel testen und 
die Erweiterungen nur in kleinen Schritten machen (selbst wenn damit 
kein Fehler zu erwarten ist), als das Auftreten der Fehlersituation 
übersehen.

: Bearbeitet durch User
von Kaj (Gast)


Lesenswert?

Alex v. L. schrieb:
> Bei 9600 bps mit Baudratenregisterwert 130 gibt das nach µC-net Rechnung
Dann schau mal ins Datenblatt... Da steht nämlich (fosc=20MHz) 
129(U2X=0) bzw. 259(U2X=1), nicht 130! aber mit den 0,2% Fehler liegst 
du richtig ;)

Grüße

von Kaj (Gast)


Lesenswert?

Alex v. L. schrieb:
> Ich nutze einen 20MHz externen NX5032GA SMD Quarz mit C=12pF beschaltet.
Schonmal mit 22pF probiert?

von Alex V. (bastel_alex) Benutzerseite


Lesenswert?

Karl Heinz schrieb:
> Hat das eigentlich einen Grund warum die send_ADC_Data so dermassen
> komplex aufgebaut ist.

Nein, nur mal wieder meine begrenzten C-Kenntnisse! ;-)

> (Ist das gewollt, dass die interne Kanalnummer nicht mit der per UART
> übertragenen übereinstimmt?)

Eigentlich nicht. Aber das ist mir bisher auch noch nicht aufgefallen! 
Eigentlich hat die konfigurierte mit der ausgegebenen bisher immer 
gestimmt (default 0)..?

Kaj schrieb:
> Dann schau mal ins Datenblatt... Da steht nämlich (fosc=20MHz)
> 129(U2X=0) bzw. 259(U2X=1), nicht 130! aber mit den 0,2% Fehler liegst
> du richtig ;)

Interessant... ich hatte die 
http://www.mikrocontroller.net/articles/AVR-Tutorial:_UART Formel 
verwendet, da bekomme ich nach Rechnung exakt 129,7 raus (aufgerundet 
130) aber: Kann in diesem fall auch nicht der punkt sein, die berechnung 
übernimmt die (funktionierende) Fleury Lib.

Kaj schrieb:
> Schonmal mit 22pF probiert?

Nein - Meinst du das macht sinn? Das könnte ich natürlich leicht 
überprüfen - aber auch hier bin ich laut 
http://www.mikrocontroller.net/articles/Quarze_und_AVR Erfahrungswert 
auf C = 2·CL – (CP+CI) = 2*8pf -(5pF) = 11 gekommen und nutze 12. Aber 
die C-Geschichte würde ja auch mit meiner Frage nach 
Quarz/Baudratenquarz zusammenhängen. Was mich an der Annahme dass es der 
quarz sein könnte allerdings stört ist, dass ich ja keine Bitfehler als 
solches erkennen kann in der Übertragung - die ASCII-Symbole bleiben die 
gleichen, nur wild zerhackt...

von Karl H. (kbuchegg)


Lesenswert?

Alex v. L. schrieb:

> Kaj schrieb:
>> Dann schau mal ins Datenblatt... Da steht nämlich (fosc=20MHz)
>> 129(U2X=0) bzw. 259(U2X=1), nicht 130! aber mit den 0,2% Fehler liegst
>> du richtig ;)
>
> Interessant... ich hatte die
> http://www.mikrocontroller.net/articles/AVR-Tutorial:_UART Formel
> verwendet, da bekomme ich nach Rechnung exakt 129,7 raus (aufgerundet
> 130) aber: Kann in diesem fall auch nicht der punkt sein, die berechnung
> übernimmt die (funktionierende) Fleury Lib.

Ich denke nicht, dass es irgendwas mit dem Quarz zu tun hat.
Der mag ein wenig daneben sein, aber einen gewissen Fehler darf man sich 
erlauben. DIe Ausgabe funktioniert ja grundsätzlich und dann ist ja auch 
noch das Stoppbit, welches einen eventuellen Baudratefehler beim 
nächsten Zeichen wieder ausnullt. Sprich: Wenn die ersten Zeichen 
korrekt rüber kommen, dann gibt es keinen Grund, warum das in weiterer 
Folge nicht auch so sein soll. Die Synchronisierung findet ja bei jedem 
Zeichen erneut mit dem Startbit statt. Ist die Baudrate daneben, dann 
wirkt sich das innerhalb eines Zeichens aus. Aber dann innerhalb jedes 
Zeichens. Bei den allerersten genauso wie bei den folgenden.

von Alex V. (bastel_alex) Benutzerseite


Lesenswert?

Merkwürdig ist, dass diese umbruchfehler im Empfang mit der Länge des zu 
sendenden Strings zu tun haben. Wenn ich mir z.B. nur die Temperatur 
ausgeben lasse "TEMP:02D2" Dann klappt das ziemlich lange fehlerfrei.

von Karl H. (kbuchegg)


Lesenswert?

Wer empfängt eigentlich?

Terminal-Programm oder etwas selbstgestricktes?

von Alex V. (bastel_alex) Benutzerseite


Lesenswert?

Terminal v1.91b von Br@y. Aber gute Frage bei mir kann man ja alles 
erwarten ;)

von Alex V. (bastel_alex) Benutzerseite


Lesenswert?

Dabei allerdings hast du mich auf etwas gebracht und rate mal:

Wenn ich hyperterminal bekomme ist alles sauber. Gleiche einstellungen 
(Jetzt mal mit 9600 bps, 8bits, kein parity, 1stopBit)...

von Alex V. (bastel_alex) Benutzerseite


Lesenswert?

Gott sagt mir jetzt nicht dass es am Terminalprogramm lag. ich glaubs 
nicht. hat ja nur nen tag gedauert das zu bemerken (verstehen tu ichs 
allerdings nicht so ganz ;-)

von Karl H. (kbuchegg)


Lesenswert?

Alex v. L. schrieb:
> Gott sagt mir jetzt nicht dass es am Terminalprogramm lag.

LOL

> ich glaubs
> nicht. hat ja nur nen tag gedauert das zu bemerken (verstehen tu ichs
> allerdings nicht so ganz ;-)

Ich kann dich beruhigen. Der Ringbuffer vom Diplomanden war mies. Deine 
Version hab ich mir dann nicht näher angesehen, als klar war, dass du 
auf Fleury wechseln wirst.

Zum Thema verstehen:
Jetzt wärs interessant zu wissen, ob dieses Terminalprogramm Handshake 
benutzt um die Gegenstelle kurz ruhig zu stellen (was natürlich auf AVR 
Seite niemanden interessiert).
Seltsam wärs aber doch: Auf einem GhZ Rechner kommt ein Terminalprogramm 
mit einer 9600 Baud Übertragung nicht hinterher? Das klingt für mich 
erst mal sehr an den Haaren herbeigezogen. Aber die Fakten sprechen 
scheinbar eine deutliche Sprache.

von Alex V. (bastel_alex) Benutzerseite


Angehängte Dateien:

Lesenswert?

Karl Heinz schrieb:
> Jetzt wärs interessant zu wissen, ob dieses Terminalprogramm Handshake
> benutzt um die Gegenstelle kurz ruhig zu stellen

Kann man alles einstellen, das Programm WIRKTE toll! ;)
Da kann ja mal wer (wenns denn von interesse ist) nen eigenen thread zu 
aufmachen um das zu evaluieren :D

Und um noch ein bisschen TNT ins Feuer zu werfen: Ich habe windows 8. 
Hyperterminal ist immerhin ein windoofs programm. man weiß ja nie ;D

: Bearbeitet durch User
von Alex V. (bastel_alex) Benutzerseite


Lesenswert?

Jetzt ist mir wirklich noch enorm ein Stein vom herzen gefallen. Das 
wollte ich unbedingt vorm Wochenende fertig bekommen.
Allerherzlichen Dank für all die Hilfe, vorallem von dir Karl-Heinz!
Dazu noch einmal das ausdrückliche Angebot: Wenn du mal was kleines 
3D-Gedruckt brauchst sag bescheid. Mann kann tolle Elektro-Basteleien 
damit aufbauen an die man vorher gar nicht denken mochte (und das sogar 
mir meinen bescheidenen c-kenntnissen): Ein beispiel was ich vor nem 
halben jahr damit angestellt habe:

http://www.youtube.com/watch?v=9wgsGA2k9a4
Meld dich falls du mal interesse haben solltest! :)

Jetzt implementiere ich endlich mal das, was ich den ganzen tag 
eigentlich machen wollte.

Gute Nacht zusammen!!

von Karl H. (kbuchegg)


Lesenswert?

Alex v. L. schrieb:
> Jetzt ist mir wirklich noch enorm ein Stein vom herzen gefallen. Das
> wollte ich unbedingt vorm Wochenende fertig bekommen.

Dann liegst du ja gut in der Zeit.
Ich denke, es hat sich trotzdem gelohnt. Da war einiges am nebenbei 
angefallenem 'Kollateralschaden' dabei, der dich auch ein wenig weiter 
gebracht hat. Und alleine das ist ja auch schon was wert.

Allerdings muss ich jetzt erst mal meine gern ausgesprochene Empfehlung 
überdenken, eine UART erst mal mit der Datenrichtung AVR->PC und einem 
Terminalprogramm überdenken. Bisher bin ich immer davon ausgegangen, das 
wäre die sichere Alternative, weil das PC-seitig auf jeden Fall erst mal 
korrekt funktioniert.


> Dazu noch einmal das ausdrückliche Angebot: Wenn du mal was kleines
> 3D-Gedruckt brauchst sag bescheid.

mach ich. Danke fürs Angebot.

: Bearbeitet durch User
von Alex V. (bastel_alex) Benutzerseite


Lesenswert?

Karl Heinz schrieb:
> weil das PC-seitig auf jeden Fall erst mal
> korrekt funktioniert.

Hängt dann wohl vom Terminalprogramm ab.
Ich muss mir jetzt auch erstmal ein neues suchen, mit dem ich 
unproblematisch einzelne bytes an den µC schicken kann (beim 
hyperterminal weiß ich zumindest noch nicht wie, das ist ja eher 
puristisch und verlangt dann noch eine datei..)

von Karl H. (kbuchegg)


Lesenswert?

HTerm ist eigentlich hier im Forum der Spitzenreiter, wenns um alle 
möglichen Spezialfälle der Übertragung geht.

http://www.der-hammer.info/terminal/

: Bearbeitet durch User
von Alex V. (bastel_alex) Benutzerseite


Lesenswert?

Grade getestet, funktioniert einwandfrei bei mir. Danke!

Ergo: Terminal von Br@y mit Vorsicht genießen!

von fbi (Gast)


Lesenswert?

Alex v. L. schrieb:
> Ergo: Terminal von Br@y mit Vorsicht genießen!

Die vorherige Version funktioniert bei mir bisher problemlos.

Auf http://sites.google.com/site/terminalbpp ist der Link zwar nicht 
mehr, geht aber trotzdem:

http://sites.google.com/site/terminalbpp/Terminal20130116.zip

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.