F: Können einzelne Pins verschiedener Ports eines Mikrocontrollers einem Register zugeordnet und ihre Werte geändert werden, wenn der Registerwert geändert wird?
Szenario: Ich habe einige Pins von jedem Port (8-Bit) des Mikrocontrollers verbraucht. Jetzt möchte ich ein Gerät anschließen, das einen 8-Bit-Bus benötigt (angenommen, D0 bis D7 IN SEQUENCE), dh ich benötige 8 Pins vom Controller, damit ich sie eins zu eins verbinden kann
portx0 -> D0 // x is the name of port followed by bit location on that port
portx1 -> D1
...
portx7 -> D7
aber ich habe keinen ganzen Port mit 8 Pins, den ich mit diesem Gerät verbinden kann, sondern ich habe einige Pins von portx, einige von porty und einige Pins von portz. Das neue Verbindungsszenario ist wie folgt (Verbindung vom Mikrocontroller zum Gerät)
portx0 -> D0
portx1 -> D1
portx2 -> D2
porty4 -> D3
porty5 -> D4
porty6 -> D5
porty7 -> D6
portz1 -> D7
In diesem Zustand, wenn ich einen Wert senden möchte, sagen Sie
unsigned char dataReg = 0xFA;
Zu meinem Gerät vom Controller muss ich bitweise Operationen an dem zu sendenden Wert durchführen und jeden Pin entsprechend dem Wert im Register einzeln einstellen. Zum Beispiel
portx0 = ((dataReg & 0x01) >> 0 ); // Masking and shifting as bit position
portx1 = ((dataReg & 0x02) >> 1 );
portx2 = ((dataReg & 0x04) >> 2 );
porty4 = ((dataReg & 0x08) >> 3 );
porty5 = ((dataReg & 0x10) >> 4 );
porty6 = ((dataReg & 0x20) >> 5 );
porty7 = ((dataReg & 0x40) >> 6 );
portz1 = ((dataReg & 0x80) >> 7 );
Kommen wir nun zur Hauptfrage, um diese individuellen Berechnungen für jedes Bit an verschiedenen Ports zu vermeiden, können einzelne Pins verschiedener Ports eines Mikrocontrollers einem Register zugeordnet und ihre Werte geändert werden, wenn der Registerwert geändert wird?
Es scheint, dass Ihre Frage darauf hinausläuft, einen 8-Bit-Wert in der Firmware zu haben und diesen von und zu einer beliebigen Sammlung von Port-Pins lesen und schreiben zu wollen.
Es gibt keine direkte Hardwaremöglichkeit, dies zu tun. Sie müssen zwei Routinen schreiben, eine zum Lesen des 8-Bit-Werts und eine zum Schreiben. Andere haben die Verwendung von Gewerkschaften erwähnt, aber das ist eine schlechte Idee. Bei Gewerkschaften müssen Sie jedes Bit einzeln behandeln, und der Code wird von der Bitreihenfolge des Mikros abhängig. Dies könnte sowieso der richtige Weg sein, wenn alle 8 Bits völlig unabhängig voneinander gestreut werden. Wenn dies der Fall ist, können Sie wenig tun, außer für jedes Bit einen speziellen Code zu erstellen.
Der bessere Weg, dies zu tun, insbesondere wenn Sie die Bits in einigen zusammenhängenden Blöcken an den physischen Ports gruppieren können, ist die Verwendung von Maskierung, Verschiebung und ODER-Verknüpfung. Wenn sich zum Beispiel die unteren drei Bits des internen Bytes auf den Bits <6-4> eines Ports befinden, verschieben Sie diesen Portwert um 4 nach rechts und verknüpfen Sie ihn mit 7, um diese Bits an ihre endgültige Position zu bringen. Verschiebe und maskiere (oder maskiere und verschiebe) Bits von anderen Ports an ihren Platz und setze das letzte 8-Bit-Byte zusammen, indem du die Ergebnisse darin ODER-verknüpfst.
Diese Art von Low-Level-Bit-Twiddling ist in Assembler einfacher als in C. Ich würde wahrscheinlich die Byte-Lese- und -Schreibroutinen in ein einziges Assembler-Modul stecken und die Schnittstelle von C aus aufrufbar machen.
Generell ist dies nicht möglich. Mit PICs geht das meines Wissens nicht.
Mir ist nur ein Mikrocontroller bekannt, der dies kann, der Cypress PSoC . Es ist ein hochgradig konfigurierbares System-on-Chip. Unter den vielen Dingen, die Sie tun können, ist, buchstäblich Ihr eigenes Register (1-8 Bit) zu definieren und es mit beliebigen Pins oder sogar mit internen Schaltkreisen zu verbinden.
Hier habe ich zum Beispiel ein 6-Bit-Steuerregister erstellt. 5 der Bits gehen direkt zu Pins, während das 6. Bit ich mit XOR mit dem Eingang von einem 7. Pin verwende.
Auf dem Chip kann ich diese Pins einem der verfügbaren GPIO-Pins zuweisen. (Es sind die grauen auf dem Bild)
Sie können Folgendes versuchen. Schreiben Sie eine eigene Struktur, die den jeweiligen Pins der 2 Ports (die verwendet werden sollen) zugeordnet ist. Wenn Sie nun den Wert in diesem Register aktualisieren, werden die Pins dieser 2 Ports gesetzt / zurückgesetzt. Probieren Sie es einfach aus und lassen Sie uns wissen, ob es funktioniert hat !!
Ich bin zuversichtlich, dass dies funktionieren sollte.
Wenn ich die Frage richtig verstanden habe, geht das ganz einfach in C:
Generische Typdeklaration, kann für jedes Register wiederverwendet werden:
typedef union // Generic 8-bit register Type
{
uint8 reg; // Whole register
struct
{
unsigned bit7 : 1; // Bit 7
unsigned bit6 : 1; // Bit 6
unsigned bit5 : 1; // Bit 5
unsigned bit4 : 1; // Bit 4
unsigned bit3 : 1; // Bit 3
unsigned bit2 : 1; // Bit 2
unsigned bit1 : 1; // Bit 1
unsigned bit0 : 1; // Bit 0
} bit;
} typ_GENERIC_REG8;
Um also einen Port zu definieren, wollen wir Folgendes adressieren:
#define MCU_GPO_PORTx (*(volatile typ_GENERIC_REG8 *)(0x12345678)) // Number is address
Und um direkt einen Pin an diesem Port zu drehen:
#define MCU_PORTx_PINn (MCU_GPO_PORTx.bit.bit0)
In Code:
MCU_PORTx_PINn = 1; // Set pin high
Gesamtes Register:
MCU_GPO_PORTx.reg = 0xF; // All pins high
Es lohnt sich, sich über Structs, Unions, Typedefs und Enums zu informieren - all dies macht das Leben in Embedded & im Allgemeinen so viel schöner!
Benutzer17592