Reset verhalten MEGA8

Gast #1883518
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
Gast #1883610
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;
}
#1883615
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-Tutorial/LCD-Ansteuerung#Datei_lcd-routines.c:


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.
Gast #1883628
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;
}
#1883632
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.
#1883701
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
1
void enablePuls()
2
{
3
  _delay_us(20);
4
  PORTB|=(1<<EN);
5
  _delay_us(20);
6
  PORTB&=~(1<<EN);
7
}

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

8
  PORTB=(0<<EN)| (0<<RS)|(1<<D4)|(0<<D5)|(0<<D6)|(0<<D7);
9
  //PORTB=0b00000001;
10
  enablePuls();
11
  _delay_ms(20);
12
}
13

14
void cursor_rechts()
15
{
16
  PORTB=(0<<EN)| (0<<RS)|(0<<D4)|(0<<D5)|(0<<D6)|(0<<D7);
17
  //PORTB=0b00000000;
18
  enablePuls();
19
  _delay_us(20);
20

21
  PORTB=(0<<EN)| (0<<RS)|(0<<D4)|(1<<D5)|(1<<D6)|(0<<D7);
22
  //PORTB=0b0000011;
23
  enablePuls();
24
  _delay_ms(20);
25
}
26

27
...

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
1
void display_command( uint8_t command )
2
{
3
  PORTB = ( command & 0xF0 );
4
  enablePuls();
5
  _delay_us(20);
6

7
  PORTB = ( command & 0x0F ) << 4;
8
  enablePuls();
9
  _delay_us(20);
10
}

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

7
void cursor_rechts()
8
{
9
  display_command( 0b00000110 );
10
  _delay_ms(20);
11
}

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

4
void display_loeschen(void)
5
{
6
  display_command( LCD_COMMAND_CLEAR );
7
  _delay_ms(20);
8
}
9

10
void cursor_rechts()
11
{
12
  display_command( LCD_COMMAND_CURSOR_RIGHT );
13
  _delay_ms(20);
14
}

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.
Gast #1883706
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

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren