Hallo, ist es möglich ein Makro zum setzen einzelner Ausgänge zu schreiben? So funktioniert es leider noch nicht :-) #define Servo1_ein (PORTD |= (1<<PD0)); #define Servo1_aus (PORTD |= (0<<PD0)); int main(void) { DDRD |= (1<<PD0); while (1) { Servo1_ein; _delay_ms(500); Servo1_aus; _delay_ms(500); } }
:
Verschoben durch User
Bimbo. schrieb: > Ich meine natürlich: >
1 | > #define Servo1_aus (PORTD &= ~(1<<PD0)); |
2 | >
|
ja, bin grad dabei ein C-Buch zu lesen. ich verstehe jedoch nicht wirklich, warum ich das Bit negieren soll anstatt eine 0 hineinzuschreiben (~ steht aber auch so im Buch). Das mit der 0 wirkt für mich übersichtlicher, gibt es einen Grund dafür? Dies funktionier ja nun auch: #define Ein (PORTD |= (1<<PD0)) #define Aus (PORTD &= (0<<PD0)) <- sollte ich dies unterlassen? int main(void) { DDRD |= (1<<PD0); while (1) { Ein; _delay_ms(500); Aus; _delay_ms(500); } }
:
Bearbeitet durch User
Philipp L. schrieb: > Das mit der 0 wirkt für mich übersichtlicher, gibt es einen Grund dafür? Du kannst eine 0 hundertmal schieben, es bleibt eine 0. Eine Variable oder ein Register mit 0 zu verodern ergibt keine Änderung des selben.
C-Buch GRÜNDLICH durchlesen ;). #define Aus (PORTD &= (0<<PD0)) ist das selbe wie #define Aus (PORTD &= 0); Und wenn du etwas mit 0 undest kommt 0 heraus. Liesnochmal ganz ganz genau nach, was |=, &=, ~, ^= etc. so machen.
PS: #define Aus (PORTD &= (0<<PD0)) macht alle Bits, nicht nur PD0 sondern auch PD1-PD7 zu 0.
Suche mal im Forum nach sbit.h von Peter Dannegger. Dann würde dein Code in etwa so aussehen: #include "sbit.h" #include // anderes
1 | #define SERVO PORT_D0
|
2 | #define SERVO_oe DDR_D0
|
3 | |
4 | #define EIN 1
|
5 | #define AUS 0
|
6 | #define OUTPUT 1
|
7 | |
8 | int main() |
9 | {
|
10 | SERVO_oe = OUTPUT; |
11 | |
12 | while(1) |
13 | {
|
14 | SERVO = EIN; |
15 | _delay_ms(500); |
16 | SERVO = AUS; |
17 | _delay_ms(500); |
18 | }
|
19 | }
|
Philipp L. schrieb: > ich verstehe jedoch nicht wirklich, warum ich das Bit löschen soll, > anstatt eine 0 hineinzuschreiben. > Das mit der 0 wirkt für mich übersichtlicher, gibt es einen Grund dafür? Es gibt einen Grund: es funktioniert nicht. Nimm doch mal das Statement auseinander: - Du schreibst ein ein (temporäres) Register eine Null und schiebst die nach links um PD0 Stellen (0<<PD0). (PDx enthält eine einfache Integerzahl von 0...7). Bleibt Null. Jetzt machst du ein OR mit '0' und dem bisherigen Inhalt von PORTD. Bewirkt rein gar nichts. Im anderen Fall schiebst du eine '1' um x Stellen nach links (1<<PD0). Gibt bei PD0 eine temporäre '1' bzw. 0x01. Das wird invertiert zu 0xFE. Und das wiederum verUNDest du mit dem Inhalt von PORTD. Damit wird die rechte Stelle auf Null gesetzt, die andern bleiben unberührt. Das wolltest du.
Philipp L. schrieb: > Bimbo. schrieb: >> Ich meine natürlich: >>
1 | >> #define Servo1_aus (PORTD &= ~(1<<PD0)); |
2 | >>
|
> > ja, bin grad dabei ein C-Buch zu lesen. > > ich verstehe jedoch nicht wirklich, warum ich das Bit negieren soll > anstatt eine 0 hineinzuschreiben (~ steht aber auch so im Buch). > Das mit der 0 wirkt für mich übersichtlicher, gibt es einen Grund dafür? Weil AND keine Zuweisung ist! Die Negation des Bits erzeugt eine Maske, bei der alle Bits, außer dem einen, gesetzt sind, bei AND also nicht gelöscht werden. > Dies funktionier ja nun auch: > > #define Ein (PORTD |= (1<<PD0)) > #define Aus (PORTD &= (0<<PD0)) <- sollte ich dies unterlassen? Ja, denn so werden ALLE PORTD Bits gelöscht.
Philipp L. schrieb: > Dies funktionier ja nun auch: > > #define Ein (PORTD |= (1<<PD0)) > #define Aus (PORTD &= (0<<PD0)) <- sollte ich dies unterlassen? Ja, das funktioniert - in deinem Fall. Aber es löscht nicht nur PD0 sondern den ganzen PORTD. Und wenn da was anderes stand? Dann ist es auch gelöscht!
HildeK schrieb: > Nimm doch mal das Statement auseinander: > - Du schreibst ein ein (temporäres) Register eine Null und schiebst die > nach links um PD0 Stellen (0<<PD0). (PDx enthält eine einfache > Integerzahl von 0...7). Bleibt Null. Jetzt machst du ein OR mit '0' und > dem bisherigen Inhalt von PORTD. Bewirkt rein gar nichts. > > Im anderen Fall schiebst du eine '1' um x Stellen nach links (1<<PD0). > Gibt bei PD0 eine temporäre '1' bzw. 0x01. Das wird invertiert zu 0xFE. > Und das wiederum verUNDest du mit dem Inhalt von PORTD. Damit wird die > rechte Stelle auf Null gesetzt, die andern bleiben unberührt. > Das wolltest du. Vielen Dank! das hatte ich etwas falsch verstanden... Noch eine Frage, welche aus deiner Antwort kommt: Der Befehl "Port_D0 = x" aus der Lib ist gut, aber wie setze ich ohne zusatz Lib einen einzelnen Ausgang in Abhängigkeit einer Variable? Ich habe hier im Forum unter Beitrag "Variable an Ausgang zuweisen" auch nur einen Thread gefunden, bei dem dies durch eine If-abfrage gelöst ist. Das kommt mir recht umständlich vor, konnte ich in Basic doch auch immer schreiben: PORTB.0 = x Das Thema habe ich auch schon "verzweifelt" im Buch gesucht..
:
Bearbeitet durch User
Philipp L. schrieb: > Der Befehl "Port_D0 = x" aus der Lib ist gut, aber wie setze ich ohne > zusatz Lib einen einzelnen Ausgang in Abhängigkeit einer Variable? Dafür sind die Makros ins sbit.h eher nicht geeignet. Da aber die Portnummerierung PD0...PD7 soweit mir bekannt ist immer letztlich mit den Zahlen 0..7 belegt sit, kannst du auch direkt schreiben (i sei die Variable): PORTD |= (1<<i) zum setzen bzw. PORTD &= ~(1<<i) zum löschen. Das gilt natürlich auch für andere Ports. Also einfach die herkömmliche Variante verwenden. Das geht natürlich auch, wenn man sonst im Programm sbit.h verwendet.
HildeK schrieb: > Philipp L. schrieb: >> Der Befehl "Port_D0 = x" aus der Lib ist gut, aber wie setze ich ohne >> zusatz Lib einen einzelnen Ausgang in Abhängigkeit einer Variable? > > Dafür sind die Makros ins sbit.h eher nicht geeignet. > Da aber die Portnummerierung PD0...PD7 soweit mir bekannt ist immer > letztlich mit den Zahlen 0..7 belegt sit, kannst du auch direkt > schreiben (i sei die Variable): > PORTD |= (1<<i) zum setzen bzw. PORTD &= ~(1<<i) zum löschen. > Das gilt natürlich auch für andere Ports. > Also einfach die herkömmliche Variante verwenden. Das geht natürlich > auch, wenn man sonst im Programm sbit.h verwendet. Ja, ich meinte aber eher folgendes Beispiel: #int x=0; int main(void) { DDRD |= (1<<PD0); while (1) { PORT_D0 = x; <-- Ist dies auch ohne sbit.h übersichtlich darstellbar? } } interruptroutine: if_xxx X=1 if_xxx X=0
:
Bearbeitet durch User
Philipp L. schrieb: > PORT_D0 = x; <-- Ist dies auch ohne sbit.h übersichtlich > darstellbar? Wenn du PORT_D0 verwendest, dann brauchst du sbit.h. Und x kann in dem Zusammenhang nur 0 oder 1 sein: den Pin D0 setzen oder rücksetzen. Was willst du mit dem x erreichen?
Philipp L. schrieb: > ich verstehe jedoch nicht wirklich, warum ich das Bit negieren soll > anstatt eine 0 hineinzuschreiben Naja Lesen ist das eine. Versuchen zu verstehen was da passiert ist halt das Andere. Vollziehe die Bitoperation mal von Hand. Dann sollte es klar werden. Einfach Copy&Paste von Dingen die man nicht versteht hilft nicht weiter.
Btw: Wenn Du "x" in einer ISR verändern möchtest muss es "volatile" sein.
HildeK schrieb: > Dafür sind die Makros ins sbit.h eher nicht geeignet. Natürlich geht das, probiers aus. x sollte aber von Typ bool sein, d.h. 0 oder 1. Sollen auch andere Werte als true zugelassen sein, kann man schreiben:
1 | PORT_D0 = !!x; |
Peter D. schrieb: > HildeK schrieb: >> Dafür sind die Makros ins sbit.h eher nicht geeignet. > > Natürlich geht das, probiers aus. > x sollte aber von Typ bool sein, d.h. 0 oder 1. > Sollen auch andere Werte als true zugelassen sein, kann man schreiben: > PORT_D0 = !!x; Das schon, ich hatte verstanden, dass er die Portnummer als Variable wollte.
Ich habe jetzt die sbit.h eingebunden und bin sehr überrascht über die Größe. Bei dem Testprogramm (siehe Anhang) ist der Code ohne die sbit.h 106 Bytes und mit der Sbit.h nur 104 Bytes groß. Das sagt zumindest "myAVR ProgTool" beim brennen. eigentlich müsste der Code doch größer werden ?
Philipp L. schrieb: > eigentlich müsste der Code doch größer werden ? Nein. Es wird ja deutlich, dass nur dieses Bit gesetzt/gelöscht werden soll, das ist weniger Aufwand als es vorher noch zu lesen
Peter D. schrieb: > PORT_D0 = !!x; Du schreibst an der Frage vorbei, welche lautete: wie geht's ohne (D)eine Lib? Philipp L. schrieb: > wie setze ich ohne > zusatz Lib einen einzelnen Ausgang in Abhängigkeit einer Variable? > konnte ich in Basic doch auch immer > schreiben: PORTB.0 = x Das geht in C nicht über einen einzelnen Befehl, das muss man zusammenbasteln und dürfte in etwa so entsprechen: > uint8_t x = 1; > PORTB = ((PORTB & ~(1 << PB0)) | ((x & 0x01) << PB0)); > x = 0; > PORTB = ((PORTB & ~(1 << PB0)) | ((x & 0x01) << PB0)); Ist x ein Bool oder wird nie größer 1, kann (x & 0x01) durch x ersetzt werden.
Was man alles bei einem Blinkprogramm lernen kann :-) Naja, aller Anfang ist schwer.. > das ist weniger Aufwand als es vorher noch zu lesen PORTD = 0xff; Ich dachte dies ist eine reine Zuweisung, warum lesen.. > Es wird ja deutlich, dass nur dieses Bit gesetzt/gelöscht werden soll Schon, aber mittels unterroutine durch sbit.h Ich dachte, hier muss mehr abgearbeitet werden..
A. S. schrieb: > Es wird ja deutlich, dass nur dieses Bit gesetzt/gelöscht werden soll, > das ist weniger Aufwand als es vorher noch zu lesen Es wird auch im anderen Fall nicht gelesen. Der eigentliche Grund dürfte sein, dass beim Prozessor der PORTD im per SBI zu erreichenden IO-Adressbereich bis 0x1F liegen dürfte und ein SBI PORTD, 0 nur ein Opcode ist, während ein PORTD = 0xff zu LDI Rxx, 0xff und STS PORTD, Rxx wird, das sind zwei Opcodes.
Philipp L. schrieb: > Ich habe jetzt die sbit.h eingebunden und bin sehr überrascht über die > Größe. > > Bei dem Testprogramm (siehe Anhang) ist der Code ohne die sbit.h 106 > Bytes und mit der Sbit.h nur 104 Bytes groß. Die beiden Codeschnipsel machen auch nicht dasselbe. Links setzt du alle PORTD-Pins auf HIGH bzw. LOW, rechts nur D0!
> Die beiden Codeschnipsel machen auch nicht dasselbe. Links setzt du alle > PORTD-Pins auf HIGH bzw. LOW, rechts nur D0! Schon, aber mittels unterroutine durch sbit.h Ich dachte, hier muss mehr abgearbeitet werden..
:
Bearbeitet durch User
Philipp L. schrieb: > Schon, aber mittels unterroutine durch sbit.h Da sind meiner Erinnerung nach nur oder fast nur #defines drin. Es werden nur Texte ersetzt.
Ist es möglich, einen Eingang ohne IF-Abfrage als 1 (0x01) oder 0 (0x00) in eine Variable zu schreiben? in meinem Buch "AVR-Mikrocontroller - Programmierung in C" (evtl. kein gutes) ist dies nur mittels IF-Abfragen gelöst: z.B. If (PINB & (1<<PB2)); X = 1; ich würde mir so etwas wünschen: #define Taster (PINB2) X = Taster Es soll nicht das ganze Eingangsregister von PINB in x geschrieben werden, sondern der Eingang (z.b.PB2) in das unterse Bit von X. also wenn das Register PINB=xxxxx1xx -> X = 0x01
:
Bearbeitet durch User
Schau dir das mal an: Beitrag "Re: Attiny85 Pin als Eingang" Basic und C sjnd nunmal unterschiedliche Sprachen mit unterschiedlicher Syntax.
Philipp L. schrieb: > z.B. > If (PINB & (1<<PB2)); > X = 1; // C++ bool X = (PINB & (1<<PB2)); // C uint8_t X = (PINB & (1<<PB2)) > 0;
Philipp L. schrieb: > PORTD = 0xff; > Ich dachte dies ist eine reine Zuweisung, warum lesen.. Sorry, hatte gedacht bezogen auf die verodern. Schaue mir Quelltext als Bild ungern an, hier ging's aber. Kenne auch deinen Prozessor nicht, ob er bitbefehle hat. Das sind aber dankbare Aufgaben, um Listings mit Assembler Mal zu erforschen.
>// C > uint8_t X = (PINB & (1<<PB2)) > 0; Aus andrem Thread >x = (PORTA & (1 << BIT)) == (1 << BIT) Wo ist denn der Unterschied, ob ich PINx oder PORTx schreibe ?
Philipp L. schrieb: > ich würde mir so etwas wünschen: > > #define Taster (PINB2) > X = Taster Geht auch mit der sbit.h x = PIN_B2;
Philipp L. schrieb: > Wo ist denn der Unterschied, ob ich PINx oder PORTx schreibe ? PORTx wird dauerhaft High sein, wenn der Pullup aktiviert ist. Aber dennoch ist PINx dann u.U. Low, z.B. wenn der daran angeschlossene Taster betätigt wird.
Philipp L. schrieb: > Wo ist denn der Unterschied, ob ich PINx oder PORTx schreibe ? Da könntest du einen Blick in das Datenblatt deines (unbekannten) Prozessors werfen. Meist gibt es dort ein ganzes Kapitel, dass sich mit dem Zusammenwirken der Register bei einem GPIO beschäftigt (inkl. Blockschaltbild)
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.