mikrocontroller.net

Forum: Compiler & IDEs bit schieben mittels schalter in C


Autor: Anfänger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
halli hallo hab ein problem dass das bit nicht geschoben wird sonder 
immer nur binär codiert könnt ihr mir helfen??

int x;



   while (true)                      // Mainloop
   {
      for (x = 1; x < 64; x=x*2 )    //Schleife

        if (!( PIND & 0b00000100))   // wenn Taster gedrückt eins weiter
           {
            x++;
            PORTB = x;               //x am PORTB ausgeben

           }
   }


mfg

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bits sind üblicherweise immer binär codiert, das liegt in ihrem Wesen 
;-)

Es ist kontraproduktiv, wenn du an 2 Stellen am x herumschraubst.
Soll wohl ein Lauflicht sein, das mit einer Taste weitergeschaltet wird?
Probiers mal so:
   x = 1;
   while (true) {                        // Mainloop
      if (!( PIND & 0b00000100)) {       // Taster gedrückt -> eins weiter
          x = x<<1;                      // wie x=x*2, nur etwas binärer
          if(x>63) x=1;
          while (!( PIND & 0b00000100)); // warten, solange Taster gedrückt 
      }
      PORTB = x;                         // x ausgeben
   }

Autor: Florian Pfanner (db1pf)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

1. Bitte schreib in ein oder zwei Sätzen was das Programm im ganzen 
eigentlich machen soll. Ich werde aus deiner Beschreibung nicht ganz 
schlau. Dann kann ich dir evt auch eher bei deinem Problem helfen.

2. Der Kommentar zur for-Schleife ist überflüssig, das es sich hier um 
eine Schleife handelt sieht man.

3. Es ist ein schlechter Stil, die for-Variable (hier x) im Codebereich 
der for-Schleife zu ändern. Das kann sehr schnell zu einem seltsamen 
Verhalten führen.

4. Du wirst von der Funktion der Schaltung nicht viel sehen: Der 
Controller ist sehr schnell, jeder Durchlauf der Schleife dauert nur ein 
paar µSekunden. Auch wenn der Code korrekt sein sollte, so werden 
(scheinbar) alle LED's leuchten. Wenn du den AVR-GCC verwendest, dann 
füge ein #include <util/delay.h> ganz oben ein und du kannst dann die 
funktionen _delay_ms( zeit ) verwenden.


Grüße,
Florian

Autor: Anfänger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
danke erstmal für die schnellen antworten

nun zur funktion will einen Lautstärkeregelung machen indem man mit 
einen taster nach oben schaltet und mit einen nach unten schalten 
sozusagen ein lauflicht was man schritt für schritt immer weiterschalten 
(zurückschaltet)



P.S.: das mit einer pause (delay) hab ich auch schon probiert aber 
leider ohne erfolg.

mfg

Autor: Anfänger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hab mit euren tipps ein bischen probiert und es geschafft

vielen vielen dank für eure tipps

Autor: Mano Wee (Firma: ---) (manow)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> nun zur funktion will einen Lautstärkeregelung machen indem man mit
> einen taster nach oben schaltet und mit einen nach unten schalten
> sozusagen ein lauflicht was man schritt für schritt immer weiterschalten
> (zurückschaltet)
      for (x = 1; x < 64; x=x*2 )    //Schleife

Versteh ich dass dann richtig, dass Du eigentlich die Zahl 64 ändern 
möchtest, denn dass ist ja die Abbruchbedingung. z.B.
      for (x = 1; x <= y; x=x*2 )    //Schleife

y kann man durch die Zahlen 1, 2, 4, 8, 16, 32, 64 schalten.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@  Mano Wee (Firma ---) (manow)
x=x*2    entspricht     x=x<<1     entspricht     x<<=1
Das ist effektiv nur ein Bitshift

Autor: Mano Wee (Firma: ---) (manow)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Lothar Miller

> x=x*2    entspricht     x=x<<1     entspricht     x<<=1

Das ist mir schon klar...


@ von mir selber

> Versteh ich dass dann richtig

Anscheinend hab ich das nicht richtig verstanden...

Autor: einer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
oder x=x+x
oder x+=x  (da zucken die grauen zellen)

c ist echt klasse

Autor: Anfänger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Mano Wee

die 64 ist das höchste bit was ich ausgeben will sprich es soll von 
1,2,4,8,16,32,64 schalten und die obergrenze ist 64

du mich zur zeit nur ein bischen hart mit den schleifen ect.. weil ich 
ja c erst angefangen hab !!!


für was ist eigentlich die while schleife bei Lothar miller??
        while (!( PIND & 0b00000100)); // warten, solange Taster 
gedrückt

versteh nicht für was das ist weil abgefragt wird es ja schon vorher 
vielleicht kann mir ja jemand helfen!

mfg

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@  Anfänger (Gast)
Nachdem du ein Programm ohne Tasterentprellung und Flankenerkennung 
zuwege gebracht hast, hatte ich gedacht, es wäre doch schön, wenn der 
Zähler nicht hochzählt solange eine Taste gedrückt wird. Denn genau 
das wird hier gemacht:
   x = 1;
   while (true) {                        // Mainloop
      if (!( PIND & 0b00000100)) {       // Taster gedrückt -> eins weiter
          x = x<<1;                      // wie x=x*2, nur etwas binärer
          if(x>63) x=1;
      }
      PORTB = x;                         // x ausgeben
   }
Ist die Taste gedrückt, wird x um eins weiter geschoben. Danach wird x 
am Port B ausgegeben. Dann beginnt die Mainloop von vorne. Bis hierher 
sind ca. 1-5µs vergangen, und die Taste ist garantiert immer noch 
gedrückt. Also wird x um 1 nach links geschoben, dann wird x an Port B 
ausgegeben, dann...
Ein µC ist (für menschliche Verhältnisse) rasend schnell ;-)

Mit dieser Zeile zusätzlich
>   while (!( PIND & 0b00000100)); // warten, solange Taster gedrückt
wird gewartet, solange der Taster noch gedrückt ist.

Was das Programm damit aber immer noch nicht macht, ist, den Taster zu 
entprellen. Da werden dir etwas später noch die Augen aufgehen ;-)

Ich würde das eher so machen (immer noch ohne Tastenentprellung)
   int x = 1;
   char t, talt;
   while (true) {                   // Mainloop
      t=!(PIND & 0b00000100);       // Taster einlesen
      if ((t!=talt) && (talt=t)) {  // Flankenauswertung
          x = x<<1;                 // wie x=x*2, nur etwas binärer
          if(x>63) x=1;
      }
      PORTB = x;                    // x ausgeben
   }

Autor: Anfänger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
mit dem entprellen hab ich mich schon eine ganze weile beschäftigt hab 
nur nicht verstanden wie der uC versteht das die flanke nach oben oder 
nach unten gerade geschalten wird.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>    if ((t!=talt) && (talt=t)) {  // Flankenauswertung
In dieser Zeile steht:
if(         Wenn 
(t!=talt)   der aktuelle Tastenpegel (t) ungleich dem vorherigen (talt) ist
&&          und
(talt=t)    das Ergebnis aus der Zuweisung von t nach talt ungleich 0 ist (also Taster betätigt)
) {         dann mach das Folgende...

Ich könnte das funktionsgleich auch so schreiben:
   int x = 1;
   char t, talt;
   while (true) {                   // Mainloop
      t=!(PIND & 0b00000100);       // Taster betätigt --> t = 1
      if ((t!=talt) && (t!=0)) {    // Flankenauswertung
          x = x<<1;                 // wie x=x*2, nur etwas binärer
          if(x>63) x=1;
      }
      talt = t;                     // Zustand von Taster merken für Flankenauswertung
      PORTB = x;                    // x ausgeben
   }

Autor: Anfänger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
aaaaaah so jetzt hab i des verstanden is nur manchmal schwer es zu 
verstehen mit den = und ! und und und weiß zwar was sie bedeuten aber es 
ist am anfang schwierig sie richtig einzusetzen!!!
weil beim tutorial ist es wirklich kompliziert geschrieben zumindest für 
anfänger (ein kollege der einen C++ kurs vor einigen jahren gemacht hat 
hat es auch nicht verstanden)

vielen dank du bist echt spitze!!

ich hoff ich kann dich wieder mal fragen wenn ich was brauche

mfg

Autor: Anfänger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was bedeutet   while(PIND&(1<<2));. ich kann damit nicht sonderlich was 
anfangen und brauche jemanden der mir das mal erklären kann. ich danke 
euch schon mal im vorraus

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Malte (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

wenn du eine 1, was ja auch 0b00000001 ist, um zwei Stellen nach links 
schiebt bekommst du 0b00000100. Also ist das selbe wie deine Bedingung
( PIND & 0b00000100 ).

Also man könnte auch schreiben  PIND & 4 , PIND & 0x04  oder
 PIND & (1<<PD2). Welche Version die schönste ist, ist meiner Meinung 
nach Geschmacksache.

Gruß Malte

Autor: Bascomfehler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sollte der Anfänger nicht erst ein mal C lernen?

http://www.guardian-online.de/c-kurs/index_c.html

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> while(PIND&(1<<2));
1. PIND ist das Pin-Register des uC.
2. Eine 1 lässt sich auch als binär 00000001 schreiben
3. Ein <<2 ist ein bitweises Links-Schieben um 2 Stellen
   aus 1. und 2. ergibt sich: (1<<2) = 00000100
4. Ein while() tut das, was danach kommt,
   solange die Abfrage in der Klammer ungleich 0 ist.
5. Das while(...); lässt sich auch so schreiben: while(...){};
   und somit tut es einfach nichts,
   als dauernd die Bedingung auswerten und warten

PIND wird UND-verknüpft mit 00000100,
solange bis das das Ergebnis ungleich 0 ist,
bis also am PinD2 high anliegt.

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.