allo Zusammen, ich habe vor kurzem angefangen mein Atmel in C zu programmieren (vorher immer in Basic). Nun habe ich ein Problem und weiß nicht wo mein Denkfehler oder Leichtsinnsfehler liegt. Ich möchte eine Kommazahl über ein Uart senden. Ich verwende die dtostrf- Funktion. Leider geht das aber nicht. Mein Terminalprogramm empfängt jediglich nur ein "H". Wär echt klasse, wenn ihr mir helfen könntet. Mein Code: #include <avr/io.h> #include <stdint.h> #include <avr/delay.h> #include <stdio.h> #include <stdlib.h> #define SYSCLK 8000000L #define BAUD 9600L #define UBRR_BAUD ((SYSCLK/(16*BAUD))-1) /* INT Deklarationen */ int init(void); int uart_out(char sende_daten[8]); int main() { char s[8]; float f = -12.345; init(); dtostrf( f, 6, 3, s ); while (1) { _delay_ms(1000); uart_out(s); } } int uart_out(char sende_daten[8]) { while (!(UCSRA & (1<<UDRE))); UDR = sende_daten; return(0); } int init(void) { /* Baudrate einstellen ( Normaler Modus ) */ UBRRH = (unsigned char)(UBRR_BAUD>>8); UBRRL = (unsigned char)UBRR_BAUD; UCSRB = (1<<RXCIE)|(1<<RXEN)|(1<<TXEN); /* Einstellen des Datenformats: 8 Datenbits, 1 Stoppbit */ UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); return(0); }
Du machst einen großen und einen kleinen Fehler. Erst einmal der kleine Fehler: 1000 ms lassen sich mit _delay_ms() bei gewöhnlichem AVR-Takt nicht erreichen. 10 ms ist ein sicherer Wert, der selbst bei den derzeit schnellsten AVRs (20 MHz) immer funktioniert. Normalerweise nimmt man für lange Verzögerungen ja sowieso einen Timer, für den einfachen Test kannst du die Funktion ja 100mal aufrufen. Der große Fehler: du willst einen String ausgeben, gibst aber nur das niedrige Byte der Adresse des Strings (die in "sende_daten" steht) aus. Bau die Funktion so um:
1 | static void |
2 | uart_out_char(char c) |
3 | {
|
4 | while (!(UCSRA & (1<<UDRE))); |
5 | UDR = c; |
6 | }
|
7 | |
8 | int uart_out(char *sende_daten) |
9 | {
|
10 | char c; |
11 | |
12 | while ((c = *sende_daten++) != '\0') |
13 | uart_out_char(c); |
14 | |
15 | // Vielleicht willst du ja das hier noch?
|
16 | uart_out_char('\r'); |
17 | uart_out_char('\n'); |
18 | |
19 | return 0; |
20 | }
|
Hallo, danke für Deine Antwort. Jedoch gehts bei mir irgendwie immer noch nicht. Wär genial, wenn mir nochmal helfen könntest. Ich zweifel grad echt an meiner Intelligenz:). Vielleicht könntest Du den Code verbessern. Weil bei mir kommt nämlich gar nichts. /* INT Deklarationen */ int init(void); static void uart_out_char(char c); int uart_out(char *sende_daten); int main() { char s; float f = -12.345; init(); dtostrf( f, 6, 3, s ); while(1) { _delay_ms(10); uart_out(s); } } int uart_out(char *sende_daten) { char c; while ((c = *sende_daten++) != '\0') uart_out_char(c); return 0; } static void uart_out_char(char c) { while (!(UCSRA & (1<<UDRE))); UDR = c; }
Wenn Du einen float in einen Character-String umwandeln willst, dann musst Du für den String auch ausreichend Speicherplatz zur Verfügung stellen. "c" ist aber nur ein einfacher char, da passt nur eine einzige Stelle (ASCII-Zeichen) rein. Du brauchst aber 7 Stellen (6 Stellen für die Zahl an sich, wenn Du als "width" 6 angibst und ein Zeichen für den Nullterminator). Dazu muss c mindestens als Array mit 7 Elementen deklariert werden, also "char s[7];". Allerdings hat die im Beispiel angegebene Zahl "-12.345" bereits 7 Stellen, da sich der Parameter "width" auf die Gesamtlänge der Ausgabe bezieht, also auf alle Ziffern zzgl. Dezimalpunkt und Vorzeichen. Du wirst diese Zahl also so nicht darstellen können. Da muss also ein Array mit 8 Elementen her, also "char s[8];". Damit sollte es funktionieren.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.