Forum: Mikrocontroller und Digitale Elektronik Zeiger Strings ausgeben?!


von Jan H. (janiiix3)


Lesenswert?

Moin Moin.

Wieso hängt sich der µC auf, wenn ich die Strings ausgeben will?
1
typedef struct  
2
{
3
  const char *ProjectName;
4
  const char *HardwareVersion;
5
  const char *SoftwareVersion;
6
  const char *HardwareDate;
7
  const char *SoftwareDate;
8
}DevBoard_t;
9
10
DevBoard_t  Message={
11
  
12
  .ProjectName    = "DevBoard\r\n",
13
  .HardwareVersion  = "Hardware Version 1.0\r\n",
14
  .SoftwareVersion  = "Software Version 1.0\r\n",
15
  .HardwareDate    = "Hardware from 18.04.17\r\n",
16
  .SoftwareDate    = "Software from 30.05.17\r\n",
17
};
18
19
uart_puts(Message.ProjectName);

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Jan H. schrieb:
> Wieso hängt sich der µC auf, wenn ich die Strings ausgeben will?

Vielleicht, weil die Funktion uart_puts() fehlerhaft implementiert 
wurde? Sonst gibt es auf kleinen µCs noch tausend andere Gründe, wie 
z.B. Größe des RAMs usw.

Ein
1
int main ()
2
{
3
    fputs (Message.ProjectName, stdout);
4
    return 0;
5
}

funktioniert unter Linux jedenfalls einwandfrei.

Um welchen µC handelt es sich denn? Und wie sieht der Rest des Programms 
aus?

Hängt sich der µC wirklich auf, wenn Du nur so eine kleine 
main()-Funktion hast, oder hast Du noch 30000 weitere Zeilen an Code?

Bitte ein compilierbares, reproduzierbares Beispiel angeben.

: Bearbeitet durch Moderator
von Jan H. (janiiix3)


Lesenswert?

Die Uart Routinen sind hier von der Seite..
Andere Strings kann ich an dieser Stelle, wo ich eigentlich diese 
Strings ausgeben will, ohne Probleme ausgeben.

Verwenden tue ich einen ATMEGA32.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Jan H. schrieb:
> Die Uart Routinen sind hier von der Seite..

Ach so. Auf µc.net gibt es auch nur genau einen Satz UART-Routinen ...

von Jan H. (janiiix3)


Lesenswert?

1
/*************************************************************************
2
Function: uart_putc()
3
Purpose:  write byte to ringbuffer for transmitting via UART
4
Input:    byte to be transmitted
5
Returns:  none          
6
**************************************************************************/
7
void uart_putc(unsigned char data)
8
{
9
    unsigned char tmphead;
10
11
    
12
    tmphead  = (UART_TxHead + 1) & UART_TX_BUFFER_MASK;
13
    
14
    while ( tmphead == UART_TxTail ){
15
        ;/* wait for free space in buffer */
16
    }
17
    
18
    UART_TxBuf[tmphead] = data;
19
    UART_TxHead = tmphead;
20
21
    /* enable UDRE interrupt */
22
    UART0_CONTROL    |= _BV(UART0_UDRIE);
23
24
}/* uart_putc */
1
/*************************************************************************
2
Function: uart_puts()
3
Purpose:  transmit string to UART
4
Input:    string to be transmitted
5
Returns:  none          
6
**************************************************************************/
7
void uart_puts(const char *s )
8
{
9
    while (*s) 
10
      uart_putc(*s++);
11
12
}/* uart_puts */

Diese werden verwendet..

von Stefan E. (sternst)


Lesenswert?

Kann es sein, dass du versuchst, die Strings innerhalb einer ISR 
auszugeben?

von Jan H. (janiiix3)


Lesenswert?

Stefan E. schrieb:
> Kann es sein, dass du versuchst, die Strings innerhalb einer ISR
> auszugeben?

Nein. Das passiert alles bevor sei() aufgerufen wird.

von Marius (Gast)


Lesenswert?

Wahrscheinlich läuft der UART-Software-Puffer voll, wenn du den String 
ohne aktivierte Interrupts ausgibst. Dann wartet die Ausgabe bei
1
;/* wait for free space in buffer */
, weil kein Interrupt passiert, der den Puffer leert.

Gruß
Marius

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Jan H. schrieb:
> UART0_CONTROL    |= _BV(UART0_UDRIE);

Das Zeichen soll also in einer ISR ausgegeben werden. Wo ist die ISR 
dazu?

> Das passiert alles bevor sei() aufgerufen wird.

Wie soll das gehen? Ohne sei() kein Interrupt, ohne Interrupt kein 
ISR-Auffruf! Ohne ISR-Aufruf keine Ausgabe von Zeichen! Das kann so 
nicht gehen.

Pardon, aber mit so einer Salamitaktik kann man den Fehler nicht finden.

Ich wiederhole nochmal:

Bitte zeige ein compilierbares Programm mit reproduzierbarem Fehler. 
Sonst ist das ein Stochern im Dunkeln. Der Fehler kann überall sein, nur 
nicht in Deinem bisher gezeigten Code.

: Bearbeitet durch Moderator
von Jan H. (janiiix3)


Lesenswert?

Ah okay.
Habs verstanden.

Jetzt funktioniert es aber. Scheint wirklich der Puffer voll zu laufen.

Besten Dank!

: Bearbeitet durch User
von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Jan H. schrieb:
> Was hat denn die Ausgabe mit einem Interrupt zu tun?

Dein oben zitiertes uart_puts() gibt das Zeichen gar nicht aus. Es 
kopiert das Zeichen nur in einen Ringbuffer und aktiviert dann den 
UART-Empty-Interrupt. Dieser wird ausgelöst, wenn der UART leerläuft. 
Die ISR kopiert dann das nächste auszugebende Zeichen ins UART-Register. 
Die eigentliche Ausgabe läuft also nicht in uart_puts(), sondern in der 
ISR.

> Das habe ich noch
> nicht ganz verstanden. Wenn ein Zeichen rein kommt, weiß ich das es ein
> Interrupt gibt.

Siehe oben. Wenn der UART kein Zeichen auszugeben hat, dann löst er 
einen UDRIE-Interrupt aus. Genau diesen aktiviert Dein uart_puts():

> UART0_CONTROL |= _BV(UART0_UDRIE);

> Jetzt funktioniert es aber. Scheint wirklich der Puffer voll zu laufen.

Lass mich raten: Du hast den sei()-Aufruf nach vorne gezogen.

Achja, bitteschön. ;)

: Bearbeitet durch Moderator
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.