mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Toggle Funktion AVR


Autor: Phillip Hommel (philharmony)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich muß um verschiedene register anzusteuern öfters eine high->low oder 
low->high Flanke auslösen.
Dazu habe ich verschiedene bit_operationen selbst geschrieben (der 
Übersicht halber) und unter anderem eine toggle-funktion.
//bestimmtes bit aus einem byte lesen
unsigned char get_bit(unsigned char byte, unsigned char bit)
{
unsigned char result; 
result = (byte >> bit);
result = (result & 0x01);
return result;
}


//bestimmtes bit in einem byte setzen oder löschen
unsigned char set_bit(unsigned char byte, unsigned char bit, unsigned char state)
{
unsigned char result;
if (state == 0) result = (byte & ~(1 << bit)); else result = (byte | (1 << bit));
return result;
}

Diese benutze ich nun auch in der Toggle_Funktion:
//auf ab togglen
void toggle_bit_up_down(unsigned char byte, unsigned char bit)
{byte = set_bit(byte, bit, 1);
byte = set_bit(byte, bit, 0);
}
*/

//ab auf togglen
void toggle_bit_down_up(unsigned char byte, unsigned char bit)
{byte = set_bit(byte, bit, 0);
byte = set_bit(byte, bit, 1);
}
*/

Wenn ich die Funktionen allerdings im Program benutzen möchte, dann 
funktioniert diese allerdings nicht.
Also
toggle_bit_up_down(port_control, pin_clk);

Funktionert nicht.
Wenn ich das ganze mit
port_control = set_bit(port_control, pin_clk, 1);
port_control = set_bit(port_control, pin_clk, 0);
dann geht es.
Weiß jemand wieso?
Grüße
Phil

Autor: NurEinGast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich würde mal sagen mit der Zuweisung

   byte = set_bit(byte, bit, 1);

im toggle_bit_up_down überschreibst Du dir Deine Eingangsvariable 
"byte", die Du in der nächsten Zeile aber wieder verwenden willst.

Gruss

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was erwartest du denn, was toggle_bit_up_down tun soll?
Es hat keinen Rückgabewert und auch der ursprünglich übergebene Wert 
wird nicht verändert.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Phillip Hommel wrote:
> Wenn ich die Funktionen allerdings im Program benutzen möchte, dann
> funktioniert diese allerdings nicht.

Du übergibst die Kopie der Variable "byte", machst damit etwas und 
schmeißt das Ergebnis weg.
Daher ist der Compiler so schlau, es komplett wegzuoptimieren.
Aber selbst wenn er es macht, bewirkt es nicht das von Dir Gewünschte, 
sondern verbraucht nur Zeit.
Gehen würde es nur mit Pointern auf volatile.
Dabei wird der Code aber sehr aufwendig.


Hier mal ein Tutorial, wie man Bits übersichtlich definiert und 
verwendet:

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

Das hat außerdem den Vorteil, daß der Code effizient ist, d.h. die 
Bitbefehle benutzt.
Das Rumgewusele mit Pointern auf IO-Ports kostet dagegen mächtig Code 
und Zeit.


Peter

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Geht so nicht. Denn in der toggle-Funktion wird nicht der Port 
getoggelt, sondern nur die lokale Variable.

Dü müsstest dazu die Adresse des Ports and die toggle-Funktion 
übergeben, nicht dessen Inhalt. Ist aber umständlich.

Tip nebenbei: Shifts deren Anzahl dem Compiler nicht bekannt sind werden 
bei AVRs recht ineffizient implementiert. Was hier solange kein Problem 
ist, bis der Compiler meinst, für übliche inlining wären die Funktionen 
zu gross.

Autor: Phillip Hommel (philharmony)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die funktion hat ja auch keinen Rückgabewert sondern soll in sich den 
übergebenen wert (der mit #define direkt dem port und pin enspricht) 
zweimal die funktion set_bit ausführen die ja direkt aufgerufen auch 
funktioniert.
ich fasse in toggle eigentlich ja nur zwei zeilen zusammen.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du willst also direkt den Pin am Port toggeln, und nicht nur ein Bit in 
einem Datenbyte?
Dann musst du einen Pointer auf den Port übergeben.
Und du musst daran denken, die Interrupts währenddessen zu sperren.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Phillip Hommel wrote:
> Die funktion hat ja auch keinen Rückgabewert

Und genau das ist der Unterschied, daß sie nicht das tut, was Du gerne 
hättest.
Sie tut natürlich genau das, was Du hingeschrieben hast.


> ich fasse in toggle eigentlich ja nur zwei zeilen zusammen.

Nein, tust Du nicht.
Es ist ein großer Unterschied, ob Du einen Returnwert einer globalen 
Variable oder einer lokalen zuweist.
Die lokale ist nach dem Verlassen der Funktion ungültig und damit die 
Zuweisung ohne Effekt.
Und deshalb passiert auch nichts mit dem Port, ihm wurde ja nichts 
zugewiesen.


Peter

Autor: Phillip Hommel (philharmony)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aaaaah ok, jetzt raff ich das.
Ich übergebe der funktion den WERT des ports, der wurschtelt damit was 
und speichert es aber nirgends?
Dh ich müßte das ganze wieder mit rückgabewert machen im sinne von
port_control = toggle_blabla
was aber keinen sinn macht da ich ja hoch- und wieder runter-togglen 
will.
Dh die beste methode ist, zweimal set_bit auszuführen, einmal mit 1 und 
einmal mit 0.
Vielen dank

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mit Macros müsst es bequem gehen....

Zum Beispiel so:

#define SB(byte,bit) byte |= (1<<bit)
#define CB(byte,bit) byte &= ~(1<<bit)
#define TOGGLE_BIT_UP_DN(byte,bit) do{SB(byte,bit);CB(byte,bit)}while(0)
#define TOGGLE_BIT_DN_UP(byte,bit) do{CB(byte,bit);SB(byte,bit)}while(0)
 .
 .
 .
 TOGGLE_BIT_UP_DN(port_control, pin_clk);
 

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wobei mehr Klammern nicht schaden würden, um sich vor unerwünschten 
Priorätiten zu schützen:
  #define SB(byte,bit) byte |= (1<<(bit))

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Macros sind in diesem Fall erst noch viel effizienter und schneller 
als Funktionsaufrufe. Falls die "bit"-Werte Konstanten sind, wird 
nämmlich der C-Präprozessor des Compilers die Shift-operationen 
erledigen und die CPU hat zu Runtime nichts mehr damit zu tun.

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ohja, die Klammern hab ich vergessen, die wären tastächlich sehr zu 
empfehlen!

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
...und es fehlt auch noch ein [;]

also...
#define SB(byte,bit) byte |= (1<<(bit))
#define CB(byte,bit) byte &= ~(1<<(bit))
#define TOGGLE_BIT_UP_DN(byte,bit) do{SB(byte,bit);CB(byte,bit);}while(0)
#define TOGGLE_BIT_DN_UP(byte,bit) do{CB(byte,bit);SB(byte,bit);}while(0)
 .
 .
 .
 TOGGLE_BIT_UP_DN(port_control, pin_clk);


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.