- 3D-Druck Einstieg und Tipps         
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 15

Thema: LC-Display am RN-Control mit C ansteuern

  1. #1
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    05.10.2005
    Ort
    Zürich
    Beiträge
    117

    LC-Display am RN-Control mit C ansteuern

    Anzeige

    LiFePo4 Akku selber bauen - Video
    Hallo Zusammen

    Ich krieg es einfach nicht hin, mein LCD anzusteuern. Überall wird geschrieben, dass sei eigentlich nicht so ein Problem, aber bei mir klappts nicht

    Also das Ganze sieht so aus: Ich habe ein 4x20Zeichen Display. Also 4 Zeilen mit je 20 Zeichen.
    Das Datenblatt könnt ihr hier herunterladen.
    Ich möchte es im 8-Bit Modus ansteuern. Dann brauche ich das Byte nicht zu zerlegen und für den Moment habe ich genug Ports.
    Ich habe das Display folgendermassen mit dem RN-Control verkabelt:
    RS auf PORTB, Pin 0
    R/W habe ich, da ich nur schreiben möchte auf VSS gelegt (richtig so, oder?)
    E auf PORTB, Pin 2
    D0-D7 auf PORTC
    Dazu erstmal eine Frage. Funktioniert das rein elektronisch? Oder funkt mir da noch irgendwas vom RN-Control rein? Den Motortreiber habe ich entfernt, und alle Jumper rausgezogen.

    Mein Code sieht so aus:

    b_setH und b_setL ist eine Präprozessordirektiven um ein Bit in einem Byte Hight bzw. Low zu setzten.

    Konfiguriert wird das Ding im Haederfile:
    m32_lcd.h
    Code:
    #ifndef M32_LCD_H_
    #define M32_LCD_H_
    
    // general ---------------------------------------------------------------------
    #ifndef F_CPU
      #define F_CPU 16000000
    #endif
    
    // LCD -------------------------------------------------------------------------
    #define CONT_DDR    DDRB
    #define CONT_PORT   PORTB
    #define CONT_E      2   // Enable (fallende Flanke)
    #define CONT_RS     0   // L:Befehl / H:Daten
    #define CONT_RW     1   // H:Read / L:Write
    #define DATA_DDR    DDRC
    #define DATA_PORT   PORTC
    
    // EOF -------------------------------------------------------------------------
    #endif /*M32_LCD_H_*/
    Und hier die Source:
    m32_lcd.c
    Code:
    #include <avr/io.h>
    #include "m32_lcd.h"
    #include "bit.h"
    
    // delay -----------------------------------------------------------------------
    void _delay_loop_1(uint8_t __count)
    {
      __asm__ volatile (
        "1: dec %0" "\n\t"
        "brne 1b"
        : "=r" (__count)
        : "0" (__count)
      );
    }
    
    void _delay_loop_2(uint16_t __count)
    {
      __asm__ volatile (
        "1: sbiw %0,1" "\n\t"
        "brne 1b"
        : "=w" (__count)
        : "0" (__count)
      );
    }
    
    void _delay_us(double __us)//max: 768us / F_CPU in Mhz
    {
      uint8_t __ticks;
      double __tmp = ((F_CPU) / 3e6) * __us;
      if (__tmp < 1.0)
        __ticks = 1;
      else if (__tmp > 255)
        __ticks = 0;  // i.e. 256
      else
        __ticks = (uint8_t)__tmp;
      _delay_loop_1(__ticks);
    }
    
    void _delay_ms(double __ms) //max: 260ms / F_CPU in Mhz
    {
      uint16_t __ticks;
      double __tmp = ((F_CPU) / 4e3) * __ms;
      if (__tmp < 1.0)
        __ticks = 1;
      else if (__tmp > 65535)
        __ticks = 0;  // i.e. 65536 
      else
        __ticks = (uint16_t)__tmp;
      _delay_loop_2(__ticks);
    }
    
    // testing ---------------------------------------------------------------------
    void init(void)
    {
      b_setH(CONT_DDR,CONT_E);
      b_setH(CONT_DDR,CONT_RS);
    //  b_setH(CONT_DDR,CONT_RW);    
    
      b_setL(CONT_PORT,CONT_E);     // E nicht setzen
      b_setL(CONT_PORT,CONT_RS);    // RS nicht setzen
    //  b_setL(CONT_PORT,CONT_RW);  // RW nicht setzen  
      DATA_DDR = 0xff;  // Ausgänge
      DATA_PORT= 0x00;
    }
    
    // lcd -------------------------------------------------------------------------
    void lcd_send(uint8_t data, uint8_t rs) //rs: L:Befehl / H:Daten
    {
      DATA_PORT = data;
      if(rs)
        b_setH(CONT_PORT,CONT_RS);
      else
        b_setL(CONT_PORT,CONT_RS);
      _delay_us(45);  // kurze Verzögerung, wahrscheinlich überflüssig
      b_setH(CONT_PORT,CONT_E);
      _delay_us(45);
      b_setL(CONT_PORT,CONT_E);
    
      _delay_ms(10); // um Befehl auszuführen, wahrscheinlch viel zu lang
    }
    
    void lcd_init(void){
      lcd_send(0x34,0); // 8-Bit Datenlänge
      lcd_send(0x09,0); // 4 Zeilen Modus
      lcd_send(0x0F,0); // Display on, Cursor on, Blink on
      lcd_send(0x01,0); // Display löschen, Cursor 1. Spalte, 1. Zeile;
    }
    
    void lcd_writeC(uint8_t c, uint8_t z, uint8_t s) //c: char, z: Zeile., s: Spalte
    {
      lcd_send(c,1);
    }
    
    // testing ---------------------------------------------------------------------
    int main(void)
    {
      init();
      lcd_init();
    
      lcd_send('a',1);
    
      return 0; 
    }
    Für die, die es noch intressiert, die bit.h
    Code:
    #ifndef BIT_H_
    #define BIT_H_
    
    // bit.h -----------------------------------------------------------------------
    // n ist immer die Bit-Position von Rechts gezählt im Intervall [0..7]
    #define b_maske(n)    (1 << n)    // generiert Make mit 1 bei n
    #define b_ifset(b,n)  (b & (1 << n) // liefert true wenn n true, sonst false
    #define b_setH(b,n)   b |= (1 << n) // setzt n auf 1
    #define b_setL(b,n)   b &= ~(1 << n)  // setzt n auf 0
    #define b_inv(b,n)    b ^= (1 << n) // invertiert n (1->0, 0->1)
    
    // setzt r auf a jedoch mit dem bit n von b als bit n von r
    #define b_qset(a,b,n) (a = (b & (1 << n)) | (a & ~(1 << n)))      //n = k
    // setzt r auf a jedoch mit dem bit k von b als das bit n von r
    #define b_qsetL(a,b,n,k)  ((b << (n-k)) & (1 << n)) | (a & ~(1 << n)) // n > k
    #define b_qsetR(a,b,n,k)  ((b >> (k-n)) & (1 << n)) | (a & ~(1 << n)) // k > n
    
    // rotiert a um ein bit
    #define b_rotL(a)     b_qsetR((a << 1),a,0,7)
    #define b_rotR(a)     b_qsetL((a >> 1),a,7,0)
    
    // EOF -------------------------------------------------------------------------
    #endif /*BIT_H_*/
    Die delay-Funktionen habe ich aus der AVR-Lib-C kopiert.
    Die Initialisierung habe ich aus dem Datenblatt des Displays abgeschrieben, ich hoffe die stimmt.

    Leider sehe ich auf dem Display überhautp nichts. An der Kontrastspannung liget es nicht, das habe ich überprüft.
    Hat jemand eine Idee, wieso, dass das nicht funktioniert?

    Vielen Dank für eure Hilfe!

    Grüsse cumi[/b]

  2. #2
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802
    Schon mal versucht, nach dem Reset nen delay einzubauen, um dem LCD Zeit für den Startup zu geben? 100ms oder so.

    Zum Code:
    -- die double-Arithmetik ist überflüssig und dafür _viel_ zu aufwändig und teuer
    -- Verwendung von b_ifset wird dir einen Compile-Fehler bringen
    -- warum kopierst du Funktionen aus der lib??? Die bekommst du mit #include <avr/delay.h> Die stehen auch nicht in einer Lib, sonder sind als static inline implementiert.
    Disclaimer: none. Sue me.

  3. #3
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    05.10.2005
    Ort
    Zürich
    Beiträge
    117
    Vielen Dank für deine Antwort, Sprinter!

    Wann soll ich genau Zeit geben? Bevor ich irgendetwas tue? Da hat das Display eine ewigkeit Zeit, denn es hat schon lange vor ich irgendetwas schreibe Strom.
    Ich jetzt einmal nach der Initialisierung ein delay reingehauen, bringt aber leider nichits.

    Zum delay. Ich habe einfach nach einem schlauen delay gesucht. Natürlich kann ich die Funktionen direkt aus der Library nehmen, nur sehe ich dann nicht, wa ich genau compiliere. Wie implementiert man ein simpleres, delay, für diesen Zweck?

    b_ifset habe ich korrigiert. Du meinst schon die Klammer, oder?

  4. #4
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802
    Achso, ich dachte, µC und LCD werden gleichzeitig eingeschaltet... Dann sollte man den µC erst etwas warten lassen vor dem lcd_init().

    ich hab mal in meine Sende-Routine geschaut. Ein Byte bzw. Nibble seinden:

    E=0
    DDR_DATA=OUT
    RW=0
    RS=rs
    PORT_DATA=data
    E=1
    WAIT
    E=0
    DDR_DATA=OUT

    Das DDR umschalten brauchst du wohl nicht (bei mir gehen noch andere Sachen auf dem Bus ab). Das WAIT ist ein _delay_loop_1(100).
    Die Ansteuerung ist für ein VFD, sollte aber für ein LCD genauso gehen.

    Fast in jeder Anwendung wird man eine Zeitbasis brauchen, die Ticks in einem bestimmten Zeitraster macht. Damit ist ein wait() dann recht einfach zu realisieren. Oder man nimmt einen freien Timer und zieht den auf und wartet, bis er abgelaufen ist. Das leidige Taktezählen fänd ich viel zu nervig und ungenau ist's nebenbei auch, insbesonders bei hoher IRQ-Last, denn die IRQ-Zyklen werden ja nicht mitgezählt in den Zählschleifen.


    Ja da fehlte ne )
    Disclaimer: none. Sue me.

  5. #5
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    05.10.2005
    Ort
    Zürich
    Beiträge
    117
    danke für dein antwort!
    Ich werde morgen das mit dem wait noch anpassen.
    Aber wenn ich das sonst so anschaue, dann man ich doch ziemlich alles gleich, oder? Also wirklich einen Fehler finde ich nicht.

    Was mich noch intressieren würde ist, wie man Zeichen genau schreibt. Also so wie ich das bis jetzt verstanden habe, brauche ich einfach die DD RAM Adresse dorthin zu setzen (Mit dem DD RAM Adress Set Befehl), wo ich hinschreiben will und dann ein data-byte mit dem gewünschten Zeichen zu senden. Der Rest (also das anzeigen auf dem Display) muss ich nicht noch speziell auslösen, oder?

    cumi

  6. #6
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802
    Das müsste eigentlich in deinem Datenblatt stehen.
    Ich kenn es von den HD44-kompatiblen, das man nur schreiben muss. Je nach Einstellungen rutscht dann auch Cursor etc mit.
    Disclaimer: none. Sue me.

  7. #7
    Neuer Benutzer Öfters hier
    Registriert seit
    08.03.2006
    Beiträge
    22
    Was hast du mit dem Restet Pin gemacht?

  8. #8
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    05.10.2005
    Ort
    Zürich
    Beiträge
    117
    @Sprinter: Hmm, das Datenblatt, welches ich habe ist ziemlich mager. Aber ich finde sicher eins vom HD44780, zu dem soll der von meinem LCD kompatibel sein.

    @tschensen: Der Resetping liegt doch auf keinem benützen Pin. Der habe ich natürlich nicht gezogen. Das der Controller läuft weiss ich. Ich lass eine LED blinken...

  9. #9
    Neuer Benutzer Öfters hier
    Registriert seit
    08.03.2006
    Beiträge
    22
    Ist das Datenblatt ausführlicher?
    http://www.lcd-module.de/eng/pdf/zubehoer/ks0073.pdf

  10. #10
    Neuer Benutzer Öfters hier
    Registriert seit
    08.03.2006
    Beiträge
    22
    Ich hock auch garade vor nem ähnlichen Display (DIP204-6) und bekomme es auch nicht zum laufen. Bekommst du schwarze Kästen auf dein Bildschirm, wenn du das Display einschaltest?

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

LiFePO4 Speicher Test