Forum: Mikrocontroller und Digitale Elektronik LCD + Wert (aus ADC) ausgeben


von Daniel S. (stoegi)


Angehängte Dateien:

Lesenswert?

Hallo,
habe jetzt endlich mein LCD zum laufen gebracht.
Die Ausgabe von Strings ist mal schon kein Problem mehr.

Habe jetzt den Wert "x" aus dem ADC, in dem die Binärzahl zum
eingelesenen Wert gespeichert ist. (Nicht im angehängten Programm
dabei)
Nun möchte ich "x" auf das LCD schreiben (bzw. den Inhalt von "x")

Lösungsvorschläge für Programmerweiterung

Danke

von Hannes L. (hannes)


Lesenswert?


von Daniel S. (stoegi)


Angehängte Dateien:

Lesenswert?

Naja, danke
aber das Hilft mir nicht weiter
keine Vorschläge wie ich mein Programm bzw. die Routine erweitern
kann.? schaut euch mal mein programm an bitte.

von Hannes L. (hannes)


Lesenswert?

Warum kein lesbarer Klartext?

Meist du, ich lade mir ein Archiv herunter, entpacke es und mülle mir
die Platte zu???

Was der Browser nicht direkt anzeigt, das schau ich mir nicht an. Denn
nicht ich habe Interesse daran, mir das anzuschaun, sondern du.
- Sorry, ist aber so.

...

von Daniel S. (stoegi)


Lesenswert?

/* LCD Include-Datei
 * PC4     = RS
 * PC5     = Enable
 * PC0-PC3 = D4-D7
 * R/W ist n.c.
*/
#include <avr/io.h>
#include <avr/delay.h>

#define delay(us)  _delay_loop_2 (((12000000/4000)*us)/1000)    // 
wartet
µs

// Enable-Leitung toggeln
void lcd_flash_e ()
{
  PORTD = PORTD | ( 1<<DDC5 ) ;    // Enable = HIGH
  delay(1);              // kurz warten, damit Flanke entsteht
  PORTD = PORTD & ~( 1<<DDC5 ) ;    // Enable = LOW
  delay(64);              // Warten, bis der durch Enable angelegte 
Befehl
hoffentlich verarbeitet wurde
}

// Kommando oder Zeichen an Display senden: rs=0 => Kommando, rs=1 =>
Zeichen
void lcd_write (uint8_t data, uint8_t rs)
{
  uint8_t dataBits ;

    if (rs)            // write data (RS=1, RW=0)
       dataBits=0x10;    // RS liegt an Pin 4 = B 0001 0000 = H 10
    else             // write instruction (RS=0, RW=0)
       dataBits=0;

    PORTD = dataBits |(data>>4);    // output high nibble first, zzgl.
Zustand für RS-Leitung
  lcd_flash_e ();
    PORTD = dataBits | (data&0x0F);  // output low nibble, zzgl.
RS-Leitung
  lcd_flash_e ();
  delay(2000);
}

// Display loeschen
void lcd_cls ()
{
  lcd_write(0x02,0);     // B 0000 0010 => Display loeschen
  delay(2000);      // dauert eine Weile, Wert ausprobiert
  lcd_write(0x01,0);     // B 0000 0001 => Cursor Home
  delay(2000);      // dauert eine Weile, Wert ausprobiert
}

// Zeichenausgabe
void lcd_writechar ( char zeichen)
{
  lcd_write (zeichen, 1);
}

// gibt eine Zeichenkette auf dem LCD aus
void lcd_writetext ( char *text)
{
  uint8_t i = 0;
  while (text[i]!=0)
  {
    lcd_writechar(text[i]);
    i++;
  }
}

// Zeilenwechsel
void lcd_gotoline (uint8_t zeile)
{
  if (zeile == 1) lcd_write(0x80,0);   // B 1000 0000 => DD-RAM Adress
Set 1. Zeile/1.Spalte
  if (zeile == 2) lcd_write(0xC0,0);   // B 1100 0000 => DD-RAM Adress
Set 2. Zeile/1.Spalte (B x100 0000 = H 40)
}

// Cursorpositionieren (Zeile, Spalte)
void lcd_gotopos (uint8_t zeile, uint8_t spalte)
{
  if (zeile == 1) lcd_write(0x80+spalte-1,0);   // DD-RAM Adress 1.
Zeile + Spalte
  if (zeile == 2) lcd_write(0xC0+spalte-1,0);   // DD-RAM Adress 2.
Zeile + Spalte
}

// Display initialisieren. Einmal als erstes aufrufen
void lcd_ini ()
{
  DDRD = 0x3F;    // setze Portrichtung (1 = Ausgang): 0011 1111
  PORTD=0x00;      // alle Leitungen LOW

  delay(10000);    // 10ms warten bis LCD wirklich bereit (max. Wert lt.
Datenblatt)

  lcd_write(0x38,0);     // B 0010 1000 => 8-Bit-Modus aktivieren, Ist
wichtig, falls LCD schon im 4-Bit Modus war und dann
              // nach einem Programm-Reset vergeblich versucht würde, 
den
4-Bit Modus erneut zu aktivieren
  lcd_write(0x2,0);    // B 0000 0010 => mit 8-Bit-Command in 
4-Bit-Modus
umschalten

  lcd_flash_e ();      // Enable

  delay(1000);      // sicherheitshalber warten

  // ab jetzt 4-Bit-Modus
  lcd_write(0x28,0);     // B 0010 1000 => Function Set: 4Bit (kein
8-Bit Bus), zweizeiliges Display, 5x7 Dots/Zeichen (kein 5x10)
  lcd_write(0x0C,0);     // B 0000 1100 => Display On/Off: Display ein,
Cursor aus, Blinken aus
  lcd_write(0x06,0);     // B 0000 0110 => Entry Mode Set: DD-RAM autom.
inkr., Cursor bewegen

  lcd_cls();        // Display löschen
}


PROGRAMM:

#include "lcd_routine.h"

void main()
{
  lcd_ini();

  lcd_gotopos (1, 6);
  lcd_writetext ("Test");


    lcd_gotopos (2, 5);
  lcd_writetext ("Klappt!");

  while(1);
}

------------------------------------------------------------------
SO.
DANKE

von Hannes L. (hannes)


Lesenswert?

Sorry, da muss ich dich leider enttäuschen. Von C habe ich keine Ahnung,
ich programmiere in ASM, das ist für mich übersichtlicher und
verständlicher. Ein Beispiel für formatierte Ausgabe von Zahlen sowie
Ausgabe von indizierten Menütexten findest du hier:
http://www.hanneslux.de/avr/zuenduhr/index.html
Allerdings wird da nicht der ADC-Wert ausgegeben.

Aber vielleicht findet sich ja jetzt, wo dein Quelltext lesbar ist,
Hilfe von Jemandem, der C versteht.

...

von Karl H. (kbuchegg)


Lesenswert?

Was Du brauchst, ist eine Funktion, die einen int
nimmt, daraus eine String-Repraesentierung deiner Zahl
baut und diesen String dann ueber die vorhandene String-
Ausgabe-Funktino ausgibt.

Schau Dir mal die C-Funktion sprintf() an.

Und Hannes hat recht: Das wird so ziemlich >15 mal pro
Woche gefragt. Wenn du ernsthaft programmieren willst,
dann wirst du lernen muessen, Informationen zu suchen
und anderer Leute Code zu analysieren. Vor allem wenn
Dir Hannes bereits eine Link-Liste mit relevanten Threads
vorgibt.

von Hannes L. (hannes)


Lesenswert?

Kann es sein, dass diese Funktion Integer TO Ascii wandeln soll und
daher den "sprechenden Namen" "ITOA" hat???

 8-)

Ich kann immer noch kein C, aber wenn man lange genug mit shit
beschmissen wird, fängt man eines Tages an zu stinken...

...

von Karl H. (kbuchegg)


Lesenswert?

Koennte sein :-)

Das Problem ist, dass _itoa() oder itoa() keine
Standardfunktion ist. D.h. sein Compiler kann sie
haben, muss aber nicht. Ein Blick in die Doku kann
das klaeren.

von Rahul (Gast)


Lesenswert?

Waschen hilft...
Man kann sich ITOA auch selber basteln, wenn man es schon nicht selber
findet.
Vielleicht sollten gewisse Leute lieber die Programmiersprache (oder
sogar die Tätigkeit) wechseln, wenn sie nicht gewillt sind, sich selber
um die Lösung trivialer Probleme zu kümmern.
Komischerweise liegt meine C-Bibel immer mit auf dem Schreibtisch...

von Hannes L. (hannes)


Lesenswert?

> Waschen hilft...

:-)

Ich meinte damit aber, dass im Laufe der Zeit etwas im Gedächtnis
hängen bleibt, weil ja diese Fragen und Antworten häufiger auftreten.

> Man kann sich ITOA auch selber basteln, wenn man es schon nicht
> selber findet.

Nunja, ich bastele meine Routinen grundsätzlich selber und wenn ich mir
mal einen "gefundenen" Algorithmus zu eigen mache, dann habe ich ihn
zumindest verstanden. Dadurch sind meine Programme zwar nicht optimal,
aber selbstgemacht und selbst verstanden.

> Komischerweise liegt meine C-Bibel immer mit auf dem Schreibtisch.

Das ist bei mir das Englisch-Wörterbuch, was das Lesen der Datenblätter
relativ mühsam macht. Und trotzdem erwische ich mich immer wieder dabei,
dass ich in AVR-Datenblättern nachschaue, um hier Fragen zu beantworten,
bei denen der Fragesteller es selbst nicht für nötig hielt, ins
Datenblatt zu schaun.

...

von Rahul (Gast)


Lesenswert?

www.dict.cc <== liegt auch quasi auf meinem Schreibtisch (ich meinte den
in der Firma; zuhause liegen die Sachen auf der Fensterbank, weil der
Schreibtisch schon voll ist...).

Prinzip von ITOA (jetzt mal so aus den Fingern gesogen):

nimm die Zahl, gucke nach, ob sie negativ ist -> -Zeichen
Nimm den Betrag der Zahl, teile sie durch die grösste 10er-Potenz (also
bei 16-Bit-Integer 10000)
Das Ergebnis + '0' ist das erste Zeichen in deinem String
Multipliziere das Ergebnis mit der 10er-Potenz und subtrahiere es von
der Zahl.
Mit der nächst kleineren 10er-Potenz macht man das gleiche,...
bis die 10er-Potenz = 1 ist. dann wird nur noch Zahl + '0' an den
String angehängt.

Das kann man bestimmt auch eleganter lösen, hab ich mir aber eben nur
mal so aus den Fingern gesogen. Ich übernehme auch keine Gewähr, dass
das so problemlos funktioniert..
(es gibt hier im Forum bestimmt eine schönere Lösung...)

@Datenblatt: Mit manchen Problemen hat man ja noch nichts zutun gehabt,
deswegen gucke ich dann auch gerne mal ins Datenblatt. So lernt man
wieder was...

von trollizei (Gast)


Lesenswert?

Hallo

Ich verfolge den Thread mit Interesse und etwas Abscheu ;-)

> nimm die Zahl, gucke nach, ob sie negativ ist

Wie man DAS bewerkstelligt war mir noch nie klar! WIE geht das bei den
AVRs, mit den negativen Zahlen und dem Rechnen damit? Dürfte wohl nicht
allzu kompliziert zu verstehen sein, aber leider habe ich noch nirgends
eine Quelle gefunden, die es kurz und schlüssig erklären könnte.
Datenblatt und Befehlscode helfen da auch nicht wirklich weiter.

Gruss

Michael

von Karl H. (kbuchegg)


Lesenswert?

Google nach 2-er Komplement

Grundsaetzlich und in Kuerze:
Dem Prozessor sind negative Zahlen sch...egal, genauso wie
ihm Character oder sonstiges egal sind. Tief im Inneren ist
alles eine ganze Zahl (auch Befehle!)
Wie kommen dann negative Zahlen, etc. ins Spiel?
Das ist alles eine Frage der Interpretation, d.h. wie ich
als Programmierer eine Zahl ansehe und verwende. Eine
Zahl die ich dem Prozessor zum Frass vorwerfe, wird vom
Prozessor als Befehl eine bestimmte Aktion auszufuehren
interpretiert. Schicke ich dieselbe Zahl an ein Terminal,
dann stellt dieses vielleicht dafuer eine kleine Minigraphik
(Pixel an/aus) dar, dass fuer mein Gehirn wie der Buchstabe
'A' aussieht. Andere Zahlen sind einfach nur dass: Zahlen.
Zahlen kommen in 2 Kategorien: mit und ohne Vorzeichen.
Wiederum: ob eine Zahl ein Vorzeichen hat oder nicht, kann man
der Zahl nicht ansehen, ist alles eine Frage der Interpretation.
Mit anderen Worten das bestimme ich, der Programmierer.

Und so funktionierts konkret bei Verwendung des 2-er Komplements:
Sagen wir mal, dass unsere Zahlen aus 8 Bit bestehen sollen.

   0000 0000

Hier sind sie.
Dann kann man ja mit diesen 8 Bit durch unterschiedliche 1
Bits die Zahlen von 0 bis 255 darstellen.
Ich kanns aber auch anders machen. Ich kann ganz einfach ein
Bit dafuer reservieren, dass es mir anzeigt, ob diese Zahl
nun negativ ist oder nicht. Meist nimmt man dazu das MSB
(most significant bit, oder ganz einfach das am weitesten links
stehende Bit).

    1000 0101

das koennte jetzt die Zahl (ohne Vorzeichen) 0x85, dez. 133
sein, oder aber es koennte die Zahl -5 sein (msb gesetzt, der
Rest ergibt 5, msb gesetzt bedeutet - )

Ist eine Moeglichkeit. Die benutzt man in der Praxis aber nicht
wirklich, da es eine bessere Moeglichkeit gibt, negative
Zahlen darzustellen: das 2-er Komplement

Dabei werden alle Bits umgedreht ( 0->1, 1->0) und dann noch
1 dazugezaehlt.

Wenn ich also das Bitmuster fuer -5 im 2-er Komplement bestimmen
will, dann geht das so:

   5 hat das Bitmuster    0000 0101
   alle Bits umdrehen     1111 1010
   und 1 addieren         1111 1011

Die Bitdarstellung von -5 lautet also: 1111 1011
Das MSB zeigt mir wiederum an, dass es sich um eine negative
Zahl handelt. Aber nur wenn ich das so interpretieren will.
Wenn ich das nicht will, dann ist 1111 1011 ganz einfach die
Dezimalzahl 251.

OK. Ein paar Beispiele
Grundlage 2-er Komplement:

  0001 0011

        Das MSB ist 0, also ist das eine positive Zahl
        Welche? 1 + 2 + 16 -> 19. Also +19

  1001 0011

        Das MSB ist 1, also ist das eine negative Zahl
        Welche?
        Dazu wenden wir wieder das 2-er Komplement an:
          alle Bits umdrehen    0110 1100
          und 1 addieren        0110 1101

          1 + 4 + 8 + 32 + 64  ->  109

          Das Bitmuster entspricht also der Zahl -109

Warum macht man so komische Verrenkungen mit dem 2-er Komplement.
Ganz einfach: Weil man dann bei Addition und Subtraktion nichts
spezielles beruecksichtigen muss. Man Addiert oder Subtrahiert
einfach dahin und hinten kommt alles richtig raus:
Bsp:  -3 + 5

  -3   ( 0000 0011 -> 1111 1100 -> 1111 1101 )
  +5   (                           0000 0101 )
 ---------------------------------------------
                                 1 0000 0010

Da wir nur ein 8 Bit Ergebnis kriegen koennen, faellt das
Bit ganz links (das 9. Bit) weg, und wir erhalten
0000 0010  oder +2 dezimal.

  20 - 78

   20 (                           0001 0100 )
  -78 ( 0100 1110 -> 1011 0001 -> 1011 0010 )
  -------------------------------------------
                                  1100 0110

  Da in diesem Ergebnis das MSB gesetzt ist, handelt es sich
  wieder um eine negative Zahl. Nur welche?
      1100 0110 -> 0011 1001 -> 0011 1010
  Und das ist das Bitmuster fuer 58. Also ist 1100 0110 das
  Bitmuster fuer -58

Wiederrum: Wenn ich das so interpretieren will!
Wenn ich das nicht so interpretieren will, dann steht das MSB
ganz einfach seiner Bitposition entsprechend fuer 128 und
1100 0110 ist ganz einfach die Zahl 198.


  -3 + 5

von peter dannegger (Gast)


Lesenswert?

>> nimm die Zahl, gucke nach, ob sie negativ ist

>Wie man DAS bewerkstelligt war mir noch nie klar!
1
if( Zahl < 0 ){
2
  // tue was
3
}

Was ist denn daran so schwer ?


Peter

von peter dannegger (Gast)


Lesenswert?


von Simon K. (simon) Benutzerseite


Lesenswert?

übrigens gibt es auch ein GCC Forum

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.