PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : LCD - Char übersenden ; Probleme mit _delay_ms();



CsMTEch
18.06.2014, 15:40
Hallo, ich bin es nochmal.

Ich wollte nun ein LCD ansteuern, die Initialisierung scheint auch geklappt zu haben, da das Display gelöscht wird und es scheinbar auch auf zweizeilig umgestellt wird. Demnach müsste ja alles richtig angeschlossen sein.

Nun wird aber aus "H a l l o W e l t" "J ° █ █ █ █ █ █ █ █". Die Anzahl der Zeichen stimmt also noch, aber es ist halt Humbug was da angezeigt wird...

Könnte das evtl am Code liegen?

Als erstes muss meines Wissens nach ja das höhere Nibble übertragen werden. Also selektiere ich erst nur die oberen 4 Bits (Bit 4-7). Das soll mit dieser Funktion geschehen:



int HigherNibble(char Char)
{
LCD_Port &= 0b00001111; //Alle Ausgänge für die Datenleitungen werden auf Low gesetzt
int Maske = Char;
Maske &= ~((1<<0)|(1<<1)|(1<<2)|(1<<3)); //Die unteren Datenleitungen werden in der Maske auf 0 gesetzt, damit sie nachher gleich bleiben
return Maske;
}


Nun muss das niedrigere Nibble übertragen werden, allerdings auch an den uC Pins PB.4 - PB.7. Also habe ich eine Funktion geschrieben, die die Nibbles vertauscht (in Assembler wäre das doch eigentlich "swap" oder?).



int LowerNibble(char Char)
{
int Counter = 0;
int Maske = 0;
int Compare = 0;
int Potenz;
LCD_Port &= 0b00001111; //Alle Ausgänge für die Datenleitungen werden auf Low gesetzt
while (Counter <= 3) // Sorgt für die 4 Durchgänge
{
Compare = Char; //Compare wird mit Char "gefüllt" um nach einem Durchlauf, diese Variable wieder auf den Anfangszustand zu setzen
Potenz = Potenzieren(2, Counter); //Durch das Potenzieren ereicht man die Masken, wo jeweils ein Bit auf 1 ist
Compare &= Potenz; //Selektiert einen Bit von Compare also 0, 1, 2 oder 3
if(Compare != 0)
{
Maske |= (1 << (Counter+4)); //Wenn dieser Bit an ist schreibe eine 1 an die entsprechende Stelle des höheren Nibbles
}

Counter++;
}
Maske &= ~((1<<0)|(1<<1)|(1<<2)|(1<<3)); //Die unteren Datenleitungen werden in der Maske auf 0 gesetzt, damit sie nachher gleich bleiben
return Maske;
}


Dazu gehört noch die Funktion Potenzieren;

int Potenzieren(int Basis, int Exponent)
{
int Ergebnis = 1;
while(Exponent>0)
{
Ergebnis = Ergebnis*Basis;
Exponent--;
}
return Ergebnis;
}

Die Nibbles werden dann nacheinander in der Funktion LCD_Char übertragen:

void LCD_Char(char Char)
{
LCD_Port |= (1<<2); //RS = 0
LCD_Port |= LowerNibble(Char);
LCD_Enable(); //Setzt E kurz auf ein 1 dann wieder auf 0
_delay_ms(20);
LCD_Port |= HigherNibble(Char);
LCD_Enable(); //Setzt E kurz auf ein 1 dann wieder auf 0
_delay_ms(20);
}

Weiß jemand wo da ein Fehler sein könnte oder woran es noch liegen könnte? ._.

Und noch was... :
Es gibt ja schon viele Threads zu Problemen mit _delay_ms(), aber zu meinem habe ich noch keinen gefunden.
Ich benutze einen ATMega32 der ja eigentlich eine Frequenz von 16 mHz besitzt. Dieses lege ich mit #define F_CPU 16000000UL fest. Nun dauert _delay_ms(1000) aber um das achtfache zu langsam. Schreibe ich _delay_ms(125) oder achtel ich Frequenz (#define F_CPU 2000000UL) dauert die Wartezeit 1 Sekunde (nicht genau gemessen). Hätte da jemand eine Lösung für?

Vielen Dank im Voraus und ich hoffe auf baldige Antwort!

LG Ulf

Hubert.G
18.06.2014, 15:51
Ob dein Mega32 mit 16MHz läuft oder mit anderer Frequenz, legst du nicht mit #define F_CPU 16000000UL fest. Hier teilst du die Frequenz nur deinem Programm mit.
Für 16MHz brauchst du einen Quarz oder Quarzoszillator und die entsprechenden Einstellungen der Fuses.

CsMTEch
18.06.2014, 16:05
Ob dein Mega32 mit 16MHz läuft oder mit anderer Frequenz, legst du nicht mit #define F_CPU 16000000UL fest. Hier teilst du die Frequenz nur deinem Programm mit.
Für 16MHz brauchst du einen Quarz oder Quarzoszillator und die entsprechenden Einstellungen der Fuses.

OK, das erklärt schon mal das eine Problem :)

Vielen Dank!

Siad
19.06.2014, 07:03
Irgendwie check ich nicht was du da machen willst. :-k
*Wenn du mit chars arbeitest, dann arbeite auch mit chars und mische nicht int und char.
*Die delays kommen mir teilweise irgendwie (zu) hoch vor.
*Verarbeite deinen char in einer Funktion, und greife auf den port in einer anderen zu. So verliert man nicht die Übersicht. Bei dir scheint das alles irgendwie vermischt zu sein und es ist nicht ganz klar was du wo machst.

Bei mir schaut das senden eines char an einen HD44780 im 4 bit Modus so aus:


#define LCD_DATA_PORT PORTB
#define LCD_DB7 PB5
#define LCD_DB6 PB4
#define LCD_DB5 PB3
#define LCD_DB4 PB2
#define LCD_E_PORT PORTB
#define LCD_E PB1
#define LCD_RS_PORT PORTB
#define LCD_RS PB0
....

void lcdShowChar(unsigned char show_ch)
{
LCD_RS_PORT |= (1 << LCD_RS);
lcdSendNibble(show_ch >> 4);
lcdSendNibble(show_ch);
_delay_us(40);
}

void lcdSendNibble(unsigned char nibble)
{
LCD_DATA_PORT &= ~(1 << LCD_E) & ~(1 << LCD_DB4) & ~(1 << LCD_DB5)
& ~(1 << LCD_DB6) & ~(1 << LCD_DB7);

LCD_E_PORT |= (1 << LCD_E);
LCD_DATA_PORT |= ((nibble & 0x01) << LCD_DB4);
nibble >>= 1;
LCD_DATA_PORT |= ((nibble & 0x01) << LCD_DB5);
nibble >>= 1;
LCD_DATA_PORT |= ((nibble & 0x01) << LCD_DB6);
nibble >>= 1;
LCD_DATA_PORT |= ((nibble & 0x01) << LCD_DB7);
LCD_E_PORT &= ~(1 << LCD_E);
}

Vielleicht hilft dir das etwas. Geht aber sicher auch schöner und man könnte den PORT auch auf einmal mit einer Maske beschreiben als den char jedesmal um 1 zu verschieben. Wenn ich das nächste mal ein lcd brauche werde ich das auch wahrscheinlich dahingehend abändern.

CsMTEch
23.06.2014, 21:23
Ich hab jetzt den Tipp, bei den Chars zu bleiben, ausprobiert und siehe da, alles funktioniert :) jetzt noch LCD_String(); schreiben und das LCD ist abgehakt \\:D/

Vielen Dank =D&gt;

Ulf