Hallo,
Ich benutze Robostix bord von Gumstix. (8Mhz Intern, mega128)
An diesem Board möchte ich gern einen UART Verbindung zum PC betreiben.
Leider macht diese Verbindung nicht das was sie soll.
Ich habe zuerst eine eigene Routine geschrieben, die ich auch in anderen
Projekten schon genutzt habe und die Ports angepasst.
Leider hat das nicht Funktioniert.
Als nächstes habe ich die bewährte UART Routine von Peter Fleury benutzt
um sicher zu gehen das in der Implementierung nichts falsch ist. leider
hat das auch nicht geklappt.
Um das Problem einzukreisen habe ich jeden Schnick Schnack entfernt und
nur eine einfache UART Implementierung genommen.
1 | #define USART_BAUDRATE_0 2400UL
| 2 | #define UBRR_0 ((F_CPU+USART_BAUDRATE_0*8)/(USART_BAUDRATE_0*16)-1)
| 3 | int main(void){
| 4 | UBRR0H = (uint8_t) (UBRR_0>>8);
| 5 | UBRR0L = (uint8_t) (UBRR_0 & 0xFF);
| 6 | UCSR0B = (1 << RXEN0) | (1 << TXEN0);
| 7 | UCSR0C = (3 << UCSZ0);
| 8 | int16_t i = -12345;
| 9 | unsigned char s[]={'k','a','t','z','e','\0'};
| 10 | void USART_Transmit( unsigned char data )
| 11 | {
| 12 | /* Wait for empty transmit buffer */
| 13 | while ( !( UCSR0A & (1<<UDRE0)) )
| 14 | ;
| 15 | /* Put data into buffer, sends the data */
| 16 | UDR0 = data;
| 17 | }
| 18 |
| 19 | void uart3_puts (char *s)
| 20 | {
| 21 | do{ /* so lange *s != '\0' also ungleich dem "String-Endezeichen" */
| 22 | USART_Transmit(*s);
| 23 | s++;
| 24 | }while (*s);
| 25 | }
| 26 |
| 27 | while(1){
|
Ein einzelnens Zeichen ausgeben funktioneirt 1 | USART_Transmit('e');//Ausgabe: e
|
Ein Zeichen aus dem char Array (s)auszugeben auch 1 | USART_Transmit(s[3]);//Ausgabe: z
|
Eine Zahl im Terminal hochzählen lassen mit einer For-Schleife 1 | for(i=0;i<=4;i++){
| 2 | USART_Transmit(i+0x30);
| 3 | USART_Transmit(',');
| 4 | }//Ausgabe: 0,1,2,3,4
|
Was nicht Funktioniert ist ein Array in einer Schleife auszugeben. 1 | for(i=0;i<=4;i++){
| 2 | USART_Transmit(s[i]);
| 3 | }//Ausgabe: S (Undefiniertes Zeichen) T (Undefiniertes Zeichen)
|
Ich hab zuerst an ein Buffer oder Timing Problem gedacht aber wenn ich
mehrere Zeichen direkt einzeln Ausgebe dann ist die Ausgabe auch
korrekt.
1 | USART_Transmit(s[0]);
| 2 | USART_Transmit(s[1]);
| 3 | USART_Transmit(s[2]);
| 4 | USART_Transmit(s[3]);
| 5 | USART_Transmit(s[4]);
| 6 | USART_Transmit('\n');//Ausgabe: Katze
|
Ich hoffe das ihr mir Helfen könnt, denn ich bin mit meinem Latein am
ende.
gruß,
Robert
>int main(void){
> UBRR0H = (uint8_t) (UBRR_0>>8);
> UBRR0L = (uint8_t) (UBRR_0 & 0xFF);
> UCSR0B = (1 << RXEN0) | (1 << TXEN0);
> UCSR0C = (3 << UCSZ0);
> int16_t i = -12345;
> unsigned char s[]={'k','a','t','z','e','\0'};
> void USART_Transmit( unsigned char data )
> {
Die Definition einer Funktion (USART_Transmit) in einer Funktion (main)
erzeugt bei deinem Compiler keinen Fehler?
Ich spekuliere im Moment darauf, dass in dem Fehlerbeispiel das Feld s
nicht mehr gültig ist, wenn die Funktion USART_Transmit es abarbeiten
will.
Meiner Ansicht nach würde es bei der Fehlersuche helfen, wenn du exakt
die verwendeten Quellcodes anhängen würdest.
Nein hat nicht mal ne Warnung gegeben.
Hab die 2 Funktionen jetzt auserhalb der main deklariert.
Aber das Problem besteht Immernoch.
Robert Maucher schrieb:
> Nein hat nicht mal ne Warnung gegeben.
Ist eine gcc Erweiterung.
Das wird vielleicht in irgendeiner der nächsten ISO-C Versionen kommen.
IMHO ist das aber in C nicht wirklich so der große Brüller, so dass es
eigentlich keinen Grund gibt, so etwas zu machen.
In C regeln sich viele Probleme, bei denen man nach Funktionen in
Funktionen schreit, durch die Aufteilung in mehrere Source Code Files
von alleine, so dass dieses Feature nicht sooooo nachgefragt ist.
> Hab die 2 Funktionen jetzt auserhalb der main deklariert.
> Aber das Problem besteht Immernoch.
Wie schon gesagt:
Zeige bitte den kompletten Code
Die Funktion uart3_puts änderst du mal so um
1 | void uart3_puts (char *s)
| 2 | {
| 3 | while( *s ) { /* so lange *s != '\0' also ungleich dem "String-Endezeichen" */
| 4 | USART_Transmit(*s);
| 5 | s++;
| 6 | }
| 7 | }
|
damit ist schon mal der Fehler, das du das \0 Zeichen mitüberträgst, weg
(oder war das Absicht?)
Robert Maucher schrieb:
> Nein hat nicht mal ne Warnung gegeben.
> Hab die 2 Funktionen jetzt auserhalb der main deklariert.
> Aber das Problem besteht Immernoch.
Die Quellcodes ist im Moment nur dieser eine. 1 | #include <stdio.h>
| 2 | #include <avr/io.h>
| 3 | #include <util/delay.h>
| 4 | #include <stdint.h>
| 5 |
| 6 | #define USART_BAUDRATE_0 2400UL
| 7 | #define UBRR_0 ((F_CPU+USART_BAUDRATE_0*8)/(USART_BAUDRATE_0*16)-1)
| 8 |
| 9 | void USART_Transmit( unsigned char data )
| 10 | {
| 11 | /* Wait for empty transmit buffer */
| 12 | while ( !( UCSR0A & (1<<UDRE0)) )
| 13 | ;
| 14 | /* Put data into buffer, sends the data */
| 15 | UDR0 = data;
| 16 | }
| 17 |
| 18 | void uart3_puts (char *s)
| 19 | {
| 20 | do{ /* so lange *s != '\0' also ungleich dem "String-Endezeichen" */
| 21 | USART_Transmit(*s);
| 22 | s++;
| 23 | }while (*s);
| 24 | }
| 25 | int main(void){
| 26 | UBRR0H = (uint8_t) (UBRR_0>>8);
| 27 | UBRR0L = (uint8_t) (UBRR_0 & 0xFF);
| 28 | UCSR0B = (1 << RXEN0) | (1 << TXEN0);
| 29 | UCSR0C = (3 << UCSZ0);
| 30 | unsigned char s[]={'k','a','t','z','e','\0'};
| 31 |
| 32 |
| 33 | while(1){
| 34 | // USART_Transmit('K');
| 35 | // USART_Transmit('a');
| 36 | // USART_Transmit('t');
| 37 | // USART_Transmit('z');
| 38 | // USART_Transmit('e');
| 39 | // USART_Transmit('\n'); //geht
| 40 |
| 41 | // uart3_puts (s); //geht nicht
| 42 |
| 43 | // USART_Transmit(s[0]);
| 44 | // USART_Transmit(s[1]);
| 45 | // USART_Transmit(s[2]);
| 46 | // USART_Transmit(s[3]);
| 47 | // USART_Transmit(s[4]);
| 48 | // USART_Transmit('\n'); //geht
| 49 |
| 50 | int i;
| 51 | unsigned char dummy;
| 52 | for(i=0;i<=4;i++){
| 53 | _delay_ms(1000);
| 54 | USART_Transmit(i+0x30); //geht
| 55 | USART_Transmit('\n');
| 56 | }
| 57 | for(i=0;i<=4;i++){
| 58 | _delay_ms(1000);
| 59 | USART_Transmit(s[i]);//geht nicht
| 60 | USART_Transmit('\n');
| 61 | }
| 62 | }
| 63 | }
|
Karl heinz Buchegger schrieb:
> Die Funktion uart3_puts änderst du mal so um
>
> 1 | > void uart3_puts (char *s)
| 2 | > {
| 3 | > while( *s ) { /* so lange *s != '\0' also ungleich dem
| 4 | > "String-Endezeichen" */
| 5 | > USART_Transmit(*s);
| 6 | > s++;
| 7 | > }
| 8 | > }
| 9 | >
|
>
> damit ist schon mal der Fehler, das du das \0 Zeichen mitüberträgst, weg
> (oder war das Absicht?)
Ja war ein Fehler. ich habe die while irgendwann mal gegen eine do while
ausgetauscht und das s++ in der Schleife vergessen zu löschen.
Das Problem mit der for Schleife besteht immer noch, da es mit der
uart3_puts nichts zu tun hat, aber trotzdem danke.
Robert Maucher schrieb:
> Das Problem mit der for Schleife besteht immer noch,
Ich sehs.
Aber ich sehe nichts, was das von dir beschriebene Verhalten erklären
könnte.
Kann es sein, dass du mit der Baudrate ein klein wenig daneben bist
(interner RC-Oszillator) und bei dieser Übertragung einfach zuviele
Zeichen am Stück gesendet werden und sich der Empfänger nicht richtig
synchronisieren kann.
Das habe ich mir auchgedacht, aber wenn ich 1 | USART_Transmit(s[0]);
| 2 | USART_Transmit(s[1]);
| 3 | USART_Transmit(s[2]);
| 4 | USART_Transmit(s[3]);
| 5 | USART_Transmit(s[4]);
| 6 | USART_Transmit('\n');
|
dauernd in der while(1) drin habe dann passt alles.
Und was anders macht die For Schleife eigentlich auch nicht.
Hab mir noch gedacht das es einen Jitter geben könnte der mir ein
Problem Macht, aber da passt alles.
bin Inzwischen auf 2400 Baud runter weniger kann ich nicht.
(Im Datenblatt steht das ein maximaler Fehler von 0,2% bei 2400 Baud
ist.)
Das Problem lässt mich langsam durchdrehen.
Werde jetzt mal alles in Assamler coden um zu schauen (was ich eher
nicht denk) ob im avr-gcc ein bug ist. was anderes kann ich mir nicht
mehr vorstellen.
@ Robert Maucher (robert_maucher)
>Werde jetzt mal alles in Assamler coden um zu schauen (was ich eher
>nicht denk) ob im avr-gcc ein bug ist. was anderes kann ich mir nicht
>mehr vorstellen.
;-)
Selten so gelacht. Lern erstmal ein paar Grundlagen.
http://www.mikrocontroller.net/articles/AVR_Checkliste#UART.2FUSART
MFG
Falk
Falk Brunner schrieb:
> @ Robert Maucher (robert_maucher)
>
>>Werde jetzt mal alles in Assamler coden um zu schauen (was ich eher
>>nicht denk) ob im avr-gcc ein bug ist. was anderes kann ich mir nicht
>>mehr vorstellen.
>
> ;-)
> Selten so gelacht. Lern erstmal ein paar Grundlagen.
>
> http://www.mikrocontroller.net/articles/AVR_Checkliste#UART.2FUSART
>
> MFG
> Falk
Danke erst mal,
-ich habe nur einen Internen Takt zu verfügung.
-die verbindung und die Übertragung funktioniert Prinzipiell
-zeichen könne ohne fehler übertragen werden wenn man sie einzeln von
hand eingibt (z.b. USART_Transmit('q');) sowie aus einen Array genommen
werden (z.b. USART_Transmit(s[1]);)
-zeichenketten gehen nicht (uart3puts ...)
-einzelne zeichen in einem Array mit einer forschleife ausgeben geht
nicht
Grundlagen habe ich schon Durchgelesen.
gruß Robert
Ps: Hilfsbedürftige ins Lächerliche zu ziehen ist nicht die feine Art
Ich spekuliere, dass es Unterschiede im Funktionsaufruf gibt. Deshalb:
Wie ist die M103 Fuse des Atmega128 eingestellt? Kannst du ein
Disassemblerlisting (oder das HEX-File) bereitstellen?
Robert Maucher schrieb:
> -ich habe nur einen Internen Takt zu verfügung.
Das ist schon mal ziemlich schlecht.
Nur testweise:
probier mal Folgendes
1 | void USART_Transmit( unsigned char data )
| 2 | {
| 3 | /* Wait for empty transmit buffer */
| 4 | while ( !( UCSR0A & (1<<UDRE0)) )
| 5 | ;
| 6 | /* Put data into buffer, sends the data */
| 7 | UDR0 = data;
| 8 |
| 9 | _delay_ms( 1 );
| 10 | }
|
wenns dann geht, dann hast du ziemlich sicher ein Problem mit dem
internen Oszillator.
Du kannst auch mal probieren, auf 2 Stoppbits zu erhöhen.
> Ps: Hilfsbedürftige ins Lächerliche zu ziehen ist nicht die feine Art
Wenn jemand den internen Oszillator zur UART Übertragung benutzt, ist
jegliches Mitleid fehl am Platze.
Karl heinz Buchegger schrieb:
> Robert Maucher schrieb:
>
>> -ich habe nur einen Internen Takt zu verfügung.
>
> Das ist schon mal ziemlich schlecht.
>
>
> Nur testweise:
> probier mal Folgendes
>
> 1 | > void USART_Transmit( unsigned char data )
| 2 | > {
| 3 | > /* Wait for empty transmit buffer */
| 4 | > while ( !( UCSR0A & (1<<UDRE0)) )
| 5 | > ;
| 6 | > /* Put data into buffer, sends the data */
| 7 | > UDR0 = data;
| 8 | >
| 9 | > _delay_ms( 1 );
| 10 | > }
| 11 | >
|
>
> wenns dann geht, dann hast du ziemlich sicher ein Problem mit dem
> internen Oszillator.
>
> Du kannst auch mal probieren, auf 2 Stoppbits zu erhöhen.
das geht auf jedenfall
auch ohne delay
ich hab nur probleme mit
einer String (char array) ausgabe
Robert Maucher schrieb:
> das geht auf jedenfall
> auch ohne delay
>
> ich hab nur probleme mit
>
> einer String (char array) ausgabe
Probiers einfach!
An deiner String Ausgabe ist nichts falsch.
Es könnte aber sein, dass dein Optimizer die Schleifenvariante schneller
realisieren kann, als wenn du die Aufrufe einzeln machst. Mit ein wenig
Pech reicht das dann schon, dass du mit dem Timing daneben bist.
Die M103 ist deaktiviert da ich später beide Uarts brauche
Robert Maucher schrieb:
> Karl heinz Buchegger schrieb:
>> Robert Maucher schrieb:
>>
>>> -ich habe nur einen Internen Takt zu verfügung.
>>
>> Das ist schon mal ziemlich schlecht.
>>
>>
>> Nur testweise:
>> probier mal Folgendes
>>
>> 1 | >> void USART_Transmit( unsigned char data )
| 2 | >> {
| 3 | >> /* Wait for empty transmit buffer */
| 4 | >> while ( !( UCSR0A & (1<<UDRE0)) )
| 5 | >> ;
| 6 | >> /* Put data into buffer, sends the data */
| 7 | >> UDR0 = data;
| 8 | >>
| 9 | >> _delay_ms( 1 );
| 10 | >> }
| 11 | >>
|
>>
>> wenns dann geht, dann hast du ziemlich sicher ein Problem mit dem
>> internen Oszillator.
>>
>> Du kannst auch mal probieren, auf 2 Stoppbits zu erhöhen.
>
> das geht auf jedenfall
> auch ohne delay
>
> ich hab nur probleme mit
>
> einer String (char array) ausgabe
Nein macht kein Unterschied,
Ich habe jetzt auch mit verschiedenen Zeiten Rumgespielt, aber hat auch
keine Veränderung gegeben.
von der Timing her müsste es eigentlich kein Problm geben, da 1 | for(i=0;i<=4;i++){
| 2 | USART_Transmit(i+0x30); //geht
| 3 | USART_Transmit('\n');
| 4 | }
|
auch ohne Probleme ausgegeben wird
Dann hilft alles nichts.
Ein Assembler Listing muss her
Karl heinz Buchegger schrieb:
> Dann hilft alles nichts.
> Ein Assembler Listing muss her
Hier die Listings und die Maps
Ich würde dir raten nochmal sehr gründlich und eindringlich die M103C
Fuse zu überprüfen.
Stefan Ernst schrieb:
> Ich würde dir raten nochmal sehr gründlich und eindringlich die M103C
> Fuse zu überprüfen.
Das lässt sich relativ leicht prüfen.
Einfach den Optimizer komplett ausschalten, so dass er nichts inlinen
kann. Wenns beim ersten Funktionsaufruf kracht, dann wars die Fuse
So dumm ist der Geadnke gar nicht.
Selbst wenn der Compiler alle Funktionen inlined, das Array kann er beim
besten Willen nicht in einem Register halten.
Liegt das SRAM aber falsch (durch die Fuse) werden falsche Daten
gelesen.
Karl heinz Buchegger schrieb:
> So dumm ist der Geadnke gar nicht.
Hey, hattest du etwa gedacht, ich hätte das "einfach mal so"
hingeschrieben? ;-)
Karl heinz Buchegger schrieb:
> Liegt das SRAM aber falsch (durch die Fuse) werden falsche Daten
> gelesen.
Wenn die Fuse gesetzt ist, ist dort, wo die Daten liegen, gar kein RAM.
Und bei den direkten Aufrufen (USART_Transmit(s[0]);) werden die
Zugriffe auf die Daten natürlich durch den Optimizer gleich durch die
Zeichen ersetzt.
Stefan Ernst schrieb:
> Karl heinz Buchegger schrieb:
>> So dumm ist der Geadnke gar nicht.
>
> Hey, hattest du etwa gedacht, ich hätte das "einfach mal so"
> hingeschrieben? ;-)
Jetzt hab ich mich in die Nesseln gesetzt.
Ich hab die Fuse jetzt nur im Zusammenhang mit Funktionsaufrufen gesehen
und laut ListFile hat der Compiler, was ich so gesehen habe, alles
inline gemacht.
(Sieh die Aussage als Selbstgespräch mit mir selber an :-)
Karl heinz Buchegger schrieb:
> Stefan Ernst schrieb:
>> Ich würde dir raten nochmal sehr gründlich und eindringlich die M103C
>> Fuse zu überprüfen.
>
> Das lässt sich relativ leicht prüfen.
> Einfach den Optimizer komplett ausschalten, so dass er nichts inlinen
> kann. Wenns beim ersten Funktionsaufruf kracht, dann wars die Fuse
>
> So dumm ist der Geadnke gar nicht.
> Selbst wenn der Compiler alle Funktionen inlined, das Array kann er beim
> besten Willen nicht in einem Register halten.
> Liegt das SRAM aber falsch (durch die Fuse) werden falsche Daten
> gelesen.
10011001 low fuse (0x99)
11100100 high fuse (0xE4)
11111111 efuse (0xFF)-> für kombi m103 oxFD
Robert Maucher schrieb:
> Karl heinz Buchegger schrieb:
>> Stefan Ernst schrieb:
>>> Ich würde dir raten nochmal sehr gründlich und eindringlich die M103C
>>> Fuse zu überprüfen.
>>
>> Das lässt sich relativ leicht prüfen.
>> Einfach den Optimizer komplett ausschalten, so dass er nichts inlinen
>> kann. Wenns beim ersten Funktionsaufruf kracht, dann wars die Fuse
>>
>> So dumm ist der Geadnke gar nicht.
>> Selbst wenn der Compiler alle Funktionen inlined, das Array kann er beim
>> besten Willen nicht in einem Register halten.
>> Liegt das SRAM aber falsch (durch die Fuse) werden falsche Daten
>> gelesen.
>
> 10011001 low fuse (0x99)
>
> 11100100 high fuse (0xE4)
>
> 11111111 efuse (0xFF)-> für kombi m103 oxFD
hab das Problem Gefunden
es war der komi Modus und die Fuse war nicht gestezt
war ein Fehler in der Makefile
hatte einen Tippfehler bei der e fuse ein read (r) anstatt write (w)
Danke euch allen für die Hilfe
gruß Robert
@ Robert Maucher (robert_maucher)
> hab das Problem Gefunden
>es war der komi Modus und die Fuse war nicht gestezt
>war ein Fehler in der Makefile
>hatte einen Tippfehler bei der e fuse ein read (r) anstatt write (w)
Und wieder einmal triumphiert die AVR Checkliste.
MfG
Falk
ja die Checkliste ist schon wichtig, noch wichtiger ist die eigene
Unfähigkeit zu tippen zu überwinden schande über mich
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
|