- Akku Tests und Balkonkraftwerk Speicher         
Ergebnis 1 bis 4 von 4

Thema: LCD will nicht

  1. #1

    LCD will nicht

    Anzeige

    Praxistest und DIY Projekte
    Hallo,

    ich wollte gern ein 16x2 LCD-Display mit meinem ATTiny26 im 8bit-Modus ansteuern. Der Tiny26 hat zwei 8bit-Ports, PORTA verwende ich für den Datenbus, die drei Steuerbits kommen vom PORTB. Taktung ist 16 Mhz.

    Das Problem ist nur, mit dem LCD passiert rein garnichts, nicht mal ein zucken.
    Ich hab schon zwei verschiedene LCD's ausprobiert ein 16x2 und ein 40x4, beide von Reichelt.
    Das 40x4 wird komplett dunkel, das 16x2 bleibt komplett hell. An einem gekauften Mega8-Board funktionieren aber beide.

    Laut Datenblatt vom HD44780 muss man eine Initialisierung machen, das hab ich aber schon in den verschiedensten Varianten probiert, null Ergebnis.
    Es gibt eine Initialisierung für den Problemfall, daß der Power-On Fehlschlug und der normale Init, falls man nur paar Einstellungen ändern will, beides aber ohne Reaktion.

    Im Internet findet man ein ganze Menge von derartigen Schaltungen, aber ich kann kein entscheidenen Unterschied entdecken.


    Habt ihr vielleicht schonmal ein LCD angeschlossen und da ähnliche Probleme gehabt und eine Lösung gefunden???



    Hier mal mein Quellcode für WinAVR (gcc):

    Code:
    #include <avr/io.h>
    #include <avr/delay.h>
    
    // Steuerbits bei PortB
    #define LCD_RS		3 		//Pin für RS
    #define LCD_RW		6		//Pin für Read/Write
    #define LCD_E		1 		//Pin für Enable
    
    #define wait500ns	_delay_loop_1(3)
    #define wait1us		_delay_loop_1(5)
    
    void avr_init(void);
    void LCD_Clear (void);
    void LCD_Command (char Data);
    void LCD_Data (char Data);
    void LCD_Init (void);
    
    void waitms(char ms);
    void waitms2(int ms);
    void waitus(char us);
    void waitus2(int us);
    
    int main(void)
    {
    	
        avr_init();
    	LCD_Init();
    		
    	while(1)
    	{
    		LCD_Clear();
    		
    		waitms2(1000);
    		
    		LCD_Data('a');
    		LCD_Data('b');
    		LCD_Data('c');
    				
    		waitms2(1000);
    	}
    	
        return 0;
    }
    
    
    
    void avr_init(void)
    {
        // Initialize device here.
        
    	DDRB = 255; 
    	PORTB=0;
    	
    	DDRA = 255;
    	PORTA=0;
    }
        
    void LCD_Clear (void)
    {
    	LCD_Command (1); //Clear Display
    	waitms(160);
    	LCD_Command (0x80);	//Set DD-Ram Adresse = 0
    }
    
    void LCD_Command (char Data)
    {		
    	cbi(PORTB,LCD_RS); //RS = 0 Steuerregister
    	cbi(PORTB,LCD_RW); //Zum Schreiben RW-Pin = Low
    	
    	sbi(PORTB,LCD_E);
        	PORTA = Data; 
    	wait500ns;
    	cbi(PORTB,LCD_E);
    	wait500ns;
    		
    	waitus(50);
    }
    
    void LCD_Data (char Data)
    {	
    	sbi(PORTB,LCD_RS); //RS = 1 Datenregister
    	cbi(PORTB,LCD_RW); //Zum Schreiben RW-Pin = Low
    	
    	sbi(PORTB,LCD_E);
        	PORTA = Data; 
    	wait500ns;
    	cbi(PORTB,LCD_E);
    	wait500ns;
    	
    	waitus(50);
    }
    
    void LCD_Init (void)
    {		
    	waitms2(30);
    		
    	
    	// --- Variante 1 ---
    	/*LCD_Command (0%00110000);	// init
    	waitms2(5);	
    
    	LCD_Command (0%00110000);	// init
    	waitus2(150);	
    
    	LCD_Command (0%00110000);	// init
    	waitms2(5);	
    
    	// -----------
    	LCD_Command (0%00111000);	// init
    	waitus2(150);	
    	
    	LCD_Command (0%00001000);	// display off
    	waitus2(150);
    	
    	LCD_Command (0%00000001);	// display clear
    	waitus2(150);
    	
    	LCD_Command (0%00000110);	// increment cursor
    	waitus(150);
    	
    	// -----------
    	LCD_Command (0%00001111);	// disp on, curs on, blink on
    	waitus2(150);
    	
    	LCD_Command (0%10000000);	//Set DD-Ram Adresse = 0
    	waitus2(150);*/
    	
    	// --- Variante 2 ---
    	LCD_Command(0%00111000);	// 8bit, 2line
    	LCD_Command(0%00001111);	// disp on, curs on, blink on
    	LCD_Command(0%00000001);	// clear
    	waitms(160);
    	LCD_Command(0%00000110);	// increment cursor
    	
    	// --- Variante 3 ---
    	/*LCD_Command(0%00110100);
    	LCD_Command(0%00001001);
    	LCD_Command(0%00110000);
    	LCD_Command(0%00001111);
    	LCD_Command(0%00000001);
    	waitms(160);
    	LCD_Command(0%00000110);*/
    }
    
    
    
    void waitms(char ms)
    {
    	for (;ms>0;ms--)
    	{
    		_delay_loop_2(4000);	// 1 = 4 cycles
    	}
    }
    
    void waitms2(int ms)
    {
    	for (;ms>0;ms--)
    	{
    		_delay_loop_2(4000);	// 1 = 4 cycles
    	}
    }
    
    void waitus(char us)
    {
    	for (;us>0;us--)
    	{
    		_delay_loop_1(4);	// 1 = 4 cycles
    	}
    }
    
    void waitus2(int us)
    {
    	for (;us>0;us--)
    	{
    		_delay_loop_1(4);	// 1 = 4 cycles -> 16 cycles
    	}
    }

  2. #2
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    12.11.2004
    Ort
    Hvalstad, Norwegen
    Beiträge
    140
    Tja, wenn ich mir Deine Definitionen für die Steuerbits so ansehe, fällt mir auf, dass Du einfache die Pin-Nummern genommen hast, sehe ich das richtig? Das funktioniert aber nicht! Für LCD_E klappt es, das ist Pin 1,
    für Pin 3(LCD_RS) musst Du 4 benutzen und für Pin 6(LCD_RW) 32.

    Bei Deiner Definition aktiviert LCD_RS Pin 1 & 2, LCD_RW PIN 2 & 4 und LCD_E Pin 1.
    (Ja ich weiß das die Pins eigentlich von 0 bis 7 gezählt werden )

    Du musst Dir die Ansteuerung so vorstellen: Der AVR schreibt einen 8-bittigen Wert ins Port-Register und dieser Wert wird binär ausgegeben.
    Da bei hat jeder Pin einen festen Wert(1,2,4,6,8,16,32,64 & 12, ob der Wert eines Pins dazu gehört oder nicht wird durch eine logische 1 am Pin signalisiert, die dazugehörigen Werte werden dann addiert.
    Beispiel: Es soll 100 ausgegeben werde
    PIN 0 1 2 3 4 5 6 7
    Wert 1 2 4 8 16 32 64 128
    Log 0 0 1 0 0 1 1 0
    ergibt: 4 + 32 + 64 = 100, die PINs 2, 5 und 6 füren eine logische 1.

    Warum hast Du die Pins eigentlich so verteilt?

  3. #3
    Hallo lorcan,

    upps, das muss ich heute gleich mal ausprobieren, wenn das der Fehler ist, dann... Schrei!

    Die Pins verteile ich so, weil ich noch zwei Pins vom PORTB für I2C brauch und da will ich die dafür vorgesehenen Standard-Pins nehmen und zwei der PORTB-Pins sind für XTAL1+2 gedacht, die ich aber nun doch nicht brauch, weil ich den internen 16MhZ-PLL-Takt verwende.

    Ich vermute bisher immer ein Problem mit der Taktung, aber die Taktlängen können wahrscheinlich lang sein wie sie wollen nur nicht zu kurz.

  4. #4
    @lorcan
    Ja aber ich setzt die Bits doch mit der Funktion sbi(<PORT>,<Bit>) und cbi(<PORT>,<Bit>). Der Compiler macht da intern den passenden PORT-Befehl draus, indem er das gewünschte Bit soweit nach links schiebt bis die resultierende Bitmaske passt (1<<Bit) und OR-t das dann zu den bereits bestehenden PORT-Bits.
    Das ist wohl nicht der Grund, die PINS leuchten nämlich auch korrekt mit einer angeschlossenen Leuchtdiode, hab ich mal im Slow-Mode durchprobiert.

    @all
    Ist der Tiny26 vielleicht anders als andere Chips?

Berechtigungen

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

Solar Speicher und Akkus Tests