www.mikrocontroller.net

Forum: GCC C-Anfängerfrage zur Tilde


Important announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: Rudi D. (rulixa)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Warum schreibt man z.B.
LCD_PORT &= ~(1<<LCD_RS)  und nicht
LCD_PORT &= (0<<LCD_RS)

Ich bin übrigens sehr froh, dass ich vorher in Assembler unterwegs war, 
da z.B. in den lcd_routines.c oder .h oft das pinning des Displays am µC 
versteckt ist.
LG Rudi

Autor: Udo Schmitt (urschmitt)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Wenn du Assemblererfahrung hast, dann weisst du doch welcher binäre 
(oder hex) Wert du möchtest.
Schreib dir doch mal auf welcher Wert in das Register soll und was bei 
den Varianten rauskommt:
~(1<<LCD_RS)
(0<<LCD_RS)

Dann siehst du selbst was richtig ist und warum.
Nimm Papier und Bleistift und gehs durch, so wie Karl Heinz das immer 
propagiert, da ist der Lerneffekt am nachhaltigsten

Autor: XXX (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Hallo

Mal dir das ganze doch mal auf, was da passiert.
Dann fällts dir wie Schuppen aus den Haaren.

Gruß
Joachim

Autor: Antworter (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Hallo,

tolle Antworten bis jetzt...

Du musst Schritt für Schritt vorgehen:
1. (1<<LCD_RS) wird bearbeitet: "Die 1 um LDC_RS Stellen nach links 
schieben"
   Beispiel: aus 1 wird 00100 wenn LDC_RS = 2 ist.
2. Das ganze wird durch die Tilde bitweise negiert. Aus 00100 wird z.B. 
11011

Wenn Du unter 1. eine 0 nach links verschiebst, kommt eben auch 0 raus.

Viele Grüße

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

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Antworter schrieb:
> Hallo,
>
> tolle Antworten bis jetzt...
>
> Du musst Schritt für Schritt vorgehen:
> 1. (1<<LCD_RS) wird bearbeitet: "Die 1 um LDC_RS Stellen nach links
> schieben"
>    Beispiel: aus 1 wird 00100 wenn LDC_RS = 2 ist.
> 2. Das ganze wird durch die Tilde bitweise negiert. Aus 00100 wird z.B.
> 11011
>
> Wenn Du unter 1. eine 0 nach links verschiebst, kommt eben auch 0 raus.

Und genau darauf wäre er auch gekommen, wenn er das selber mit Papier 
und Bleistift durchgespielt hätte. Nur mit einem Unterscheid: Er hätte 
es nie wieder vergessen, weil er selber drauf gekommen ist. Einziger 
Nachteil: Es hätte 3 Minuten länger gedauert, bis er begriffen hat, dass 
er das Bitmuster

   0000 0000

so oft er will um x Stellen nach links verschieben kann und sich nichts 
ändert.

Autor: Antworter (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Hallo,

@Karl Heinz Buchegger:

Ich gehe schon davon aus, dass hier nicht jeder aus jux und tollerei 
Fragen stellt.
Wenn er dann seine Frage vernünftig formuliert hat, finde ich es gelinde 
gesagt albern, ihm keine vernünftige Antwort zu geben.

Das kann jeder sehen wie er will. Eine ordentliche Antwort muss man dann 
auch nicht unbedingt noch kommentieren. Man kann seine persönliche 
Meinung auch für sich behalten...

Fazit: Wer gut fragt bekommt auch gute Antworten.

Viele Grüße

Autor: Nachtaktiver (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Antworter schrieb:
> Fazit: Wer gut fragt bekommt auch gute Antworten.
>
> Viele Grüße

+1.

Autor: Peter Dannegger (peda)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Rudi D. schrieb:
> Ich bin übrigens sehr froh, dass ich vorher in Assembler unterwegs war,
> da z.B. in den lcd_routines.c oder .h oft das pinning des Displays am µC
> versteckt ist.

Das Pinning sollte niemals im Code versteckt sein, sondern an zentraler 
Stelle definiert werden, z.B. im "main.h" oder "hardware.h".

http://www.avrfreaks.net/index.php?name=PNphpBB2&f...

In dem Beispiel sieht man auch sehr schön, wie man sich diese 
umständliche Schieberei-Schreibweise ersparen kann. Ein Pin wird dann 
einfach als Bitvariable angesehen.


Peter

Autor: Rudi D. (rulixa)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
So hab ich's in Assembler gemacht
;create  enable pulse 5 cycles auf 1 macht 0,75 us ändert kein Register
;mit fallender Flanke werden Daten übernommen
lcd_enable:
       sbi LCD_PORTB, PIN_E         ;2; Enable high
       nop
       nop
       nop
       cbi LCD_PORTB, PIN_E         ;2; Enable low
     rcall  delay50us    ;ab H>L Enable braucht das Display 38 us
     ret        ;bis es wieder bereit ist

in C sieht es so aus (nur abgeschrieben)
// erzeugt den Enable-Puls
void lcd_enable(void)
{
  LCD_PORT |= (1<<LCD_EN1);
    _delay_us(10);                   // kurze Pause
   // Bei Problemen ggf. Pause gemäß Datenblatt des LCD Controllers verlängern
   // http://www.mikrocontroller.net/topic/80900
   LCD_PORT &= ~(1<<LCD_EN1);
} 

Für mich, dachte ich, sollte das ident sein.
 cbi LCD_PORTB, PIN_E  == LCD_PORT &= ~(1<<LCD_EN1) == LCD_PORT &= 
(0<<LCD_EN1)

Mit cbi ändere ich ja nur den Status des Enable_pins und sonst kein 
anderes Bit des LCD_PORTs. Ich dachte dass &= ~(1<<LCD_EN1); auch nur 
dieses Bit ändert und nicht gleich alle Bits des Ports beeinflusst.

Deshalb gefällt mir die Lösung von peda in avr.freaks, weil für mich 
nicht mißverständlich. O.k. die Sache ist geklärt.
LG Rudi

Autor: Rudi D. (rulixa)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Das hier ist noch einfacher zu verstehen, für mich fast wie Assembler, 
wieder am Beispiel des
 void lcd_enable(void)
{
  sbi (LCD_PORT, LCD_PIN_E);
  cbi (LCD_PORT, LCD_PIN_E); //wenn die Pulsdauer stimmt
}

#define sbi(PORT, bit)     (PORT|=(1<<bit)) // set bit in PORT
#define cbi(PORT, bit)     (PORT&=~(1<<bit))// clear bit in PORT
#define  LCD_PORT    PORTD
#define  LCD_DDR      DDRD
#define LCD_PIN_RS    0
#define LCD_PIN_E    3


auch abgeschrieben.
Wie bekommt man die Ausführungszeiten in C heraus. Ist ja in Assembler 
höchst einfach.

Da ist, wie von peda schon gesagt, die Bitschieberei nur 1x nötig zu 
definieren. Ich nähere mich halt langsam und verstehe, dass die Version 
auf AVR-freaks viel umfassender ist.

Autor: Peter Dannegger (peda)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Rudi D. schrieb:
> Wie bekommt man die Ausführungszeiten in C heraus. Ist ja in Assembler
> höchst einfach.

Erstmal rechnet ein Compiler alle Konstanten schon zur Compilezeit aus, 
d.h. das ~ und << erzeugt keinen Code.
Und dann schlägt der Optimierer zu und erkennt, daß nur ein Bit 
gesetzt/gelöscht wird und die Adresse im Bereich der Bitbefehle liegt.
Er mach also ein SBI/CBI daraus.

Das geht aber nicht immer, die größeren AVRs haben auch Ports im 
Memory-Bereich. Dann muß er LDS+ANDI/ORI+STS nehmen. Muß man aber in 
Assembler auch.


Peter


P.S.:
Ich hab mir die Schreibarbeit noch etwas vereinfacht und alle Ports in 
der sbit.h definiert:

http://www.avrfreaks.net/index.php?name=PNphpBB2&f...

Autor: Rolf Magnus (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Rudi D. schrieb:
> Wie bekommt man die Ausführungszeiten in C heraus.

Am besten, indem du den vom Compiler genrierten Assembler-Code 
anschaust, denn ...

> Ist ja in Assembler höchst einfach.

Autor: Rudi D. (rulixa)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Peter Dannegger schrieb:
> Ich hab mir die Schreibarbeit noch etwas vereinfacht und alle Ports in
> der sbit.h definiert:
>
> http://www.avrfreaks.net/index.php?name=PNphpBB2&f...

Habe 2 sbit.h gefunden 300 byte und 9,5kByte, die eine ein Teil der 
anderen.
Da blicke ich noch nicht durch, zu neu für mich, to date.
In C scheint's ja viele legale Möglichkeiten zu geben dasselbe Ziel zu 
erreichen.
Weiss auch noch nicht was C allg. Statements sind und AVR extra ergänzt 
hat. Geschützte Bezeichnungen etc. Na ja, klein anfangen eben.
Verschiedene Sachen von mir sind bei Burkhard K's Labor zu finden. Das 
war aus Not, dieses allererste Projekt, www.b-kainka.de/ELO/rc5trans.pdf

LG Rudi

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




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 erkennst du die Nutzungsbedingungen an.

webmaster@mikrocontroller.netImpressumNutzungsbedingungenWerbung auf Mikrocontroller.net