Forum: Mikrocontroller und Digitale Elektronik Look-up Tabelle wird nicht anständig gelesen


von Stephan (Gast)


Lesenswert?

Hallo!

Vorweg: ich wünsche ein frohes neues Jahr!


Folgendes, hochkomplexe Softwarekonstrukt, verwirrt mich:
1
const unsigned char tabelle[] = {0x01,0x10,0x20,0x30,0x10,0x20,0x30,0x20,0x30};
2
3
void show_values(void)
4
{      
5
  unsigned int i;  
6
  
7
  for (i=0; i<6; i++)
8
  {      
9
      uart_putc(tabelle[i]);
10
  }

Denn die Ausgabe liefert nur sechs Nullen!

Wenn ich aber die Schleife verkürze, also i<5 oder noch kürzer, werden 
die korrekten Wert der Tabelle ausgegeben, also 0,1,2,3,4

Woher kommt sowas?!

von Peter II (Gast)


Lesenswert?

Stephan schrieb:
> korrekten Wert der Tabelle ausgegeben, also 0,1,2,3,4

wie kommst du auf diese werte? Ich kann keinen Bezug zu den Hexzahlen 
herstellen.

von Stephan (Gast)


Lesenswert?

Peter II schrieb:
> wie kommst du auf diese werte? Ich kann keinen Bezug zu den Hexzahlen
> herstellen.

Oh shit, tschuldige.
Die Ausgabe lautet natürlich 1,0,20,30... bei der gegebenen Tabelle.

von Peter II (Gast)


Lesenswert?

Stephan schrieb:
> Oh shit, tschuldige.
> Die Ausgabe lautet natürlich 1,0,20,30... bei der gegebenen Tabelle.

das kann auch nicht sein.

von Stephan (Gast)


Lesenswert?

Peter II schrieb:
> das kann auch nicht sein.

Jetzt aber.. 1,10,20,30 (hex)
Bzw. 1,16,3,48,16 (dec)

von Mladen G. (mgira)


Lesenswert?

unsigned int als index fuer ein Byte Array?

Meine C Zeiten sind lange vorbei, meine aber mich zu erinnern dass dein 
index wohl besser auch ein byte ist, da C einfach nur die Index 
"groesse" (Datentyp) mit dem Indexwert zu Arrayoffset Addresse addiert.

: Bearbeitet durch User
von Stephan (Gast)


Lesenswert?

Stephan schrieb:
> Jetzt aber.. 1,10,20,30 (hex)
> Bzw. 1,16,3,48,16 (dec)

ICH DREH GLEICH AM RAD!!

von SkyperHH (Gast)


Lesenswert?

Was macht Funktion uart_putc(...); aus den Werten?

Wenn die Zahlen in ASCII Zeichen überzsetzt werden, kommen für die Werte 
der Tabelle folgende "Sonderzeichen" zu stande:

{0x01,0x10,0x20,0x30,0x10,0x20,0x30,0x20,0x30};
  SOH, DLE,  SP,   0, DLE,  SP,   0,  SP,   0

von Peter II (Gast)


Lesenswert?

Mladen G. schrieb:
> Meine C Zeiten sind lange vorbei, meine aber mich zu erinnern dass dein
> index wohl besser auch ein byte ist, da C einfach nur die Index
> "groesse" (Datentyp) mit dem Indexwert zu Arrayoffset Addresse addiert.

nein das ist schon so ok. Byte gibt es in C nicht. Und ein index darf 
sogar negativ sein.

von Stephan (Gast)


Lesenswert?

SkyperHH schrieb:
> Was macht Funktion uart_putc(...); aus den Werten?

Werden ohne Übersetzung in den Ringbuffer gelegt und gesendet.

von Schlumpf (Gast)


Lesenswert?

Stephan schrieb:
> ICH DREH GLEICH AM RAD!!

pruuuust ;-)

So, jetzt konzentriere dich mal, atme ein, und aus und dann gaaaaaanz 
langsam.....

von SkyperHH (Gast)


Lesenswert?

Aha... und Empfangen tut das ein Terminal am PC?

von Stephan (Gast)


Lesenswert?

Schlumpf schrieb:
> So, jetzt konzentriere dich mal, atme ein, und aus und dann gaaaaaanz
> langsam.....

Zu viel Kaffee.

SkyperHH schrieb:
> Aha... und Empfangen tut das ein Terminal am PC?

Genau!

von Schlumpf (Gast)


Lesenswert?

Stephan schrieb:
> Werden ohne Übersetzung in den Ringbuffer gelegt und gesendet.

... und dann am PC von einem Terminalprogramm empfangen und 
dargestellt???

von Peter II (Gast)


Lesenswert?

Stephan schrieb:
>> Was macht Funktion uart_putc(...); aus den Werten?
>
> Werden ohne Übersetzung in den Ringbuffer gelegt und gesendet.

und ist der Ringpuffer auch gross genug?

von Stephan (Gast)


Lesenswert?

1
int i;
2
i=0;
3
4
uart1_putc(tabelle[i]);
5
i++;
6
uart1_putc(tabelle[i]);
7
i++;
8
uart1_putc(tabelle[i]);
9
i++;
10
uart1_putc(tabelle[i]);
11
i++;
12
uart1_putc(tabelle[i]);
13
i++;
14
uart1_putc(tabelle[i]);
15
i++;
16
uart1_putc(tabelle[i]);

liefert das richtige Ergebnis....

von Schlumpf (Gast)


Lesenswert?

Stephan schrieb:
> Genau!

Und was stellt das Terminalprogramm dar? Ich vermute mal ASCII-Zeichen? 
oder? :-)

von Stephan (Gast)


Lesenswert?

Schlumpf schrieb:
> Ich vermute mal ASCII-Zeichen?

Nein, Asciizeichen sind Müll bzw unlesbar.
Dezimal und Hex ist lesbar. Ich benutzt HTerm.

von Stephan (Gast)


Lesenswert?

Peter II schrieb:
> und ist der Ringpuffer auch gross genug?

Der ist groß.

von SkyperHH (Gast)


Lesenswert?

Ok, Dir ist schon klar, das alles ASCII-Zeichen kleiner als 0x1f - 31d 
reine Steuerzeichen sind... wie Sie das Terminal umsetzt, bzw. sie 
überhaupt anzeigt, keine Ahnung... 0x20 - 32d ist Space, also ein 
Leerzeichen, ist also auch nichts zu sehen...

Einziges sichtbares Zeichen ist 0x30 48d, das entspricht der "0" ...

von Mladen G. (mgira)


Lesenswert?

Peter II schrieb:
> nein das ist schon so ok. Byte gibt es in C nicht. Und ein index darf
> sogar negativ sein.

Kommt darauf an ;)

Ob es bytes etc. gibt, liegt an der HW.
Klar, wenn ein usigned byte genauso "breit" ist wie ein unsigned int (16 
bit), dann passt das natuerlich.
Ansonsten passt das aber nicht.

Muesste nochmals in der Literatur nachschlagen, aber Array Indizes 
sollten m.E. folgerndermassen berechnet werden:

Array Adresse + (Index * Datenbreite)

: Bearbeitet durch User
von Peter II (Gast)


Lesenswert?

Mladen G. schrieb:
> Muesste nochmals in der Literatur nachschlagen, aber Array Indizes
> sollten m.E. folgerndermassen berechnet werden:
>
> Array Adresse + (Index * Datenbreite)

nein nicht ganz:

Array Adresse + (Index * sizeof( Datentype ) )

von JojoS (Gast)


Lesenswert?

Stephan schrieb:
> int i;
> i=0;
>
> uart1_putc(tabelle[i]);
>

>
> liefert das richtige Ergebnis....

Ist jetzt aber geschummelt weil uart1_putc statt uart_putc.
Falsche Bitrate?

von Mladen G. (mgira)


Lesenswert?

Peter II schrieb:
> nein nicht ganz:
>
> Array Adresse + (Index * sizeof( Datentype ) )

Eben, hast es nur anders ausedrueckt ;)

Wenn dieser C Dialekt auf dieser HW aber doch 8 Bit Bytes unterstuetzt, 
dann sollte man auch ein Byte als Index verwenden, das war es worauf ich 
hinaus wollte.

von Stephan (Gast)


Lesenswert?

SkyperHH schrieb:
> Einziges sichtbares Zeichen ist 0x30 48d, das entspricht der "0" ...

Das verwendete HTerm zeigt alles an, in Hex, Dez, Ascii


Ich bin aber weiter mit meinen Forschungen und es kommt hinzu:
1
  for (i=0; i<5; i++)
2
  {      
3
    uart1_putc(tabelle[i]);
4
  }

liefert ein korrektes Ergebnis,
1
  for (i=0; i<5; i++)
2
  {      
3
    uart1_putc(tabelle[i]);
4
    _delay_ms(10);
5
  }

liefert nur Nullen!
Graue Wolken tun sich auf...

von Schlumpf (Gast)


Lesenswert?

Stephan schrieb:
> Stephan schrieb:
>> Jetzt aber.. 1,10,20,30 (hex)
>> Bzw. 1,16,3,48,16 (dec)

Warum wird dann aus einer 20hex eine 3dez?

von Peter II (Gast)


Lesenswert?

Mladen G. schrieb:
> Wenn dieser C Dialekt auf dieser HW aber doch 8 Bit Bytes unterstuetzt,
> dann sollte man auch ein Byte als Index verwenden, das war es worauf ich
> hinaus wollte.

das ist aber falsch. Denn die Speicher-Adressen sind 16bit. Auch wenn es 
eine 8bit cpu ist.

von SkyperHH (Gast)


Lesenswert?

Dann runter mit der Hose, zeige uns mal die Funktion --> 
uart1_putc(...);

von Fachmann (Gast)


Lesenswert?

In dem code sind keine Fehler, ausser das nur 5 zeichen aus dem Array 
angezeigt werden.

Um alle zu zeigen muss man das tun.

for (i=0; i<10; i++)
  {
      uart_putc(tabelle[i]);
  }

von Stephan (Gast)


Lesenswert?

Schlumpf schrieb:
> Stephan schrieb:
>> Stephan schrieb:
>>> Jetzt aber.. 1,10,20,30 (hex)
>>> Bzw. 1,16,3,48,16 (dec)
>
> Warum wird dann aus einer 20hex eine 3dez?

Fipptehler.

von Stephan (Gast)


Lesenswert?

SkyperHH schrieb:
> Dann runter mit der Hose, zeige uns mal die Funktion -->
> uart1_putc(...);
1
void uart0_putc(unsigned char data)
2
{
3
  uart0txcounter++;
4
    unsigned char tmphead;    
5
    tmphead  = (UART0_TxHead + 1) & UART_TX_BUFFER_MASK;    
6
    while ( tmphead == UART0_TxTail ){
7
        ;/* wait for free space in buffer */
8
    }
9
    UART0_TxBuf[tmphead] = data;
10
    UART0_TxHead = tmphead;
11
    UART0_CONTROL    |= _BV(UART0_UDRIE);    /* enable UDRE interrupt */
12
}

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Mladen G. schrieb:
> dann sollte man auch ein Byte als Index verwenden, das war es worauf ich
> hinaus wollte.

Das ist kompletter Unfug. Meinst Du, ein Array aus mehr als 256 Bytes 
wäre nicht möglich?

von Justus S. (jussa)


Lesenswert?

Stephan schrieb:
> void uart0_putc(unsigned char data)
> {
>   uart0txcounter++;
>     unsigned char tmphead;
>     tmphead  = (UART0_TxHead + 1) & UART_TX_BUFFER_MASK;
>     while ( tmphead == UART0_TxTail ){
>         ;/* wait for free space in buffer */
>     }
>     UART0_TxBuf[tmphead] = data;
>     UART0_TxHead = tmphead;
>     UART0_CONTROL    |= _BV(UART0_UDRIE);    /* enable UDRE interrupt */
> }

von einer Funktion uart0_putc() war bis jetzt nie die Rede...

von Stephan (Gast)


Lesenswert?

Justus Skorps schrieb:
> von einer Funktion uart0_putc() war bis jetzt nie die Rede...

Ich sollte auf Koffeinfreien Kaffee umsteigen. Der µC hat UART, die 
Funktionen dazu sind -bis auf den Index- alle gleich.

von Stephan (Gast)


Lesenswert?

Stephan schrieb:
> Der µC hat UART

Der µC hat 4 UART

von Schlumpf (Gast)


Lesenswert?

Stephan schrieb:
> SkyperHH schrieb:
>> Dann runter mit der Hose, zeige uns mal die Funktion -->
>> uart1_putc(...);

Gefragt war nach uart1_putc() !
                     -

von SkyperHH (Gast)


Lesenswert?

Ok... da fehlt aber noch was, die ISR die den Puffer ausliest und 
übeträgt, die Initalisierung des Puffers... usw.

von Karl H. (kbuchegg)


Lesenswert?

Wie wärs erst mal die Rungbufferausgabe durch eine stink normale zu 
ersetzen? Dann kannst du dich erst mal davon überzeugen, dass die 
Arrayzugriffe klappen, anstatt da von einem Problem zum anderen zu 
hampeln.

von Mladen G. (mgira)


Lesenswert?

Rufus Τ. Firefly schrieb:
> Das ist kompletter Unfug. Meinst Du, ein Array aus mehr als 256 Bytes
> wäre nicht möglich?

Genau darum ging es doch.
Mit 8 Bit Adressen waere genau da schicht im Schacht, die Formel fuer 
die Addressarithmetik nutzt ja die Breite des Datentyps.

von Schlumpf (Gast)


Lesenswert?

Wer oder was ist denn "uart0txcounter" ?
Eine globale Variable? Vermutlich wird an ihr dann auch noch im 
Interrupt und ggf anderen Stellen rumgeschraubt?

Wenn ja, dann mach die mal bitte "Volatile".

von Stephan (Gast)


Lesenswert?

SkyperHH schrieb:
> Ok... da fehlt aber noch was, die ISR die den Puffer ausliest und
> übeträgt, die Initalisierung des Puffers... usw.

Karl Heinz schrieb:
> Wie wärs erst mal die Rungbufferausgabe durch eine stink normale zu
> ersetzen?

Bin ich dabei.

Was mich allerdings wirklich verwundert:
1
  for (i=0; i<5; i++)//kurze Schleife
2
  {      
3
    uart1_putc(tabelle[i]);
4
  }  
5
  
6
  uart1_putc(tabelle[i]);
7
  i++;
8
  uart1_putc(tabelle[i]);
9
  i++;
10
  uart1_putc(tabelle[i]);
11
  i++;
12
  uart1_putc(tabelle[i]);

liefert das richtige Ergebnis vom ersten bis zum letzten 
Tabelleneintrag,
1
  for (i=0; i<6; i++)//lange Schleife
2
  {      
3
    uart1_putc(tabelle[i]);
4
  }  
5
  
6
  uart1_putc(tabelle[i]);
7
  i++;
8
  uart1_putc(tabelle[i]);
9
  i++;
10
  uart1_putc(tabelle[i]);
11
  i++;
12
  uart1_putc(tabelle[i]);
liefert für die ersten 6 Tabelleneinträge Nullen, danach aber korrekte 
Werte. Riecht mir irgendwie nicht nach UART-Problem.

von JojoS (Gast)


Lesenswert?

Doch eher UART bzw Buffer Problem. Sonst müssten ja auch bei der langen 
Schleife die ersten fünf Zeichen richtig ankommen.
Theorie: die Zeichen laufen erst in den Buffet bevor gesendet wird. Bei 
5 (oder sogar nur 4?) Zeichen ok, bei mehr geht etwas kaputt.

von SkyperHH (Gast)


Lesenswert?

Ich würde eher auf Zeiger-Fehler tippen...

von OldMen (Gast)


Lesenswert?

Stephan schrieb:
> liefert für die ersten 6 Tabelleneinträge Nullen, danach aber korrekte
> Werte.

Das glaubt Dir keiner. Mit i<5 soll es gehen, mit i<6 nicht?
Änderst Du evt. noch andere Codezeilen, wenn Du i<6 programmierst?
Übersetzt Du auch die richtige Datei?

von Stefan E. (sternst)


Lesenswert?

Mladen G. schrieb:
> Mit 8 Bit Adressen waere genau da schicht im Schacht, die Formel fuer
> die Addressarithmetik nutzt ja die Breite des Datentyps.

Nein. Die Breite des Datentyps geht als Zahl in die Berechnung ein. Das 
hat rein gar nichts damit zu tun, in welcher Breite die Berechnung und 
Indexierung durchgeführt wird.

von Stephan (Gast)


Lesenswert?

OldMen schrieb:
> Das glaubt Dir keiner. Mit i<5 soll es gehen, mit i<6 nicht?
> Änderst Du evt. noch andere Codezeilen, wenn Du i<6 programmierst?
> Übersetzt Du auch die richtige Datei?

Ohne Flachs!
Auch wenn ich ohne Ringbuffer sende, also
1
  while (!(UCSR1A & (1<<UDRE1)))  /* warten bis Senden moeglich */
2
    {
3
    }                             
4
    UDR1 = c;                      /* sende Zeichen */
verwende, werden bei der langen Schleifenversion aus der Schleife heraus 
nur Nullen gesendet!

von Stephan (Gast)


Lesenswert?

1
static const unsigned char tabelle[10] = {0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x80,0x90};
2
3
void show_values (void)
4
{      
5
  unsigned int  i;  
6
  i = 0;
7
  
8
  for (i=0; i<=3; i++)
9
  {      
10
    rausdamit(tabelle[i]);
11
  }    
12
}  
13
  
14
void rausdamit(char c)
15
{
16
  while (!(UCSR1A & (1<<UDRE1)))  /* warten bis Senden moeglich */
17
    {
18
    }                             
19
    UDR1 = c;                      /* sende Zeichen */
20
}

Das ist nun alles. und immernoch das gleiche: lange Schleife: schlecht, 
kurze Schleife: gut.

von Peter II (Gast)


Lesenswert?

mache mal ein sleep in die lange schleife. Nicht das deine Baudrate 
nicht richtig stimmt und der sync verloren geht.

von Stephan (Gast)


Lesenswert?

Peter II schrieb:
> mache mal ein sleep in die lange schleife

Hab ich schon gemacht. Das führt dazu, dass selbst bei kleiner Schleife 
nur Nullen rauskommen! Verwirrung weicht Verzweiflung.

von SkyperHH (Gast)


Lesenswert?

Welche Baudrate zum senden? Was für einen Quarz verwendest Du?

von Schlumpf (Gast)


Lesenswert?

Stimmt deine Abfrage, ob der UART sendebereit ist?

von Justus S. (jussa)


Lesenswert?

willst du nicht mal endlich den ganzen Code posten, anstatt immer nur 
Bruchstücke?

von Stephan (Gast)


Lesenswert?

SkyperHH schrieb:
> Welche Baudrate zum senden? Was für einen Quarz verwendest Du?

38,4k, 16MHz

Schlumpf schrieb:
> Stimmt deine Abfrage, ob der UART sendebereit ist?

Normal senden tut er ja ohne Murren.

von Schlumpf (Gast)


Lesenswert?

Stephan schrieb:
> Normal senden tut er ja ohne Murren.

Na ja aber wenn deine Abfrage immer "true" ist, dann sendet er, sobald 
er in die Funktion kommt. Ist zu dem zeitpunkt aber der vorangegangene 
Sendevorgang noch nicht abgeschlossen, dann.....

Und hast du parallel noch irgendwelche Interrupts am laufen?

von Stephan (Gast)


Lesenswert?

Schlumpf schrieb:
> Und hast du parallel noch irgendwelche Interrupts am laufen?

Ja, Windows!

Ich habe 0 Ahnung, warum, aber nach An-und-Ausmachen von Windows klappt 
es plötzlich. 2h für die Tonne!
Danke für die Unterstützung!

von SkyperHH (Gast)


Lesenswert?

Die 0,2% Fehlerrate sollten nicht das Problem sein...


Stephan schrieb:
> SkyperHH schrieb:
>> Welche Baudrate zum senden? Was für einen Quarz verwendest Du?
>
> 38,4k, 16MHz

von Schlumpf (Gast)


Lesenswert?

Stephan schrieb:
> Ja, Windows!

Ach du Schreck ;-)

von Stephan (Gast)


Lesenswert?

Schlumpf schrieb:
> Ach du Schreck ;-)

Das ist wie mit dem Alkohol. Es schadet nur aber man kann auch nicht 
ohne.

von Schlumpf (Gast)


Lesenswert?

Stephan schrieb:
> Das ist wie mit dem Alkohol. Es schadet nur aber man kann auch nicht
> ohne.

Aber Alk macht mehr Spass ;-)

von Stefanus (Gast)


Lesenswert?

War das ein Witz mit dem reboot? Oder läuft es jetzt tatsächlich 
problemlos?

von Stephan (Gast)


Lesenswert?

Stefanus schrieb:
> War das ein Witz mit dem reboot? Oder läuft es jetzt tatsächlich
> problemlos?

Leider kein Witz! Alles gut! Vielleicht hatte AVRStudio einen Pups quer.

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.