Toggle Funktion AVR

OP #1019715
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.
1
//bestimmtes bit aus einem byte lesen
2
unsigned char get_bit(unsigned char byte, unsigned char bit)
3
{
4
unsigned char result; 
5
result = (byte >> bit);
6
result = (result & 0x01);
7
return result;
8
}
9

10

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

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

8
//ab auf togglen
9
void toggle_bit_down_up(unsigned char byte, unsigned char bit)
10
{byte = set_bit(byte, bit, 0);
11
byte = set_bit(byte, bit, 1);
12
}
13
*/

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

Funktionert nicht.
Wenn ich das ganze mit
1
port_control = set_bit(port_control, pin_clk, 1);
2
port_control = set_bit(port_control, pin_clk, 0);
dann geht es.
Weiß jemand wieso?
Grüße
Phil
Gast #1019723
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
#1019738
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&file=viewtopic&t=67368

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
#1019740
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.
OP #1019781
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.
#1019824
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
OP #1019927
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
1
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
Gast #1019950
Mit Macros müsst es bequem gehen....

Zum Beispiel so:

1
#define SB(byte,bit) byte |= (1<<bit)
2
#define CB(byte,bit) byte &= ~(1<<bit)
3
#define TOGGLE_BIT_UP_DN(byte,bit) do{SB(byte,bit);CB(byte,bit)}while(0)
4
#define TOGGLE_BIT_DN_UP(byte,bit) do{CB(byte,bit);SB(byte,bit)}while(0)
5
 .
6
 .
7
 .
8
 TOGGLE_BIT_UP_DN(port_control, pin_clk);
Gast #1019957
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.
Gast #1020443
...und es fehlt auch noch ein [;]

also...
1
#define SB(byte,bit) byte |= (1<<(bit))
2
#define CB(byte,bit) byte &= ~(1<<(bit))
3
#define TOGGLE_BIT_UP_DN(byte,bit) do{SB(byte,bit);CB(byte,bit);}while(0)
4
#define TOGGLE_BIT_DN_UP(byte,bit) do{CB(byte,bit);SB(byte,bit);}while(0)
5
 .
6
 .
7
 .
8
 TOGGLE_BIT_UP_DN(port_control, pin_clk);

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.