Hallo liebe Profis.
nachdem ich mich durch die Tiefen des Internets gewühlt habe, frage ich
nun hier mal um Hilfe:
Ich habe ein 16x4 Display(Datenblatt siehe Anhang) und möchte dieses
gerne an einem ATMEGA32 betreiben, im 4 Bit Modus.
Da ich absolute Anfängerin bin, habe ich mich an das Tutorial auf der
folgenden Website gehalten und den Code fürs erste 1:1 übernommen:
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/LCD-Ansteuerung
Auch bei der Anschlussbelegung des Displays habe ich mich genau an das
Tutorial gehalten.
Nun habe ich das Programm auf meinen Mikrocontroller geladen. Ohne
Programm zeigt das Display einen schwarzen Balken in Zeile 1 und 3. Mit
Programm zeigt es nun in jeder Zeile einen Balken, aber nicht den im
Beispiel erwähnten Text.
Ich habe mich bereits auf eine Fehlersuche begeben und denke, dass der
Fehler im header file in der Variablen LCD_FUNCTION_2LINE =0x08 steckt,
denn diese sagt ja dem Display: Du bist ein 2 zeiliges Display.
Wie kann ich ihm nun sagen, dass es ein 4 zeiliges Display ist?
Oder muss ich die Initialisierungs Methode ändern?
Ich hoffe ihr könnt mir helfen!
Liebe Grüße
Starfire
Hatte letzthin ein 4x20 Zeilen.
Musste die Startadressen der Zeilen anpassen.
Und beim KS0066 dreimal die erste Initialisierung aufrufen.
Habe den Code nicht zur Hand.
Nun habe ich die Initialisierung 3 mal aufgerufen, so im Sinne von:
lcd_init();
warte 30ms
lcd_init();
warte 30ms
lcd_init();
warte 30ms
nun werden meine Felder nicht mehr dunkel angeeigt, sondern nur das Feld
in Zeile 0 Spalte 0 und in Feld Zeile 0 Spakte 1 2 3 sowie in Feld Zeile
1 Spalte 2 werden random zeichen angzeigt. immerhin ein Fortschritt....
weitere Ideen?
Also wenn du sagst, dass in allen 4 Zeilen die schwarzen Balken zu sehen
sind, dann ist immerhin die Initialisierung schonmal erfolgreich
gewesen.
Das Kontrastpoti hast du auch schonmal runter gestellt.
Nun ist die Frage offen, ob dein Display zu dem Code passt. Daher musst
du mal schauen ob die Controller kompatibel sind. Ansonsten mal sehen
was geändert werden muss.
Nur so ein Hüftschuss, ohne den Code zu kennen:
Könnte es sein, dass Deine waitschlaufen zu schnell sind, weil Dein
Prozi höher getaktet ist als in der Software angenommen? Ich denke mal,
das sollte auch im Headerfile anzupassen sein.
Simon Huwyler schrieb:> Könnte es sein, dass Deine waitschlaufen zu schnell sind, weil Dein>> Prozi höher getaktet ist als in der Software angenommen? Ich denke mal,>> das sollte auch im Headerfile anzupassen sein.
Hallo Simon,
leider kann ich mit dieser Antwort nichts anfangen. Was soll höher
getaktet sein? Ich nutze keinen Quarz, sondern den internen Takt.
Ich habe mal in den Link geschaut. Leider nur sehr kurz (mangels Zeit).
Gell, Hardware-Initialisierungen sind in diesem Beispiel keine drin,
oder? Die Ports scheinen aber initialisiert zu sein, zumal es zumindest
etwas tut.
Wie schnell taktest Du den Prozi denn? Ich kenne AVR zwar gar nicht,
aber ich nehme doch sehr stark an, dass auch bei interner Taktung
beliebige Taktraten möglich sind. Und davon ist dann wieder so ein
delay_ms abhängig.
Ich habe eine Frequenz von 3686400 eingestellt, falls du das meinst.
Bei der Optimierung habe ich die Option -Os ausgewählt, so wie es in dem
Tutorial steht.
Starfire schrieb:> Ich habe eine Frequenz von 3686400 eingestellt, falls du das meinst.> Bei der Optimierung habe ich die Option -Os ausgewählt, so wie es in dem> Tutorial steht.
Kann mich nicht erinnern das man diese Frequenz einstellen kann. Versuch
mal lieber 1000000UL oder 8000000UL.
> Was soll höher getaktet sein? Ich nutze keinen Quarz,> sondern den internen Takt.> Ich habe eine Frequenz von 3686400 eingestellt
Das beißt sich. Du kannst nicht 3686400 am Mega32 eingestellt haben.
Diese Möglichkeit gibt es dort nicht.
In deinen Code kannst du für F_CPU alles mögliche reinschreiben. Das
bedeutet noch lange nicht, dass der µC dann auch mit der Frequenz läuft.
F_CPU ist eine Information für den Compiler, wie schnell der µC läuft.
Mehr nicht.
Hi,
Ich habe jetzt in meinem Quellcode in der Lcd_routines.h eingestellt:
#ifndef F_CPU
#define F_CPU 1000000UL
#endif
außerdem habe ich in der Konfiguration die Frequenz auf 1000000
geändert. Trotzdem werden auf meinem Display weiterhin kryptische
Zeichen angezeigt.
Karl Heinz Buchegger schrieb:> Das beißt sich. Du kannst nicht 3686400 am Mega32 eingestellt haben.>> Diese Möglichkeit gibt es dort nicht.>>>> In deinen Code kannst du für F_CPU alles mögliche reinschreiben. Das>> bedeutet noch lange nicht, dass der µC dann auch mit der Frequenz läuft.>> F_CPU ist eine Information für den Compiler, wie schnell der µC läuft.>> Mehr nicht.
Wo stelle ich dann aber die richtige Frequenz ein? Ich habe rechtsklick
auf das Pojekt gemacht, dann auf "Edit Configuration Options" und dort
dann eine Frequenz eingestellt... In AVR Studio
War das richtig? Oder muss ich meinem Code noch was hinzufügen?
> Wo stelle ich dann aber die richtige Frequenz ein? Ich habe rechtsklick> auf das Pojekt gemacht, dann auf "Edit Configuration Options" und dort> dann eine Frequenz eingestellt... In AVR Studio> War das richtig? Oder muss ich meinem Code noch was hinzufügen?
Das kann man mit den Fuses machen, aber lass da erstmal lieber die
Finger von, das macht bei Anfängern nur Probleme, weil wenn man die
falsche Frequenz einstellt, kann man sich ausm Controller ausperren und
man kommt nicht mehr so leicht rein.
Am besten ist du schaust nach welche Frequenz standartmäßig gefused ist.
Ist oft 1 oder 8 MHz. Überprüfen kannst du es mit einer Led die du
toggelst mit einem _delay_ms(500); oder sowas. Dann sollte die Led ca.
1x pro Sekunde blinken. Dann hast ungefähr die richtige Frequenz.
Hier mal ein Auszug aus dem Datasheet:
>The default clock source setting is>therefore the 1MHz Internal RC Oscillator with longest startup time.
Also musst du für F_CPU 1000000UL einstellen. Das UL gibt an das es sich
um einen unsigned long Typ handelt.
Starfire schrieb:> Wo stelle ich dann aber die richtige Frequenz ein? Ich habe rechtsklick> auf das Pojekt gemacht, dann auf "Edit Configuration Options" und dort> dann eine Frequenz eingestellt...
Das ist nichts anderes als die F_CPU Einstellung. Nur das man sie nicht
direkt im Code macht.
> In AVR Studio> War das richtig? Oder muss ich meinem Code noch was hinzufügen?
Das hat mit Code nichts zu tun.
Um den µC umzustellen, musst du an die Fuse-Bits rann. Die
Einstellmöglichkeiten finden sich im Brennprogramm (zumindest war das in
AVR-Studio 4 noch so)
Hi mr. mo,
ich hatte gerade unter fuses nachgesehen:
dirt steht SUT_CKSEL: Int. RC Osc. 1MHz; Start-up time: 6CK+64ms;
default value
Es scheint also ein Takt von 1MHz eingestellt zu sein...
Sorry habe grad keine LED zur Hand
Aber wenn dein Display jetzt initialisiert, dann ist diese Phase schon
vorbei. Es liegt dann nicht mehr am Timing.
Wenn du falsche Zeichen bekommst, dann überpüf noch mal die Verkabelung
der Datenleitungen. Scheinbar hast du dort irgendwelche Leitungen
vertauscht.
Gib nur in der ersten Zeile den Text "abcdefgh" aus. Und dann zeig uns,
was statt dessen am LCD steht. Dann kann man durch Bitvergleich
identifizeren, welche Leitungen du vertauscht hast, wenn du selber den
Fehler nicht findest.
Starfire schrieb:> Hi mr. mo,>> ich hatte gerade unter fuses nachgesehen:> dirt steht SUT_CKSEL: Int. RC Osc. 1MHz; Start-up time: 6CK+64ms;> default value> Es scheint also ein Takt von 1MHz eingestellt zu sein...>> Sorry habe grad keine LED zur Hand
Ok dann ist alles auf Werkseinstellung.
Als nächsten Schritt hätte ich einen ähnlichen wie Karl Heinz Buchegger
vorgeschlagen.
Dr.Kurzschluss schrieb:> Wie lang ist denn das Kabel zwischen Display und µC?
5-7 cm ca.
Karl Heinz Buchegger schrieb:> Gib nur in der ersten Zeile den Text "abcdefgh" aus. Und dann zeig uns,>> was statt dessen am LCD steht. Dann kann man durch Bitvergleich>> identifizeren, welche Leitungen du vertauscht hast, wenn du selber den>> Fehler nicht findest.
Ich habe jetzt den Code so geändert:
lcd_data('a');
lcd_data('b');
lcd_data('c');
lcd_data('d');
Als Ergebnis Zeigt das Display nun in der ersten Zeile:
(ich werde immer die schwarzen Punkte hinschreiben)
Feld 0: voll ausgemaltes Feld (schwarz)
Feld 1: 0;0 schwarz 0;4 schwarz
1;0 schwarz; 1;2 schwarz; 1;4 schwarz
2;0 schwarz; 2;2 schwarz
3;0 schwarz; 3;2 schwarz; 3;4 schwarz
4;0 schwarz; 4;2 schwarz; 4;4 schwarz
5;0 schwarz; 5;2 schwarz; 5;4 schwarz
6;0 schwarz; 6;2 schwarz; 6;4 schwarz
7;0 schwarz; 7;3 schwarz; 7;4 schwarz
Feld 2: analog Feld 1
Feld 3: analog Feld 1
Feld4: 0;1 schwarz; 0;3 schwarz
1;1 schwarz; 1;3 schwarz
2;1 schwarz; 2;3 schwarz
Feld 5: blinkender Cursor
> Als Ergebnis Zeigt das Display nun in der ersten Zeile:> (ich werde immer die schwarzen Punkte hinschreiben)
Bitte beschreibs nicht.
Mach ein Photo oder identifiziere das Zeichen in dieser Tabelle
(Das müssen wir dann nämlich auch tun, wenn wir dein Photo haben)
http://de.wikipedia.org/wiki/HD44780#Schrift_und_Zeichensatz
?
Ist ja interessant. Sieht so als als ob da die Benutzerdefinierten
Zeichen gekommen wären. Die Zeichen gibt es tatsächlich nicht im
Zeichensatz.
Irgendwer welche Ideen?
Kannst du noch ein Photo von deiner Verkabelung machen?
(Aber diesmal bitte nicht wieder 1.1Mb. Und wenn die Datei dann auch
noch die korrekte Endung .jpg hätte wär das wunderbar. Denn dann kann
man sie direkt ohne Klimmzüge aufmachen. Danke)
Probier' das mal aus:
Beitrag "Re: Das LCD-Problem / Lösungsansatz"Starfire schrieb:> Ich habe mich bereits auf eine Fehlersuche begeben und denke, dass der> Fehler im header file in der Variablen LCD_FUNCTION_2LINE =0x08 steckt,> denn diese sagt ja dem Display: Du bist ein 2 zeiliges Display.> Wie kann ich ihm nun sagen, dass es ein 4 zeiliges Display ist?
Die Register im DB scheinen mir nicht mit dem Code kompatibel.
Ersetze mal:
1
lcd_command(LCD_SET_FUNCTION|
2
LCD_FUNCTION_4BIT|
3
LCD_FUNCTION_2LINE|
4
LCD_FUNCTION_5X7);
gegen:
1
lcd_command(LCD_SET_FUNCTION);
Das dürfte ausreichen, die anderen Register hab' ich jetzt noch nicht
verglichen.
MWS schrieb:> Ersetze mal: lcd_command( LCD_SET_FUNCTION |>> LCD_FUNCTION_4BIT |>> LCD_FUNCTION_2LINE |>> LCD_FUNCTION_5X7 );>>>> gegen: lcd_command( LCD_SET_FUNCTION);>>>> Das dürfte ausreichen, die anderen Register hab' ich jetzt noch nicht>> verglichen.
Hallo MWS,
das habe ich gemacht, hat aber keine Veränderung erbracht. Ich habe eben
meinen Schaltplan durchgeschaut, der stimmt mit den Vorgaben des
Tutorials überein. Werde aber jetzt mal in die Werkstatt düsen um zu
schauen ob ich mich nicht bei der Verkabelung vertan hab und auch ein
Foto davon machen (obwohl ich bezweufle das das bei meinen mangelnden
Lötkünsten hilfreich ist).
Starfire schrieb:> das habe ich gemacht, hat aber keine Veränderung erbracht.
Wenn das noch nicht hilft, ist es möglich daß in den anderen Registern
auch andere Bits zuständig sind, da müsste man nach DB alles vergleichen
und anpassen.
Wenn Du immerhin eine kryptische Anzeige bekommst, versuch doch mal auf
den zweiten Zeichensatz zu schalten.
Liebe Community,
ich muss wohl betrunken gewesen sein, als ich Display und Controller
miteinander verbunden habe. Ich habe 6(!) Kabel miteinander vertauscht
O_o
Ich möchte euch allen ganz vielmals für eure Hilfe danken, der Fehler
ist behoben :D
DANKE DANKE DANKE
Starfire
Starfire schrieb:> Liebe Community,>> ich muss wohl betrunken gewesen sein, als ich Display und Controller> miteinander verbunden habe. Ich habe 6(!) Kabel miteinander vertauscht> O_o
Das grenzt schon fast an ein Wunder, das du es damit durch die
Initialisierungsphase gebracht hast.
Starfire schrieb:> Ich habe 6(!) Kabel miteinander vertauscht
Eins links, eins rechts, eins fallenlassen :D
> Ich möchte euch allen ganz vielmals für eure Hilfe danken, der Fehler> ist behoben
Das ist schön, vielleicht magst Du aber dem Leser, der sich später
einmal diesen Thread ansieht, noch sagen mit welchem Code jetzt genau
das LCD läuft. Dann hat das einen bleibenden Nutzen für Andere.
Denn während diese Defines hier passen, Bit "DL":
#define LCD_FUNCTION_4BIT 0x00
#define LCD_FUNCTION_8BIT 0x10
So spricht das hier mit 0x00 = 5x7 Zeichen an, oder 0x08 = 5x10, Bit "N"
#define LCD_FUNCTION_1LINE 0x00
#define LCD_FUNCTION_2LINE 0x08
Dies hier wählt dagegen den Zeichensatz Englisch / Japanisch aus, Bit
"F"
#define LCD_FUNCTION_5X7 0x00
#define LCD_FUNCTION_5X10 0x04
Hallo ihr Süßen,.
ich habe mal weiter gebastelt und bin auf ein erneutes Problem gestoßen
:)
Mein Display zeigt nun Texte an. Es soll jetzt dazu auf Tastendrücke
reagieren. Das Gerät hat 5 Tasten (rauf runter, links, rechts und OK).
Es gibt keine externen Pull-up Widerstände. Die Tasten sind mit PC0 bis
PC4 erbunden (die Hardware hab ich diesmal schon vorher kontrolliert
:D). Falls es jemanden interessiert: Schaltplan ist im Anhang.
Im folgenden nun der Code:
1
#include<avr/io.h>
2
#include"lcd_routines.h"
3
#include<util/delay.h>
4
#include<stdlib.h>
5
6
intmain(void)
7
{
8
9
DDRC=0b11100000;//Pin 0 bis 4 sind Eingänge, dort hängen die Tasten
10
PORTC=0b00011111;//Alle Tasten sind default mäßig auf 1, werden sie
11
//gedrückt, dann gehen sie auf 0.
12
13
// Initialisierung des LCD
14
// Nach der Initialisierung müssen auf dem LCD vorhandene schwarze Balken
15
// verschwunden sein
16
lcd_init();
17
18
lcd_string("* Pruefgeraet *");
19
lcd_setcursor(0,2);
20
lcd_string("* fuer *");//Zeige den Begrüßungstext
21
lcd_setcursor(0,3);
22
lcd_string("* Sensoren *");
23
lcd_setcursor(0,4);
24
lcd_string("****************");
25
26
_delay_ms(3000);
27
28
lcd_clear();
29
lcd_setcursor(0,1);//Hauptmenü
30
lcd_string(" Hauptmenue ");
31
lcd_setcursor(0,2);
32
lcd_string("Eingabe SNR");
33
lcd_setcursor(9,3);
34
lcd_string("-> \"OK\"");
35
36
_delay_ms(1000);
37
38
39
40
while(1)
41
{
42
uint8_ti=PINC;//Es muss an jedem Anfang der Schleife
43
//abgefragt werden wie NUN die Taster gedrückt sind
44
45
if(i==(i&0b00011011))//OK wuede gedrückt
46
{
47
lcd_setcursor(0,4);
48
lcd_string("TEST");
49
}
50
51
52
return0;
53
}
54
}
Man sieht also: nach den einfachen Texten oben soll PIN C abgefragt
werden und dann darauf reagiert werden.
jetzt kommt das komische: Es wird immer TEST in zeile 4 geschrieben,
d.h. der PIN hat schon die Belegung 00011011, obwohl NICHTS gedrückt
wurde. Warum ist das so?
uint8_t i = PINC; //Es muss an jedem Anfang der Schleife
//abgefragt werden wie NUN die Taster gedrückt sind
if(i == (i&0b00011011)) //OK wuede gedrückt
spiel mal ein paar werte durch
i = 0
-> if (0 == (0 & 0b00011011))
-> wird wahr
i = 1
-> if (1 == (1 & 0b00011011))
-> wird wahr
usw..
es wird also bei vielen Werten die Bedingung erfüllt.
Ist es das, was du willst?
Ja, ich habe mehrere Werte durchgespielt und einige liefern 1 und andere
nicht... was müsste ich tun. damit nur bei i == 00011011 eine 1
geliefert wird?
Der PORTC hat die Pins für den JTAG (PC2..PC5), dieser ist per default
bei dem ATmega32 enabled. D.h. Du kannst die Pins nicht so einfach für
Deine Anwendung verwenden. Entweder lege die Tasten an einen anderen
Port (was ich Dir empfehlen würde), oder Du mußt den JTAG in den Fuses
abschalten.
Wie schon oben geschrieben, fasse die Fuses am besten erstmal nicht an.
Lieber Stefan,
ich verstehe zwar nicht so ganz genau was die von dir vorgeschalgene
Lösung bedeutet, habe es aber ausprobiert und es komt zum selben
ergebnis: es wird in die if Anweisung gesprungen, obwohl kein Knopf
gedrückt wurde.
while(1)
{
uint8_t i = PINC;
//Es muss an jedem Anfang der Schleife
//abgefragt werden wie NUN die Taster gedrückt sind
// gute idee! nur würde ich das nicht wirklich PINC nennen
// aber seisdrumm...
// eventuell mehrfach lesen, addieren und dividieren des PORTInputs
// zur Vermeidung von Prellungen...
// if(i == (i&0b00011011)) //OK wuede gedrückt
i = i & 00011111) // entferne nicht angeschlossenes
if ( i != 0 ){
/*
so, wenn wir hier angekommen sind, kann man annehmen, daß
mindestens eine Taste gedrückt wurde.
Jetzt muss man anhand des Bitmusters entscheiden, welche das sind.
*/
Ich habe den Text nun wie folgt geändert:
Weiterhin habe ich JTAG im AVR Studio ausgeschaltet (unter Fuses, dort
wo man auch das Programm hochlädt).
Leider wird immer noch der Text angezeigt, obwohl kein Knopf gedrückt
wurde.
Lieber Volkmar,
ich habe deinen Post von um 12:09 Uhr gelesen.
Leider erlaubt es meine Schaltung nicht, die Schalter woanders
hinzulegen....
PORTA ist voll, dort muss ich mehrere Signale aufnehmen
An PORTD sitzt mein Display,
und an PortB wäre zwar wg. der ISP noch was frei, aber ich habe nicht
mehr genügend Leiterbahnen auf der Platine um das umzubauen.
Deshalb habe ich wie oben erwähnt JTAG unter Fuses abgeschaltet.
Völlig richtig, es möge doch mal binäre dessen ausgegeben werden, was
eingelesen wird. Hier kann man dann feststellen, zB ob überhaupt gelesen
wird und wenn ja, was.
++++++++++++++++++++++++++++++++++++++
Definiere eine testvariable =0
setze diese auf null
lese den Port ein in i
do{
subtrahiere EINS von i
incrementiere testvariable}
until (testvariable ==0)
unsigned char a = itoa (testvariable);
lcd_setcursor(0,4);
lcd_string(testvariable);
end
R. Freitag schrieb:> do{>> subtrahiere EINS von i>> incrementiere testvariable}>> until (testvariable ==0)>>>> unsigned char a = itoa (testvariable);>> lcd_setcursor(0,4);>> lcd_string(testvariable);>> endBeitrag melden | Bearbeiten | Löschen |
Macht das sinn?
Ich rechne "immer" i=i-1 und testvariable =testvariable +1
bis Testvariable ==0... aber testvariable kann so niemals 0 sein, oder?
Hallo,
Starfire schrieb:> (die Hardware hab ich diesmal schon vorher kontrolliert :D)
ich frage trotzdem noch mal nach, da Du ja JTAG jetzt abgeschaltet hast
(vielleicht kannst Du ja sicherheitshalber einen Screenshot von den
Fuses anhängen?). Hast Du an diesem Pin mal die Spannung gemessen? Liegt
dort wirklich ca. 5V wie bei den anderen Taster-Eingängen an? Und ändert
sich diese auf ca. 0V wenn Du den Taster drückst?
Hi,
ich habe sowohl R.s Teil mal einprogrammiert (es lieferte 1) als auch
Karl Heinz seins (Es wird bei keinem Knopfdruck etwas angezeigt).
Als nächstes werde ich denke ich mal Volkmars Tipp versuchen, und das
ganze mal durchmessen. Leider hat das Labor schon zu (Programmiere im
Büro) und ich werde Montag bis Mittwoch auf Geschäftsreise sein, weshalb
das wohl mein nächstes Task für Donnerstag sein wird.
Ich danke euch allen für eure Hilfe, wenn ich könnte würde ich euch
Kuchen backen!!!!!
<3
Melde mich dann wieder sobald es neues gibt!
Eure
Starfire
Starfire schrieb:> Hi,>> ich habe sowohl R.s Teil mal einprogrammiert (es lieferte 1) als auch> Karl Heinz seins (Es wird bei keinem Knopfdruck etwas angezeigt).
OK.
Dann check noch mal dein JTAG> Als nächstes werde ich denke ich mal Volkmars Tipp versuchen, und das> ganze mal durchmessen. Leider hat das Labor schon zu (Programmiere im> Büro)
1
intmain()
2
{
3
charBuffer[20];
4
5
...
6
DDRC=0x00;
7
PORTC=0x04;
8
9
...
10
11
while(1)
12
{
13
utoa(PINC,Buffer,2);
14
lcd_setcursor(0,4);
15
lcd_string(Buffer);
16
}
17
}
du siehst den Zustand deiner Portbits als 0-en und 1-en
Wenn du auf die Tasten drückst, muss sich was ändern.
ungedrückt muss für jede Taste ein 1 Bit da sein und wenn du
draufdrückst muss das auf 0 gehen.
Wenn nicht:
* entweder stimmt an der Verkabelung was nicht und deine Tasten
sind nicht an C
* oder aber dein JTAG ist noch immer eingeschaltet.
Hallo,
ich habe mal einige Dateien angehängt. Eine Keyboard Routine für eine
4x4 Matrix und eine LCD Routine für dein Display. Ich habe diese auch
sehr lange benutzt, bis ich auf DIP und DOGM Grafikdisplays umgestiegen
bin. Die LCD Routine sollte im 4 Bit Modus laufen.
Vielleicht hilft es.