Forum: Compiler & IDEs avr register ausläsen und umwandeln zu ascii, wie?


von Georg G. (Firma: gmbh-keine) (georgino)


Lesenswert?

Hallo,

hab ein kleines Problem!


wie wandle ich ein Binärcode eines ausgelesennen emfangsregister UDR ins 
Dezimale?

buffer = UDR;

lcd_string(buffer); und am LCD ausgeben?

Kann jemand helfen?

von Krapao (Gast)


Lesenswert?

UDR ist ein 8-Bit Register, d.h. man kann ein Byte auslesen. Aber die 
Funktion lcd_string() erwartet einen String (= Folge von Bytes) als 
Argument, jedenfalls wenn sie sinnvoll benannt ist. Dein Codeschnippsel 
ist unlogisch.

Die Umwandlung eines Bytes in einen String kann man mit der 
Bibliotheksfunktion itoa() machen. Doku dazu ibt es im Artikel FAQ 
und in jedem C-Buch sowieso.

von Michael H. (michael_h45)


Lesenswert?

Krapao schrieb:
> Funktion lcd_string() erwartet einen String (= Folge von Bytes) als

Das ist so nicht richtig - C kennt keinen Datentyp string. Funktionen 
dieser Natur erwarten einen Pointer auf ein Char-Array.

georg georg schrieb:
> buffer = UDR;
> lcd_string(buffer); und am LCD ausgeben?
Grundsätzlich: keine Aufgaben in einer ISR erledigen, die man problemlos 
auch aus main() erledigen kann. Du blockierst damit nämlich andere 
Interrupts.

> Kann jemand helfen?
http://www.mikrocontroller.net/articles/FAQ#Wie_kann_ich_Zahlen_auf_LCD.2FUART_ausgeben.3F
AVR-GCC-Tutorial/LCD-Ansteuerung: LCD Beispiel 2

von Georg G. (Firma: gmbh-keine) (georgino)


Lesenswert?

Hallo,

Danke für denn Tipp..

Ich habs dann so gemacht!

in der 2. Zeile soll dann die Variable aus denn UDR Register ausgegeben 
werden. Tut es aber nicht! Hmmm...
1
 #include <avr/io.h>
2
 #include <inttypes.h>
3
 #include <util/delay.h>
4
 #include "lcd-routines.h"
5
6
 #define BAUD 19200UL
7
 #define UBRR_BAUD ((F_CPU/(16L*BAUD))-1)
8
9
 // USART initialisieren
10
 void uart_init(void)
11
 {
12
 // Baudrate einstellen (Normaler Modus)
13
 UBRRH = (uint8_t) (UBRR_BAUD>>8 );
14
 UBRRL = (uint8_t)UBRR_BAUD;
15
16
 // Aktivieren von receiver und transmitter
17
 UCSRB = (1<<TXEN) | (1<<RXEN);
18
 
19
 // Einstellen des Datenformats: 8 Datenbits, 1 Stoppbit
20
 UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);
21
 //UCSRC |= (1<<URSEL)|(3<<UCSZ0);
22
 }
23
24
 int main(void){ 
25
26
    lcd_init();
27
28
  set_cursor(0,1);
29
    lcd_string("Drueck Taste!");
30
31
 DDRB=0xFF; //all pins of PORTB declared as output
32
 PORTB=0x00;//DDRB = ( 1 << PB0 );        // PB0 an PORTB als Ausgang setzen
33
34
35
 //uint8_t variable;
36
  uint8_t reg;
37
  char Buffer[20]; // in diesem {} lokal
38
39
 uart_init();  // USART initialisieren
40
 
41
 while (1)
42
 {
43
 // Warten bis Daten empfangen wurden
44
 while ( !(UCSRA & (1<<RXC)) );
45
46
 reg = UDR;   // Empfangsregister auslesen
47
   
48
 // Warten bis der Sendepuffer frei ist
49
 while ( !( UCSRA & (1<<UDRE)) );
50
51
 // Daten in den Puffer schreiben und damit senden
52
     itoa( reg, Buffer, 10 ); 
53
     set_cursor(0,2);
54
     // ... ausgeben  
55
     lcd_string( Buffer );
56
57
  // _delay_ms(5000);
58
UDR = reg ;
59
60
}
61
return 0;
62
}

1 Zeile wird ausgegeben, die 2 Zeile aber nicht!?

von Karl H. (kbuchegg)


Lesenswert?

georg georg schrieb:

> 1 Zeile wird ausgegeben, die 2 Zeile aber nicht!?

Dann wird dein Programm wahrscheinlich nichts über die UART empfangen.
Funktioniert denn deine UART prinzipiell? Hast du das kontrolliert?


(Eine UART nimmt man in Betrieb, indem man sie dauer-senden lässt und 
auf der anderen Seite der Leitung mit einem Terminalprogramm an der 
Leitung lauscht. Macht man sich ein µC Programm, welches ständig 'X' 
sendet, dann muss logischerweise am PC im Terminalprogramm ein 
ununterbrochener Strom von 'X' auftauchen. Ehe man diesen Zustand nicht 
hat, braucht man die Gegenrichtung (PC->µC) gar nicht erst in Angriff zu 
nehmen. Das wäre Stochern im Nebel, weil man nie weiß, wo das Problem 
liegt, bzw. zuviele mögliche Problem existieren, die eine korrekte 
Funktion verhindern.


Und ich möchte dir auch ans Herz legen, deinen Code besser und vor allen 
Dingen konsistenter zu formatieren! Die Einrückungstiefen sind nicht 
willkürlich und nach gutdünken zu wählen, sondern ein vitales Element, 
ob ein Code gut oder schlecht zu lesen ist. Und was eng damit 
zusammenhängt: Ob man gewisse Fehlerklassen gut oder nur mühsam 
überprüfen kann.

von Georg G. (Firma: gmbh-keine) (georgino)


Lesenswert?

Danke!

Am Terminal kommt ein Signal zurück! Das Funktioniert!

Bleibt das Signal nicht im Register stehen?

Kann es einer anderen Variable zuweisen und etwas mit anstellen?

von Karl H. (kbuchegg)


Lesenswert?

OK, dann ändere dein Programm doch mal so ab, dass du die Ausgabe DIREKT 
nach dem Empfang machst
1
...
2
3
  while (1)
4
  {
5
    // Warten bis Daten empfangen wurden
6
    while ( !(UCSRA & (1<<RXC)) )
7
      ;
8
    reg = UDR;   // Empfangsregister auslesen
9
10
    itoa( reg, Buffer, 10 ); 
11
    set_cursor(0,2);
12
    lcd_string( Buffer );
13
   
14
    // Warten bis der Sendepuffer frei ist
15
    while ( !( UCSRA & (1<<UDRE)) )
16
      ;
17
    UDR = reg ;
18
  }
19
20
  return 0;
21
}

Womit sendest du Zeichen zum µC?

von Georg G. (Firma: gmbh-keine) (georgino)


Lesenswert?

mit RS232 Terminal und RealTerm

beide gehen!

ich habs so wie oben gemach, aber nichts! Hmmm.?
Jetzt Ratloss!

von Karl H. (kbuchegg)


Lesenswert?

georg georg schrieb:
> mit RS232 Terminal und RealTerm
>
> beide gehen!
>
> ich habs so wie oben gemach, aber nichts! Hmmm.?
> Jetzt Ratloss!


Hast du am PC das Handshake abgeschaltet?
Sprich: sendet der PC überhaupt?
(Das lässt sich zb gut mit einer LED, die man an die entsprechende 
Leitung hält überprüfen)

von Georg G. (Firma: gmbh-keine) (georgino)


Lesenswert?

wie macht man sowas?

von SCNR (Gast)


Lesenswert?

Michael H. schrieb:
> Krapao schrieb:
>> Funktion lcd_string() erwartet einen String (= Folge von Bytes) als
>
> Das ist so nicht richtig - C kennt keinen Datentyp string. Funktionen
> dieser Natur erwarten einen Pointer auf ein Char-Array.

Und deshalb kann es auch gar keine Funktion mit dem Namen lcd_string() 
in C geben!

von Karl H. (kbuchegg)


Lesenswert?

georg georg schrieb:
> wie macht man sowas?

LED nehmen, 330 Ohm als Vorwiderstand. Das eine Ende des Gebildes kommt 
an Masse, mit dem anderen Ende tippst du an die Datenleitung. Wenn da 
eine Übertragun läuft, dann blinkt die LED wie wild.

von Georg G. (Firma: gmbh-keine) (georgino)


Lesenswert?

Das mit der Led klapt! kurzes blinken bei Ein- und Ausgang...
Eine Daten Übertragung ist da.

von Georg G. (Firma: gmbh-keine) (georgino)


Lesenswert?

Hallo,

hab das sorce code modifiziert, ausgegeben wird am lcd was anderes?
Es herscht Rahtlosigkeit!?

LCD: senden ein "r" kommt dann 333 am LCD
 bei einer Zahl 73
 und wenn ich statt lcd_string, lcd_data nehme dann kommt "w"...
1
 #include <avr/io.h>
2
 #include <inttypes.h>
3
 #include <util/delay.h>
4
 #include "lcd-routines.h"
5
6
 #define BAUD 19200UL
7
 #define UBRR_BAUD ((F_CPU/(16L*BAUD))-1)
8
9
 // USART initialisieren
10
 void uart_init(void)
11
 {
12
 // Baudrate einstellen (Normaler Modus)
13
 UBRRH = (uint8_t) (UBRR_BAUD>>8 );
14
 UBRRL = (uint8_t)UBRR_BAUD;
15
16
 // Aktivieren von receiver und transmitter
17
 UCSRB = (1<<TXEN) | (1<<RXEN);
18
 
19
 // Einstellen des Datenformats: 8 Datenbits, 1 Stoppbit
20
 UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);
21
 //UCSRC |= (1<<URSEL)|(3<<UCSZ0);
22
 }
23
24
 int main(void){ 
25
26
    lcd_init();
27
28
  lcd_clear();
29
30
  _delay_ms(1000);
31
32
  set_cursor(0,1);
33
    lcd_string("Taste!");
34
  set_cursor(0,2);
35
36
  uint8_t reg;
37
  char Buffer[20]; // in diesem {} lokal
38
39
 uart_init();  // USART initialisieren
40
 
41
while (1)
42
  {
43
    // Warten bis Daten empfangen wurden
44
    while ( !(UCSRA & (1<<RXC)) )
45
      ;
46
    reg = UDR;   // Empfangsregister auslesen
47
48
49
  if(reg == ""){
50
               }
51
52
         else{
53
                    itoa( reg, Buffer, 10 ); 
54
                    lcd_string( Buffer );
55
                    _delay_ms(1000);
56
                   }
57
58
 // Warten bis der Sendepuffer frei ist
59
    while ( !( UCSRA & (1<<UDRE)) )
60
      ;
61
    UDR = reg ;
62
  reg = "";
63
  }
64
65
  return 0;
66
}

von Karl H. (kbuchegg)


Lesenswert?

> if(reg == ""){

du musst dir in C den Unterschied zwischen einem String und einem 
Einzelzeichen klar machen. Das hier macht etwas völlig anderes, als was 
du denkst das es tut.

>                    itoa( reg, Buffer, 10 );
>                    lcd_string( Buffer );
>                    _delay_ms(1000);

tu dir selbst einen Gefallen und mach nach der Zahlenausgeba noch ein 
Leerzeichen rein, damit du an der Ausgabe erkennen kannst, wo die 
Codezahl für 1 Zeichen endet und wo die Codezahl für das nächste Zeichen 
anfängt. Auch das Erstellen von sinnvollen Testausgaben will gelernt 
sein.

von Karl H. (kbuchegg)


Lesenswert?

> LCD: senden ein "r" kommt dann 333 am LCD
> bei einer Zahl 73
> und wenn ich statt lcd_string, lcd_data nehme dann kommt "w"...

klingt für mich immer noch danach, als ob deine UART nicht richtig 
funktioniert.

von Georg G. (Firma: gmbh-keine) (georgino)


Lesenswert?

das Uart hab ich getestet, es geht.

wenn ich mit dem Terminal ein zeichen schicke kommt es 1:1 wieder...
Hab probeweise dies eineggeben: UDR = 'B' ; kommt auch am Termianl an!

ich lese aus den URD ein 8Bit Binär code aus (0b00101101) die dann der 
Variable >> uint8_t reg; zugeordnet wird.
jetz bin ich mir nicht sicher ob ich den Binärcode zu ASCII vorher 
wandeln muß!?

von Marcus P. (marc2100)


Lesenswert?

Hi,
ich weiß gar nicht warum du überhaupt irgendwas umwandeln willst.

Wenn du auf dem PC-Terminal z.B. Taste 'A' drückst, sendet er den Wert 
0x41
bzw. in binär 0b00100001, was der ASCII-Code von 'A' ist.
Da dein LCD ja offentsichtlich mit dem ASCII-Code arbeitet brauchst du 
nichts umzuwandeln.

Allerdings must du aufpassen was du brauchst, weil es kommt ja immer nur 
genau 1 Zeichen an, und wird ausgegeben, weshalb es wahrscheinlich 
ungünstig ist eine Funktion zu nehmen die einen "String" haben möchte, 
also eine Reihe von char-werten.
Was du brauchst, ist also eine Funktion die 1 Zeichen auf dem LCD 
ausgibt und danach auf die nächste Spalte/Zeile (je nach dem was du 
willst) im LCD spring (für das nächste Zeichen).

Und nur nochmal fürs Verständnis, in C gibt es einmal mit 'Zeichen' das 
eigendliche ASCII-Zeichen, wenn du aber "Zeichen" schreibst, dann wird 
ein String erwartet, der 1. aus mehreren char-werten besteht, und 2. mit 
einer binären 0 (0x00 oder auch als \0 dargestellt) beendet werden muss.

Gruß
Marcus

von Georg G. (Firma: gmbh-keine) (georgino)


Lesenswert?

ojjjj..

jetzt ist das Licht angegangen!!

TX, DX sind mit PD0 und PD1 gekreuzt die auch am LCD liegen!!!

Desweil kommt dann Mist am LCD raus!!

Na dann umlöten..

2:0 für @karl :-)
Lg Georg

von Hilfreicher Helfer (Gast)


Lesenswert?

georg georg schrieb:
> while ( !( UCSRA & (1<<UDRE)) )
>       ;
>     UDR = reg ;

Eigentlich müsste es "while ( !( UCSRB & (1<<UDDE)) )" heißen...

von Karl H. (kbuchegg)


Lesenswert?

Hilfreicher Helfer schrieb:
> georg georg schrieb:
>> while ( !( UCSRA & (1<<UDRE)) )
>>       ;
>>     UDR = reg ;
>
> Eigentlich müsste es "while ( !( UCSRB & (1<<UDDE)) )" heißen...

???
Von welchem µC gehst du aus?

von Georg G. (Firma: gmbh-keine) (georgino)


Lesenswert?

ein Atmega32, 12Mhz.

wie kann ich ein Binäres zu einen AscII machen und das ASCII Zeichen 
einer variable zuordnen? Ich brauch da ASCII Zeichen um damit zu 
Arbeiten!

Das "itoa( reg, Buffer, 10 ); " macht genau das gegenteil!

von Karl H. (kbuchegg)


Lesenswert?

georg georg schrieb:
> ein Atmega32, 12Mhz.
>
> wie kann ich ein Binäres zu einen AscII machen und das ASCII Zeichen
> einer variable zuordnen? Ich brauch da ASCII Zeichen um damit zu
> Arbeiten!
>
> Das "itoa( reg, Buffer, 10 ); " macht genau das gegenteil!

Wie kommst da darauf?
itoa macht genau das, was du hier forderst
> wie kann ich ein Binäres zu einen AscII machen

Ich nehme mal an du brauchst die Umkehrung.
entweder die UMkehrung von itoa, dann eben atoi

   I TO A
   Integer to ASCII

   A TO I
   Ascii to Integer


oder aber, was in so einer Situation meist einfacher ist: Die Zahl 
aufbauen, während die Zeichen eintrudeln.


    Zahl = 10 * Zahl + ( Zeichen - '0' );

so kann man mit jedem Zeichen, welches aus der UART rauskommt, die Zahl 
immer mehr vervollständigen

  Zeichen             Zahl
                        0
    '1'             10 * 0 -> 0; + 1 -> 1
    '2'             10 * 1 -> 10; + 2 -> 12
    '8'             10 * 12 -> 120; + 8 -> 128
    '3'             10 * 128 -> 1280; + 3 -> 1283

Der Vorteil: mann muss die Zeichen nicht erst in einem String 
zwischenspeichern.

: Wiederhergestellt durch User
von Georg G. (Firma: gmbh-keine) (georgino)


Lesenswert?

Das einzige was ich im NET gefunden habe war dies:
1
//DEV-C++
2
#include <stdio.h>
3
#include <stdlib.h>
4
5
char string[] = "01100001";
6
7
  main()
8
  {
9
    int sum;
10
    sum = atoi( string ); 
11
    printf("Sum = %c\n", sum );
12
    
13
    
14
    
15
 system("pause");
16
 return 0;
17
  }

kommen aber falsche Zeichen heraus!?
hm..

von Karl H. (kbuchegg)


Lesenswert?

georg georg schrieb:

> Das einzige was ich im NET gefunden habe war dies:

Ich will dir wirklich nicht zu nahe treten.
Aber an dieser Stelle ist das Netz die falsche Adresse. Fehlendes 
Grundwissen kann auch das Netz nicht ersetzen, weil du nicht wießt 
wonach du suchen sollst.
Kauf dir ein C-Buch und arbeite es durch!


> char string[] = "01100001";
>
>   main()
>   {
>     int sum;
>     sum = atoi( string );
>     printf("Sum = %c\n", sum );
>
> kommen aber falsche Zeichen heraus!?

Nämlich welche? Und warum sind sie falsch?
Was hättest du von diesem Code erwartet und was passiert statt dessen?

Das Problem ist, dass dieser Code nicht besonders sinnvoll ist. Welchen 
Sinn soll es haben ein ASCII Character auszugeben, dessen ASCII Code 
1_Million_100_Tausend_und_1 ist. So ein Zeichen gibt es nicht.


Was willst du wirklich machen?
Beschreib das doch mal aus Sicht einer höheren Warte! Ich denke du hast 
dich verlaufen und suchst an der falschen Stelle nach Hilfe.

Wenn deine Frage lautet: Wie komm ich über die Mauer drüber?
dann kann man dir natürlich mit Bergsteigertricks aushelfen. Wenn du 
dann allerdings in einem Nebensatz erwähnst, dass du in einer Sackgasse 
stehst, an deren Ende die Mauer steht, dann ist die einfachere Lösung: 
fahr aus der Sackgassse zurück. Wenn sich dann noch rausstellt, dass du 
in Stuttgart in der Sackgasse stehst und du eigentlich von Hamburg nach 
Berlin fahren wolltest, dann ist klar, dass dein eigentliches Problem 
nicht darin besteht, wie du über die Mauer drüberkommst. Dieses Problem 
ist nur jetzt momentan vor dir aufgetaucht, aber dein eigentliches 
Problem ist, dass du schon vor Stunden eine Autobahnabfahrt verpasst 
hast und du eigentlich wieder zurück auf die Autobahn musst. Die Mauer 
ist nur Nebenschauplatz und es bringt nichts da jetzt großartig zu 
überlegen, wie du dein Auto über die Mauer drüber bringst.

Ich denke dein eigentliches Problem könnte zum Beispiel auch darin 
bestehen, dass du noch nicht verstanden hast, dass im Computer alles 
einfach nur ein Bitmuster ist.
D.h. aus dem UDR Register kriegst du nicht etwas was 'Binär ist' und du 
musst das zur Ausgabe in ASCII umwandeln.

   c = 0b0100001;
   c = 0x41;
   c = 65;
   c = 'A';

diese 4 Anweisungen machen alle dasselbe! Sie unterscheiden sich nur in 
der Schreibweise. Aber der Effekt ist in allen Fällen der gleiche. In 
der Variablen c wird das Bitmuster 0100 0001 abgelegt. Und wenn man 
dieses Bitmuster an ein LCD schickt, oder über eine UART an ein 
Terminal, dann zeigt das LCD bzw. das Terminal eine Punktwolke an, in 
der wir Menschen den Buchstaben A erkennen.
Aber im µC ist alles einfach nur ein Bitmuster. Und dieses Bitmuster 
kann auf unterschiedliche Arten visualisiert werden, je nachdem welche 
Ansichtz am sinnvollsten ist.

   c = 'A';

werde ich dann benutzen, wenn ich den Focus darauf legen will, dass ich 
in c den ASCII Code von 'A' geladen haben möchte. Wobei mich der genaue 
Code nicht interessiert, denn ich weiß, wenn ich diesen Code an ein LCD 
gebe, dann zeigt es auch wieder 'A' an.

  c = 65;

werde ich dann nehmen, wenn ich betonen möchte, dass es sich um eine 
Dezimalzahl handelt, wenn also Dezimal für mich als Programmierer das 
natürlichste ist. zb 65 Sekunden oder 65 Äpfel oder das 65.te Stockwerk.

  c = 0b0100001;

nehme ich dann, wenn ich speziell betonen möchte, dass ich ein Bitmuster 
haben will, bei dem das unterste und das vorletzte Bit gesetzt ist. Zb 
dann, weil dort LED an einem Port hängen.

Und die Hex-Schreibweise nehme ich im Prinzip ebenfalls genau dann, wenn 
es mir auf die Bits ankommt, mir aber die Binärschreibweise zu 
geschwätzig ist.


Aber abgesehen davon, sind alle 4 Schreibweisen vom Effekt her 
identisch! Da geht es nur darum, was mir als Mensch in dieser Situation 
am besten hilft, zu verstehen was an dieser Stelle im Programm passiert.

von Georg G. (Firma: gmbh-keine) (georgino)


Lesenswert?

langsam Behirn ich das!

Wie kann ich eine im Integer befindliche 65 zu einen ASCII machen und 
dann um ihn in einen als String anzulegen?

mein ansatz:
1
int8_t num = 65; // ein Wert wie aus einem UART UDR
2
char buf[5];
3
4
5
      // convert 65 to string [buf]
6
  itoa(num, buf, 10); // Wert im buf = 65

ich hätte gerne denn wert A im buf.

von Michael H. (michael_h45)


Angehängte Dateien:

Lesenswert?

georg georg schrieb:
> Wie kann ich eine im Integer befindliche 65 zu einen ASCII machen und
Du musst dir mal klarmachen, was ein Integer (Ganzzahl) und was ASCII 
(nur eine Umsetzungtabelle) ist.

ASCII ist nämlich integer.

Man hat einfach festgelegt, dass die ersten 127 Zahlen einem bestimmen 
Buchstaben oder Zeichen entsprechen sollen. (Später kam dann noch ein 
Erweiterungs-Satz von Sonderzeichen dazu).
Mehr ist das nicht.

Ein 'a' ist im ASCII-Code nichts anderes als die Zahl 97.
z.B.
1
if ('a' == 97)
ist immer wahr.

> dann um ihn in einen als String anzulegen?
Ein String ist nicht anderes als eine Kette von Integern.
1
char test0[6] = "Hallo";                           // ist das gleiche wie
2
char test1[6] = {'H', 'a', 'l', 'l', 'o', '\0'};   // ist das gleiche wie
3
char test2[6] = {72, 97, 108, 108, 111, 0};


Sagen wir also mal, du hast von mir aus einen ADC-Messwert von 0x86.
Das ist 134 in dezimal.
Du musst also eine '1', eine '3' und dann eine '4' ausgeben. Und genau 
diese Zeichenkette bekommst du von der Funktion itoa().


georg georg schrieb:
> mein ansatz:
Ist richtig.
Aufpassen musst du allerdings, dass du unsigned Variablen deklarierst.

von Stefan W. (dl6dx)


Lesenswert?

georg georg schrieb:
> Wie kann ich eine im Integer befindliche 65 zu einen ASCII machen und
> dann um ihn in einen als String anzulegen?

Hallo Georg,

nimm mir meine Offenheit bitte nicht übel, aber so lange du so fragst, 
hast du die Sache noch nicht wirklich verstanden.

Im µC gibt es nur Bitmuster. 8 Bit parallel nebeneinander, 0 und 1 
"bunt gemischt".

Je nachdem, was man gerade machen will, interpretiert man das 
Bitmuster auf unterschiedliche Weise.

Ich nehme mal dein Beispiel '01000001'. Das kann man ganz verschieden 
interpretieren:

- Als Bitmuster, also als eine mehr oder weniger willkürliche 
Anordnung. Das wäre z.B. der Fall, wenn man darüber Steuerleitungen 
schalten würde. Jedes Bit hätte dann eine von der Hardware abhängige 
Bedeutung.

- Als Binärzahl, also eine im Zweiersystem dargestellte Zahl. 
Allgemeine Konvention bei Zahlenangaben ist, die Stellen von rechts nach 
links zu schreiben. 0b01000001 (der Präfix '0b' zeigt eine Binärzahl an) 
hat in dezimaler Darstellung (Zehnersystem) die Darstellung 65. Man kann 
sie aber auch in einem auf 16 Werten aufgebauten System 
(Hexadezimalsystem) schreiben, dann ist die Darstellung 0x41.

- Und dann kann man sich darauf einigen, diesen Wert als Platzangabe 
in einer Tabelle von Schriftzeichen zu interpretieren. In der 
ASCII-Zeichensatztabelle findet sich auf Platz Nr. 65 (0x41, 0b01000001) 
das Zeichen 'A'. Willst du auf einem ASCII-Ausgabegerät (z.B. ein 
LC-Display) den Buchstaben 'A' ausgeben, sendest du den Wert für seine 
Position in der Tabelle an das Display. Dabei ist es egal, ob du 
diesen Wert nun als 65, 0x41 oder 0b01000001 interpretierst, das Display 
interpretiert ihn so, dass es das Bild des Buchstabens 'A' anzeigt.

Um es also noch mal zusammen zu fassen: Alle diese Darstellungen 
(0b01000001, 65, 0x41, 'A') bezeichnen das selbe Bitmuster!

Jetzt zu deinem Beispielcode:
1
// convert 65 to string [buf]
2
3
int8_t num = 65; // ein Wert wie aus einem UART UDR
4
char buf[5];
5
6
itoa(num, buf, 10); // Wert im buf = 65

itoa() interpretiert den Parameter num als Zahl und erzeugt eine 
Zeichenfolge (mehrere Werte), die auf ein Display ausgegebene werden 
können. Du hast als Basis des Zahlensystems 10 angegeben, also wird es 
eine Dezimalzahl. In buf steht also nach der Rückkehr aus itoa(num, buf 
10) die Wertefolge '6', '5', 0x00. (Warum da als dritter Wert 0x00 
steht, erkläre ich gern später.) Auf ein Display ausgegeben, siehst du 
"65".

Du wolltest aber "A" lesen. Das geht ganz einfach. Du schickst den Wert 
(65, 0x41 ...) an das Display. Und schon steht da "A".

> ich hätte gerne denn wert A im buf.
1
// convert 65 to string [buf]
2
3
int8_t num = 65; // ein Wert wie aus einem UART UDR
4
char buf[5];
5
6
buf[0] = num;
7
buf[1] = 0;

Mehr ist das nicht!

Grüße

Stefan

PS: Warum der Wert 0 an der Stelle buf[1] bzw. am Ende des von itoa() 
erzeugten Strings? In C werden Strings per Definition mit einem 
bestimmten Wert (0) abgeschlossen. Alle Bibliotheksfunktionen, die mit 
Strings arbeiten, verwendet diese Konvention.

von Karl H. (kbuchegg)


Lesenswert?

georg georg schrieb:
> langsam Behirn ich das!
>
> Wie kann ich eine im Integer befindliche 65 zu einen ASCII machen und
> dann um ihn in einen als String anzulegen?
>
> mein ansatz:
>
1
> int8_t num = 65; // ein Wert wie aus einem UART UDR
2
> char buf[5];
3
> 
4
> 
5
>       // convert 65 to string [buf]
6
>   itoa(num, buf, 10); // Wert im buf = 65
7
> 
8
> 
9
>
>
> ich hätte gerne denn wert A im buf.

Das widerspricht sich.

Wenn du ein 'A' auf der AUsgabe haben willst, brauchst du gar nichts 
tun. Du 'schickst' die (dezimalen) 65 an die Ausgabe und die Ausgabe 
zeigt ein 'A' an. Dies dehshalb, weil die AUsgabe davon ausgeht, dass du 
sowieso immer einen ASCII Code schickst. Und 65 (dezimal) ist nun mal 
der ASCII Code von 'A'.

Was anderes ist es, wenn auf der Ausgabe tatsächlich 65 stehen soll. 
Dann brauchst du itoa. Denn itoa generiert aus den dezimalen 65 dann 
eben einen String (eine Abfolge von Zeichen), welche '6' und '5' lautet. 
Schickt man diese beiden Zeichen (die ihrerseits ja auch wieder einen 
ASCII Code haben) an das Terminal, dann zeigt das die beiden Zeichen '6' 
und '5' an, die du dann als 65 liest.


Ein normales Ausgabegerät interpretiert ALLES einfach als ASCII Code 
(nach ASCII Tabelle googeln). D.h. du schickst ihm einen Code und es 
zeigt das entsprechende Zeichen laut ASCII-Tabelle an.
(Ausgenommen davon sind jetzt Steuersachen, aber die lass ich jetzt mal 
aussen vor)

Anstelle von lcd_string ist an dieser Stelle die primitivere Funktion 
besser, denn du hast ja nur 1 Zeichen. Wozu da also erst mal einen 
String zusammenbauen, wenn du sowieso nur ein Zeichen hast.
Ich weiß jetzt nicht, welches die primtivere Funktion ist, die dein 
lcd_string zur Ausgabe benutzt. Die heißt meistens entweder lcd_char 
oder lcd_data. Probier das mal aus:
1
    lcd_data( 65 );         // malt ein 'A' auf die Anzeige
2
    lcd_data( 'A' );        // malt ebenfalls ein 'A' auf die Anzeige
3
    lcd_data( 0x41 );       // auch das malt ein 'A' auf die Anzeige
4
    lcd_data( 0b01000001 ); // und noch eine Version, die ein 'A' hinmalt

warum ist das so? Weil 65, 'A', 0x41, 0b01000001 nur unterschiedliche 
Schreibweise sind, wie man immer dasselbe ausdrücken kann. Mit all den 
unterschiedlichen Schreibweisen wird das Bitmuster 0100 0001 
ausgedrückt, und wenn dieses Bitmuster ans LCD gegegeben wird, dann malt 
es ein 'A' hin. (Warum dieses? Weil die ASCII Tabelle diese Zuordnung 
gemacht hat).

Ich weiß, das ist auf den ersten Blick unintuitiv. Aber auch 'A' oder 
'B' sind in C nichts anderes als Beschreibungen für Zahlen. Diese Zahlen 
sind einfach nur der ASCII Code, der für dieses 'Zeichen' vereinbart 
wurde. So etwas wie 'Zeichen' in dem Sinne, dass das irgendwas 
Besonderes wäre, gibt es in C in Wirklichkeit gar nicht.
Man kann auch mit 'Zeichen' rechnen.
1
    lcd_data( 'A' + 1 );
was passiert hier? 'A' ist nichts anderes als die Beschreibung des ASCII 
Codes für das Zeichen A. Welcher lautet: 65. 65 + 1 ergibt 66. UNd wenn 
man die 66 an das LCD gibt, dann sieht das LCD mit diesem Code (den 66) 
in seiner Tabelle nach und malt die Pixel so hin, dass du ein 'B' liest.

von Georg G. (Firma: gmbh-keine) (georgino)


Angehängte Dateien:

Lesenswert?

das mit dem Int und char geht mir schon ein!!

Aber:
1
 uart_init();
2
  uint8_t c;
3
 
4
   char i[10];
5
    
6
7
    c = uart_getc(); //URC Auslessen terminal ein : A
8
9
    itoa(c,i,10);
10
11
  lcd_data(c);  // ausgabe am LCD : A
12
        lcd_string(i); // ausgabe am LCD : 65

will mit der Variable i an einem 8x8Dot-Led-Matrix-display ein String 
ausgeben was ich in der Form von "Hallo" brauche.

 const char * text = "Hallo"; // 8x8 Dot-Matrix wird ein Hallo 
ausgegeben!
  (Lauftext)
jetzt hab ich vor:

const char * text = i; // wird aber 65 ausgegeben!

Brauche aber umbeding das A im string und weis nicht wie ich es 
reinbekomme?

Ich glaube ich henge in einer schleife!?

von Karl H. (kbuchegg)


Lesenswert?

georg georg schrieb:
> das mit dem Int und char geht mir schon ein!!

gut.
Dann hast du das wichtigste schon verstanden.
Ab sofort sollte dir damit klar sein, wann du itoa oder atoi brauchst.

>     c = uart_getc(); //URC Auslessen terminal ein : A

genauer: Du hast hier den Code, der für das Zeichen 'A' steht.
Im eigentlichen Sinn gibt es keine 'Zeichen'. Die Interpretation, dass 
die 65 ein 'A' darstellen sollen, findet erst bei der Verwendung von c 
statt.

>
>     itoa(c,i,10);
>
>   lcd_data(c);  // ausgabe am LCD : A
>         lcd_string(i); // ausgabe am LCD : 65 [/c]
>
> will mit der Variable i an einem 8x8Dot-Led-Matrix-display ein String
> ausgeben was ich in der Form von "Hallo" brauche.
>
>  const char * text = "Hallo"; // 8x8 Dot-Matrix wird ein Hallo
> ausgegeben!
>   (Lauftext)
> jetzt hab ich vor:
>
> const char * text = i; // wird aber 65 ausgegeben!

Logisch wird da 65 ausgegeben.
Genau das hat ja itoa gemacht.
Es hat aus der Zahl 65 (dem ASCII Code von 'A') einen String erzeugt, 
der aus den Buchstaben '6' und '5' (und dem für STrings obligatorischem 
\0 Zeichen) besteht.

> Brauche aber umbeding das A im string und weis nicht wie ich es
> reinbekomme?
1
  i[0] = c;
2
  i[1] = '\0';   // weil in C ja jeder String mit einem \0 aufhören muss.
Ist das zu einfach?

Wenn natürlich in i schon ein String besteht, dann kannst du das c auch 
'hinten drannhängen', indem du ganz normale Array-Operationen benutzt. 
Sagt ja keiner, dass nur weil in einem char Array ein String drinnen ist 
(der mit einem \0 aufhört) man nicht mittels Array Indizes auf jeden 
einzelnen char zugreifen darf.

von Uwe (Gast)


Lesenswert?

> 8x8Dot-Led-Matrix-display ein String ausgeben
Finde ich schon merkwürdig ! Sag jetzt bitte nicht das du die LEDs über 
Widerstände direkt am Controller hast, sondern das das Ding über SPI 
oder so dran ist und nen Controller drauf hat der den Text dann 
vorbeiscrollen läßt.

von Georg G. (Firma: gmbh-keine) (georgino)


Lesenswert?

benütze protouis 7 isis!

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.