Mit folgender Funktion, versuche ich mit den übergebenen Parameter in meiner Main, nur bestimmte Ports als Output zu deklarieren. void PortOut_init(unsigned char port, unsigned char von, unsigned char bis){ unsigned char ports_out = 0; for (int i=von; i <= bis; i++) { ports_out += pow(2, i); } switch (port) { case 'B': DDRB = ports_out; PORTB &= ~ports_out; break; case 'C': DDRC = ports_out; PORTC &= ~ports_out; break; case 'D': DDRD = ports_out PORTD &= ~ports_out; break; default: break; } } der main Aufruf ist wie folgt: PortOut_init('C', 2, 5); Also, nur die Ports PORTC2 - PORTC5 sollen als Output dienen. Jedoch kommt der folgende Build-Fehler: Error called object 'ports_out' is not a function or function pointer Warum will er ports_out als funktion oder pointer deklariert haben, wenn ich doch einfach nur den Wert übergeben will. Sprich ... Die Ports von PORTC von 2 bis 5 sollen als Output deklariert werden, also Register DDRC: 0b00111100 ... entspricht 0x3C entspricht dem Wert 60. und Register PORTC (Angeschlossene LED's aus) entspricht 0xff
Moinsen schrieb: > Warum will er ports_out als funktion oder pointer deklariert haben, wenn > ich doch einfach nur den Wert übergeben will. Weil du ein Semikolon vergessen hast.
wie kommt's das meine for-schleife auf den Wert 56 kommt und nicht wie erwartet 60? ... Hierdurch wir der eine Output nicht deklariert.
unsigned char ports_out = 0; for (int i=von; i <= bis; i++) { ports_out += pow(2, i); } hierbei: von = 2 ... bis = 5 also: 2^2 + 2^3 + 2^4 + 2^5 = 60... aber der kommt auf den wert 56. ... hab ich da ein Denkfehler?
Eine Floating Point Library Funktion zu verwenden um Bits zu erzeugen ist pervers. Ich sehen den Fehler auch nicht, aber würde es so machen:
1 | #include <stdio.h> |
2 | |
3 | int main() |
4 | {
|
5 | unsigned char von = 2; |
6 | unsigned char bis = 5; |
7 | unsigned char bit = 1<<von; |
8 | unsigned char ports_out = 0; |
9 | |
10 | for (int i=von; i<=bis; i++) |
11 | {
|
12 | ports_out += bit; |
13 | printf ("ports_out = %i \n", ports_out); |
14 | bit <<= 1; |
15 | }
|
16 | }
|
Anders Rum schrieb: > Eine Floating Point Library Funktion zu verwenden um > Bits zu erzeugen ist pervers. Ich sehen den Fehler auch > nicht, aber würde es so machen: > #include <stdio.h> > > int main() > { > unsigned char von = 2; > unsigned char bis = 5; > unsigned char bit = 1<<von; > unsigned char ports_out = 0; > > for (int i=von; i<=bis; i++) > { > ports_out += bit; > printf ("ports_out = %i \n", ports_out); > bit <<= 1; > } > } Das funktioniert wunderbar. Das mit dem Schieben von Bits sitzt noch nicht ganz. Muss mir diese Technik aneignen. Hilf mir ma, ich versuche es ma zu erklären und du schaust ob ich richtig liege. mit " unsigned char ports_bit = 1<<von; " ... deklarierst du, welches Bit bei ports_bit gesetzt wird mittels übergebenen Wert "von". mittels " ports_bit <<= 1; " schiebst du jeweils die Bits setzend links durch. Okay ... soweit alles gut. Aber durch die Deklaration von den Ports, wie bspweise "PORTC |= (1<<PORTC0);" bin ich der überzeugung dass immer eine Oder Verknüpfung verwendet werden soll. Also in dem Sinne: unsigned char ports_bit |= (1<<von); ... Ist hierbei die Überlegung falsch?
Moinsen schrieb: > Ist hierbei die Überlegung falsch? Funktioniert auch, aber hier ist die Addition einfacher und übersichtlicher. Ich darf addieren solange nur ein Bit in der Variable gesetzt ist.
Moinsen schrieb: > mit " unsigned char ports_bit = 1<<von; " ... deklarierst du, welches > Bit bei ports_bit gesetzt wird mittels übergebenen Wert "von". Einfach gesagt: Er nimmt eine 1 (also einen Integer, bei dem genau ein Bit, nämlich das unterste gesetzt ist) und schiebt sie um "von" Bits nach links. Also in einzelnen Bits geschrieben: Man nehme die 1: 00000001 und schiebe sie um 2 Bits nach links: 00000100 > mittels " ports_bit <<= 1; " schiebst du jeweils die Bits setzend links > durch. Es werden bei jedem Schleifendurchlauf alle Bits in der Variable um ein Bit nach links geschoben. Da in der Variable nur eine einzige 1 vorkommt, läuft die quasi durch, also: 00001000 00010000 00100000 Und was passiert jetzt, wenn ich diese vier Werte addiere? 00000100 + 00001000 + 00010000 + 00100000 = -------- 00111100 = 60⏨ > Aber durch die Deklaration von den Ports, wie bspweise "PORTC |= > (1<<PORTC0);" bin ich der überzeugung dass immer eine Oder Verknüpfung > verwendet werden soll. Wenn du die gewünschten Bits setzen, aber alle anderen unverändert lassen willst, ja. > Also in dem Sinne: unsigned char ports_bit |= > (1<<von); ... += hat in diesem speziellen Fall das gleiche Ergebnis, aber üblicher ist, die ODER-Operation zu verwenden.
Bedanke mich für die ausführliche Erklärung. Diesem Ausdruck bezüglich: unsigned char ports_bit |=(1<<von); Liefert mir aber das Atmel-Studio folgenden Fehler: Error expected '=', ',', ';', 'asm' or '__attribute__' before '|=' token Also ist dieser Befehl doch nur den Registern vorbehalten?
unsigned char ports_bit = (1<<von); ------------------------!----------
Moinsen schrieb: > Also ist dieser Befehl doch nur den Registern vorbehalten? Bitte nur im Schritttempo denken.
Moinsen schrieb: > Also ist dieser Befehl doch nur den Registern vorbehalten? Nein, aber er ist bereits existierenden Variablen vorbehalten. Worauf soll die ODER-Verknüpfung denn angewendet werden wenn gleichzeitig die Variable auf der linken Seite erst erzeugt wird?
Ein bisschen irritierend finde ich die Fehlermeldung allerdings schon. Schließlich könnte man ja wirklich wollen, dass einfach der letzte Speicherinhalt mit dem Ausdruck Oder-Verknüpft wird. Auch wenn mir jetzt dafür kein wirkliches Szenario einfällt...
liegt vllt daran, dass ich ports_bit nicht vorher die "0" zugewiesen habe und dieser irgend ein Wert annimmt.
Moinsen schrieb: > liegt vllt daran, dass ich ports_bit nicht vorher die "0" > zugewiesen > habe und dieser irgend ein Wert annimmt. Jain! Es liegt daran, dass die Variable, welche du verändern willst, zu dem Zeitpunkt noch nicht fertig definiert ist. Du kannst sie erst nach abgeschlossener Definition lesend verwenden.
jz23 schrieb: > Ein bisschen irritierend finde ich die Fehlermeldung allerdings schon. Es gibt einen fundamentalen Unterschied zwischen
1 | name = wert; |
und
1 | typ name = wert; |
auch wenn es sehr ähnlich aussieht. Ersteres ist eine Zuweisung, zweiteres eine Definition einer neuen Variable mit Initialisierung. Ersteres gibt es als Variationen auch mit den ganzen logischen und aritmetischen Operationen, letzteres nicht, weil die Variable wie schon gesagt da erst zu existieren beginnt und keinen voherigen Wert hat, mit dem man den Wert rechts verknüpfen könnte. Es gibt keinen sinnvollen Grund, eine "ODER-Initialisierung" zu definieren, da sie legal nicht nutzbar wäre. > Schließlich könnte man ja wirklich wollen, dass einfach der letzte > Speicherinhalt mit dem Ausdruck Oder-Verknüpft wird. Es gäbe einen Weg:
1 | int x = x | 5; |
aber es gibt einfach keine sinnvolle Anwendung dafür, und das Verhalten ist undefiniert.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.