mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Reset verhalten MEGA8


Autor: Anton (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich hätte nochmal eine kurze frage.

Nach drücken der Reset Taste an meinem Mega 8 stellt sich 
unterschiedliches verhalten bezüglich eines LCD dar.
Es ist ein HD447 kompatibles display.

Nach Reset Funktioniert es meist. Leider tritt ab und zu ein Fehler auf, 
sodass das Display initialisiert, aber der Cursor nicht blinkt.
Teilweise bleiben zeichen stehen.


Woran könnte das liegen? Muss das Display ebenso, wie der uc 
ausgeschaltet werden, damit es richtig funktioniert?

Vielen dank

Autor: Klaus De lisson (kolisson)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>> Muss das Display ebenso, wie der uc
>> ausgeschaltet werden, damit es richtig funktioniert?

Na dann sieht man wenigstens die Fehler nicht mehr.


Takt ? Software ? Beschaltung ?

Gruss K

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

Sieht nach einer zu kurzen Wartezeit vor der Initialisierung aus.

MfG Spess

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Unvollständige Initialisierung, Du setzt zu Anfang nicht korrekt in den 
8Bit-Modus zurück. Die Sequenz im Datenblatt enthält nicht umsonst 
"überflüssige" Befehle.

8Bit-Kommandos im 4Bit-Modus oder sogar auf dem falschen Nibble, geht 
schief.


Peter

Autor: Anton (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Okay,

also hier mal der Code für die initialisierung. An Port D habe ich eine 
LED hängen. Damit ich sehe, dass erst ein paar mal geblinkt wird, bevor 
das LCD initialisiert wird.

leider erscheint danach kein cursor.
Trotz beseitigung meines verdrahtungsfehlers.
R/W liegt auf GND.
Aktuell ist der interne 1mhz takt aktiviert (per fuses).

Code:

#include <avr/io.h>
  #define F_CPU 1000000UL
#include <util/delay.h>



int main(void){
int i=0;
DDRC=0xff;
PORTC=0x00;
DDRD=0xff;
PORTD=0b00100000;
for(i=0;i<5;i++){
PORTD^=(1<<5);
_delay_ms(200);
}


PORTC=0b00000011;
_delay_ms(1);
PORTC|=(1<<4);
_delay_ms(1);
PORTC&=~(1<<4);
_delay_ms(100);

PORTC=0b00000011;
_delay_ms(1);
PORTC|=(1<<4);
_delay_ms(1);
PORTC&=~(1<<4);
_delay_ms(50);

PORTC=0b00000011;
_delay_ms(1);
PORTC|=(1<<4);
_delay_ms(1);
PORTC&=~(1<<4);
_delay_ms(50);

/*4 bit*/
PORTC=0b00000010;
_delay_ms(1);
PORTC|=(1<<4);
_delay_ms(1);
PORTC&=~(1<<4);
_delay_ms(50);




/*2 Zeilen*/
PORTC=0b00000010;
_delay_ms(1);
PORTC|=(1<<4);
_delay_ms(1);
PORTC&=~(1<<4);
_delay_ms(50);

PORTC=0b00001000;
_delay_ms(1);
PORTC|=(1<<4);
_delay_ms(1);
PORTC&=~(1<<4);
_delay_ms(50);

/*display aus*/
PORTC=0b00000000;
_delay_ms(1);
PORTC|=(1<<4);
_delay_ms(1);
PORTC&=~(1<<4);
_delay_ms(50);

PORTC=0b00001000;
_delay_ms(1);
PORTC|=(1<<4);
_delay_ms(1);
PORTC&=~(1<<4);
_delay_ms(50);

/*löschen*/
PORTC=0b00000000;
_delay_ms(1);
PORTC|=(1<<4);
_delay_ms(1);
PORTC&=~(1<<4);
_delay_ms(50);
PORTC=0b00000001;
_delay_ms(1);
PORTC|=(1<<4);
_delay_ms(1);
PORTC&=~(1<<4);
_delay_ms(50);

/*cursor rechts shift*/
PORTC=0b00000000;
_delay_ms(1);
PORTC|=(1<<4);
_delay_ms(1);
PORTC&=~(1<<4);
_delay_ms(50);
PORTC=0b00000110;
_delay_ms(1);
PORTC|=(1<<4);
_delay_ms(1);
PORTC&=~(1<<4);
_delay_ms(50);




/*einschalten*/
PORTC=0b00000000;
_delay_ms(1);
PORTC|=(1<<4);
_delay_ms(1);
PORTC&=~(1<<4);
_delay_ms(50);
PORTC=0b00001100;
_delay_ms(1);
PORTC|=(1<<4);
_delay_ms(1);
PORTC&=~(1<<4);
_delay_ms(50);



while(1){
PORTD^=(1<<5);
_delay_ms(1000);

};
return 0;
}

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mit dem Code macht es echt keinen Spass, da Fehlersuche zu betreiben.

Das ist ein Spaghetticode erster Güte.
Schau doch mal ins Tutorial, wie man das richtig macht.

http://www.mikrocontroller.net/articles/AVR-GCC-Tu...


PS: Nachdem du das LCD auf 4-Bit Modus umgestellt hast, musst du jedes 
Byte (auch die nachfolgenden Konfigurationsbytes) als 2 Nibbles 
übertragen. Ich kann das in deinem Code nicht erkennen, muss aber 
zugeben auch nicht so genau analysiert zu haben.

Autor: Anton (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo, entschuldige bitte,

ich hatte mir erlaubt, das ganze zusammenzufassen.
Hier die Version, die ich zu Anfang hatte.

Darin ist erstmal das Initialisieren enthalten.


#include <avr/io.h>
  #define F_CPU 16000000UL
#include <util/delay.h>
/*PORT B für Display*/
/*R/W auf GND*/

#define EN 4
#define RS 5
#define D4 0
#define D5 1
#define D6 2
#define D7 3

void wartefunktion(void){
_delay_ms(500);


void einschalt_verzoegerung(void){

wartefunktion();

}

void display_loeschen(void){
PORTB=(0<<EN)| (0<<RS)|(0<<D4)|(0<<D5)|(0<<D6)|(0<<D7);
//PORTB=0b00000000;
_delay_us(10);
PORTB|=(1<<EN);
_delay_us(10);
PORTB&=~(1<<EN);
_delay_us(10);

PORTB=(0<<EN)| (0<<RS)|(1<<D4)|(0<<D5)|(0<<D6)|(0<<D7);
//PORTB=0b00000001;
_delay_us(10);
PORTB|=(1<<EN);
_delay_us(10);
PORTB&=~(1<<EN);
_delay_ms(20);
}
void cursor_rechts(){
PORTB=(0<<EN)| (0<<RS)|(0<<D4)|(0<<D5)|(0<<D6)|(0<<D7);
//PORTB=0b00000000;
_delay_us(20);
PORTB|=(1<<EN);
_delay_us(20);
PORTB&=~(1<<EN);

_delay_us(20);
PORTB=(0<<EN)| (0<<RS)|(0<<D4)|(1<<D5)|(1<<D6)|(0<<D7);
//PORTB=0b0000011;
_delay_us(20);
PORTB|=(1<<EN);
_delay_us(20);
PORTB&=~(1<<EN);
_delay_ms(20);
}

void display_ein(void){
PORTB=(0<<EN)| (0<<RS)|(0<<D4)|(0<<D5)|(0<<D6)|(0<<D7);
//PORTB=0b00000000;
_delay_us(20);
PORTB|=(1<<EN);
_delay_us(20);
PORTB&=~(1<<EN);
_delay_us(20);

PORTB=(0<<EN)| (0<<RS)|(1<<D4)|(1<<D5)|(1<<D6)|(1<<D7);
//PORTB=0b00001111;
_delay_us(20);
PORTB|=(1<<EN);
_delay_us(20);
PORTB&=~(1<<EN);
_delay_us(20);
}
void display_aus(void){ //wartezeiten hier wichtig!
PORTB=(0<<EN)| (0<<RS)|(0<<D4)|(0<<D5)|(0<<D6)|(0<<D7);
//PORTB=0b00000000;
_delay_us(20);
PORTB|=(1<<EN);
_delay_us(20);
PORTB&=~(1<<EN);
_delay_us(20);
PORTB=(0<<EN)| (0<<RS)|(0<<D4)|(0<<D5)|(0<<D6)|(1<<D7);
//PORTB=0b00001000;
_delay_us(20);
PORTB|=(1<<EN);
_delay_us(20);
PORTB&=~(1<<EN);
_delay_ms(20);
}

void zwei_zeilig(void){
PORTB=(0<<EN)| (0<<RS)|(0<<D4)|(1<<D5)|(0<<D6)|(0<<D7);
//PORTB=0b00000010;
_delay_us(10);
PORTB|=(1<<EN);
_delay_us(10);
PORTB&=~(1<<EN);
_delay_us(10);
PORTB=(0<<EN)| (0<<RS)|(0<<D4)|(0<<D5)|(0<<D6)|(1<<D7);
//PORTB=0b00001000;
_delay_us(10);
PORTB|=(1<<EN);
_delay_us(10);
PORTB&=~(1<<EN);
_delay_ms(20);
}

void cursor_home(void){
PORTB=(0<<EN)| (0<<RS)|(0<<D4)|(1<<D5)|(0<<D6)|(0<<D7);
_delay_ms(1);
PORTB|=(1<<EN);
_delay_us(1);
PORTB&=~(1<<EN);
_delay_ms(20);

PORTB=(0<<EN)| (0<<RS)|(0<<D4)|(1<<D5)|(0<<D6)|(0<<D7);
_delay_ms(1);
PORTB|=(1<<EN);
_delay_us(5);
PORTB&=~(1<<EN);
_delay_ms(20);
}
void display_init(void){
//DDRB|=(1<<EN) | (1<<RS) | (1<<D4) | (1<<D5) | (1<<D6) | (1<<D7);


/*first*/
PORTB =(0<<EN) | (0<<RS) | (1<< D4)| (1<<D5) | (0<<D6)| (0<<D7);
//PORTB=0b00000011;
_delay_us(10);
PORTB|=(1<<EN);
_delay_us(10);
PORTB&=~(1<<EN);
_delay_ms(40);

/*second*/
PORTB =(0<<EN) | (0<<RS) | (1<< D4)| (1<<D5) | (0<<D6)| (0<<D7);
//PORTB=0b00000011;
_delay_us(10);
PORTB|=(1<<EN);
_delay_us(10);
PORTB&=~(1<<EN);
_delay_ms(20);


/*drei*/
PORTB =(0<<EN) | (0<<RS) | (1<< D4)| (1<<D5) | (0<<D6)| (0<<D7);
//PORTB=0b00000011;
_delay_us(10);
PORTB|=(1<<EN);
_delay_us(10);
PORTB&=~(1<<EN);
_delay_us(10);

PORTB =(0<<EN) | (0<<RS) | (0<< D4)| (1<<D5) | (0<<D6)| (0<<D7);
//PORTB=0b00000010;
_delay_us(10);
PORTB|=(1<<EN);
_delay_us(10);
PORTB&=~(1<<EN);
_delay_us(10);





/*vier*/
zwei_zeilig();
_delay_ms(50);
/*fünf*/
display_aus();
_delay_ms(50);
/*sechs*/
display_loeschen();
/*sieben*/
_delay_ms(50);
cursor_rechts();
/*acht*/
_delay_ms(50);
display_ein();
_delay_ms(50);
}

int main(void){
DDRB=0b00111111;
DDRD=0xff;
PORTB=0x00;

einschalt_verzoegerung();
display_init();

while(1){
};


return 0;
}

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Anton schrieb:

> ich hatte mir erlaubt, das ganze zusammenzufassen.
> Hier die Version, die ich zu Anfang hatte.


Die ist auch nicht besser, bzw. noch schlimmer.

Schreib das doch erst mal einfacher hin. Kein Mensch hat hier Lust deine 
Bitkonstanten aufzudröseln und sich zusammenzusuchen, was du da 
eigentlich ans LCD schickst, ob du dich vielleicht irgendwo ein Bit 
vergessen hast.

Funktionen einführen, die Bitkonstanten durch was Lesbares ersetzen.
Das Tutorium-Beispiel zeigt dir
  wie man eine lesbare Struktur hinkriegt
  welche Aufteilung in Funktionen bzw. Subfunktionen sinnvoll ist.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du kannst auch mal probieren die Tutorial-Funktionen einfach zu 
übernehmen. Im Header File die Konfiguration anpassen und dann nachsehen 
ob die zuverlässiger laufen. Wenn ja, dann ist es irgendwas in deiner 
Software. Wenn nein, dann wird es wohl deine Hardware sein.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
PS:
Es muss jetzt natürlich nicht sein, dass dein Code nach der 
Aufräumarbeit stabiler läuft. Aber zumindest ist es einfacher sich davon 
zu überzeugen, dass du da keinen Bock geschossen hast.

Autor: Anton (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hmm, also ich finde das eigentlich garnicht so schlecht lesbar.

Prinzipiell,

ins port schreiben, enable an/aus, nächster befehl...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Anton schrieb:
> Hmm, also ich finde das eigentlich garnicht so schlecht lesbar.

Dann bist du nicht sehr anspruchsvoll

>
> Prinzipiell,
>
> ins port schreiben, enable an/aus, nächster befehl...

Mach dir wenigstens für enable an/aus eine eigene Funktion
void enablePuls()
{
  _delay_us(20);
  PORTB|=(1<<EN);
  _delay_us(20);
  PORTB&=~(1<<EN);
}

und schon verkürzt sich der Rest. Zb.:
void display_loeschen(void)
{
  PORTB=(0<<EN)| (0<<RS)|(0<<D4)|(0<<D5)|(0<<D6)|(0<<D7);
  //PORTB=0b00000000;
  enablePuls();
  _delay_us(10);

  PORTB=(0<<EN)| (0<<RS)|(1<<D4)|(0<<D5)|(0<<D6)|(0<<D7);
  //PORTB=0b00000001;
  enablePuls();
  _delay_ms(20);
}

void cursor_rechts()
{
  PORTB=(0<<EN)| (0<<RS)|(0<<D4)|(0<<D5)|(0<<D6)|(0<<D7);
  //PORTB=0b00000000;
  enablePuls();
  _delay_us(20);

  PORTB=(0<<EN)| (0<<RS)|(0<<D4)|(1<<D5)|(1<<D6)|(0<<D7);
  //PORTB=0b0000011;
  enablePuls();
  _delay_ms(20);
}

...

Jetzt bedenken wir noch, dass ein Kommando übertragen IMMER nach dem 
gleichen Muster abläuft: Zuerst das höherwertige Nibble, dann das 
niederwertige Nibble und schreiben dafür auch noch eine Funktion
void display_command( uint8_t command )
{
  PORTB = ( command & 0xF0 );
  enablePuls();
  _delay_us(20);

  PORTB = ( command & 0x0F ) << 4;
  enablePuls();
  _delay_us(20);
}

und schon können die Einzelfunktionen schon wieder kürzer und 
übersichtlicher geschrieben werden
void display_loeschen(void)
{
  display_command( 0b00000001 );
  _delay_ms(20);
}

void cursor_rechts()
{
  display_command( 0b00000110 );
  _delay_ms(20);
}

Für die magischen Konstanten noch ein paar #define
#define LCD_COMMAND_CLEAR          0b00000001
#define LCD_COMMAND_CURSOR_RIGHT   0b00000110

void display_loeschen(void)
{
  display_command( LCD_COMMAND_CLEAR );
  _delay_ms(20);
}

void cursor_rechts()
{
  display_command( LCD_COMMAND_CURSOR_RIGHT );
  _delay_ms(20);
}

und jetzt vergleich mal deine Funktionen mit dieser letzten Version. 
Welche ist leichter zu lesen und zu verstehen?

Aus 15 Zeilen Code für display_löschen ist ein schicker 2-Zeiler 
geworden, den jeder mit einmal Hinsehen verifizieren kann, solange

   die Konstanten richtig sind
   display_command richtig geschrieben ist.


Und das beste am ganzen: display_löschen ist nicht mehr abhängig davon, 
wie und wo du dein LCD angeschlossen hast. Ändert sich da was, dann ist 
die einzige Stelle die Anpassung benötigt, die Funktion display_command 
bzw. enablePuls. Und die gilt dann automatisch auch für alle anderen 
Kommando-Funktionen.

Autor: Anton (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Okay, da bin ich jetzt überzeugt :)

Ich werde meinen code nochmal überarbeiten.

Nebenher:
Auf meinem Board gibt es zwei steckplätze. Ich habe das Programm jetzt 
mal auf einen Mega 8538 geladen.
es funktioniert.
Das "aufhängen" und stehenlassen von zeichen ist verschwunden.

Anscheindn ist etwas mit der Verdrahtung des Sockels nicht in Ordnung? 
Vielleicht ist auch der Mega8 defekt.

Ich werde morgen einen neuen kaufen. Bis dann programmier ich auf dem 
anderen.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.