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

Thema: mal wieder LCD probs

  1. #1
    Benutzer Stammmitglied
    Registriert seit
    07.12.2004
    Beiträge
    34

    mal wieder LCD probs

    Anzeige

    Praxistest und DIY Projekte
    hallo,
    also nach wochen des codens hab ich nun das erschaffen:
    Code:
    #include <avr/io.h>
    
    #define LCD_PORT        PORTD        
    #define LCD_DATA0_PORT  LCD_PORT    
    #define LCD_DATA1_PORT  PORTB     
    #define LCD_DATA2_PORT  LCD_PORT     
    #define LCD_DATA3_PORT  LCD_PORT     
    #define LCD_RS_PORT     LCD_PORT     
    #define LCD_RW_PORT     LCD_PORT     
    #define LCD_E_PORT      LCD_PORT     
    
    #define LCD_RS 			4
    #define LCD_RW 			5
    #define LCD_E  			6
    #define DB0    			7
    #define DB1    			0
    #define DB2	   			2
    #define DB3    			3
    
    
    void toggle_e(void) 
     { 
      LCD_E_PORT |= _BV(LCD_E); 
      asm volatile ("rjmp 1f\n 1:");  //warte 500ns 0,543 us
      LCD_E_PORT &= ~_BV(1 << LCD_E); 
     }
     
     
    void delay(unsigned int count)
     {
      asm volatile ("rjmp 1f\n 1:");  //warte 500ns 0,543 us
      asm volatile ("rjmp 1f\n 1:");  //warte 500ns 0,543 us  // also 1 us
     }
     
     
    void busy(void)
     {
      char dataH;
      char dataL;
      LCD_RW_PORT |= _BV(LCD_RW);
      LCD_RS_PORT &= ~_BV(LCD_RS); 
      DDRD = 0xF7;                         //PD3 als Eingang definieren 0b11110111 
      LCD_E_PORT  |= _BV(LCD_E);			// LCD_E auf high
      do{
      __asm__ __volatile__( "rjmp 1f\n 1:" );         //delay (500ns)
      dataH = PIND;                                               //zuerst hohes Nibble lesen
      LCD_E_PORT  &= ~_BV(LCD_E);
      __asm__ __volatile__( "rjmp 1f\n 1:" );         //delay
      LCD_E_PORT  |= _BV(LCD_E);
      __asm__ __volatile__( "rjmp 1f\n 1:" );         //delay
      dataL = PIND;                                                //lese niederes Nibble
      LCD_E_PORT  &= ~_BV(LCD_E);
      //Dieser Code liest neben dem Busy-Flag gleich noch den Adresszähler aus
      }while(dataH & (1<<DB3));
      //while(PIND & (1<<DB3)) {}		   // solange warten, bis DB3 (busyFlag) auf  0
      //LCD_E_PORT  &= ~_BV(LCD_E);			// LCD_E auf low
     }
     
    int main()
    {
    	DDRD = 0xFF;
    	DDRB = 0xFF;
    	
    	delay(20000);  //warte 20 ms (20000us)
    	
    	LCD_DATA1_PORT |= _BV(DB1);  
        LCD_DATA0_PORT |= _BV(DB0);
    	
    	toggle_e();
    	
    	delay(5000);  //mehr als 4,1 ms warten (4992)
    	
    	toggle_e();
    	
    	delay(200);   // es muss mehr als 100 us gewartet werden
    	
    	toggle_e();
    	
    	delay(200);   // es muss mehr als 100 us gewartet werden
    	
    	LCD_DATA0_PORT &= ~_BV(DB0); //LCD_DATA0_PORT &= ~_BV(DB0);
    	//PORTD = 0x20>>4;                                             //entspricht 0b00100000
    	toggle_e();
    	delay(100);   //mehr als 100us warten
    	
    	busy();
    	
    	LCD_RS_PORT &= ~_BV(LCD_RS);
    	LCD_RW_PORT &= ~_BV(LCD_RW); //Daten als Befehl zu deuten sind. Dies erfolgt durch RS=0 und RW=0
    	
    	//Die beiden Nibble werden nun hintereinander an das LCD gesendet, das obere zuerst.
    	LCD_DATA3_PORT &= ~_BV(DB3);			//0
    	LCD_DATA2_PORT &= ~_BV(DB2);			//0
    	LCD_DATA1_PORT  =  _BV(DB1);			//1   -> high nibble 0b0010   (36)   von 40
    	LCD_DATA0_PORT &= ~_BV(DB0);			//0
    		  
    																							// macht insgesamt 4 + 36 = 40 -> 0x28
    	toggle_e();
    	LCD_DATA3_PORT &= ~_BV(DB3);			//0
    	LCD_DATA2_PORT  =  _BV(DB2);			//1
    	LCD_DATA1_PORT &= ~_BV(DB1);			//0  -> high nibble 0bxxxx0100   (4)   von 40
    	LCD_DATA0_PORT &= ~_BV(DB0);			//0
    	toggle_e();
    	
    	//In diesem Fall ist data = 0x28, wie es bereits oben erwähnt wurde.
    	//Dann werden alle Datenpins wieder auf logisch '0' gesetzt.
    	LCD_DATA3_PORT &= ~_BV(DB3);			//0
    	LCD_DATA2_PORT &= ~_BV(DB2);			//0
    	LCD_DATA1_PORT &= ~_BV(DB1);			//0  
    	LCD_DATA0_PORT &= ~_BV(DB0);			//0
    
    
    // Als nächstes soll das Display ausgeschaltet werden. Dies erfolgt durch das Senden von 0x08 (vgl. Datenblatt).
    // Das Senden erfolgt analog zu der obigen Erklärung (dort war es 0x28 für den 4-Bit-Modus).
    // Danach muss das Display gelöscht werden. Hierzu muss 0x01 gesendet werden (vgl. Datenblatt).
    // Zu guter letzt muss noch der Start-Modus (entry mode) definiert werden. 
    // Hier soll das Display einfach aktiviert und der Cursor deaktiviert werden. Dies erfolgt durch Senden von 0x0C.
    //Die beiden Nibble werden nun hintereinander an das LCD gesendet, das obere zuerst. (s.u.)
    //////////////////////////////////////////////////////
    //////////////////////////////////////////////////////
    //////////////////////////////////////////////////////
    	delay(100);
    	//0x08 <- Als nächstes soll das Display ausgeschaltet werden.
    	LCD_DATA3_PORT &= ~_BV(DB3);			//0
    	LCD_DATA2_PORT &= ~_BV(DB2);			//0
    	LCD_DATA1_PORT &= ~_BV(DB1);			//0   -> high nibble 0b0000   (0)   von 8
    	LCD_DATA0_PORT &= ~_BV(DB0);			//0
    		  
    																							// macht insgesamt 0 + 8 = 8 -> 0x08
    	toggle_e();
    	LCD_DATA3_PORT  =  _BV(DB3);			//1
    	LCD_DATA2_PORT &= ~_BV(DB2);			//0
    	LCD_DATA1_PORT &= ~_BV(DB1);			//0  -> high nibble 0bxxxx1000   (8)   von 8
    	LCD_DATA0_PORT &= ~_BV(DB0);			//0
    	toggle_e();
    	
    	//Dann werden alle Datenpins wieder auf logisch '0' gesetzt.
    	LCD_DATA3_PORT &= ~_BV(DB3);			//0
    	LCD_DATA2_PORT &= ~_BV(DB2);			//0
    	LCD_DATA1_PORT &= ~_BV(DB1);			//0  
    	LCD_DATA0_PORT &= ~_BV(DB0);			//0
    	
    	
    	
    	
    	/////////////////////////////////////////////////////////////////////////////////
    	/////////////////////////////////////////////////////////////////////////////////
    	delay(100);
    	//Danach muss das Display gelöscht werden. Hierzu muss 0x01 gesendet werden
    	//Die beiden Nibble werden nun hintereinander an das LCD gesendet, das obere zuerst.
    	LCD_DATA3_PORT &= ~_BV(DB3);			//0
    	LCD_DATA2_PORT &= ~_BV(DB2);			//0
    	LCD_DATA1_PORT &= ~_BV(DB1);			//0   -> high nibble 0b0000   (0)   von 1
    	LCD_DATA0_PORT &= ~_BV(DB0);			//0
    		  
    																							// macht insgesamt 0 + 1 = 1 -> 0x01
    	toggle_e();
    	LCD_DATA3_PORT &= ~_BV(DB3);			//0
    	LCD_DATA2_PORT &= ~_BV(DB2);			//0
    	LCD_DATA1_PORT &= ~_BV(DB1);			//0  -> high nibble 0bxxxx0001  (1)   von 1
    	LCD_DATA0_PORT  =  _BV(DB0);			//1
    	toggle_e();
    	
    	//Dann werden alle Datenpins wieder auf logisch '0' gesetzt.
    	LCD_DATA3_PORT &= ~_BV(DB3);			//0
    	LCD_DATA2_PORT &= ~_BV(DB2);			//0
    	LCD_DATA1_PORT &= ~_BV(DB1);			//0  
    	LCD_DATA0_PORT &= ~_BV(DB0);			//0
    	
    	
    	
    	
    	
    	////////////////////////////////////////////////////////////
    	////////////////////////////////////////////////////////////
    	////////////////////////////////////////////////////////////
    	delay(100);
    	//Hier soll das Display einfach aktiviert und der Cursor deaktiviert werden. Dies erfolgt durch Senden von 0x0C.
    		//Die beiden Nibble werden nun hintereinander an das LCD gesendet, das obere zuerst.
    	LCD_DATA3_PORT &= ~_BV(DB3);			//0
    	LCD_DATA2_PORT &= ~_BV(DB2);			//0
    	LCD_DATA1_PORT &= ~_BV(DB1);			//0   -> high nibble 0b0000   (0)   von 12
    	LCD_DATA0_PORT &= ~_BV(DB0);			//0
    		  
    																							// macht insgesamt 0 + 12 = 12 -> 0x0c
    	toggle_e();
    	LCD_DATA3_PORT  =  _BV(DB3);			//0
    	LCD_DATA2_PORT  =  _BV(DB2);			//1
    	LCD_DATA1_PORT &= ~_BV(DB1);			//0  -> high nibble 0bxxxx1100   (12)   von 12
    	LCD_DATA0_PORT &= ~_BV(DB0);			//0
    	toggle_e();
    	
    	//Dann werden alle Datenpins wieder auf logisch '0' gesetzt.
    	LCD_DATA3_PORT &= ~_BV(DB3);			//0
    	LCD_DATA2_PORT &= ~_BV(DB2);			//0
    	LCD_DATA1_PORT &= ~_BV(DB1);			//0  
    	LCD_DATA0_PORT &= ~_BV(DB0);			//0
    	
    	delay(100);
    	///////////////////////////////////////////////////////////////
    	//////////////////////INITIALIESIERUNG ABGESCHLOSSEN///////////
    	///////////////////////////////////////////////////////////////
    	
    	
    	//Das Schreiben von Daten auf dem Display funktioniert mit 
    	//den bereits oben angeführten Befehlen. RS muss auf H-Pegel sein, R/W auf Low.
    	LCD_RS_PORT |= _BV(LCD_RS);
    	LCD_RW_PORT |= _BV(LCD_RW);
    	
    	//0010 0001=!
    	delay(100);
        //Die beiden Nibble werden nun hintereinander an das LCD gesendet, das obere zuerst.
    	LCD_DATA3_PORT &= ~_BV(DB3);			//0
    	LCD_DATA2_PORT &= ~_BV(DB2);			//0
    	LCD_DATA1_PORT  =  _BV(DB1);			//1   -> high nibble 
    	LCD_DATA0_PORT &= ~_BV(DB0);			//0
    		  
    	toggle_e();
    	LCD_DATA3_PORT  =  _BV(DB3);			//1
    	LCD_DATA2_PORT &= ~_BV(DB2);			//0
    	LCD_DATA1_PORT &= ~_BV(DB1);			//0  -> high nibble 
    	LCD_DATA0_PORT &= ~_BV(DB0);			//0
    	toggle_e();	
    }
    nun funktioniert das display mit diesem Code nicht, es kommen nur 2 schwarze Balken. (generell geht das display schon).

    Hat jemand ne idee was da nicht stimmt?.....


    Gruß
    Scrat1

  2. #2
    Ich denk mal, so simpel wird's net sein, aber deine delay Funktion delay't doch immer nur 1 us, oder seh ich das falsch?

    Die als Parameter übergebene Variable count wird doch gar nicht miteinbezogen in die Funktion...

  3. #3
    Benutzer Stammmitglied
    Registriert seit
    07.12.2004
    Beiträge
    34
    oh danke,
    habs jetzt so gmacht:
    Code:
    void delay(unsigned int count)
     {
      int i;
      for(i=0;count>i;i++)
      {
        asm volatile ("rjmp 1f\n 1:");  //warte 500ns 0,543 us
        asm volatile ("rjmp 1f\n 1:");  //warte 500ns 0,543 us  // also 1 us
      }
     }
    es geht aber trotzdem net..

    Gruß
    Scrat1

  4. #4
    Erfahrener Benutzer Robotik Einstein Avatar von Felix G
    Registriert seit
    29.06.2004
    Ort
    49°32'N 8°40'E
    Alter
    41
    Beiträge
    1.780
    Code:
    void toggle_e(void) 
     { 
      LCD_E_PORT |= _BV(LCD_E); 
      asm volatile ("rjmp 1f\n 1:");  //warte 500ns 0,543 us 
      LCD_E_PORT &= ~_BV(1 << LCD_E); 
     }
    Also diese _BV Geschichte bei den Flags kenne ich nicht,
    ich mache das immer direkt mit "|= (1 << Flagname)"bzw "&= ~(1 << Flagname)"

    aber so oder so muss ja eigentlich eine der beiden Varianten in deinem Code falsch sein.
    (da sonst auch überall das "1 <<" fehlt nehme ich mal an die zweite Schreibweise ist die falsche)
    So viele Treppen und so wenig Zeit!

  5. #5
    Benutzer Stammmitglied
    Registriert seit
    07.12.2004
    Beiträge
    34
    Hallo,
    ja danke..
    habs verbessert, funzt aber immer noch net.

    nun noch ne 2te Frage:

    was is das beste um bits zu setzen?
    PORTD |= (1 << 6);
    PORTD |= _BV(1 << 6);
    oder sbi()


    Gruß
    Scrat1

  6. #6
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    17.11.2003
    Ort
    Alfeld (50km südl. Hannover)
    Alter
    40
    Beiträge
    237
    sbi() ist veraltet und wird bald entfernt.
    _BV(bit) ist ein Makro, der preprozessor ersetzt es zu (1 << (bit))
    Ob man _BV oder (1<<(bit)) verwendet ist geschmackssache,
    persöhnlich finde ich (1<<(bit)) besser, weil _BV nicht jeder kennt.

    _BV(1<<6) wird nicht Funktionieren, die 1 wird 6 mal nach rechts
    geschoben, _BV() schiebt die 1 noch mal mit dem Ergebnis von
    (1<<6) nach rechts, ergibt also Murks.

    EDIT:
    siehe:
    http://jubal.westnet.com/AVR/doc/avr-libc-user-manual/
    und dann auf Modules --> Special function registers
    Open Minds. Open Sources. Open Future

  7. #7
    Gast
    Hallo

    Du hast doch schon schön mit den Markos angefangen, dann bleibe auch
    dabei. Macht doch alles viel besser lesbar.

    Beispiel:

    Code:
    #define SET_ENABLE	PORTD |=   _BV(LCD_E);
    #define RESET_ENABLE	PORTD &= ~ _BV(LCD_E);
    #define TOGGLE_ENABLE   PORTD  ^=  _BV(LCD_E);
    
    Im Code dann einfach:
    
    SET_ENABLE;

    MFG
    Dieter

  8. #8
    Benutzer Stammmitglied
    Registriert seit
    07.12.2004
    Beiträge
    34
    Danke für den Tipp, aber erstmal sollte das Programm funktionieren...


    Gruß
    Scrat1

  9. #9
    Gast
    Hallo

    Recht hast du schon, das das Programm erstmal laufen sollte.

    Wenn du meinen Rat befolgt hättest, wär es dir selber aufgefallen.

    Code:
       //Das Schreiben von Daten auf dem Display funktioniert mit
       //den bereits oben angeführten Befehlen. RS muss auf H-Pegel sein, R/W auf Low.
       LCD_RS_PORT |= _BV(LCD_RS);
       LCD_RW_PORT |= _BV(LCD_RW);
    Oben im Text schreibst du es noch richtig und dann.

    Hoffe das wars.

    Denn Fehler hast du ja bestimmt schon verbessert.

    Code:
    void toggle_e(void)
     {
      LCD_E_PORT |= _BV(LCD_E);
      asm volatile ("rjmp 1f\n 1:");  //warte 500ns 0,543 us
      LCD_E_PORT &= ~_BV(1 << LCD_E);
     }
    MFG
    Dieter

  10. #10
    Benutzer Stammmitglied
    Registriert seit
    07.12.2004
    Beiträge
    34
    Gut danke (wurde verbessert)

    so langsam könnts was werden

    also am schluss soll auf dem display ein "!" zu sehen sein.
    des is der Binärcode: 00101000 ganz am Ende.





    Gruß
    Scrat1

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

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

12V Akku bauen