Ich weiß nicht mehr weiter: Ich hab nun schon fast drei Tage mit der Fehlersuche verbracht! Meine Probleme: 1. Das LCD wird nicht richtig initialisiert, wenn ich ein Zeichen schreibe(wenn denn eins geschrieben wird!), bleibt meist die erste Position frei oder so etwas "|||"erscheint, was in der Zeichentabelle gar nicht auftaucht. Wenn ich dann jede sek. ein Zeichen schreibe verschwindet der Cursor am Ende des LCD und taucht irgendwann in der 2. Zeile wieder auf,.. verschwindet wieder..taucht in der 1. wieder auf --> ist dann wohl mit 2x16 initialisiert, obwohl ich nur 2x8 hab 2. es erscheint nicht immer ein Zeichen, hab's ausprobiert mit 0b11001100: im Display erscheint dann aber das Zeichen aus der Tabelle mit 0b11001111, sieht aus wie ein chin. Schriftzeichen auch wenn's unübersichtlich wird: hier der Quelltext (Für die Daten nutze ich PA0-PA3; PF4=E, PF6=Rs) ======================================================================== === #include "config.h" #include "lcd.h" #include <util/delay.h> #define Lcd_write PORTF&=0b11011111 #define Lcd_read PORTF|=0b00100000 #define Lcd_order PORTF&=0b10111111 #define Lcd_data PORTF|=0b01000000 #define Lcd_enable PORTF|=0b00010000 #define Lcd_disable PORTF&=0b11101111 U8 swap(U8 x) { return ((x >> 4) | (x << 4)); } void Port_init_lcd(void) { DDRA=0xFF; DDRF|=1<<DDF4; DDRF|=1<<DDF5; DDRF|=1<<DDF6; } void write_lcd_once(U8 n) { U8 nib; nib=n; nib&=0x0F; Lcd_write; PORTA = nib; Lcd_enable; PORTA = nib; Lcd_disable; } void write_lcd(U8 d) { U8 dat; dat=d; dat=swap(dat); dat&=0x0F; Lcd_write; PORTA = dat; Lcd_enable; PORTA = dat; Lcd_disable; write_lcd_once(d); } void lcd_clear(void) { Lcd_order; write_lcd(0b00000001); } void lcd_init(void) { _delay_ms(40); Lcd_order; write_lcd_once(0x03); _delay_us(37); write_lcd(0x28); _delay_us(37); write_lcd(0x28); _delay_us(37); write_lcd(0x0F); _delay_us(40); write_lcd(0x01); _delay_ms(1.52); write_lcd(0x06); _delay_us(37); } void cursor_home(void) { Lcd_order; write_lcd(0b00000010); } void cursor_set_row2(void) { int i; Lcd_order; cursor_home(); for (i=0;i<8;i++) write_lcd(0b00010100); } ======================================================================== === Ich hoffe jemand kann mir helfen, oder Tipps für die Fehlersuche geben. MfG Olli
Hmmm, welchen Controller hat das Display nen HD oder nen KS? Beim KS ist die initsequenz ein klein wenig anderst, das verursacht dann diesen Fehler das das LCD nur müll anzeigt (ist mir auch schon passiert). ST7066U ist das der Controller oder die bez. des LCDs? Poste mal mehr infos bitte. :) Roland
jo, das wirds sein. Hat mich auch schon mal sinnlos Zeit gekostet. 99,x% Kompatibilität reichen eben manchmal nicht.
ST7066U ist der Controller, soll mit HD... auf jeden Fall Pin kompatibel sein. Hab jetz noch ein bißchen rumgespielt mit versch. Zeichen: Das obere Nibble wird korrekt übertragen, das untere ist immer 1111: so wird z.B. aus 'W'(ASCII 0x57) im Display "_"(0x5F) oder aus 'A'(0x41),'B'(0x42).. "O"(0x4F) Wnn ich dann an PA0-PA3 messe bekomme ich das korrekte unter Nibble, also bei 'W' --> 0111 Wenn ich das LCD dranhänge(ohne Datenleitungen) erscheint ein Balken in der 1. Zeile, wenn ich das Prog. starte kommen dann 2 Zeilen(sind aber etwas heller), dann fängt er meist auch nicht gleich an zu schreiben, sondern erst wenn ich dann noch mal ca. 1s Reset(auf dem Board) halte ...? Olli
Das würde dann auch erklären, warum Clear Display('0b00000001') nicht funktioniert. Gib es eig. bei der Init einen Befehl der aus dem Display 2x16 macht oder hat es was mit Shift zu tun, dass der Cursor aus dem Anzeigebereich läuft? und was könnte die Ursache für das untere Nibble, dass immer 1111 ist, sein?
Hallo Olli. Dann ist entweder der Controller kaputt, oder mit deinen Steuersignalen stimmt was nicht. Bei der Init-Sequenz kann man die Größe des Displays mit einem bestimmten Befehl festlegen. Da hilft immer das Datenblatt des Controllers. Da sind meist besispielroutinen angegeben. Habe danach auch eine Headrer-Datei für nen LCD geschrieben und es war kein Problem. Bevor du aber das Problem mit dem unteren Nibble nicht geklärt hast, funktioniert natürlich auch kein Befehl richtig (Außer er endet aus Zuall mit 0xFF). MfG Muecke
> 1. Das LCD wird nicht richtig initialisiert, wenn ich ein Zeichen > schreibe(wenn denn eins geschrieben wird!), bleibt meist die erste > Position frei oder so etwas "|||"erscheint, was in der Zeichentabelle > gar nicht auftaucht. mach mal ein (oder 2-3) "asm volatile ("nop");" vor und nach den Lcd-disable; vielleicht ist der AVR zu schnell (der E-Takt muss unter 2 MHz bleiben) > Wenn ich dann jede sek. ein Zeichen schreibe > verschwindet der Cursor am Ende des LCD und taucht irgendwann in der 2. > Zeile wieder auf,.. verschwindet wieder..taucht in der 1. wieder auf Das ist normal, die 2. Zeile fängt (wahrscheinlich) in der Mitte des Kontroller-RAMs an
1 | //so kommst du da hin..
|
2 | #define ROW2 0x40
|
3 | lcd_order; |
4 | //hier waeren Macros fuer die LCD befehle, wie DDRAM_ADR, nett...
|
5 | write_lcd(0x80 | ROW2); |
>2. es erscheint nicht immer ein Zeichen, hab's ausprobiert mit >0b11001100: ist, btw. kein ASCII Zeichen ;) >im Display erscheint dann aber das Zeichen aus der Tabelle mit >0b11001111, sieht aus wie ein chin. Schriftzeichen dann gehts doch... schick mal ein 'A' (genau so eintippen!!) hth. Jörg
>Dann ist entweder der Controller kaputt, oder mit deinen Steuersignalen >stimmt was nicht. Ich denke/hoffe nicht, da ja anscheinend auch ein Nibble richtig ist. Mit nop hat's leider auch nicht funktioniert, bei 'A' erscheint im LCD O. Hinzu kommt jetzt noch, dass er in den Zeilen springt, obwohl ich weiter nichts geändert habe(noch keion ROW2). 3 Zeichen werden geschrieben, Sprung in die andere Zeile, schreibt Zeile zu Ende, kommt in der gleichen Zeile wieder, schreibt 3 Zeichen, springt zurück in die vorherige Zeile, schreibt zu Ende... Nach einem HW-Reset läuft's wieder normal! ??? Aber wo kommt 1111 her? Olli
Habe nochmal ein bißchen gemessen: wenn das Prog. nicht läuft, das Bord aber an ist und das LCD auch (Init nach Reset --> ein Balken) sind die Datenleitungen alle auf 5V, kann es evtl. damit zusammenhängen? Olli
Ich weiß nicht mehr weiter,... Kann mir einer von euch ein LCD 8x2 empfehlen, dass den HD44780 als Controller hat. Ich möchte wenigstens erstmal ein LCD richtig angesteuert bekommen, dann werd ich mich wohl nochmal an diesem versuchen! MfG Olli
Kannst du nicht mal dein Programm soweit wie nötig zusammenstreichen und dann hier anhängen? Und bitte das Datenblatt vom Display(!) verlinken? Und die Schaltung NOCH MAL kontrollieren (Kurzschlüsse, Massen verbunden...) gib doch nicht so leicht auf ;) hth. Jörg
>gib doch nicht so leicht auf ;)
Ist nur das erste mal, dass ich mich an einem LCD versuche und das
frustet, wenn's nicht funktionieren will, zumal es ja nichts
weltbewegendes ist so ein 8x2 LCD anzusteuern.
Zum Programm:
cdc_task.c ist die Hauptroutine, habe das Beispiel von Atmel zu CDC
verwendet.
Vielleicht sollte ich auch mal den 8-bit Modus probieren...
Häh? wo ist bei deinem Code denn "main()" ? SOWAS: >> PORTD&=10001111; (aus "void Port_init_lcd(void)") klappt ja (wahrscheinlich ;) nicht. evtl. geht's aber so: > PORTD &= 0b10001111; obwohl es so lesbarer wäre
1 | #define EN 1<<PD4
|
2 | #define RS 1<<PD5
|
3 | #define RW 1<<PD6
|
4 | PORTD &= ~(EN|RW|RS);// loesche alle drei... |
Für die Fehlersucher ist der 'Programmers Notepad' (der Editor, der bei Winavr dabei ist) deutlich besser geeignet, als das AVR-Studio. ...und mit zusammenstreichen meinte ich eher sowas:
1 | //... Header etc.
|
2 | int main(void) |
3 | {
|
4 | Port_init_lcd(); |
5 | lcd_init(); |
6 | lcd_write_value('A'); /* hab ich geraten - die Funktion fehlt in |
7 | deinem Code , die Funktion muss RS setzen....*/
|
8 | while(1) |
9 | ;
|
10 | return 0; |
11 | }
|
hth. Jörg
>>>PORTD&=10001111; (aus "void Port_init_lcd(void)")
das war keine Absicht, passiert mir aber oft
das main() ist in einer anderen Datei, da steht watchdog und scheduler,
der dann init etc. aufruft
ich versuch's dann noch mal zusammenzustreichen, das mit dem notepad von
winavr hab' ich auch noch nicht probiert, werd ich gleich mal machen.
MfG Olli
Hab's jetzt auf das wesentliche beschränkt und ein paar Kommentare gemacht. Jetzt erscheint im Display nur an erster Position ein Zeichen(schwarzer Kasten im DB Zeichen mit 0b11111111) und der Cursor läuft durch ohne etwas zu schreiben!? Olli
Der Init-Fehler ist in dem Code aber auch nicht beseitigt :( > PORTD&=10001111; es soll doch vermutlich >> PORTF &= ~((1<<PF6)|(1<<PF5)|(1<<PF4)) heißen was man NOCH leserlicher schreiben könnte:
1 | // "lcd.h"
|
2 | #define LCD_EN (1<<PF4)
|
3 | #define LCD_RW (1<<PF5)
|
4 | #define LCD_RS (1<<PF6)
|
5 | #define LCD_PINS 0x0F
|
6 | //"lcd.c"
|
7 | void Port_init_lcd(void) |
8 | {
|
9 | DDRA |= LCD_PINS; |
10 | PORTA &= ~LCD_PINS; |
11 | |
12 | DDRF |= (LCD_EN|LCD_RW|LCD_RS); |
13 | PORTF &= ~(LCD_EN|LCD_RW|LCD_RS); |
14 | }
|
Im Prinzip kannst du auch gleich macros für die PORTS PINS DDR schreiben... Du hast nirgends erwähnt mit welcher Frequenz der AVR arbeitet -- sieht nach USB aus, also nehme ich mal an 12MHz? Die _delay_Xs()-Funktionen haben ja schließlich ein Limit, was z.B. bedeutet, dass du das 40ms delay als 2* _delay_ms(20) schreiben müsstest (bei 12MHz). Ich häng's mal an. hth. Jörg
Danke. Ja, ist eine USB-Anwendung bzw. USB als Virtueller ComPort. Der AVR arbeitet aber nur mit 8MHz. Gibt man den Takt für delay.h(F_CPU) eig. in kHz an, hab ich so gemacht.. #define F_CPU 8000 wenn das falsch ist... Auf dem LCD tut sich immer noch nix, manchmal passiert gar nix, oder es gibt "O" anstatt "A" aus. Ich werd wohl noch vier Leitungen dranhängen müssen. Kann es evtl. auch damit was zu tun haben, dass ich keinen busy-check mache wie es im Datenblatt geschrieben ist..irgendwelche timing-Sachen? Olli
Olli wrote: > arbeitet aber nur mit 8MHz. Gibt man den Takt für delay.h(F_CPU) eig. in > kHz an, hab ich so gemacht.. > #define F_CPU 8000 > wenn das falsch ist... Ja, das ist falsch. Der Takt wird in Hz angegeben #define F_CPU 8000000 Da du hier um einen Faktor 1000 falsch liegst, würde ich mal nicht darauf wetten, dass die _delay_xx Funktionen überhaupt irgendwelche sinnvollen Zeiten ermittelt haben.
Jap, das war's! Hab' zwar schon die Leitungen dran, die werd ich aber wohl nicht mehr brauchen(hoffentlich, wer weiß was da noch kommt) So'n Mist. Ich hab das eig. nur in kHz angegeben, weil's in der config.h bei meinem Beispielprog auch in kHz angegeben wurde und dachte, dass wäre die Standard-Angabe, naja man sollte bei sowas wohl immer auf Nummer sicher gehen und noch mal nachlesen. Vielen Dank an alle für die Hilfe! MfG Olli
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.