Hallo, Ich habe volgendes problem: PORTB = 0xff; funktioniert ohne probleme mit WinAVR, aber PA0 = 1; will einfach nicht, ich bekomme dannn folgenden fehler: error: invalid lvalue in assignment Woran kann das liegen??? PS: Ich hab die neuste version von winAVR MFG Jörn
Siehste, dass ist jetzt genau so ein Fehler, der durch die furchterregende Programmiertechnik mit direkter Hardware-Adressierung herrührt, obwohl Atmel diese Schreibweise neuerdings ja propagiert. Aber nicht alles, was der Hersteller sagt, muss auch zwangsläufig gut sein. Aber so oder so PORTB bezeichnet einen Port. Auf einen Port darf man mit direkter Zuweisung zugreifen. PA0 bezeichnet hingegen einen einzelnen Portpin. Auf diesen kannst du nicht direkt zugreifen. Um ein Bit auf dem Port zu setzen kannst du z.B. folgende Anweisung verwenden: PORTA |= (1 << PA0); Dabei bleiben die restlichen Pins unberührt. Um ein Bit zu löschen nimmst du entsprechend PORTA &= ~(1 << PA0); Gruss Christian
Christian, Deine Polemik in allen Ehren, aber Du willst doch nicht ernsthaft behaupten, daß outp(1 << PA0, PORTA); wesentlich einleuchtender und weniger error-prone war. ;-) Erstens wäre da die unsinnige vertauschte Argumentreihenfolge, zweitens kann man genauso schöne Verständnisfehler machen wie outp(PA0, PORTA); :-) Nee, Du, an der direkten Zuweisung liegt's wirklich nicht. Eher daran, daß es ziemlich blödsinnig ist, für ein und dieselbe Zahl 0 so viele verschiedene #defines zu haben, daß kein Mensch mehr weiß, welche davon wirklich gebraucht werden... Was bitte soll der Unterschied zwischen PA0, PINA0, DDRA0 usw. sein? Das Ganze dann nochmal mit PORTB, PORTC, PORTD, PORTE, PORTF, und ein ATmega128 hat auch noch PORTG... 21 verschiedene Varianten, die Ziffer 0 zu schreiben. Wenn man den Unfug nicht benutzt (auch wenn der ebenfalls aus den Atmel-Datenblättern stammt), wird der Fehler dann auch sofort offensichtlich: 0 = 1; kann nicht funktionieren. ;-) PORTA |= _BV(0); dagegen wohl schon eher. (Wer _BV() nicht mag, kann es ja ruhig ausschreiben, aber ich finde, daß es die Lesbarkeit etwas verbessert, vor allem wenn man mehr als ein Bit setzen will.)
Ich bin auch noch ein ziemlich Anfänger, aber ich mach das atm z.b. so: sbi(PORTD,PD6); Ob das stylistisch so gut ist weiß ich nicht, aber zumindest ich komme damit gut zurecht ;)
Es ist abgekündigt. ;-) Naja, noch nicht ganz, aber es läuft unter `deprecated'. Vom generierten Code her ist es identisch zu PORTD |= 1 << PD6; (wie Du Dir in den Macros selbst ansehen kannst).
Hi erstmal danke für die antworten!! Ich versteh aber trotzdem nicht warum PA0 = 1; in vielen anderen C Programmen funktioniert die ich mir als Beispiel angeschaut habe. Liegt das am Compiler? AVR-GCC? MFG Jörn
Ich denke, das ist alles nur eine Gewöhnungssache. Obwohl ich zugeben muß, daß mir die Keil-C51 Lösung besser gefällt: sbit GRAY_A = P1^1; Da ist dann in einem Namen sowohl die Byteadresse als auch die Bitnummer mit drin. Ich kann es also wie jede andere Variable ansprechen, z.B.: GRAY_A = 1; Peter
@Jörn wer schreibt denn PA0 = 1 irgendwo? Habe ich noch nicht gesehen. Die aktuelle avr-gcc Version folgt schlicht der Atmel-Konvention, und die wiederum dürfte in Zusammenarbeit mit IAR entstanden sein. Was ich (für andere Controller) schon gesehen habe, ist sowas wie PORTX.0 = 1; Dabei ist mir aber die C-syntaktische Auflösung des Knotens unklar. Nach einem Punkt müßte ein struct tag folgen, aber eine Zahl oder Ziffer ist kein gültiger struct tag. @Peter Hmm, wäre sicher machbar, Du kannst dann eben nur nicht mehrere Bits eines Registers in einer Anweisung setzen, oder übersehe ich da was? Anyway, Atmel hat sich das halt nicht so ausgedacht.
Wusste gar nicht das sbi() deprecated ist, zumindest stehts so nicht in meiner libc Beschreibung, die bei WinAVR dabei war ;)
Ja, es ist noch keiner dazu gekommen, das endlich mal aufzuschreiben. ;-)
@Joerg Wunsch In dem angehängten programm zum Beispiel: #define RESET PORTD.5 RESET = 1; RESET = 0; So wie da würd ich das auch gerne Programmieren und statt der Zahl eventuell eine Variable einsetzen die 1 oder 0 enthält. Funktioniert aber leider nur mit einem kompletten port. MFG Jörn
Ist aber nicht das, was Du weiter oben geschrieben hast, sondern vielmehr das, was ich selbst auch als ,,unklare C-Syntax'' beschrieben habe. Ich weiß wirklich nicht, wie man das innerhalb der C-Syntax unterbekommt. Nichtsdestotrotz machen es einige Compilerhersteller so. War mir bisher nur in der MCS51-Welt untergekommen, bei AVR noch nicht. Für welchen Compiler ist das denn?
@Joerg Wunsch Leider weis ich selbst nicht für welchen compiler das prog ist, ich hab das zufällig in der codesammlung gefunden. MFG Jörn
@Jörg: Habe mal ein paar Codeabrisse gesammelt, die das von Jörn gewünschte Verhalten beschreiben. Die von dir angesprochen "unklare C-Syntax" läßt sich prima (und sauber) über #defines herstellen. Greenhills C-Compiler für NEC: --------------------------------------- struct bitf { unsigned char bit00:1; unsigned char bit01:1; [usw.] }; #define P0 *((volatile unsigned char *)0xfffff000) #define P0_0 ((volatile struct bitf *)0xfffff000)->bit00 dann: P0_0=1; --------------------------------------- Codewarrior für Motorola: --------------------------------------- extern volatile PORTBSTR _PORTB @(REG_BASE + 0x00000001); #define PORTB _PORTB.Byte #define PORTB_BIT0 _PORTB.Bits.BIT0 Zugriff über: PORTB_BIT0=1; --------------------------------------- Softune für Fujitsu: --------------------------------------- typedef union{ /* PORT DATA Registers */ IO_BYTE byte; struct{ IO_BYTE P00 :1; IO_BYTE P01 :1; [usw.] }bit; }PDR0STR; __IO_EXTERN __io PDR0STR _pdr0; /* PORT DATA Registers */ #define PDR0 _pdr0.byte #define PDR0_P00 _pdr0.bit.P00 Zugriff über: PDR0_P00=1; --------------------------------------- Vorteil (wie von Jörn schon geäußert): Direkter Zugriff auch auf Portbits mittels Zuweisung. Keine "Kunstgriffe" wie _BV() oder Bitschiebereien. Widerspricht hierbei was der C-Syntax? Warum kann das AVR-GCC nicht? Liegt es daran, daß auf die IO-Register nicht wie auf RAM zugegriffen werden kann und folglich auch kein Bitfeld darübergestülpt werden kann? Schmittchen.
Das würde mit dem GCC funktionieren, wird auch im MSP430-Port so ähnlich gemacht. Dagegen spricht, dass ein Compiler die Bits theoretisch in belibiger Reihenfolge im Speicher anordnen darf.
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.