Frage AVR-GCC-Tutorial => lcd-routines.c

Gast #1018995
Hallo,
ich (Anfänger) gehe gerade das o.g. Tutorial durch und habe eine 
Verständnisfrage. Funktionieren wird der Code wohl, sonst stünde er hier 
ja nicht, also verzweifle ich gerade mit meinem C-Büchlein. Also:
1
// Pinbelegung für das LCD, an verwendete Pins anpassen
2
#define LCD_PORT      PORTD
3
#define LCD_DDR       DDRD
4
#define LCD_RS        PD4
5
#define LCD_EN        PD5
6
// DB4 bis DB7 des LCD sind mit PD0 bis PD3 des AVR verbunden 
7
// sendet ein Datenbyte an das LCD
8
 
9
void lcd_data(unsigned char temp1)
10
{
11
   unsigned char temp2 = temp1;
12
 
13
   LCD_PORT |= (1<<LCD_RS);        // RS auf 1 setzen
14
 
15
   temp1 = temp1 >> 4;
16
   temp1 = temp1 & 0x0F;
17
   LCD_PORT &= 0xF0;
18
   LCD_PORT |= temp1;               // setzen
19
   lcd_enable();
20
 
21
   temp2 = temp2 & 0x0F;
22
   LCD_PORT &= 0xF0;
23
   LCD_PORT |= temp2;               // setzen
24
   lcd_enable();
25
   
26
   _delay_us(42);
27
}

temp1 = temp1 >> 4;
Soweit klar: Soll ein unsigned char um 4 Stellen nach rechts shiften; 
dadurch kommen von links Nullen nach und das höherwertige Nibble 
befindet sich nun im niederwertigen Nibble, da PD0 bis PD3 im 
höherwertigen Nibble DB4 bis PD7 des LCD entsprechen und zuerst 
übertragen werden.

temp1 = temp1 & 0x0F;
Verstehe ich inhaltlich schon nicht mehr, denn nach meinem bisherigen 
Verständnis kann sich der Inhalt von temp1 dadurch überhaupt nicht 
verändern (höherwertiges Nibble ist ja schon Null und niederwertiges 
Nibble wird mit 1111 verUNDet; ergibt das, was vorher schon im 
niederwertigen Nibble da war).

LCD_PORT &= 0xF0;
Hier wird DB0 bis DB3 auf Null gesetzt. Warum? Mit dem nächsten Befehl

LCD_PORT |= temp1;
wird doch sowieso das ins Register geschrieben, was in temp1 steht?

Und hier hör ich lieber auf, denn wenn ich 2 Schritte hintereinander 
schon nicht verstehe, frage ich lieber nach.

Danke und Gruß
Lutz
Persönliche Seite #1019017
Stelle 1:

> temp1 = temp1 >> 4;
> ...
> temp1 = temp1 & 0x0F;
> ...

Schritt 2 könnte man an der Stelle weglassen. Mag sein, dass das ein 
Rest von der Ururversion ist. Die Zeile "schadet" aber auch nicht.

Stelle 2:

> LCD_PORT &= 0xF0;
> Hier wird DB0 bis DB3 auf Null gesetzt. Warum? Mit dem nächsten Befehl
>
> LCD_PORT |= temp1;
> wird doch sowieso das ins Register geschrieben, was in temp1 steht?

"Durch das ODER (|) werden nur die 1-en aus temp1 nach LCD_PORT 
gschrieben".

Nimm Papier und Bleistift und rechne ab Stelle 2 mit den Anfangswerten

LCD_PORT = 0x81;
temp1 = 0x82;

durch und lasse dann die Anweisung

LCD_PORT &= 0xF0;

mal weg...

Weitere Lektüre: Bitmanipulation
Gast #1019150
Autsch! Die 1 von 0x81 bleibt beim verODERn stehen und wird 
"durchgereicht". Mit LCD_PORT &= 0xF0; wird das niederwertige Nibble 
vorher "gereinigt".
=> Kapiert.

Vielen Dank.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 18 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.