define Ausdruck mit shift in 2 Richtungen

OP #2380749
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.
#2380757
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)))
#2380764
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);
OP #2381031
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.
OP #2381038
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.
Gast #2381119
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
Gast #2381180
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.
Gast #2381227
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.
Gast #2381435
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...
Gast #2381448
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>

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren