Forum: Mikrocontroller und Digitale Elektronik define Ausdruck mit shift in 2 Richtungen


von Thorsten S. (whitejack)


Lesenswert?

Hi,

wie wird dieses Makro behandelt?

#define TEST(x)     ((x>>1)<<3)

geht das?

T.S.

von Uwe (de0508)


Lesenswert?

klar, warum denn nicht ?

Wir wissen aber nicht warum das so sein soll, deshalb zur Sicherheit
1
#define TEST(x)     (((x)>>1)<<3)

Die Expansion hängt entscheidend auf Datentyp von x ab.

von Thorsten S. (whitejack)


Lesenswert?

es geht darum dass ich für mein LCD alle pins einzeln frei 
konfigurierbar gemacht habe und jetzt ein Makro mit einem 8-Bit Port 
erstelle.

Das Dipslay ist im 8 Bit Modus betrieben.

#define LCD_P_D0          7
#define LCD_R_D0_OUT      PORTD

#define LCD_P_D1          2
#define LCD_R_D1_OUT      PORTC

#define LCD_P_D2          0
#define LCD_R_D2_OUT      PORTA

etc...


#define LCD_DATA_MAK0(x) 
LCD_R_D0_OUT&=((((x)>>0)<<LCD_P_D0)|(~(1<<LCD_P_D0)))
#define LCD_DATA_MAK1(x) 
LCD_R_D1_OUT&=((((x)>>1)<<LCD_P_D1)|(~(1<<LCD_P_D1)))
#define LCD_DATA_MAK2(x) 
LCD_R_D2_OUT&=((((x)>>2)<<LCD_P_D2)|(~(1<<LCD_P_D2)))
#define LCD_DATA_MAK3(x) 
LCD_R_D3_OUT&=((((x)>>3)<<LCD_P_D3)|(~(1<<LCD_P_D3)))
#define LCD_DATA_MAK4(x) 
LCD_R_D4_OUT&=((((x)>>4)<<LCD_P_D4)|(~(1<<LCD_P_D4)))
#define LCD_DATA_MAK5(x) 
LCD_R_D5_OUT&=((((x)>>5)<<LCD_P_D5)|(~(1<<LCD_P_D5)))
#define LCD_DATA_MAK6(x) 
LCD_R_D6_OUT&=((((x)>>6)<<LCD_P_D6)|(~(1<<LCD_P_D6)))
#define LCD_DATA_MAK7(x) 
LCD_R_D7_OUT&=((((x)>>7)<<LCD_P_D7)|(~(1<<LCD_P_D7)))


#define LCD_DATA_PORT_OUT(y) 
LCD_DATA_MAK0(y);LCD_DATA_MAK1(y);LCD_DATA_MAK2(y);LCD_DATA_MAK3(y);LCD_ 
DATA_MAK4(y);LCD_DATA_MAK5(y);LCD_DATA_MAK6(y);LCD_DATA_MAK7(y)


T.

von Thorsten S. (whitejack)


Lesenswert?

wird das lins und rechts schieben mit 2 Konstanten vorher berechnet oder 
auf dem Prozessor ausgefürt?

wenn ich

(((x)>>1)<<3)

habe, ist ja klar dass es x<<2 ist...

Das Makro oben muss noch einen kleinen Haken haben...

T.

von Uwe (de0508)


Lesenswert?

Hallo Thorsten,

Thorsten S. schrieb:
> wird das lins und rechts schieben mit 2 Konstanten vorher berechnet oder
> auf dem Prozessor ausgefürt?

Das steht im ASM File..

> wenn ich
>
> (((x)>>1)<<3)
>
> habe, ist ja klar dass es x<<2 ist...

Nein.

Bsp.: x:=0b00001111
(1) x>>1
x':= 0b00000111

(2) x<<3
x'':= 0b00111000

Versuche bitte verbal zu beschreiben was das Macro machen soll:
1
#define LCD_DATA_MAK0(x) \
2
LCD_R_D0_OUT&=((((x)>>0)<<LCD_P_D0)|(~(1<<LCD_P_D0)))

von Uwe (de0508)


Lesenswert?

Schöner finde ich dieses Macro:
1
#ifndef SBIT
2
struct bits {
3
  uint8_t b0:1;
4
  uint8_t b1:1;
5
  uint8_t b2:1;
6
  uint8_t b3:1;
7
  uint8_t b4:1;
8
  uint8_t b5:1;
9
  uint8_t b6:1;
10
  uint8_t b7:1;
11
} __attribute__((__packed__));
12
13
#define SBIT_(port,pin) ((*(volatile struct bits*)&port).b##pin)
14
#define  SBIT(x,y)  SBIT_(x,y)
15
#endif

Man kann schreiben:
1
SBIT(PORTA,1) = 0; 
2
SBIT(PORTA,2) = 1;

und
1
if ( SBIT(PINA,0) == 0 ) { /* test */ } 
2
uint8_t j = SBIT(PINA,3);

von Peter D. (peda)


Lesenswert?


von Uwe (de0508)


Lesenswert?

Danke Peter,

jetzt hat Thorsten kaum noch etwas zum nachdenken.

Deine LCD Routine läuft super, danke dafür.

von Thorsten S. (whitejack)


Lesenswert?

Hi,

das muss ich mir erstmal auf der Zunge zergehen lassen, also das SBIT 
Makro.

Ich suche ein/e Makro/Funktion bei dem/r ich einen 8 Bit Wert übergebe 
und alle 8 Pins mit Portregister und Pinnummer angeben kann.

Eine möglichkeit war für mich das abfragen des Bits in dem übergebenen 8 
bit Wert und dann das Setzen oder Rücksetzen des entsprechenden Pins.

Eine weitere wäre den übergebenen 8 bit Wert zu maskieren und dann in 
den PORT einzumaskieren.

Es gibt sicher noch mehr, ich möchte es nicht unnötig kompliziert 
machen. Ziel ist es möglichst codereduziert zu erzeugen und dennoch 
einige Freiheiten zu haben.Ich werde dieses Makro auch für andere Dinge 
nutzen.

Ich denke den Fehler in meinem habe ich gefunden, werde ich gleich 
ausprobieren.

Zu dem Shiften:

wenn ich es so schreibe:

((x)>>1<<3)

das geht auch nicht!

Das Problem entsteht dadurch, dass ich weiß wo das bit in dem 
übergebenen 8 bit Wert steht, aber nicht welchen Pin der User angibt. 
Wenn das bit 1 in dem 8 bit Wert nach Pin 3 soll, dann muss es 2 nach 
links, wenn es nach Pin 0 soll dann muss es einen nach recht... dadurch 
kommt die Frage zustande.

T.

von Thorsten S. (whitejack)


Lesenswert?

...hier jetzt noch meine Lösung in einem Beispiel für ein Bit des 8 Bit 
Wertes x - ich habe das Problem gefunden.

#define LCD_R_D0_OUT     PORTB
#define LCD_P_D0         3

LCD_R_D0_OUT=(LCD_R_D0_OUT&(~(1<<LCD_P_D0)))|((((x)>>0)<<LCD_P_D0)&(1<<L 
CD_P_D0));

Es ist sicher nicht die codeärmste sondern eher die codeintensivste, 
oder?

Wie kann ich denn mein Problem am besten lösen? Heute Nachmittag mache 
ich mich mal über Eure Sachen oben her.

T.

von Matthias L. (Gast)


Lesenswert?

>Versuche bitte verbal zu beschreiben was das Macro machen soll

Ich befürchte, dass er zu wenig Hirnschmalz in die Hardware steckt.

Natürlich kann man das LCD beliebig an die Pins des uC anschliessen.

Aber manchmal macht es eben Sinn wenn man die Bitwertigkeiten des 
Display an dieselben des uC anschliesst:

LCD_D0 - Portx_0
LCD_D1 - Portx_1
...
LCD_D7 - Portx_7

von T.S. (Gast)


Lesenswert?

@Uwe

was passiert wenn ich:

SBIT(PORTA,1) = 0xA3;

schreibe,oder:

SBIT(PORTA,1) = 0x40;

@Matthias

ich finde es ja nett dass du dir um meinen Hirnschmalz gedanken machst, 
aber manchmal hat man am Controller Pins die hardwaremäßig eindeutig 
einer Zusatzfunktion zugeschrieben werden. Ich befürchte daran hast du 
nicht gedacht, oder? Schau mal ins Datanblatt es gibt da (Serielle 
Schnittstellen, AD-Wandler, PWM Kanäle und viele weitere Funktionen im 
Controller die man nutzen kann) und die sind sehr häufig anscheinend 
fast wahllos über die I/Os verteilt.

Gruß,
T.

von Matthias L. (Gast)


Lesenswert?

Da hast du natürlich recht.

Bei meinen Projekten war es immer so, dass es gelang, einen kompletten 
Port für ein Display zu haben ohne mit Spezialfunktionen zu kollidieren. 
Entweder weil ich nur wenige benötigt habe, oder der uC relativ gut an 
Ports ausgestattet war.

Also ich versuche sowas immer zu vermeiden.

von T.S. (Gast)


Lesenswert?

:-)

hmm zu dem Thema:

((x)>>1<<3)

bzw.:

(((x)>>1)<<3)

ist mir gerade noch das

((x)/(2^1)*(2^3))

eingefallen. das muss ich mal ausprobieren.

T.

von T.S. (Gast)


Lesenswert?

es ist interessant was daraus wird:

int main(void)
{
 2d6:  25 e0         ldi  r18, 0x05  ; 5


    while (1)
    {

        LCD_R_D0_OUT=(LCD_R_D0_OUT&(~(1<<LCD_P_D0)))|((((x)>>1)<<LCD_P_D0)&(1<<L 
CD_P_D0));
 2d8:  98 b3         in  r25, 0x18  ; 24
 2da:  82 2f         mov  r24, r18
 2dc:  88 0f         add  r24, r24
 2de:  88 0f         add  r24, r24
 2e0:  88 70         andi  r24, 0x08  ; 8
 2e2:  97 7f         andi  r25, 0xF7  ; 247
 2e4:  89 2b         or  r24, r25
 2e6:  88 bb         out  0x18, r24  ; 24

        x++;
 2e8:  2f 5f         subi  r18, 0xFF  ; 255
 2ea:  f6 cf         rjmp  .-20       ; 0x2d8 <main+0x2>


kein shift zu sehen...

von T.S. (Gast)


Lesenswert?

dennoch sieht das abfragen und dann entsprechend setzen kürzer aus:

#define LCD_R_D0_OUT     PORTB
#define LCD_P_D0         3


         ...


        if(x&(1<<1))
 2d8:  81 ff         sbrs  r24, 1
 2da:  02 c0         rjmp  .+4        ; 0x2e0 <main+0xa>
        {
            LCD_R_D0_OUT|=(1<<LCD_P_D0);
 2dc:  c3 9a         sbi  0x18, 3  ; 24
 2de:  01 c0         rjmp  .+2        ; 0x2e2 <main+0xc>
        }
        else
        {
            LCD_R_D0_OUT&=~(1<<LCD_P_D0);
 2e0:  c3 98         cbi  0x18, 3  ; 24
        }

        x++;
 2e2:  8f 5f         subi  r24, 0xFF  ; 255
 2e4:  f9 cf         rjmp  .-14       ; 0x2d8 <main+0x2>

von Peter D. (peda)


Lesenswert?

T.S. schrieb:
> kein shift zu sehen.


Doch, hier

T.S. schrieb:
> 2dc:  88 0f         add  r24, r24
>  2de:  88 0f         add  r24, r24


Peter

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.