Forum: Compiler & IDEs Wie mache ich eine Textausgabe 8Bit auf Display?


von Jensgzm (Gast)


Lesenswert?

Hallo,

ich benutze einen Atmega16 und ein 4x20 Display, dass ich im 8-Bit Modus 
anspreche. Meine Kenntnisse im Programmieren sind noch nicht sehr weit 
fortgeschritten. Ich programmiere übrigens mit dem AVR Studio.
Ich würde mich sehr freuen, wenn mir jemand ein kleines Testprogramm 
hätte, in dem z.B. das Wort "Hallo Welt" oder ähnliches ausgegeben wird.
Mich interessiert lediglich der Block, in dem der Text ans Display 
gesendet wird. Die Init vom Display habe ich schon.
Ich verstehe nicht ganz, woher das Studio, bzw. der Compiler wissen 
soll, welche Signale er über die 8 Datenleitungen übertragen muß, damit 
der gewollte Text erscheint?
Ich hoffe auf eure Hilfe.

Gruß Jens

von AVR Freund (Gast)


Lesenswert?

Programmieren in was ? C ? Assembler ?

http://www.mikrocontroller.net/articles/AVR-Tutorial
Vielleicht hilft dir das etwas weiter?

von Jensgzm (Gast)


Lesenswert?

Hi AVR Freund,

sorry, ich dachte es wäre klar dass ich in C programmieren will, weil 
ich meinen Thread im GCC Forum eingestellt habe.
Also, ich möchte gern in C programmieren.
Danke für deinen Link, das Tutorial kenne ich schon, beim Assembler hat 
es mir geholfen mein Display zu initialsieren, was ich nun in meinem 
C-Programm auch übertragen habe, aber leider ist in dem Tutorial keine 
Textausgabe dabei.
Habe das Forum auch schon nach möglichen Threads durchsucht. Bin auch 
weiterhin auf der Suche.

Gruß Jens

von AVR Freund (Gast)


Lesenswert?

Schau mal da nach.
Beitrag "lib für Pollin LCD (WINTEK2704)"
vielleicht hilfts dir weiter?

von Joe (Gast)


Lesenswert?

Meinst du so was:
1
void LCD_puts (const char *lcd_string)  {
2
  while (*lcd_string)  {
3
    Zeichenausgabe (*lcd_string++);  // String auslesen -> LCD
4
  }
5
}

Wobei ich unterstelle das du eine "Zeichenausgabe" Funktion hast.

Für eine Ausgabe schreibst du dann LCD_Puts ("moin moin");

Alles klar ?

von Jensgzm (Gast)


Lesenswert?

Hi Joe,

das sieht ja mal nicht schlecht aus.
Also, wenn  du mit Zeichenausgabe meinst, dass ich die Daten an den 
richtigen Port schicke, dann ja, allerdings halt momentan für einzelne 
Buchstaben und nicht für nen ganzen Text. Den Buchstabe schicke ich als 
hex-Wert ans Display. Deswegen tue ich mich schwer, mir vorzutellen, wie 
das bei einem langen Text geht.
Kannst du mir kurz erklären was deine Funktion da macht?
Ich verstehe es so, du übergibst der while-Schleife den lcd-string.
Und in der Schleife wird in der Funktion "Zeichenausgabe" der string 
hochgezählt. Aber was zählt er denn hoch? Die Buchstaben?
Wie du siehst, fehlt mir noch bissle Verständnis der Materie.
Aber wer nicht fragt wird nicht aufgeschlaut.

Gruß Jens

von Ulrich (Gast)


Lesenswert?

Das Problem ist warscheinlich das du noch nie was Pointern gehört hast?

Ein Pointer ist ein Zeiger auf eine Speicheradresse. Mit dem *-Operator 
kann man nun die Adresse dereferenzieren und erhält das Zeichen an der 
Stelle im Speicher. Mit dem ++-Operator wird nichts am Zeichen geändert 
dondern der Pointer zeigt nun auf das nächste Zeichen im Speicher.
Jedes Char-Array (so nent man diese "Strings") hat am Ende als Letztes 
Zeichen eine NULL. Soblad die dereferenzierung im Schleifenkopf zu 
dieser NULL führt wird die Schleife abgebrochen, da der String zu ende 
ist

von Ulrich (Gast)


Lesenswert?

http://www.mikrocontroller.net/articles/AVR-Tutorial:_LCD#Ausgabe_eines_konstanten_Textes

Dort ist es eigenltich auch sehr gut erklärt. Warscheinlich macht der 
c-Cpmpiler aus der lcd_puts() auch so einen ählnichen assemblercode

von Joe (Gast)


Lesenswert?

> Also, wenn  du mit Zeichenausgabe meinst, dass ich die Daten an den
> richtigen Port schicke, dann ja, allerdings halt momentan für einzelne
> Buchstaben

Ja, das meine ich. Eine Erklärung hast du ja bereits von Ulrich 
bekommen. Probiers einfach mal aus, ist doch in 2 Minuten ausgestanden.

von Jensgzm (Gast)


Angehängte Dateien:

Lesenswert?

Danke an Ulrich für die gute Erklärung, hattest Recht, von Pointern 
wußte ich nichts.
Ich habe mal mein Programm angehängt. Ist bestimmt verbesserungswürdig 
aber darum gehts ja jetzt net.
Ich steh grad auf dem Schlauch, habe den Tip von Joe integriert, nun 
hänge ich grad an der Zeichenausgabe.
Vorher habe ich immer sowas geschrieben:

PORTC=0x57   // Entspricht dem Buchstaben "w"

Jetzt kann ich den Buchstaben ja nicht definieren, sondern will ja z. B. 
"moin moin" übergeben. Deswegen die Fragezeichen unter void 
Zeichenausgabe.
Was muß denn da alles rein?

von Joe (Gast)


Lesenswert?

Hab mir deinen Code jetzt nicht angesehen aber was du nun brauchst ist 
eine Funktion welche die Zeichen aufnimmt, das RS BIT setzt und nach 
anlegen der Daten das ENABLE signalt schaltet.

Das sieht dann z.B. so aus:
1
void display_data_out (uint8_t dsp_char_out_)  {
2
  SETBIT (PORTB, DATA);          // Daten an Display => RS BIT=1
3
  PORTC = dsp_char_out_;
4
  SETBIT (PORTB, OENABLE);       // ENABLE = HIGH
5
  CLRBIT (PORTB, OENABLE);       // ENABLE = LOW, Datenübernahme des Displays
6
}

Bei den PORT PIN's mußt du natürlich deine verwenden.

von Michael G. (glunzl)


Lesenswert?

Du könntest auf die fertige Lib von Fleury nutzen, zumindest mal 
reinschauen:

http://homepage.hispeed.ch/peterfleury/avr-software.html#libs

Gruß
Michael

von Joe (Gast)


Lesenswert?

> Du könntest auf die fertige Lib von Fleury nutzen, zumindest mal reinschauen:

Machs nicht, sorry Michael, aber er will lernen und als Ergebnis hat er 
dann seine eigene Routine.

Die Fleury LIB ist für einen Anfänger ne Zumutung. Wenn diese auch den 
Eindruck einer eierlegenden Wollmilchsau macht, ich find se Grotte.

von Michael G. (glunzl)


Lesenswert?

Zum Reinschauen und Ausprobieren, gerade als Anfänger, fand ich die 
einzelnen Funktionen doch hilfreich. Aber das sollte jeder für sich 
entscheiden.

Gruß
Michael

von Jensgzm (Gast)


Lesenswert?

Mahlzeit,

danke für den Tip mit der Fleury Lib, die hab ich mir schon angeschaut 
und wie Joe richtig vermutet hat, bin ich daraus nicht schlau geworden, 
eher im Gegenteil.
Okay, das mit Enable und RS weiß ich.
Du übergibst dann an den Port den Inhalt von dsp_char_out.

Jetzt muß ich doch den LCD_puts-Befehl irgendwie mit dem dsp_char_out 
verwurschteln, damit mein Text in der Variable dsp_char_out steht 
richtig?


von Joe (Gast)


Lesenswert?

Ja, das ist schon geschehen:

Zeichenausgabe (*lcd_string++);  // String auslesen -> LCD

dsp_char_out (*lcd_string++);  // String auslesen -> LCD

Alles klar ? und wenn du nur ein einzelnes Zeichen ausgeben willst dann 
schreibst du:

dsp_char_out ('b'); oder dsp_char_out (0x57);

von Joe (Gast)


Lesenswert?

Sorry, hab ich was übersehen ?

LCD_puts ist ja deine Funktion und an die übergibst du:

LCD_puts ("moin");

Vielleicht hast du es noch nicht erkannt ? Du übergibst einfach einen 
Wert oder Pointer an eine Funktion.

von Jensgzm (Gast)


Lesenswert?

Hey, klasse, das gefällt mir gut so.
Mein Studio meckert jetzt nur noch weil ich dsp_char_out_ und LCD_puts 
nicht deklariert habe.
Was für ein Typ sind die denn? Char? Int?
Das Prinzip habe ich schon mal verstanden.
Großes Lob an Joe !!

von Joe (Gast)


Lesenswert?

Deklarier sie so wie sie heißen:

void display_data_out (uint8_t dsp_char_out_);

wobei du nur die #include <stdint.h> ISO C99 Integer types noch 
hinzufügst.

Du kannst aber auch unsigned char verwenden.

von Jensgzm (Gast)


Lesenswert?

Joe du bist wirklich spitze.
Er hats geschluckt und er gibt genau den Text wieder, der in meinem Code 
steht.
Hatte noch ein paar Probleme im Code aber jetzt ist alles aufgeräumt.
Da wäre ich sicher nie drauf gekommen.
Jetzt werde ich mal bissle experimentieren.

Nochmals danke an Dich, Joe, speziell und die anderen.
So machts Spaß.

Grüße aus m Süden.


von Karl H. (kbuchegg)


Lesenswert?

Wenn du mit Pointern noch auf Kriegsfuss stehst,
kann man das ganze auch mit Array Syntax schreiben.
Ev. hilft dir das besser zu verstehen, was da abgeht.
1
void LCD_puts (const char *lcd_string)
2
{
3
  int i = 0;
4
5
  while( lcd_string[i] != '\0' ) {
6
    Zeichenausgabe( lcd_string[i] );
7
    i++;
8
  }
9
}

Mit etwas Glück optimiert der Compiler beide Versionen
(Pointer / Array Indizierung) auf gleichwertigen
Code.

von Joe (Gast)


Lesenswert?

An der Initialisierung kann man noch einiges verbessern, stell mal den 
aktuellen Code rein und ich schau noch einmal drüber.

von Joe (Gast)


Lesenswert?

Ja, der Karl Heinz hat schon recht, die neue WINAVR Version würde 
meckern.

void LCD_puts (const char *lcd_string)

const char steht dafür das die Zeichenkette im Programmspeicher abgelegt 
wird.

von Jensgzm (Gast)


Angehängte Dateien:

Lesenswert?

Ja, der Vorschöag von Heinz macht es etwas verstädnlicher.
Nebenbei könnte einer kurz erklären, woher das Programm weiß, wie es die 
Buchstaben in hex-Werte umzuwandeln hat?
Weil, ich seh dass es funktioniert, aber verstanden habe ich es soweit 
noch nicht.
Anbei mal der aktuelle Code.

Gruß jens

von Karl H. (kbuchegg)


Lesenswert?

Jensgzm wrote:
> Ja, der Vorschöag von Heinz macht es etwas verstädnlicher.
> Nebenbei könnte einer kurz erklären, woher das Programm weiß, wie es die
> Buchstaben in hex-Werte umzuwandeln hat?

Das macht bereits der Compiler.
Ich verrat dir ein Geheimnis: Im Rechner gibt es keine
Buchstaben. Im Rechner gibt es nur Zahlen. Je nachdem
wie diese Zahlen verwendet werden, stellen die Zahlen
was anderes dar.

Deine Zeichenausgabe Funktion gibt keine Buchstaben aus.
Deine Zeichenausgabefunktion schickt zb. die Zahl 0x41 an
das Display. Im Display ist eine Tabelle eingebaut, in der
steht, welche Pixel beim Empfang der Zahl 0x41 aufleuchten
sollen. Aus der Tabelle folgt zb. dass das Muster so aussehen
soll

      . . * . .
      . * . * .
      . * . * .
      . * . * .
      .   * .
      . * . * .
      . . . . .

und dein Gehirn macht dann ein 'A' daraus. Nun könnte man
viele beliebige Zuordnungen machen. Bei 0x41 könnte man auch
andere 'Buchstaben' ausgeben. Daher hat man sich auf einige
Schemata geeinigt. Das am weitesten verbreitet ist sicherlich
das ASCII Schema.

http://de.wikipedia.org/wiki/ASCII

Wenn du also in deinem Programm den Text "Testtext" verwendest.
dann sind da keine Buchstaben gespeichert (Erinnerung: im
Rechner ist alles eine Zahl), sondern die Zahlenfolge:

0x54 0x65 0x73 0x74 0x74 0x65 0x78 0x74 0x00

Diese Zahlenfolge kann jetzt alles mögliche bedeuten.
Schickt man aber diese Zahlenfolge an ein Anzeigegerät
welches ASCII versteht, dann pinselt es "Testtext" hin.
(Das letzte 0x00 ist ein Zugeständnis an C. Daran wird in
C erkannt, dass ein Text zu Ende ist. Daher wird auch in
der weiter oben gezeigten Schleife abgeprüft, ob 0x00
schon erreicht wurde).

von Karl H. (kbuchegg)


Lesenswert?

Jensgzm wrote:

> Anbei mal der aktuelle Code.

Ein wichtiger Punkt in der Programmierung, der leider von
Neueinsteigern immer unterschätzt wird, ist die Codeformatierung.

Gewöhn dir gleich von Anfang an an, eine ordentliches Einrückschema
sowie ein konssistentest { } Schema zu machen.
Auch wenn es oft belächelt wird, ist es doch wichtig das zu tun.

Weiters: In Standard-C gibt es keine funktionslokalen Funktionen.
Auch wenn gcc dies als Erweiterung erlaubt, würde ich dir doch
empfehlen, dich hier an Standard-C zu halten.
1
#include <avr/io.h> 
2
#include <stdint.h>         
3
4
void E_toggle (void) 
5
{
6
  for (i=0; i<1000; i++)
7
    ;
8
  PORTA |= (1<<5);           // Enable High
9
10
  for (i=0; i<500; i++)
11
    ;
12
  PORTA &= ~(1<<5);          // Enable Low
13
}
14
15
void dsp_char_out_ (uint8_t dsp_char_out_)  
16
{
17
  PORTA |= (1<<6);           // Daten an Display => RS BIT=1
18
  PORTC = dsp_char_out_;
19
  E_toggle();
20
}
21
22
void LCD_puts (const char *lcd_string)  
23
{
24
  while (*lcd_string)  
25
  {
26
    dsp_char_out_ (*lcd_string++);  // String auslesen -> LCD
27
  }
28
}
29
30
void LCD_init()
31
{
32
  DDRA  = 0xff;
33
  DDRC  = 0xFF;
34
  PORTA = 0x10;              // Beleuchtung ein
35
  PORTC = 0x00;
36
37
  PORTC = 0x38;              // 8 Bit, 4 Zeilen
38
  E_toggle();
39
  PORTC = 0x01;              // Display löschen
40
  E_toggle();
41
  PORTC = 0x0E;              // Display an, Cursor an, Blinken aus
42
  E_toggle();
43
  PORTC = 0x06;              // Entry Mode Set, Incrementieren, no Shift
44
  E_toggle();
45
  PORTC = 0x02;              // Cursor home
46
}
47
48
int main (void) 
49
{            
50
  unsigned long int i;
51
52
  for (i=0; i<10000; i++)
53
    ;   
54
55
  LCD_init();
56
  
57
  LCD_puts( "Druck und Temperatur" );
58
   
59
  while( 1 ) {                
60
    ;  
61
  }                         
62
 
63
   /* wird nie erreicht */
64
   return 0;                 
65
}

Sieht doch gleich viel besser aus. Mit den Warteschleifen
in E_toggle must du dir noch was überlegen. Spätestens
wenn du den Compiler optimieren lässt, fliegen die sowieso
raus. Zumindest die 2.te Warteschleife ist überflüssig. Das
Display ist schnell genug, sodass du den Pin nur setzten und
gleich darauf wieder löschen kannst.
1
void E_toggle (void) 
2
{
3
  for (i=0; i<1000; i++)
4
    ;
5
  PORTA |= (1<<5);           // Enable High
6
  PORTA &= ~(1<<5);          // Enable Low
7
}

Die erste Warteschleife ist wie gesagt problematisch. Zum
einen ist deren Ausführungszeit von der Taktfrequenz des µC
abhängig. D.h. die 1000 sind manchmal viel zu viel, und bei
einem schneller getaktetem µC sind sie viel zu wenig.
Zum anderen wird sie dir der Optimizer sowieso rauswerfen,
wenn er mal optimieren darf.

Für solche Warteschleifen gibt es in "delay.h" eigene Funktionen,
denen man die gewünschte Zeit übergibt und die sich ausrechnen,
wieviele Schleifenwiederholungen dafür notwendig sind.
Schau aber unbedingt in "delay.h" rein, denn diese Funktionen
haben eine beschränkung für die maximal mögliche Zeit.

von Joe (Gast)


Lesenswert?

> Daher wird auch in der weiter oben gezeigten Schleife abgeprüft, ob 0x00
> schon erreicht wurde).

Und das macht eben auch ne while Schleife, in C ist alles Null 
terminiert.

von Jensgzm (Gast)


Lesenswert?

Danke für die Änderung des Codes, muß zugeben es sieht übersichtlicher 
aus.
Ich denke halt immer, dass ich es auch noch aufräumen kann wenn ich mal 
fertig bin, aber eigentlich ist das Programm ja nie fertig.
Werd versuchen mich dran zu halten.

Mit "keine funktionslokalen Funktionen" meinst du, dass du die Init
ausgelagert hast oder?

von Joe (Gast)


Lesenswert?

So, wir optimieren noch ein bischen. Du hast eine Funktion die Zeichen 
ausgibt und eine die Zeichenketten beherrscht. Machen wir doch noch eine 
für Steuerzeichen (für die Initialisierung und clear display, cursor 
home etc.).
1
void lcd_command (uint8_t dsp_control_out)  {    
2
  RS = LOW;                       // Steuersignale an Display (RS BIT=0)
3
  lcd_char (dsp_control_out);     // Steuersignal ausgeben
4
  _delay_ms (4.1);                // Warteschleife 4,1 mSec.
5
  RS = HIGH;                      // RS BIT=1 => Daten
6
}

Diese Funktion wird immer mit RS = 1 verlassen und somit ist innerhalb 
der Routine der Focus auf LCD Daten ausgeben. Du kannst also in 
lcd_char_out RS=1 weglassen.

Wenn du nun noch #define lcd_clear 0x01 verwendest dann schreibst du:

lcd_command (lcd_clear);

Der Code wird immer lesbarer und du kannst deine Initialisierung mittels 
dieser lcd_command Funktion durchführen.

Für die delays verwendest du den Tipp von Karl Heinz. Den delay Aufruf 
habe ich schonmal eingefügt.

von Karl H. (kbuchegg)


Lesenswert?

Jensgzm wrote:
>
> Mit "keine funktionslokalen Funktionen" meinst du, dass du die Init
> ausgelagert hast oder?

Dein ursprüngliches Pgm hat so ausgesehen
1
int main()
2
{
3
  void E_toggle (void)
4
  {
5
    ...
6
  }
7
 
8
  void dsp_char_out_ (uint8_t dsp_char_out_)
9
  {
10
    ...
11
  }
12
13
  void LCD_puts (const char *lcd_string)
14
  {
15
    ...
16
  }
17
 
18
  ...
19
}

d.h. die Funktionen E_toggle, dsp_char_out_ und LCD_puts waren
innerhalb von main() definiert (Siehst du, ohne konsequent
durchgezogene Einrückung hättest du das gar nicht gesehen).
Das ist aber in Standard-C nicht erlaubt.

von Joe (Gast)


Lesenswert?

muß natürlich heißen:

dsp_char_out_ (dsp_control_out);

von Jensgzm (Gast)


Lesenswert?

Wenn ich aber den Vorschlag von Karl Heinz in meinem Studio compiliere, 
dann meckert es, weil das "i" in der E_Toggle nicht definiert ist. 
Deswegen hatte ich es vorhin auch unten angehängt. Eben nach der 
Definition von i. Mach ich da einen Fehler?

von Karl H. (kbuchegg)


Lesenswert?

Jensgzm wrote:
> Wenn ich aber den Vorschlag von Karl Heinz in meinem Studio compiliere,
> dann meckert es, weil das "i" in der E_Toggle nicht definiert ist.
> Deswegen hatte ich es vorhin auch unten angehängt. Eben nach der
> Definition von i. Mach ich da einen Fehler?

Nein. Ich hab nicht aufgepasst.
E_Toggle muss natürlich so aussehen:
1
void E_toggle (void) 
2
{
3
  uint16_t i;
4
5
  for (i=0; i<1000; i++)
6
    ;
7
8
  PORTA |= (1<<5);           // Enable High
9
  PORTA &= ~(1<<5);          // Enable Low
10
}

d.h. die Funktion E_toggle kriegt ihre eigene Variable i

von Joe (Gast)


Lesenswert?

Ich will jetzt nicht zuviel Verwirrung hereinbringen aber ne seperate 
Togglefunktion braucht es nicht, man muß nur das Programm entsprechend 
aufbauen.

void dsp_char_out_ (uint8_t dsp_char_out_)

Hier gehört das Togglen mit hinein und die Wartezyklen packst du in die 
Steuerzeichenausgabe.

Denn togglen mußt du immer wenn du ein Zeichen an das LCD übergibst, ob 
Steuerzeichen oder Daten.

Ist das mit der Steuerzeichenausgabe klar ?

von Joe (Gast)


Lesenswert?

Deine Initialisierung sieht dann so aus:
1
void lcd_init (void)  {
2
  uint8_t n = 3;                    // Init. Sequenz
3
  do  {                             // 3x 38H (0x38), init cycle 3x
4
        lcd_command (0x38);         //
5
  }while (--n);
6
  lcd_command (function_set_1);     // 8 Bit Modus
7
  lcd_command (on_off_control_1);   // Display An / Cursor Aus / Blink Aus
8
  lcd_command (clear_display);      // Clear Display
9
  lcd_command (entrymode_1);        // Cursor nach rechts / kein Shift
10
}

Vorrausgesetzt du hast dir alles in #Defines gepackt. Das Timing ist 
schon in der Steuerzeichenausgabe gelöst.

von Jensgzm (Gast)


Angehängte Dateien:

Lesenswert?

Ja, das mit der Steuerzeichenausgabe ist klar.
Ich muß sagen Ihr legt ein gutes Tempo vor, aber bis jetzt komm ich noch 
mit.
So schnell bin ich bis jetzt noch nie voran gekommen. Mußte immer ewig 
suchen bis ich mal was hilfreiches (auf meinem Niveau) gefunden habe.
Hier mal wieder der aktuelle Code.
Das Delay mußte ich ausschalten, weil ich keine delay.h Datei habe. 
Konnte auch keine auf meiner Fetsplatte finden.

von Joe (Gast)


Lesenswert?

Ich häng dir später mal meinen Code komplett hierein, aber du hast ja 
auch jetzt schon eine Menge gelernt.
1
#ifndef F_CPU
2
#define F_CPU 1000000UL       /* Quarz Frequenz = 1 MHz                      */
3
#endif
4
5
#include <util/delay.h>       /* delay Lib.

Die delay.h gehört zum WINAVR versuchs mal so und trage deine CPU 
Frequenz ein.

von Jensgzm (Gast)


Lesenswert?

Ja Tatsache, im WINAVR Ordner steckte die blöde Datei.
Dachte die müßte unter Atmel sein.
Nunja, also das mit dem Delay klappt auch.
Alles wunderbar.

von Joe (Gast)


Lesenswert?

Na dann, ab in die letzte Runde, her mit dem aktuellen Code und wir 
optimieren noch ein bischen ;-))

von Jensgzm (Gast)


Angehängte Dateien:

Lesenswert?

Man man, du bist ja unersättlich.
Aber es hilft ja.
Ich hoffe du bist öfters im Forum, denn ich muß noch ein paar Sachen 
umsetzen, die ich aber heute noch nicht umsetzen kann und da könnte ich 
deine Hilfe gut gebrauchen. ;-)

von Joe (Gast)


Lesenswert?

1
void dsp_char_out (uint8_t dsp_char_out)  {
2
  uint16_t i;
3
4
  PORTC = dsp_char_out;
5
  PORTA |= (1<<5);           // Enable High
6
  PORTA &= ~(1<<5);          // Enable Low
7
  _delay_us (42);
8
}
9
10
int main (void)  {            
11
  _delay_ms (15);            // wait 15 mSec. after Power ON
12
13
  LCD_init();  
14
  LCD_puts( "Druck und Temperatur" );
15
   
16
  while( 1 );
17
}

Für die Zeichen reichen 42 uSec, und die Steuerzeichen haben ja ihre 4,1 
mSec. schon. Nach Power ON sinds dann 15 mSec.

Wenn du noch folgende #Defines hinzufügst:

#define cursor_line_1       0x80
#define cursor_line_2       0xC0

dann setzt dieser Befehl:

lcd_command (cursor_line_2);

Deine Ausgabe in die 2te Zeile.

von Joe (Gast)


Lesenswert?

Deine Zählvariable kann auch noch weg, und dann bitte noch einmal deinen 
Code als Anhang.

von Jensgzm (Gast)


Angehängte Dateien:

Lesenswert?

Ja, dass mit dem Cursor wollte ich auch noch ausprobieren.
So ähnlich hab ich es mir vorgestellt.
Mittlerweile ist der Code echt übersichtlich und geschrumpft ist er 
auch.
Habe den Cursorsprung in die 4.Zeile gemacht.

von Joe (Gast)


Angehängte Dateien:

Lesenswert?

So stelle ich mir einen Display Code vor, gut gemacht ;-))

Nun Vergleiche mal die Codegröße mit irgendeiner LIB und du verstehst 
warum ich zum selber schreiben rate.

Im Prinzip ist es fertig aber man kann noch nen bischen dran schrauben.
1
void dsp_char_out (uint8_t dsp_char_out)  {
2
  
3
  PORTC = dsp_char_out;
4
  PORTA |= (1<<5);           // Enable High
5
  PORTA &= ~(1<<5);          // Enable Low
6
  _delay_us (42);
7
}

Auch die Anschlüsse RS und ENABLE können noch in ein #define. Wenn man 
es richtig macht dann kann man auch:

ENABLE = HIGH;
ENABLE = LOW;

schreiben. Im Anhang findest du meinen Code für eine 4 BIT Ansteuerung. 
Du wirst feststellen das deiner nun fast genauso aussieht ;-))

Hier findest du noch eine schöne Erklärung zu den PORT's & BIT's, wie du 
siehst lerne auch ich aus dem Forum.

Beitrag "sbit macro für avr-gcc"



von Jensgzm (Gast)


Lesenswert?

Hi Joe,

ja, das Programm ähnelt schon ziemlich.
Werde weiterhin Optimierungen durchführen.
Wie gesagt, es gibt noch einiges zu tun.
Für heute ist aber mal Schluß.
Vielleicht treffen wir uns mal wieder in einem anderen Thread.
Nochmals danke für die Lehrstunde, ich bin heute weit gekommen.

Gruß Jens

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.