Egal was ich mache na meinem LED Display erscheinen nach der Initalisierung beim senden von Daten immer das Zeichen: _ _ _ _
Geht um dat Ding: LCD-Modul TC1602A-08 von Pollin verwende die Funktionen vom Tutorial
Was denn nun? Balken oder '_'? Wenns nur __ sind, dann stimmt was am Programm nicht. Wenns wirklich Balken sind (d.h. alle Pixel sind schwarz), dann ist der Kontrast zu hoch.
Ich habe irgendwie das Gefühl, dass in dem ATMEGA8 die FuseBits noch falsch gesetzt sind. Habe folgende Port Belegung für den 4 Bit Modus: #define LCD_RS_PORT PORTB #define LCD_RS_DDR DDRB #define LCD_RS_NR 0 #define LCD_RS_PIN PB0 #define LCD_EN_PORT PORTD #define LCD_EN_DDR DDRD #define LCD_EN_NR 7 #define LCD_EN_PIN PD7 #define LCD_DATA_4_PORT PORTD #define LCD_DATA_4_DDR DDRD #define LCD_DATA_4_NR 6 #define LCD_DATA_4_PIN PD6 #define LCD_DATA_5_PORT PORTD #define LCD_DATA_5_DDR DDRD #define LCD_DATA_5_NR 5 #define LCD_DATA_5_PIN PD5 #define LCD_DATA_6_PORT PORTD #define LCD_DATA_6_DDR DDRD #define LCD_DATA_6_NR 4 #define LCD_DATA_6_PIN PD4 #define LCD_DATA_7_PORT PORTD #define LCD_DATA_7_DDR DDRD #define LCD_DATA_7_NR 3 #define LCD_DATA_7_PIN PD3
Boah ich könnte druchdrehen, alle PINS haben die richtigen Zustände, alle Verbindungen passen, nur das Display schreibt nur ein Zeichen
Also die Routinen funktionieren auf zwei anderen Displays wunderbar, nur bei dem Sch.. Ding nicht: #include <avr/io.h> #include "lcd.h" #include "mydefs.h" #include <util/delay.h> // sendet ein Datenbyte an das LCD void LCD_data(unsigned char temp1) { unsigned char temp2 = temp1; LCD_rs_enable(); // RS auf 1 setzen temp1 = temp1 >> 4; temp1 = temp1 & 0x0F; LCD_write_in_ports(temp1); LCD_enable(); temp2 = temp2 & 0x0F; LCD_write_in_ports(temp2); LCD_enable(); _delay_us(42); } // sendet einen Befehl an das LCD void LCD_command(unsigned char temp1) { unsigned char temp2 = temp1; LCD_rs_disable(); // RS auf 0 setzen temp1 = temp1 >> 4; // oberes Nibble holen temp1 = temp1 & 0x0F; // maskieren LCD_write_in_ports(temp1); LCD_enable(); temp2 = temp2 & 0x0F; // unteres Nibble holen und maskieren LCD_write_in_ports(temp2); LCD_enable(); _delay_us(42); } // erzeugt den Enable-Puls void LCD_enable(void) { // Bei Problemen ggf. Pause gemäß Datenblatt des LCD Controllers einfügen // Beitrag "Re: Bitte helft mir. Schon wieder AtMega16" sbi(LCD_EN_PORT,LCD_EN_NR); _delay_ms(10); // kurze Pause // Bei Problemen ggf. Pause gemäß Datenblatt des LCD Controllers verlängern // Beitrag "LCD -> Probleme mit Optimierungsgrad" cbi(LCD_EN_PORT,LCD_EN_NR); } // Initialisierung: // Muss ganz am Anfang des Programms aufgerufen werden. void LCD_init(void) { // Alle LCD PORTS auf Ausgang schalten sbi(LCD_RS_DDR,LCD_RS_NR); sbi(LCD_EN_DDR,LCD_EN_NR); sbi(LCD_DATA_4_DDR,LCD_DATA_4_NR); sbi(LCD_DATA_5_DDR,LCD_DATA_5_NR); sbi(LCD_DATA_6_DDR,LCD_DATA_6_NR); sbi(LCD_DATA_7_DDR,LCD_DATA_7_NR); // muss 3mal hintereinander gesendet werden zur Initialisierung _delay_ms(15); // Schreiben einer 0x03 LCD_write_in_ports(0x03); LCD_rs_disable(); LCD_enable(); _delay_ms(5); LCD_enable(); _delay_ms(1); LCD_enable(); _delay_ms(1); // 4 Bit Modus aktivieren LCD_enable(); _delay_ms(1); // 4Bit 2 Zeilen 5x7 LCD_command(0x28); // Display ein Cursor aus kein Blinken LCD_command(0x0C); // inkrement / kein Scrollen LCD_command(0x06); LCD_clear(); } // Sendet den Befehl zur Löschung des Displays void LCD_clear(void) { LCD_command(CLEAR_DISPLAY); _delay_us(100); } // Sendet den Befehl: Cursor Home void LCD_home(void) { LCD_command(CURSOR_HOME); _delay_ms(100); } // setzt den Cursor in Zeile y (1..4) Spalte x (0..15) void LCD_set_cursor(unsigned char x, unsigned char y) { unsigned char tmp=0; switch (y) { case 1: tmp=0x80+x; break; // 1. Zeile case 2: tmp=0xC0+x; break; // 2. Zeile case 3: tmp=0x94+x; break; // 3. Zeile case 4: tmp=0xD4+x; break; // 4. Zeile } LCD_command(tmp); } // Schreibt einen String auf das LCD void LCD_string(char *data) { while(*data) { LCD_data(*data); data++; } } void LCD_rs_enable(void) { sbi(LCD_RS_PORT,LCD_RS_NR); } void LCD_rs_disable(void) { cbi(LCD_RS_PORT,LCD_RS_NR); } void LCD_write_in_ports(unsigned char data) { unsigned char i = 0, data_temp=0; while(i < 4) { data_temp = data; data_temp = data_temp >> i; data_temp &= 0x01; if(data_temp && (i == 0)) sbi(LCD_DATA_4_PORT,LCD_DATA_4_NR); else cbi(LCD_DATA_4_PORT,LCD_DATA_4_NR); if(data_temp && (i == 1)) sbi(LCD_DATA_5_PORT,LCD_DATA_5_NR); else cbi(LCD_DATA_5_PORT,LCD_DATA_5_NR); if(data_temp && (i == 2)) sbi(LCD_DATA_6_PORT,LCD_DATA_6_NR); else cbi(LCD_DATA_6_PORT,LCD_DATA_6_NR); if(data_temp && (i == 3)) sbi(LCD_DATA_7_PORT,LCD_DATA_7_NR); else cbi(LCD_DATA_7_PORT,LCD_DATA_7_NR); i++; } }
Vielleicht hilft das noch weiter, wenn die Initialisierungsroutine durchgelaufen ist, dann steht der Cursor in der ersten Zeile an der letzten Stelle blinkend. Wenn ich den Kontrast erhöhe, wird die erste Zeile mit schwarzen Balken gefüllt. Die Initioalisierung auf den 4 Bit 2 Zeilen 16 Zeichen funktioniert so gar nicht.
So nun habe ich ein Electronic Assemblys LCD drangehängt. Selbes Problem. Kann mir denn keiner weiterhelfen?
Vermutlich ne kurzschluß zwischen zwei Signalleitungen, Flasche Taktfrequenz oder ein Software/Verdrahtungsfehler.
cbi(LCD_EN_DDR,LCD_RW_NR); Solltest auch noch hinzufügen. Wenn RW irgendwo ausversehen gestzt wird könnte es auch zu Problemen kommen. Ansonsten liegt das am richtigen Timing würde ich sagen. Busy Flag wird ja nicht abgefragt.
Also RW ist auf Masse gelegt. Kurzschluss zwischen den Signalleitungen habe ich nicht, Softwareverdrahtungsfehler ist auszuschließen, bereits 1000 mal überprüft, an der Hardware und an der Software. Beim Electronic Assemblies schreibt er immer dieses Zeichen "|||".
Wenn alles okay ist müßte es ja funktionieren... Zeig doch mal den gesamten Quellcode, hast du die Delays mal verlängert?
So ein ähnliches 'Problem' hatte ich vor kurzem auch an einem LCD. Mein Problem war, dass ich die Datenleitungen am LCD an D0 bis D3 anstelle von D4 bis D7 angelötet habe. Im Nachhinein war ich verblüfft, das das LCD überhaupt initialisiert wurde, aber das wurde es zweifellos. Aber anstelle von Zeichen kamen bei einem Test nur lauter ausgefüllte Rechtecke zum Vorschein.
Danke für die Anmerkungen, da das Ding immer nur die selben Zeichen schreibt, egal welches Zeichen ich schicke, gehe ich von einem Hardwarefehler aus. Also habe ich zunächst überprüft ob Kurzschlüsse zwischen den Signalleitungen sind. Dann habe ich die einzelnen Verbindungen vom Steckverbinder des LCD zum uC gemessen und vom Steckverbinder zu den Anschlüssen am LCD. Dann habe ich mal die Funktion LCD_write_in_ports(0x03) am Steckverbinder nachgemessen: DB4 = 1,2 V DB5 = 1,2 V DB6 = 0 V DB7 = 0 V Das habe ich variiert, die Bits werden richtig geschrieben. Dann habe ich die Delayzeiten hochgeschraubt. Habe das alles nun mit drei Pollin Displays und mit einem Electronic Assembly Display durchgeführt. Der Cursor springt immer in der ersten Zeile an die letzte Stelle. Dann werden immer die selben Zeichen "|||" geschrieben. Die Belegung der Pins habe ich wie folgt gemacht: PIN 1 = GND PIN 2 = VCC PIN 3 = Schleifer von Poti zw. Vcc und GND PIN 4 = RS = PB0 PIN 5 = R/W = GND PIN 6 = EN = PD7 PIN 7 bis PIN10 = offen PIN 11 = PD6 PIN 12 = PD5 PIN 13 = PD4 PIN 14 = PD3 PIN 15 = VCC PIN 16 = 330 Ohm -> GND Welche Infos benötigt ihr noch? Vielen Dank für die Hilfe.
void LCD_clear(void) { LCD_command(CLEAR_DISPLAY); _delay_us(100); } Das delay fürs löschen ist viel zu klein.
> PIN 11 = PD6 > PIN 12 = PD5 > PIN 13 = PD4 > PIN 14 = PD3 Hmmm, nicht umgekehrt? ...
In Verbindung mit der Funktion LCD_write_in_ports(); und der Header Definitionen müsste > PIN 11 = PD6 > PIN 12 = PD5 > PIN 13 = PD4 > PIN 14 = PD3 korrekt sein.
So nun tut sich folgendes: Ich schreibe nach der Initialisierung eine 0x03 mit der Funktion LCD_write_in_ports(); dann kann ich am Steckverbinder an den Ports DB4 = 1,2 V DB5 = 1,2 V DB6 = 0 V DB7 = 0 V die Spannungen messen. Schreibe ich nun danach ein LCD_enable() ohne das Display am Steckverbinder zu haben, liegen an allen Ports nur DB4 = 0 V DB5 = 0 V DB6 = 0 V DB7 = 0 V an. Irgendetwas stimmt also mit der Enable Leitungen oder dem Code nicht.
> // 4 Bit Modus aktivieren Da fehlt doch was? > LCD_enable(); > _delay_ms(1); So wie ich das sehe schreibst du viermal 0x03. Und damit bist du im 8 Bit Mode.
Also wenn ich die Ports einzeln high setze mit der Funktion sbi(...) kommen da immer korrekte 5 V an. Nehme ich die write_in_ports() kommen da 1,2 V bei High an und wenn ich nach der write_in_ports ein enable mache, dann liegen nur 0 V an. Irgendwas stimmt komischerweise mit den Funktionen nicht.
Habs raus: void LCD_write_in_ports(unsigned char data) { unsigned char i = 0, data_temp=0; while(i < 4) { data_temp = data; data_temp = data_temp >> i; data_temp &= 0b00000001; if(data_temp) { if(i == 0) sbi(LCD_DATA_4_PORT,LCD_DATA_4_NR); if(i == 1) sbi(LCD_DATA_5_PORT,LCD_DATA_5_NR); if(i == 2) sbi(LCD_DATA_6_PORT,LCD_DATA_6_NR); if(i == 3) sbi(LCD_DATA_7_PORT,LCD_DATA_7_NR); } else { if(i == 0) cbi(LCD_DATA_4_PORT,LCD_DATA_4_NR); if(i == 1) cbi(LCD_DATA_5_PORT,LCD_DATA_5_NR); if(i == 2) cbi(LCD_DATA_6_PORT,LCD_DATA_6_NR); if(i == 3) cbi(LCD_DATA_7_PORT,LCD_DATA_7_NR); } i++; } } keine Ahnung warum, für mich ist die Logik die selbe
>keine Ahnung warum, für mich ist die Logik die selbe
Ist sie aber nicht ;)
Wenn i für den entsprechenden Pin nicht ==x ist
wird das else ausgeführt.
Mach das doch ohne Schleife dann sparst du Code:
1 | void LCD_write_in_ports(unsigned char data) |
2 | {
|
3 | |
4 | if(data & 0x01) sbi(LCD_DATA_4_PORT,LCD_DATA_4_NR); |
5 | else cbi(LCD_DATA_4_PORT,LCD_DATA_4_NR); |
6 | |
7 | if(data & 0x02)) sbi(LCD_DATA_5_PORT,LCD_DATA_5_NR); |
8 | else cbi(LCD_DATA_5_PORT,LCD_DATA_5_NR); |
9 | |
10 | if(data & 0x04) sbi(LCD_DATA_6_PORT,LCD_DATA_6_NR); |
11 | else cbi(LCD_DATA_6_PORT,LCD_DATA_6_NR); |
12 | |
13 | if(data & 0x08) sbi(LCD_DATA_7_PORT,LCD_DATA_7_NR); |
14 | else cbi(LCD_DATA_7_PORT,LCD_DATA_7_NR); |
15 | |
16 | }
|
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.