mikrocontroller.net

Forum: Compiler & IDEs Port, Pin auf 1 oder null setzen


Autor: Jörn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Christian Schifferle (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Joerg Wunsch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.)

Autor: Christoph (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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 ;)

Autor: Joerg Wunsch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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).

Autor: Jörn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Joerg Wunsch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@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.

Autor: Christoph (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wusste gar nicht das sbi() deprecated ist, zumindest stehts so nicht in
meiner libc Beschreibung, die bei WinAVR dabei war ;)

Autor: Joerg Wunsch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, es ist noch keiner dazu gekommen, das endlich mal aufzuschreiben.
;-)

Autor: Jörn (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
@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

Autor: Joerg Wunsch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: Jörn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@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

Autor: Schmittchen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@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.

Autor: Andreas Schwarz (andreas) (Admin) Benutzerseite Flattr this
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

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.