Forum: Mikrocontroller und Digitale Elektronik PORT-BIT Verwendng mit define


von Kenia (Gast)


Lesenswert?

Hallo ich möchte ein Portbit verwenden für ein Eingang und eines für 
einen Ausgang.

Hierbei will ich über define z.B. IN_A für PINA0 definieren
und OUT_A_ON für PORTB0

Sodass ich später im mainprogramm schreiben kann:

If(IN_A==1)
OUT_A_ON;
else
OUT_A_OFF;

was muss im Vorfeld dafür getan werden?


#define IN_A  PINC0;
#define OUT_A_ON  (PORTB |= (1<<PINB0);
#define OUT_A_OFF (PORTB &= ~(1<<PINB0);

Ist das richtig

Danke für Eure Ideen

von Klaus (Gast)


Lesenswert?

so könnte es gehen

#define IN_A      (PIND & (1<< PIND2))
#define OUT_A_ON  (PORTD |= (1<<PD5))
#define OUT_A_OFF (PORTD &= ~(1<<PD5))

int main(void)
{

    DDRD = 0xf0;


    while(1)
    {
        if(IN_A)
        OUT_A_ON;
        else
        OUT_A_OFF;

    }
}

von Karl H. (kbuchegg)


Lesenswert?

Kenia schrieb:
> Hallo ich möchte ein Portbit verwenden für ein Eingang und eines für
> einen Ausgang.
>
> Hierbei will ich über define z.B. IN_A für PINA0 definieren
> und OUT_A_ON für PORTB0
>
> Sodass ich später im mainprogramm schreiben kann:
>
> If(IN_A==1)
> OUT_A_ON;
> else
> OUT_A_OFF;
>
> was muss im Vorfeld dafür getan werden?
>
>
> #define IN_A  PINC0;
> #define OUT_A_ON  (PORTB |= (1<<PINB0);
> #define OUT_A_OFF (PORTB &= ~(1<<PINB0);
>
> Ist das richtig

Makros machen nur Textersetzung.
D.h. wenn du wissen willst, ob das richtig ist, dann ersetze einfach mal 
die Texte.

aus
  if( IN_A == 1 )

wird dann nach der Textersetzung

  if( PINC0; == 1 )

jetzt frag dich: ist das richtig?
(mach ruhig auch bei den anderen Makros die Textersetzung.

Daher: Im Umkehrschluss.
Du schreibst dir dein Programm zuerst so, wie es richtig ist. Also zum 
Beispiel

  if( PINC & (1<<PC0) )


und dann überlegst du dir, welchen Textteil da davon durch einen anderen 
ersetzt haben willst, damit das Ganze in der Verwendung besser lesbar 
wird.

  if( PINC & (1<<PC0) )
müsstest du schreiben. Du möchtest aber gerne schreiben

  if( IN_A )

daher muss der Text IN_A durch den Text PINC & (1<<PC0) ersetzt werden. 
Daher muss dein Makro lauten

#define IN_A  PINC & (1<<PC0)

und natürlich kann man das ganze dann auch noch weiter treiben und 
natürlich gibt es auch noch Stolpersteine und Fallen. Aber im 
wesentlichen läuft es immer aufs gleiche raus: Welcher Programmtext muss 
durch welchen anderen Programmtext ersetzt werden?
Und dazu zäumt man zweckmässigerweise das Pferd von hinten auf. Erst mal 
muss klar sein, welcher Programmtext eigentlich letzten endes rauskommen 
muss.

von Kenia (Gast)


Lesenswert?

Vielen Dank Euch,

aber muss oder kann es statt PC0 auch PINC0 heißen, da mir die 
Intelisense vom AVR Studio das so vorschlägt oder ist das es egal.PC0 
ist schwarz und wenn ich PINC0 schreibe ist die Schrift rosa.

von Karl H. (kbuchegg)


Lesenswert?

Kenia schrieb:
> Vielen Dank Euch,
>
> aber muss oder kann es statt PC0 auch PINC0 heißen, da mir die
> Intelisense vom AVR Studio das so vorschlägt oder ist das es egal.PC0
> ist schwarz und wenn ich PINC0 schreibe ist die Schrift rosa.

Ist wurscht.
PC0, PINC0, PB0, PINB0, ... ist alles dasselbe.
Das sind Makros, die (in diesem Fall) zu einer 0 ersetzt werden.

Im Grunde könnte da auch stehen

  if( PINC & ( 1 << 0 ) )

denn darauf kommt es an: Dass da zu einer 0 (weil Pin 0) expandiert 
wird.

  if( PINC & ( 1 << BIT_0 ) )

wäre besser gewesen, wenn es ein Makro BIT_0 geben würde. Aber aus 
irgendeinem Grund hat man sich dazu entschieden, diese '0' in Form von 
verschiedenen Makronamen zur Verfügung zu stellen. Daher gibt es ein 
PA0, PINA0, PB0, PINB0, PB0, PINC0, DDRA0, DDRB0, etc. etc.
Aber im Grunde sind das nur lauter verschiedene Namen für: 0
Irgendeine gesonderte spezielle Funktionalität ist damit nicht 
verknüpft, dass man der 0 verschiedene Namen gegeben hat.

von Kenia (Gast)


Lesenswert?

der Konstanten IN_A wird 00000001 zugewiesen
durch

#define IN_A  PINC & (1<<PC0)



Bei Abfrage

if( PINC & (1<<PC0) )

fragt ob vom PORTPIN C das Bit0  1 ist oder ?


Ist doch richtig?


Danke vielmals

von Fabian O. (xfr)


Lesenswert?

Karl Heinz Buchegger schrieb:
> if( PINC & ( 1 << BIT_0 ) )
>
> wäre besser gewesen, wenn es ein Makro BIT_0 geben würde.

Bei einem Makro BIT_0 würde ich eher erwarten, dass es gleich als (1<<0) 
und nicht nur als 0 definiert ist. Man braucht ja kein allgemeines Makro 
für 0, das keine zusätzliche Bedeutung hat. Dann schreibt man lieber 
gleich 0 hin.

> Aber aus
> irgendeinem Grund hat man sich dazu entschieden, diese '0' in Form von
> verschiedenen Makronamen zur Verfügung zu stellen. Daher gibt es ein
> PA0, PINA0, PB0, PINB0, PB0, PINC0, DDRA0, DDRB0, etc. etc.
> Aber im Grunde sind das nur lauter verschiedene Namen für: 0
> Irgendeine gesonderte spezielle Funktionalität ist damit nicht
> verknüpft, dass man der 0 verschiedene Namen gegeben hat.

Ich vermute mal, man wollte sich die Option offen halten, dass die Bits 
bei bestimmten Mikrocontrollern anders in den Registern angeordnet sind. 
Also dass DDRA0 bei einem bestimmten Modell 7 statt 0 ist, PINA0 aber 
weiterhin 0.

Soweit ich weiß, gibt es so einen Contoller aber zum Glück nicht. Also 
hat man es beim Xmega aufgeräumt, da gibt es nur noch:
1
#define PIN0_bp 0      // bit position
2
#define PIN0_bm (1<<0) // bit mask

In C ist imo das Bitmask-Makro wesentlich nützlicher, weil man sich dann 
die ganzen (1<<XYZ) sparen kann.

von Fabian O. (xfr)


Lesenswert?

Kenia schrieb:
> der Konstanten IN_A wird 00000001 zugewiesen
> durch
>
> #define IN_A  PINC & (1<<PC0)

IN_A ist keine Konstante! IN_A enthält nichts anderes als den Text, den 
Du definierst hast. Also hier "PINC & (1<<PC0)" (ohne 
Anführungszeichen). Der wird vom Preprozessor vor dem Compilieren an 
allen Stellen eingesetzt, an denen Du im Code IN_A geschrieben hast. 
Mehr passiert dabei nicht.

> Bei Abfrage
>
> if( PINC & (1<<PC0) )
>
> fragt ob vom PORTPIN C das Bit0  1 ist oder ?

Ja. Als Übung solltest Du Dir jetzt noch überlegen, wie Du abfrägst, ob 
das Bit 0 ist. Tipp: if( PINC & (0<<PC0) ) ist falsch.

von Peter D. (peda)


Lesenswert?

1
#include "sbit.h"
2
#define IN_A      PIN_D2
3
#define OUT_A     PORT_D5
4
#define OUT_A_oe  DDR_D5
5
6
int main(void)
7
{
8
    OUT_A_oe = 1;
9
10
    while(1)
11
    {
12
        if(IN_A)
13
          OUT_A = 1;
14
        else
15
          OUT_A = 0;
16
        // oder so:
17
        OUT_A = IN_A; // ist aber mehr Code
18
    }
19
}

http://www.mikrocontroller.net/attachment/157663/sbit.h

Peter

von Kenia (Gast)


Lesenswert?

Klaus schrieb:
> so könnte es gehen
>
> #define IN_A      (PIND & (1<< PIND2))
> #define OUT_A_ON  (PORTD |= (1<<PD5))
> #define OUT_A_OFF (PORTD &= ~(1<<PD5))
>
> int main(void)
> {
>
>     DDRD = 0xf0;
>
>
>     while(1)
>     {
>         if(IN_A)
>         OUT_A_ON;
>         else
>         OUT_A_OFF;
>
>     }
> }

bei erster Zeile muss es doch heißen
#define IN_A (PIN |=(1<<PIND2))

& ist für Check zuständig oder ?

von blub (Gast)


Lesenswert?

Kenia schrieb:
> & ist für Check zuständig oder ?

ne ne. & ist binäres oder. Lies mal Bitmanipulation.

von blub (Gast)


Lesenswert?

Argh! binäres UND natürlich!

von Kenia (Gast)


Lesenswert?

Klaus schrieb:
> so könnte es gehen
>
> #define IN_A      (PIND & (1<< PIND2))
> #define OUT_A_ON  (PORTD |= (1<<PD5))
> #define OUT_A_OFF (PORTD &= ~(1<<PD5))
>
> int main(void)
> {
>
>     DDRD = 0xf0;
>
>
>     while(1)
>     {
>         if(IN_A)
>         OUT_A_ON;
>         else
>         OUT_A_OFF;
>
>     }
> }

was für Werte werden in Zeile 1  verunded, sodass hier nur der 
PORTD-PIN2 gemeint ist

würde wenn ich später OUT_A = 1(0)  schreiben wollte die
Definition so aussehen:

#define OUT_A (PORTD&(1<<PORTD5)

von Karl H. (kbuchegg)


Lesenswert?

Sag mal, machst du das absichtlich, dass du jeglichen Erklärungsversuch, 
dass derartige #define Makros lediglich Textersetzungen sind, 
ignorierst?


> würde wenn ich später OUT_A = 1(0)  schreiben wollte die
> Definition so aussehen:
>
> #define OUT_A (PORTD&(1<<PORTD5)

Setze den Text ein.
Wenn du OUT_A durch den Ersatztext ersetzt, dann wird aus

   OUT_A = 1;

dieses hier

   PORTD &( 1<<PORTD5 ) = 1;

Frage an dich: Ist das Ergebnis korrekt oder nicht?

Wie setzt man denn (ohne von dir geschriebene Makros) einen Portpin 
korekterweise auf 1?

von Peter D. (peda)


Lesenswert?

Kenia schrieb:
> wenn ich später OUT_A = 1(0)  schreiben wollte

Dazu muß OUT_A aber als Bitvariable definiert sein, siehe mein Beispiel.

Die Macros von Klaus können das nicht.


Peter

von Klaus (Gast)


Lesenswert?

>was für Werte werden in Zeile 1  verunded, sodass hier nur der
>PORTD-PIN2 gemeint ist
Ja!
so wie Karl Heinz Buchegger schon sagte ist es eine reine Textersetzung.

>würde wenn ich später OUT_A = 1(0)  schreiben wollte die
>Definition so aussehen:

>#define OUT_A (PORTD&(1<<PORTD5)

Nein!  Für den fall besser Peter Dannegger Beispiel folgen.

von Bernd N (Gast)


Lesenswert?

Vielleicht wird es einfacher wenn du ein zusammenhängendes Beispiel 
siehst. Wenn man Peters Idee folgt dann sieht das so aus...
1
int main (void)
2
{
3
    PORTD = 0xFF;                                                 // Pullups an PortD ON
4
5
    myLED_PIN = isOutput;
6
    myKey_PIN = isInput;
7
8
    for (;;) {
9
        if (myKey == isPressed) {
10
            myLED = ON;
11
        } else {
12
            myLED = OFF;
13
        }
14
    }
15
}

Wobei ich denke das du auf einen deratrtigen Code aus bist.

Dazu machst du dir folgendes .h file...
1
#ifndef global_h
2
#define global_h
3
4
#include <stdint.h>                                             /* ISO C99 Integer types                       */
5
#include <avr/io.h>                                             /* ATMEGA-32 I/O's                             */
6
#include <util/delay.h>                                         /* delay Lib.                                  */
7
8
/* ---- Define BIT Variablen --------------------------------------------------------------------------------- */
9
/*                                                                                                             */
10
#define ON  1                                                   /* digital High Pegel                          */
11
#define OFF 0                                                   /* digital Low Pegel                           */
12
#define isOutput 1
13
#define isInput 0
14
#define isPressed 0
15
16
/* ---- Define I/O's, AVR I/O's sind nicht BITadressierbar! -------------------------------------------------- */
17
/*                                                                                                             */
18
struct bits {
19
    uint8_t b0:1;
20
    uint8_t b1:1;
21
    uint8_t b2:1;
22
    uint8_t b3:1;
23
    uint8_t b4:1;
24
    uint8_t b5:1;
25
    uint8_t b6:1;
26
    uint8_t b7:1;
27
} __attribute__((__packed__));
28
29
#define SBIT(port,pin) ((*(volatile struct bits*)&port).b##pin) /* I/O Defines vereinfachen                    */
30
31
/* ---- Define Signale --------------------------------------------------------------------------------------- */
32
/*                                                                                                             */
33
#define myLED       SBIT (PORTD, 7)                             /* LED Signal                                  */
34
#define myLED_PIN   SBIT (DDRD, 7)
35
36
#define myKey       SBIT (PIND, 6)
37
#define myKey_PIN   SBIT (DDRD, 6)
38
#define myKeyPullup SBIT (PORTD, 6)
39
#endif

Das ganze habe ich kurz auf dem ATMEGA 32 getestet.

von Kenia (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> daher muss der Text IN_A durch den Text PINC & (1<<PC0) ersetzt werden.
> Daher muss dein Makro lauten
>
> #define IN_A  PINC & (1<<PC0)

Du meinst wohl

#define IN_A (PINC |= (1<<PC0))

von Karl H. (kbuchegg)


Lesenswert?

Kenia schrieb:
> Karl Heinz Buchegger schrieb:
>> daher muss der Text IN_A durch den Text PINC & (1<<PC0) ersetzt werden.
>> Daher muss dein Makro lauten
>>
>> #define IN_A  PINC & (1<<PC0)
>
> Du meinst wohl
>
> #define IN_A (PINC |= (1<<PC0))

Nein. Meinte ich nicht

Bitmanipulation

Und jetzt wirds Zeit, dass du die Operationen mal mit ein paar 
Bytewerten und Pinwerten auf dem Papier durchprobierst.

Die 3 Operationen | & ~ musst du in der µC Programmierung im Schlaf 
beherrschen, was sie machen und wie und warum man sie einsetzt.

von Peter D. (peda)


Lesenswert?

Kenia schrieb:
> Du meinst wohl
>
> #define IN_A (PINC |= (1<<PC0))

Damit wird PORTC.0 getoggled und alle anderen gelöscht, sofern sie 
Ausgänge sind.
Wozu brauchst Du sowas?


Peter

von Sven P. (Gast)


Lesenswert?

Bernd N schrieb:
> Das ganze habe ich kurz auf dem ATMEGA 32 getestet.
Mache ich auch so. Zwei Anmerkungen hätte ich dazu aber dennoch:
1
#define SBIT(port,pin) ((*(volatile struct bits*)&port).b##pin)

Da würde ich um 'port' noch eine Klammer setzen und ich würde indirekt 
expandieren. Momentan hast du folgendes Problem:
1
#define PIN 1
2
#define PORT 0xAA+2
3
#define SBIT(port,pin) ((*(volatile struct bits*)&port).b##pin)
4
5
SBIT(PORT, PIN)
6
/* expandiert zu */
7
((*(volatile struct bits*)&0xAA+2).b##PIN)

Formulierst du aber so:
1
#define SBIT2(port,pin) ((*(volatile struct bits*)&(port)).b##pin)
2
#define SBIT(port,pin) SBIT2(port,pin)
dann funktionierts. Macro Magic :-)

von Sven P. (Gast)


Lesenswert?

Und noch etwas:
Die Struktur ist mit 'volatile' qualifiziert. Wenn man das Dingen nun 
für einfache Variablen benutzt, wird der Quelltext ganz fürchterlich 
ineffizient.

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
Noch kein Account? Hier anmelden.