Hi, wie wird dieses Makro behandelt? #define TEST(x) ((x>>1)<<3) geht das? T.S.
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.
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.
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.
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)))
|
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); |
Danke Peter, jetzt hat Thorsten kaum noch etwas zum nachdenken. Deine LCD Routine läuft super, danke dafür.
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.
...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.
>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
@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.
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.
:-) 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.
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...
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>
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.