- 12V Akku mit 280 Ah bauen         
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 12

Thema: LCD-Ansteuerung funktioniert nicht

  1. #1
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    22.07.2004
    Beiträge
    270

    LCD-Ansteuerung funktioniert nicht

    Anzeige

    Praxistest und DIY Projekte
    Hallo,
    ich versuche gerade eine eigene LCD-Ansteuerung ohne Lib hinzukriegen, leider wird auf dem Display nicht angezeigt...

    Code:
    #include <inttypes.h>
    #include <avr/io.h>
    #include <util/delay.h>
    
    #define LCD_RS_PORT PORTB
    #define LCD_RS_PIN 3
    #define LCD_DATA0_PORT   PORTD     /**< port for 4bit data bit 0 */
    #define LCD_DATA1_PORT   PORTD     /**< port for 4bit data bit 1 */
    #define LCD_DATA2_PORT   PORTD     /**< port for 4bit data bit 2 */
    #define LCD_DATA3_PORT   PORTB     /**< port for 4bit data bit 3 */
    #define LCD_DATA0_PIN    5            /**< pin for 4bit data bit 0  */
    #define LCD_DATA1_PIN    6           /**< pin for 4bit data bit 1  */
    #define LCD_DATA2_PIN    7            /**< pin for 4bit data bit 2  */
    #define LCD_DATA3_PIN    0 
    #define LCD_RW_PORT      PORTB     /**< port for RW line         */
    #define LCD_RW_PIN       4            /**< pin  for RW line         */
    #define LCD_E_PORT       PORTB     /**< port for Enable line     */
    #define LCD_E_PIN        2            /**< pin  for Enable line     */
    #define LCD_E_PORT       PORTB     /**< port for Enable line     */
    #define LCD_E_PIN        1            /**< pin  for Enable line     */
    
    
    		
    void write_data(uint8_t wert)
    {
     if(wert & (1<<0))
      {
       LCD_DATA0_PORT &=  ~(1 << LCD_DATA0_PIN);
      }
     else
      {
       LCD_DATA0_PORT |=  (1 << LCD_DATA0_PIN);
      }
      
     if(wert & (1<<1))
      {
       LCD_DATA1_PORT &=  ~(1 << LCD_DATA1_PIN);
      }
     else
      {
       LCD_DATA1_PORT |=  (1 << LCD_DATA1_PIN);
      }  
      
     if(wert & (1<<2))
      {
       LCD_DATA2_PORT &=  ~(1 << LCD_DATA2_PIN);
      }
     else
      {
       LCD_DATA2_PORT |=  (1 << LCD_DATA2_PIN);
      }
     if(wert & (1<<3))
      {
       LCD_DATA3_PORT &=  ~(1 << LCD_DATA3_PIN);
      }
     else
      {
       LCD_DATA3_PORT |=  (1 << LCD_DATA3_PIN);
      }
     
    }
    void init_lcd(void)
    {
     _delay_ms(20);
     LCD_RS_PORT &= ~(1<<LCD_RS_PIN);  /* Steuerregister wird angesprochen */
     _delay_ms(8);
     write_data(0x3);
     _delay_ms(1);
     write_data(0x3);
     LCD_RW_PORT |= (1<<LCD_RW_PIN);                /*Lesezugriff, warten bis RW 0 */
     DDRB = 0xfe;           /*PB0 als Eingang, um Busyflag einzulesen*/
     while(LCD_DATA3_PORT & (1<<LCD_DATA3_PIN));  
     LCD_RW_PORT &= ~(1<<LCD_RW_PIN);
     DDRB = 0xff;
     write_data(0x2);    
     LCD_RW_PORT |= ~(1<<LCD_RW_PIN);
     DDRB = 0xfe;
     while(LCD_DATA3_PORT & (1<<LCD_DATA3_PIN));
     LCD_RW_PORT &= (1<<LCD_RW_PIN);
     DDRB = 0xff;
     write_data(0x2);     /*System-Set oberes Nibble */
     write_data(0x8);     /*System-Set unteres Nibble */
     
     write_data(0x0);     /*Display on/off, Display on, Unterstrich Cursor on, blinkender Cursor on*/
     write_data(0xF);
     
     write_data(0x0);   /* Cursor Home */
     write_data(0x2);
     
     LCD_RS_PORT |= (1<<LCD_RS_PIN);  /*Datenregister auswählen*/
     write_data(0x19);
     
     
    }
    
    void main(void)
    {
     DDRB = 0xFF;
     DDRD = 0xFF;
     init_lcd();
     for(;;);
    }
    Ich habe versucht nach der Anleitung im PDF zu gehen, aber irgendwie habe ich nie Enable verwendet..

    Gruß
    Martin
    Angehängte Dateien Angehängte Dateien

  2. #2
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    52
    Beiträge
    2.236
    Ich habe versucht nach der Anleitung im PDF zu gehen, aber irgendwie habe ich nie Enable verwendet
    O weh,

    Eben, Enable ist dabei der "Auslöser"
    Stell Dir mal vor Du liegst im Schützengraben, Deine Waffe ist geladen,gespannt und entsichert, Du Zielst auf denen Feind, und ....
    ...da fehlt noch was.
    Du mußt den DataPort, RW und RS entsprechend belegen, und wenn das stimmt, den Enable Pin kurz auf High und dann wieder auf Low ziehen.
    Bei der fallenden Flanke werden die Daten dann vom LCD übernommen.

    Hoffe geholfen zu haben.

    Gruß Sebastian
    Software is like s e x: its better when its free.
    Linus Torvald

  3. #3
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    22.07.2004
    Beiträge
    270
    Hallo,
    ich hab jetzt versucht das umzusetzten, aber es geht immer noch nicht:
    Code:
    void init_lcd(void)
    {
     
     _delay_ms(20);
     LCD_E_PORT |= (1<<LCD_E_PIN);
     LCD_RS_PORT &= ~(1<<LCD_RS_PIN);  /* Steuerregister wird angesprochen */
     write_data(0x3);                  /* 1.0x3 */
     LCD_E_PORT &= ~(1<<LCD_E_PIN);
     
     _delay_ms(8);
     LCD_E_PORT |= (1<<LCD_E_PIN);
     write_data(0x3);                    /* 2.0x3 */
     LCD_E_PORT &= ~(1<<LCD_E_PIN);
     
     _delay_ms(1);
     LCD_E_PORT |= (1<<LCD_E_PIN);
     write_data(0x3);                      /* 3.0x3 */
     LCD_E_PORT &= ~(1<<LCD_E_PIN);
     
     LCD_RW_PORT |= (1<<LCD_RW_PIN);                /*Lesezugriff, warten bis RW 0 */
     DDRB = 0xfe;           /*PB0 als Eingang, um Busyflag einzulesen*/
     LCD_E_PORT |= (1<<LCD_E_PIN);
     while(LCD_DATA3_PORT & (1<<LCD_DATA3_PIN));   /*Warten bis Busy-Flag = 0 */
     LCD_RW_PORT &= ~(1<<LCD_RW_PIN);         /*Schreibzugriff einstellen*/
     DDRB = 0xff;
     LCD_E_PORT &= ~(1<<LCD_E_PIN);
     
     LCD_E_PORT |= (1<<LCD_E_PIN);     /*System-Set*/
     write_data(0x2);    
     LCD_E_PORT &= ~(1<<LCD_E_PIN);
     LCD_E_PORT |= (1<<LCD_E_PIN);
     write_data(0xC);    
     LCD_E_PORT &= ~(1<<LCD_E_PIN);
     
    
     LCD_E_PORT |= (1<<LCD_E_PIN);
     write_data(0x0);     /*Display on/off, Display on, Unterstrich Cursor on, blinkender Cursor on*/
     LCD_E_PORT &= ~(1<<LCD_E_PIN);
     LCD_E_PORT |= (1<<LCD_E_PIN);
     write_data(0xF);
     LCD_E_PORT &= ~(1<<LCD_E_PIN);
     
     LCD_E_PORT |= (1<<LCD_E_PIN);
     write_data(0x0);   /* Cursor Home */
     LCD_E_PORT &= ~(1<<LCD_E_PIN);
     LCD_E_PORT |= (1<<LCD_E_PIN);
     write_data(0x2);
     LCD_E_PORT &= ~(1<<LCD_E_PIN);
     
     LCD_RS_PORT |= (1<<LCD_RS_PIN);  /*Datenregister auswählen*/
     write_data(0x8);
     LCD_E_PORT &= ~(1<<LCD_E_PIN);
     
    }
    Das Display ist ein 4x27 mit 2 Controllern und es sind in der 1 und 3 Zeile die Balken zu sehen, was meiner Meinung nach darauf hindeutet, dass schon das System Set nicht funktioniert, da dort eigentlich mehr Zeilen eingestellt werden.

  4. #4
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    22.07.2004
    Beiträge
    270
    Nochwas, kann es sein, dass das mit der Busyflag Abfrage nicht richtig hinhaut? Oder brauche ich die überhaupt? Bei anderen init-Routinen habe ich die nämlich nicht immer gesehen...

  5. #5
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    52
    Beiträge
    2.236
    Fang am besten ohne Busy an, nur delays, damit sparst Du Dir ein Pin UND kommst schneller ans Ziel.

    und den Enable Puls erzeugst Du am besten in einer extra Funktion:
    Code:
    void enable(void){
    LCD_E_PORT |= (1<<LCD_E_PIN);
    __asm volatile ("nop"); 
    __asm volatile ("nop");
    __asm volatile ("nop");
    __asm volatile ("nop");
    __asm volatile ("nop");
    LCD_E_PORT &= ~(1<<LCD_E_PIN);
    }
    Die Anzahl der nop's hängt vom Takt ab.

    schau Dir diese Seite an.
    Es ist zwar für Assembler, aber man kann sich schön angucken, wie die Ansteuerung funktioniert.

    Gruß Sebastian
    Software is like s e x: its better when its free.
    Linus Torvald

  6. #6
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    20.06.2004
    Beiträge
    1.941
    Stell Dir mal vor Du liegst im Schützengraben, Deine Waffe ist geladen,gespannt und entsichert, Du Zielst auf denen Feind, und ....
    ...da fehlt noch was.


    ..ja..ladehemmung...

  7. #7
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    22.07.2004
    Beiträge
    270
    Hallo,
    ich hab jetzt das enable in eine extra Routine verpackt und das Busy wegelassen, dafür mehr delays.
    Code:
    void init_lcd(void)
    {
     _delay_ms(20);
     
     LCD_RS_PORT &= ~(1<<LCD_RS_PIN);  /* Steuerregister wird angesprochen */
     write_data(0x3);                  /* 1.0x3 */
     lcd_enable;
     
     _delay_ms(8);
     write_data(0x3);                    /* 2.0x3 */
     lcd_enable;
     
     _delay_ms(1);
     write_data(0x3);                      /* 3.0x3 */
     lcd_enable;
     _delay_ms(5);
                                         /*System-Set 4bit...*/
     write_data(0x2);    
     lcd_enable;
     _delay_ms(5);
     write_data(0x8);                  /* <-- Hier */
     lcd_enable;
     _delay_ms(5);
     
     write_data(0x0);     /*Display on/off, Display on, Unterstrich Cursor on, blinkender Cursor on*/
     lcd_enable;
     _delay_ms(5);
     write_data(0xF);
     lcd_enable;
     _delay_ms(5);
     
     write_data(0x0);   /* Cursor Home */
     lcd_enable;
     _delay_ms(5);
     write_data(0x2);
     lcd_enable;
     _delay_ms(5);
      
    }
    Eigentlich müsste laut dem geposteten DB der Cursor blinken, und zwar an der Home-Position.
    Mache ich vielleicht mit der Übertragung von oberem und unterem Nibble was falsch?

    An der Stelle wo im Code "Hier" steht übertrage ich z.B., nachdem 4-Bit eingestellt wird, das untere Nibble von SystemSet.
    Wenn man einmal vergisst, zB. ein unteres Nibble zu übertragen, ist dann ab dem Zeitpunkt alles so verschoben, dass das nächste obere Nibble als das vergessene untere Nibble gezählt wird?

    Gruß
    Martin

  8. #8
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    52
    Beiträge
    2.236
    @pebi,
    glaub mir, wenn ich Dich vor die Flinte kriegen würde, hätte ich keine Ladehemmungen...

    @Martin,
    Die Nibbles mußt Du schon komplett übertragen, allergings habe ich das noch nie so über die Pins verstreut gemacht...

    So mach ich das z.B.
    Code:
    void lcd_data(uint8_t data) {
            uint8_t temp = data;
            warte(0x00C8);
            RSPORT |=(1<<RS);
    	DATAPORT = (data>>4);
    	enable();
    	DATAPORT = temp;
    	enable();
    	RSPORT &= ~(1<<RS);
    	
    }
    mit lcd_data werden beide Nibbles übertragen, und ich brauche mir keine Sorgen zu machen, daß ich die Hälfte vergesse.
    Aber die Datapins liegen schön hintereinander auf einem Port .
    Vielleicht kannst Du das irgendwie gebrauchen.

    Gruß Sebastian
    Software is like s e x: its better when its free.
    Linus Torvald

  9. #9
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    22.07.2004
    Beiträge
    270
    Hallo Sebastian,
    erstmal Danke dass du dich so bemühst!
    Um meine Werte auf die verschiedenen Pins zu bekommen habe ich mir ja extra die Routine write_data geschrieben, mit der ich auch die gewünschten Portzustände bekomme.
    Muss ihc nach den ertsen 3 0x3 jedesmal noch das untere Nibble übertragen, dass 0x0 ist?
    Die 4-Bit stelle ich jetzt so ein:

    Code:
    write_data(0x2);                     /* Explizit 4-Bit einstellen */
     lcd_enable;
     _delay_ms(5);
     write_data(0x0);                  
     lcd_enable;
     _delay_ms(5);
                                         /*Nochmal System-Set 4bit...*/
     write_data(0x2);    
     lcd_enable;
     _delay_ms(5);
     write_data(0x8);                  /* Anderes von System Set einstellen */
     lcd_enable;
     _delay_ms(5);
    Die Verkabelung sollte auch stimmen, da es mit der Lib von Fleury geht, allerdings braucht der RW.

  10. #10
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    22.07.2004
    Beiträge
    270
    Immer noch nicht gelöst...

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

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

fchao-Sinus-Wechselrichter AliExpress