Forum: Mikrocontroller und Digitale Elektronik Komischer UART


von Schorsch (Gast)


Lesenswert?

Hallo,

ich programmiere gerade meinen ersten mega64. Der UART verhält sich 
komisch.

kann mit
1
int uart_putc(unsigned char c)
2
{
3
    while (!(UCSR0A & (1<<UDRE0)))  /* warten bis Senden moeglich */
4
    {
5
    }                             
6
 
7
    UDR0 = c;                      /* sende Zeichen */
8
    return 0;
9
}

einzelne Zeichen verschicken

strings hingegen gehen nicht:
1
void uart_puts (char *s)
2
{
3
    while (*s)
4
    {   /* so lange *s != '\0' also ungleich dem "String-Endezeichen" */
5
        uart_putc(*s);
6
        s++;
7
    }
8
}

wenn ich so was in main stehen habe
1
int main(void)
2
{
3
  UART_init();
4
  sei();
5
  uart_putc('A');
6
    for(;;){
7
      //uart_putc('T');
8
      uart_puts("Huhu\r\n");
9
      _delay_ms(1000);
10
    }
11
    return 0;  
12
}

ist meine screen-Ausgabe
1
AHuhu
2
AHuhu
3
AHuhu
4
AHuhu
5
...

die Sekunde sind auch bei weitem nicht eingehalten. Packe ich nur ein 
char in den loop ist alles gut. da sag ich nur ---hä?---

Any hint?

Georg

von Achim M. (minifloat)


Lesenswert?

Ist der Watchdog an? Dann resettet der Prozessor brav, wenn er im 
delay() Rechenzeit verheizt. Nur so erklärt sich, dass da immer wieder 
auch das 'A' raus kommt...
mfg mf

von Olek (Gast)


Lesenswert?

wann soll den "while(*s)" kontrolliert false werden?

von Schorsch (Gast)


Lesenswert?

Hi,

Die Theorie mit dem Watchdog hatte ich auch schon, habe aber nicht 
bewußt etwas umgestellt.

Habe gerade mal das delay rausgeschmissen und immernoch das gleiche

interessant ist auch folgende Codeveränderung
1
void uart_puts (char *s)
2
{
3
    while (*s)
4
    {   /* so lange *s != '\0' also ungleich dem "String-Endezeichen" */
5
        uart_putc(*s);
6
        s++;
7
    }
8
    uart_putc('X');
9
}

bewirkt keinerlei Änderung in der Ausgabe.

das \0 ist nicht als false erkannt

Schorsch

von Schorsch (Gast)


Lesenswert?

Olek schrieb:
> wann soll den "while(*s)" kontrolliert false werden?

Hi,

habe den Code für einen mega8 schon 100mal benutzt, da geht er,


*s != \0  identisch zu *s

Schorsch

von Olek (Gast)


Lesenswert?

Ich meine mal das *s ein pointer ist und aus der while gehts nur raus 
wenn der mal zufällig auf die 0 kommt und damit meine ich nicht die 
ascii 0 sondern 0x00.

für so sachen ist meiner meinung nach die strlen(string) geschrieben 
worden.

von troll (Gast)


Lesenswert?

Olek schrieb:
> Ich meine mal das *s ein pointer ist
und ich meine du hast keine Ahnung. *s ist ein char, das while-Konstrukt 
wird millionenfach verwendet und passt so. RTFK&R :-)

von Olek (Gast)


Lesenswert?

wie wäre es mal \0 zu setzen?

wenn du schon keinen debugger hast könntest dir mal einen counter in die 
schleife packen...

von troll (Gast)


Lesenswert?

Olek schrieb:
> wie wäre es mal \0 zu setzen?
Hö? \0 wird automatisch an jeden String gehängt, das macht der Compiler 
schon richtig. Grundlagen.

von HalloHallo (Gast)


Lesenswert?

Probiers mal so aus:

void uart_puts (char *s)
{
    uint8_t i = 0;

    while (s[i])
    {
        uart_putc(s[i]);
        i++;
    }
    uart_putc('X');
}

von Stefan E. (sternst)


Lesenswert?

M103C-Fuse deaktivieren.

von amateur (Gast)


Lesenswert?

Ist es möglich, dass Du irgendwo eine ungewollte Rekursion eingebaut 
hast?
Die Namen Deiner Funktionen kommen mir so schrecklich bekannt vor.

von Uwe (Gast)


Lesenswert?

>     return 0;
Wohin denn ?

von Stefan (Gast)


Lesenswert?

Uwe schrieb:
>>     return 0;
> Wohin denn ?

Von der int main wird eine Rückgabe erwartet, auch wenn sie diese 
Codestelle nie erreicht. Das ist vollkommen richtig so.

Auch alles andere schaut für mich richtig aus / ist millionenfach 
bewährter Code. Ich würde den Fehler wirklich in der Konfiguration / der 
Hardware suchen. Da auch das 'A' immer wieder gesendet wird, sieht es 
für mich so aus, als würde der Controller reseten. Probier mal, ob eine 
längere Zeichenkette abgeschnitten wird.
Was ist das für eine Schaltung? Eval. Board oder Eigenbau?
Wie ist der Reset beschaltet? Kann dir da was rein spucken?
Hast du ein Oszi, mit dem du mal auf die Versorgungsspannung schauen 
kannst?

von Wilhelm F. (Gast)


Lesenswert?

Auch mal ins Assembler-Listing schauen, was der Compiler für einen Code 
fabrizierte.

von Uwe (Gast)


Lesenswert?

> als würde der Controller reseten.
bzw. der Stack ist kaputt oder wurde falsch initialisiert (z.B. durch 
falsche CPU definition. Watchdog in den Fuses aktiviert ?
Hast schon recht war nur ein passendes Fehlerbild.

von Bronco (Gast)


Lesenswert?

Schorsch schrieb:
> ich programmiere gerade meinen ersten mega64. Der UART verhält sich
> komisch.

Schorsch schrieb:
> habe den Code für einen mega8 schon 100mal benutzt, da geht er,

Wenn sich der gleiche Code auf einem Mega8 korrekt verhält, auf einem 
Mega64 aber nicht, dann mußt Du die Unterschiede prüfen:
- Quarz?
- Fuses? Wichtig!!!
- Register richtig konfiguriert?
- Hardware drumherum?

von Sascha W. (sascha-w)


Lesenswert?

@Schorsch
was wird in uart_init() alles eingeschaltet? Auch RX und RXIE? Dann 
liegts an der nicht vorhandenen ISR für den uart-rx-int.
Schmeiß mal das sei() raus, für den Test brauchst du das nicht.

Sascha

von Schorsch (Gast)


Lesenswert?

Hallo,
sorry, das ich mich erst jetzt melde, musste den Tag über arbeiten...

ich versuche mal die meisten Fragen zu beantworten:

die Fuses stehen so

1
avrdude: Device signature = 0x1e9602
2
avrdude: safemode: lfuse reads as E0
3
avrdude: safemode: hfuse reads as 99
4
avrdude: safemode: efuse reads as FD

mit dem d in der e-fuse müsste der 103c-mode aus und der watchdog 
eigentlich an sein (p293 im Manual)

meine init-routine sieht so aus:
1
UBRR0H = (unsigned char)(UBRR_VAL>>8); 
2
UBRR0L = (unsigned char)UBRR_VAL; 
3
  
4
UCSR0B = (1<<RXEN0)|(1<<TXEN0);

wobei UBBR_VAL so definiert ist
1
#define F_CPU 14745600UL 
2
#define BAUD 115200UL 
3
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)
4
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))
5
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD)
6
 
7
#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
8
  #error Systematischer Fehler der Baudrate gršsser 1% und damit zu hoch! 
9
#endif

Die Frage nach den Fuses und den Registern sollte hinreichend 
beantwortet sein.

Zum Board: siehe hier:
Beitrag "Atmega64 PDI/O und RXD/TXD gleichzeitig"

Zusammenfassend, durch einen Flüchtigkeitsfehler werden PDI/O und 
RXD/TXD bei mir doppelt verwendet, das ließ sich beheben, indem ich 4.7k 
in die RXD-Leitung gehängt habe.

Das der UART nun grundsätzlich funktioniert sollte hinreichend gezeigt 
worden sein. Das selbstständige resetten (Wechselwirkung UART in den 
Programmer ???) kann man ausschließen, da das gleiche Problem auch 
auftritt, wenn ich den Programmer abziehe


ah, nochwas
1
void uart_puts (char *s)
2
{
3
  uint8_t n = 0;
4
    while (*s)
5
    {   /* so lange *s != '\0' also ungleich dem "String-Endezeichen" */
6
        //uart_putc(*s);
7
        uart_putc(s[n]);
8
        s++;
9
    }
10
    uart_putc('X');
11
}

liefert mir immnoch die selbe Ausgabe. Laienhaft ausgedrückt, es scheint 
als zeit ein Pointer ins Nirvana und der Programmcode fängt wieder von 
vorn an. Ist das ein gcc-bug?


Schorsch

von Schorsch (Gast)


Lesenswert?

addendum:

wenn ich das sei weglasse ändert sich die Ausgabe
1
XAHuhu
2
XAHuhu
3
...

von Wusel D. (stefanfrings_de)


Lesenswert?

Wie ruft Du uart_puts(char* s) auf? Auf was zeigt s?

von Stefan E. (sternst)


Lesenswert?

Schorsch schrieb:
> mit dem d in der e-fuse müsste der 103c-mode aus und der watchdog
> eigentlich an sein (p293 im Manual)

Nein, umgekehrt. Also, wie ich bereits sagte, M103C-Fuse deaktivieren.

PS: Aber auch die Watchdog-Fuse wäre verheerend für dein Programm.

von Schorsch (Gast)


Lesenswert?

Ja es geht,

ganz, ganz großes Danke schön


ich war natürlich zu doof das Datenblatt zu lesen. efuse auf ff heißt, 
watchdog aus, 103c mode aus
1
avrdude: safemode: lfuse reads as E0
2
avrdude: safemode: hfuse reads as 99
3
avrdude: safemode: efuse reads as FF

Warum ist dieses Programm verherend mit einem Watchdog?

von Stefan E. (sternst)


Lesenswert?

Schorsch schrieb:
> Warum ist dieses Programm verherend mit einem Watchdog?

Weil du ihn nirgendwo im Programm zurücksetzt, und er daher den 
Controller unweigerlich nach seinem Ablauf resettet.

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.