Hallo, Ich mache gerade meine ersten Schritte mit WinAVR und C. Ich habe bereits einzelne Ports erfolgreich angesprochen, nun zu meiner Frage Problem: Ich möchte gerne bei einem Atmage8 ein "virtuelles Port" durch C erstellen. Genau genommen so: PB.4 = Bit1 PB.5 = Bit2 PC.0 = Bit3 PC.1 = Bit4 PC.2 = Bit5 PC.3 = BIT6 PC.4 = Bit7 PC.5 = Bit8 Es soll dann die Möglichkeit bestehen das virtuelle Port mit einem Byte zu füttern, und dieses Byte soll dann richtig an den einzelnen Pins von Portb und Portc rauskommen. Ich war bereits fleißig und hab gegoogelt und auch ihr im Forum folgenden Beitrag gefunden: http://www.mikrocontroller.net/forum/read-2-219856.html#new darin steht folgende Lösung: #define MYPORT ((PINB & 0x01)<<8 | (PINB & 0x04)<<7 | ....) uint8_t bla; bla = MYPORT; Leider, da ich c anfänger bin versteh ich das leider nicht ganz: (PINB & 0x01)<<8 Was bedeutet diese Zeile den genau? (PINB & 0x01) bedeutet dies, dass Pinb.0 angesprochen werden soll? ...<<8 bedeutet dies, dass bit8 von myport zugeordnet wird? Demnach sollte das bei mir dann so gehen?: #define MYPORT ((PORTC & 0x20)<<8 | (PINC & 0x10)<<7 | (PINC & 0x08)<<6 | (PINC & 0x04)<<5 | (PINC & 0x02)<<4 | (PINC & 0x01)<<3 | (PINB & 0x20)<<2 | (PINB & 0x10)<<1 | ) Stimmt das?Danke schon mal!
Sollen natürlich Ausgänge sein! Also dann so: #define MYPORT ((PORTC & 0x20)<<8 | (PORTC & 0x10)<<7 | (PORTC & 0x08)<<6 | (PORTC & 0x04)<<5 | (PORTC & 0x02)<<4 | (PORTC & 0x01)<<3 | (PORTB & 0x20)<<2 | (PORTB & 0x10)<<1 | ) uint8_t test; MYPORT = test;
1 | #define MYPORT(x) \
|
2 | do { \
|
3 | PORTC = (PORTC & 0xc0) | ((x) & 0xfc) >> 2); \
|
4 | PORTB = (PORTB & 0xcf) | ((x) & 3) << 4); \
|
5 | } while(0)
|
6 | ...
|
7 | MYPORT(test); |
Verstehen musst du es bitte selbst. Lies dir im C-Buch oder -Artikel deiner Wahl das Kapitel über Bitoperatoren durch. Die Bedeutung des do ... while(0)-Konstrukts ist hier im Forum schon paarmal durchgekaut worden. Nur kurz dazu: überleg dir, wie sich der Makro verhält, wenn du
1 | if (some_condition) |
2 | MYPORT(test); |
3 | else
|
4 | do_something_else(); |
schreibst.
mh... danke! aber da versteh ich jetzt leider nich viel... also geht mein vorschlag nicht, oder?
ich komm da nicht so zurecht, bitte helft mir! Hier mal nochmal eine Idee von mir: #include <io.h> #include <inttypes.h> void setport (unsigned char x) main() { DDRC = 0xff; DDRB = 0xff; setport(0x0f) }; void setport(unsigned char x) { (PORTC & 0x20)<<Myport.b8; (PORTC & 0x10)<<Myport.b7; (PORTC & 0x08)<<Myport.b6; (PORTC & 0x04)<<Myport.b5; (PORTC & 0x02)<<Myport.b4; (PORTC & 0x01)<<Myport.b3; (PORTB & 0x20)<<Myport.b2; (PORTB & 0x10)<<Myport.b1; }; typedef struct { unsigned char b1:1; unsigned char b2:1; unsigned char b3:1; unsigned char b4:1; unsigned char b5:1; unsigned char b6:1; unsigned char b7:1; unsigned char b8:1; } Myport;
Nein, das geht alles so nicht, glaub's doch. Du kannst meinen Macro gern nehmen, auch als ,blackbox', aber bevor du weiter mit trial&error irgendwelchen unsinnigen (sorry) Code zusammennagelst, bitte, bitte, lies' dir die Geschichte mit den Bitmanipulationsoperatoren in einem ordentlichen C-Buch durch.
Jörg hat Recht. Dir fehlen zuviele Grundlagen. Lies ein C-Buch. > (PINB & 0x01) bedeutet dies, dass Pinb.0 angesprochen werden soll? Nein. Es bedeutet, dass der Wert von PINB geholt wird und mit einer Maske von (hex) 01 ein einzelnes Bit isoliert wird (alle anderen Bits werden definiert auf 0 gesetzt). > ...<<8 bedeutet dies, dass bit8 von myport zugeordnet wird? Nein: << ist in C der Links-Schiebe-Operator Der vorher erhaltene Wert wird um 8 bits nach links geschoben.
Du kannst auch schon sehr viel lehrreiches im hiesigen AVR-GCC Tutorial finden: http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial
Hallo Sebastian, ich hatte ein ähnliches Problem. Beschäftige mich nach über 20 Jahren zum ersten mal wieder mit uC´s. Teilweise war das LCD mit 3 Segmenten so an einen Atmega16 angeschlossen, dass ein Segment auf 3 Ports verteilt war. Den Tipp habe ich von einem Kollegen bekommen. Du kannst das ganze lösen indem du mit Shift und logischen Operatoren arbeitest. z.B. PORTB = (LCD.d2&0x1c)|((LCD.d3<<4)&0xc0)|((LCD.d1>>3)&0x03)|(1>>PB5); LCD.dx ist die Variable die die Segmentausgabe enthält. Wie du siehst war das PORTB auf 3 Segmente verteilt PB5 steuerte den Dezimal Punkt des Displays. z.B. PB2-PB4 bildeten die bits 2-4 von LCD.d2 mit (LCD.d2&0x1c) maskierst du die restlichen Bits PB6 und PB7 bildeten die Bits 2 und 3 von LCD.d3 mit ((LCD.d3<<4)&0xc0 shiftest du die Stellen auf die richtige Position für dein PORTB und maskiert Sie wieder durch die Oder Verknüpfung werden Sie in dein PORTB stellenrichtig integriert. usw. Damit kannst du jede Verdrahtung realisieren. Gruß Bernhard
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.