Hast du schon versucht statt der Berechnung der Baudrate es fix einzustellen? Im DB steht für einige übliche Frequenzen die Baudraten mit den Einstellungen.
MfG Hannes
Hast du schon versucht statt der Berechnung der Baudrate es fix einzustellen? Im DB steht für einige übliche Frequenzen die Baudraten mit den Einstellungen.
MfG Hannes
Hallo,
habe jezt auch mal die Baudrate fix eingestellt dies hat aber auch nichts gebracht. Immer der selbe "Müll".
Habe meinen externen Quarz mal weggenommen und habe intern den RCOsc. mal auf 8MHz; 6CK+64ms gestellt, und habe meine F_CPU auf 8000000 gestellt
Meine LED's blinken alle noch im sekundentakt.
Wenn ich mir einen festen Wert oder Buchstabe übertragen lassen will, kommt in ANSI nichts mehr an und in Ascii nur noch komische Symbole, ich sehe aber an meinen RXD das irgendwelche daten ankommen.
Hier nochmal mein Programm
Kann das wirklich nur an der CPU-Frequenz liegen?Code:#include <avr/io.h> #include <util/delay.h> #include <stdlib.h> #define F_CPU 8000000// 12000000 /* evtl. bereits via Compilerparameter definiert */ #define BAUD 300 // Baudrate // Berechnungen #define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1) // clever runden #define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1))) // Reale Baudrate #define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) // Fehler in Promille, 1000 = kein Fehler. #include <util/setbaud.h> //------------------------------------------------------------------------------------------ //USART initialisieren void uart_init(void) { //Set Baudrate UBRRH = UBRR_VAL >> 8; UBRRL = UBRR_VAL & 0xFF; UCSRB |= (1<<TXEN) | (1<<RXEN); //UART TX und RX einschalten UCSRC = (1<<URSEL) |(1<<UCSZ1) | (1<<UCSZ0); // Einstellen des Datenformats: 8 Datenbits, 1 Stoppbit } //------------------------------------------------------------------------------------------ //Warteschleife void delay_ms(unsigned int ms) { unsigned int zaehler; while (ms) { zaehler = F_CPU / 5000; while (zaehler) { __asm volatile("nop"); zaehler--; } ms--; } } //------------------------------------------------------------------------------------------ // Zeichen senden int uart_putc(unsigned char c) { while (!(UCSRA & (1<<UDRE))) { } UDR = c; return 0; } //------------------------------------------------------------------------------------------ //String senden void uart_puts(char *s) { while (*s) { /* so lange *s != '\0' also ungleich dem "String-Endezeichen(Terminator)" */ uart_putc(*s); s++; } } //------------------------------------------------------------------------------------------ //Zeichen empfangen uint8_t uart_getc(void) { while (!(UCSRA & (1<<RXC))) //warten bis Zeichen verfügbar ; return UDR; //Zeichen aus UDR an Aufrufer zurückgeben } //------------------------------------------------------------------------------------------ //Sting empfangen void uart_gets(char *Buffer, uint8_t MaxLen) { uint8_t NextChar; uint8_t StringLen = 0; NextChar = uart_getc(); // Warte auf und empfange das nächste Zeichen // Sammle solange Zeichen, bis: // * entweder das String Ende Zeichen kam // * oder das aufnehmende Array voll ist while( NextChar != '\n' && StringLen < MaxLen - 1 ) { *Buffer++ = NextChar; StringLen++; NextChar = uart_getc(); } // Noch ein '\0' anhängen um einen Standard // C-String daraus zu machen *Buffer = '\0'; } //------------------------------------------------------------------------------------------ //Hauptprogramm int main(void) { int Line[2]; //Array vom Typ int char Buffer[3]; //String mit maximal 8 zeichen int a; DDRB = 0xFF; PORTB = 0xFF; a=12; uart_init(); // UART einstellen while (1) { if ((UCSRA & (1<<RXC))) //überprüfen ob neue Zeichen vorhanden sind { uart_gets(Line, sizeof(Line)); //Zeichen wurden empfangen, jetzt abholen a=atoi (Line); //aus Text eine Zahl machen itoa (Line, Buffer, 10); // Aus der Variablen a ein Text erstellen uart_puts("j"); //Senden festen Buchstaben j } else { uart_puts(a); //Variable a senden Testzwecke PORTB = 0b00000000; uart_puts(a); //Variable a senden Testzwecke delay_ms(1000); uart_puts(a); //Variable a senden Testzwecke PORTB = 0b00001111; uart_puts(a); //Variable a senden Testzwecke delay_ms(1000); PORTB = 0b11110000; delay_ms(1000); PORTB = 0b11111111; delay_ms(1000); } } }
Habe eben mal noch Versucht eine feste Variable zu Übertragen das heißt ich habe
geschrieben und es kommt auch die 12 an auch wenn ich buchstaben übertrage funktioniert das.Code:uart_puts("12")
Wenn ich jetzt aber eine Variabel deklariere zum Beispiel
Aber hier kommt dann nur wirres zeug an.Code:char a; a = 65;
Geändert von knoddelpusch (28.10.2015 um 21:50 Uhr)
Hallo,
Versuchs mal mit
uart_putc(a);
an Stelle von
uart_puts(a);
"a" ist ein int und kein String, da ist kein '/0' am Ende!
"12" ist ein String und wird im Speicher als
0x32, 0x32, 0x00
abgelegt.
12 ist eine dezimale Zahl und wird als
0x0C
im Speicher abgelegt. 0x0C ist übrigens das Steuerzeichen FF (Form Feed). Auf einem Drucker würde dies einen Seitenvorschub auslösen.
Mit a=65 würdest du ein "a" senden, dahinter kommt dann aber irgendwelcher Schott bis uart_puts(a); irgend wo auf 0x00 im Speicher stösst.
Wenn du Pech hast, ergeben sich aber auch Steuerzeichen, welche das "a" oder die ganze Zeile in deiner Terminalemulation wieder löschen.
Das ist auch der Unterschied zwischen ANSI- und ASCII-Darstellung.
Im ANSI-Mode werden Steuer-Zeichen und -Sequenzen interpretiert und ausgeführt. Alle Zeichen < 0x20 sind Steuerzeichen und werden nicht angezeigt, lösen aber meistens eine Funktion aus, sofern auf dem Terminal umsetzbar. 0x07 sollte einen Beeb erzeugen, 0x0A ist eine Zeilenvorschub und 0x0D ein Wagenrücklauf (der Cursor wird nach ganz links gestellt). 0x0C macht auf dem Terminal keinen Sinn und wird meistens ignoriert. Dann gibt es noch Befehle mit Parametern, wie z.B. das Positionieren des Cursors an einer beliebigen Stelle auf dem Terminal. Diese beginnen, bei ANSI, mit 0x1B (ESC). Die folgenden Bytes sind dann der Befehl und die Parameter.
Im ASCII-Mode wird jedes Zeichen angezeigt und nicht als Steuerbefehl interpretiert.
Grundsätzlich kennt ein Prozessor nur Zahlen, Buchstaben gibt es für ihn gar nicht!
Buchstaben sind eine Art Verschlüsselung. In einer Tabelle werden den Zahlen Buchstaben zugeordnet.
Die bekannteste Codierung ist ASCII, welche aber nur für die ersten für die Werte 0...127 Zeichen gilt.
https://de.wikipedia.org/wiki/Americ...#ASCII-Tabelle
Besonders IBM bevorzugte aber eine andere Codierung Namens EBCDIC:
http://www.astrodigital.org/digital/ebcdic.html
Dummerweise kennen die AMIs aber keine Umlaute und andere Sonderzeichen!
Ein Problem durch die ASCII-Norm, war noch, dass vor allem bei der Datenübertragung nur oft 7 Bit übertragen wurden (Teilweise wurde Bit-8 als Parity-Bit verwendet und beim Empfang dann auf 0 gesetzt).
Der erste Ansatz war dann z.B. die deutschen Umlaute auf normalerweise wenig benutzte Zeichen zu legen.
Ein weiteres Problem war dadurch, dass man so keine Binärdaten Übertragen konnte, weshalb man die 8 Bit in ein Format mit 6 Bit umpacken musste.
Deshalb werden heute noch Binärdaten in E-Mails als MIME-64 codiert:
https://de.wikipedia.org/wiki/Multip...ail_Extensions
Man hat dann z.B. Umlaute auf die Zeichen "[" und "]" gelegt. Als Programmierer bekam man dann aber lustige Listings ausgedruckt
Da ein Byte aber die Werte 0...255 annehmen kann und in ASCII z.B. keine Umlaute vorgesehen sind, haben die Hersteller dann den Erweiterten-ASCII-Code, welcher den Werten 128...255 Zeichen zuordnet. Entwickelt. Allerdings waren diese Erweiterungen für jede Sprache unterschiedlich und die meisten Hersteller kochten ein eigenes Süppchen.
Mit dem IBM-PC und DOS hat dann IBM eine Defaktostandard geschaffen. Allerdings waren auch hier die Zuordnungen je nach eingestellter Code-Page unterschiedlich.
Eine genormte Vereinheitlichung entstand dann erst vor etwa 25 Jahren mit dem Unicode:
https://de.wikipedia.org/wiki/Unicode#Versionen
Windows unterstützt Unicode seit NT 4.0 (1996) bzw. Windows 2000 (2000).
MfG Peter(TOO)
Geändert von Peter(TOO) (29.10.2015 um 14:42 Uhr) Grund: ASCII tippfehler
Manchmal frage ich mich, wieso meine Generation Geräte ohne Simulation entwickeln konnte?
Viel Text von Peter. Aber genau so sehe ich das auch. Du überträgst ein einzelnes Byte mit einer Funktion, die auf ein \0 wartet. Das geht schief. wenn du puts verwenden willst, musst du ein char array verwenden und nach den eigentlichen zu übertragenden Zeichen in einer weiteren Arraystelle mit einem \0 abschließen.
char s[11];
int a;
a = 65;
sprintf(s, "%d,%c\n", a, a);
uart_puts(s);
überträgt dir den Wert von a erst als 65 und dann als A. sprintf fügt das \0 selbständig an. Musst also immer eine Speicherstelle mehr planen als du füllen willst im Array.
Ansonsten hast du ja die richtige Baudrate, sonst würde deine Stringfolge "12" nicht übertragen. Jedenfalls habe ich das so verstanden, dass das geht.
Dann liegts nur noch an den Programmierfähigkeiten.
sast
雅思特史特芬
开发及研究
Hallo,
habe das Problem mit dem Übertragen gelöst.
Das habe ich noch nicht ganz verstanden
sprintf(s, "%d,%c\n", a, a);
es wird ein Array s erstellt von den Zeichn a, aber was beudet jetzt das %d und das %c.
Ich vermute mal das das c wird für char steht.
Wie kann ich am besten ein Array in teile aufteilen. Die Trennstellen sind durch ein komma getrennt.
Das heist ich bekomme eine Zeichen folge von 12,345,6.
Dies wandle ich dann in eine Integer Zahl um, aber wie teile ich die dann in z.B, x=12, y=345 und z=6 auf.
Ich habe da auch schon viel von strtok, sscanf oder strsep gelesen aber so richtig schau bin ich da nicht draus geworden.
Hallo,
so habe die Probleme gelöst es funktioniert alles. Naja fast alles, muss jezt noch mein Kommunikation mit VB.Net hinbekommen (auch schon fast am verzweifeln).
Ich möchte mich mal bei allen beteiligten bedanken, für die groß Hilfe, viel Dank!
Das Hauptproblem lag wahrscheinlich darin das mein 12MHz Quarz einen defekt hatte bzw hat, habe das jetzt alles auf dem intern 8MHz laufen und funktioniert alles,
es waren aber auch noch genug kleine fehler dabei.
Ich habe mein Aufteilung mit der "strtok" und "strcpy" funktionen erledigt.
Mit der strtok habe ich auf meine String auf Trennzeichen untersucht
und mit der strcpy in die entsprechenden Variablen gespeichert.
Wenn ich jetzt über das RealTerm eine 1,2,3,4\n sende veränderen sich auch die Blink Zeiten entsprechend.
Hier mal mein Programm
Code:#include <avr/io.h> #include <util/delay.h> #include <stdlib.h> #include <string.h> #define F_CPU 8000000 /* evtl. bereits via Compilerparameter definiert */ #define BAUD 300 // Baudrate // Berechnungen #define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1) // clever runden #define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1))) // Reale Baudrate #define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) // Fehler in Promille, 1000 = kein Fehler. #include <util/setbaud.h> struct _S_DATA S_DATA; int Line[9]; //Array vom Typ int //------------------------------------------------------------------------------------------ //USART initialisieren void uart_init(void) { //Set Baudrate UBRRH = UBRR_VAL >> 8; UBRRL = UBRR_VAL & 0xFF; UCSRB |= (1<<TXEN) | (1<<RXEN); //UART TX und RX einschalten UCSRC = (1<<URSEL) |(1<<UCSZ1) | (1<<UCSZ0); // Einstellen des Datenformats: 8 Datenbits, 1 Stoppbit } //------------------------------------------------------------------------------------------ struct _S_DATA { char Rot[2]; char RG [2]; char GR [2]; char GE [2]; }; //------------------------------------------------------------------------------------------ //Warteschleife void delay_ms(unsigned int ms) { unsigned int zaehler; while (ms) { zaehler = F_CPU / 5000; while (zaehler) { __asm volatile("nop"); zaehler--; } ms--; } } //------------------------------------------------------------------------------------------ // Zeichen senden int uart_putc(unsigned char c) { while (!(UCSRA & (1<<UDRE))) { } UDR = c; return 0; } //------------------------------------------------------------------------------------------ //String senden void uart_puts(char *s) { while (*s) { /* so lange *s != '\0' also ungleich dem "String-Endezeichen(Terminator)" */ uart_putc(*s); s++; } } //------------------------------------------------------------------------------------------ //Zeichen empfangen uint8_t uart_getc(void) { while (!(UCSRA & (1<<RXC))) //warten bis Zeichen verfügbar ; return UDR; //Zeichen aus UDR an Aufrufer zurückgeben } //------------------------------------------------------------------------------------------ //Sting empfangen void uart_gets(char *Buffer, uint8_t MaxLen) { uint8_t NextChar; uint8_t StringLen = 0; NextChar = uart_getc(); // Warte auf und empfange das nächste Zeichen // Sammle solange Zeichen, bis: // * entweder das String Ende Zeichen kam // * oder das aufnehmende Array voll ist while( NextChar != '\n' && StringLen < MaxLen - 1 ) { *Buffer++ = NextChar; StringLen++; NextChar = uart_getc(); } // Noch ein '\0' anhängen um einen Standard // C-String daraus zu machen *Buffer = '\0'; } //------------------------------------------------------------------------------------------ //String Zerlegung void string_zer(void) { unsigned char i; //Case Hochzählung char Trennzeichen[]=","; //Trennungszeichen char *ptr; //Variable zum zwischenspeichern i = 2; //Variable i auf 2 setzten ptr=strtok(Line, Trennzeichen); // Line durchsuchen bis zum Trennzeichen und in ptr zwischen speichern strcpy (S_DATA.Rot, ptr); // Erster Teil in Rot kopiern wo in der Struct _S_DATA liegt while (ptr != NULL) //weiter durchsuchen bis das nächste Trennzeichen oder Ende kommt { ptr = strtok (NULL, Trennzeichen); // Line durchsuchen bis zum Trennzeichen oder Ende und in ptr zwischen speichern switch (i) //Um in Unterschiedlichen Variablen zu speichern { case 2: strcpy(S_DATA.RG,ptr); break; case 3: strcpy(S_DATA.GR,ptr); break; case 4: strcpy(S_DATA.GE,ptr); break; } i++; //Variable i um eins hochzählen } } //------------------------------------------------------------------------------------------ //Hauptprogramm int main(void) { //Variablen Deklartion int time = 1000; int time1 = 1000; char Buffer[9]; //String mit maximal 8 zeichen int a; //Umwandlung ascii zu integer DDRB = 0xFF; PORTB = 0xFF; uart_init(); // UART einstellen while (1) { //--------------------------------------------------------------------------------------------- if ((UCSRA & (1<<RXC))) //überprüfen ob neue Zeichen vorhanden sind { uart_gets(Line, sizeof(Line)); //Zeichen wurden empfangen, jetzt abholen string_zer(); //String in seine Teile zerlegen uart_puts(S_DATA.Rot); uart_puts(S_DATA.GE); a = atoi (S_DATA.Rot); //Rot in integer wandeln time = a *1000; // mal 1000 um auf sekunden zu kommen itoa (time, Buffer, 10); //time in char umwandeln uart_puts(Buffer); //Buffer senden } //--------------------------------------------------------------------------------------------- else { PORTB = 0b00000000; delay_ms(time1); PORTB = 0b00001111; delay_ms(time); PORTB = 0b11110000; delay_ms(time1); PORTB = 0b11111111; delay_ms(time); } } }
Lesezeichen