Look-up Tabelle wird nicht anständig gelesen

Gast #3467686
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?!
Gast #3467720
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
Gast #3467725
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.
Gast #3467733
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....
Gast #3467742
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" ...
#3467743
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)
Gast #3467748
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...
Gast #3467761
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
}
#3467764
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...
Gast #3467788
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".
Gast #3467793
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.
Gast #3467800
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.
Gast #3467821
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!
Gast #3467836
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.
Gast #3467862
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?

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren