Forum: Mikrocontroller und Digitale Elektronik struct - Port emulieren - MPLAB C18


von *Michael* (Gast)


Lesenswert?

Hallo,
ich weis manche werden sich warscheinlich den Kopf halten, aber für mich 
ist das noch neuland!

Ich Programiere in C mit MPLAB C18 den pic 18F2550.

1. Ich möchte ihn jetzt auch mit I²C betreiben, und deswegen fallen an 
PORTB 2 ausgänge weg, die ich zufor für das display benutzt habe (DIP 
204-4). Ich hab das Display über 8bit angesprochen:
1
PORTB = "c";
Das ging wunderbar, doch jetzt fällt das weg.
Ich hab mir gedacht das ich ja eine eigene struktur machen kann, aber es 
will net.
1
extern volatile near unsigned char LCD_DATA;
2
extern volatile near struct {
3
  unsigned LATA0:1;
4
  unsigned LATA1:1;
5
  unsigned LATA2:1;
6
  unsigned LATA3:1;
7
  unsigned LATA4:1;
8
  unsigned LATB5:1;
9
  unsigned LATB7:1;
10
  unsigned LATB6:1;
11
} LCD_DATAbits;

2. Können auch 2 Master Pics auf I²C miteinander komuniezieren, Wie?

von Sven P. (Gast)


Lesenswert?

Michael schrieb:
>
1
> extern volatile near unsigned char LCD_DATA;
2
> extern volatile near struct {
3
>   unsigned LATA0:1;
4
>   unsigned LATA1:1;
5
>   unsigned LATA2:1;
6
>   unsigned LATA3:1;
7
>   unsigned LATA4:1;
8
>   unsigned LATB5:1;
9
>   unsigned LATB7:1;
10
>   unsigned LATB6:1;
11
> } LCD_DATAbits;
12
>

Bitfelder sind eines der am wenigsten definierten Konstrukte in C 
überhaupt. Bis auf die Tatsache, dass du einer Komponente eines 
Bitfeldes einen Wert zuweisen kannst und ihn danach auch wieder 
herausbekommst, ist nix festgelegt.
Zitat:
> If insufficient space remains, whether a bit-field that does not fit
> is put into the next unit or overlaps adjacent units is
> implementation-defined. The order of allocation of bit-fields within
> a unit (high-order to low-order or low-order to high-order) is
> implementation-defined. The alignment of the addressable storage unit
> is unspecified.

von Be B. (bebo)


Lesenswert?

Wie wäre es mit einem #define Macro?

Z.B. sowas (nur Beispielhaft):
1
#define LCD_DATA(x) {\
2
LATB &= ~0xF3;\
3
LATC &= ~0x03;\
4
LATB |= x & 0xF3;\
5
LATC |= (x>>2) & 0x03;\
6
}

Hiermit könntest Du Dein Byte beliebig zerlegen und auf mehrere Ports 
verteilen.

Dann würdest Du anstatt
1
PORTB = x
2
LCD_DATA(x);
schreiben.

Übrigens, würde ich Dir empfehlen zum Schreiben die LATx Register zu 
verwenden. Insbesondere dann, wenn ein Port von verschiedenen 
Programmteilen angesprochen wird.

Zu den Bitfeldern: Dadurch, daß Du die Namen änderst, ändert sich nichts 
an den Bitpositionen. Du hast damit nur die Bits in PortB umbenannt. Bei 
Dir heißt das erste Bit in PortB nun LATA0, aber physikalisch wird ist 
Dein LATA0 das gleiche Bit, das vorher LATB0 hieß.

von *Michael* (Gast)


Lesenswert?

Be Bo schrieb:
> #define LCD_DATA(x) {\
> LATB &= ~0xF3;\
> LATC &= ~0x03;\
> LATB |= x & 0xF3;\
> LATC |= (x>>2) & 0x03;\
> }

das &= und |= irritiert mich grad ein bissle.
kannst du das vllt auch in ganz "billiger" schreibweise für mich 
schreiben? :)

Be Bo schrieb:
> Übrigens, würde ich Dir empfehlen zum Schreiben die LATx Register zu
> verwenden. Insbesondere dann, wenn ein Port von verschiedenen
> Programmteilen angesprochen wird.

xD oops ja mach ich ja eigentlich, hab vorhin nur ein bissle hektik 
gehabt





Michael schrieb:
> 2. Können auch 2 Master Pics auf I²C miteinander komuniezieren, Wie?

von Be B. (bebo)


Lesenswert?

Hi,

& und | sind sognannte binäre Verknüpfungen.
Also wenn ein Byte %10101010 enthält und Du es mit 0x0F verUNDest 
erhältst Du %00001010. Das | ist das gleiche nur mit ODER Verknüfung.

Die Schreibweise

VARIABLE &= 0x0F   ist das selbe wie    VARIABLE = VARIABLE & 0x0F

Gibt's auch für alle andere Operatoren. Z.B.:

x++ <==> x=x+1 <==> x+=1

oder

y = y<<2  <==>  y<<=2

von *Michael* (Gast)


Lesenswert?

Be Bo schrieb:
> Hi,
>
> & und | sind sognannte binäre Verknüpfungen.
> Also wenn ein Byte %10101010 enthält und Du es mit 0x0F verUNDest
> erhältst Du %00001010. Das | ist das gleiche nur mit ODER Verknüfung.
>
> Die Schreibweise
>
> VARIABLE &= 0x0F   ist das selbe wie    VARIABLE = VARIABLE & 0x0F
>
> Gibt's auch für alle andere Operatoren. Z.B.:
>
> x++ <==> x=x+1 <==> x+=1
>
> oder
>
> y = y<<2  <==>  y<<=2


Blick ich jetzt trotzdem net, was bringt das mir nun?
kannst du mir vllt ein einer ganz billigen schreibweise zeigen wie ich 
pins von  verschiedenen ports in eine struktur unterbringe?

von Dieter W. (dds5)


Lesenswert?

Eine Struktur aus "verteilten" Bits ist grundsätzlich nicht möglich, die 
Bits einer Struktur müssen zusammenhängend sein.

Es dürfte daher am einfachsten sein, sich eine Funktion zur 
(Port-)Bitmanipulation selbst zu schreiben.

von *Michael* (Gast)


Lesenswert?

Ich hab jetzt mal ein bisschen probiert:

[c]
#define LCD_DATA(x) {\
LATAbits.LATA0 = x & 0x01;\
LATAbits.LATA1 = x & 0x02;\
LATAbits.LATA2 = x & 0x04;\
LATAbits.LATA3 = x & 0x08;\
LATAbits.LATA4 = x & 0x10;\
LATBbits.LATB5 = x & 0x20;\
LATBbits.LATB7 = x & 0x40;\
LATBbits.LATB6 = x & 0x80;\
}
[\c]

Stimmt das mit meinen zielen überein?

von *Michael* (Gast)


Lesenswert?

Also ich hab nun am Display die reihenfolge geändert (notdürftig, 2 pins 
getauscht)
D7 A0
D6 A1
D5 A2
D4 A3
D3 A4
D2 B5
D1 B6
D0 B7

dann hab ich mir eine kleine funktion geschrieben:
1
void LCD_DATA (char x)
2
{
3
  LATA = x & 0xF8;
4
  LATB = x & 0x07;
5
 }

Was ich leider erst jetzt herausgefunden habe, ist das eigentlich

D7 B7
D6 B6
D5 B5
D4 A4
D3 A3
D2 A2
D1 A1
D0 A0

Also genau umgekehrt.
wie kann ich nun praktisch
1
x = !x;
machen, um diesen effekt aufzuheben?

von *Michael* (Gast)


Lesenswert?

Michael schrieb:
> Also genau umgekehrt.
> wie kann ich nun praktisch
> x = !x;
> machen, um diesen effekt aufzuheben?

ähm, x = !x; net aber halt verdrehen:

aus
01110000 mach
00001110

von *Michael* (Gast)


Lesenswert?

Michael schrieb:
> aus
> 01110000 mach
> 00001110

stimmt ja au net, oh man,
kann mir denn keiner helfen?

von *Michael* (Gast)


Lesenswert?

Michael schrieb:
> Michael schrieb:
>> aus
>> 01110000 mach
>> 00001110
>
> stimmt ja au net, oh man,
> kann mir denn keiner helfen?

Also ich müsste die bits verschieben können, wie mach ich das? kann ich 
au einzelne einem ausgang übergeben. wie?

Beispiel:

11010101
  | |
  | +-> Ausgang B7
  +---> Ausgang A0

von Sven P. (Gast)


Lesenswert?

Mit >> und <<. 'Einzeln' geht mit Masken, zuerst mit einer 
UND-Verknüpfung das alte oder die alten Bits im Register löschen, dann 
mit ODER die neuen einbauen.
1
char reg, v;
2
3
/* Lösche Bits 2 und 3 */
4
reg &= ~0b00001100;
5
6
/* Schreibe Bit 1 von v ins 3. Bit des Registers */
7
reg |= ( v & (1 << 1) ) << 2;
8
9
/* Schreibe Bit 6 von v ins 2. Bit des Registers */
10
reg |= ( v & (1 << 6) ) >> 4;

von *Michael* (Gast)


Lesenswert?

Dankeschön an alle die geholfen haben und mich auf den richtigen weg 
gebracht haben. :D

Ich hab nun für folgende verbindung eine kleine funktion geschireben.

D7 B7
D6 B6
D5 B5
D4 A4
D3 A3
D2 A2
D1 A1
D0 A0
1
void LCD_DATA (char x)
2
{
3
  char Er_1 = 0x00;
4
  char Er_2 = 0x00;
5
6
  Er_1 = LATA & 0xE0; // A5 - A7 aufheben
7
  Er_2 = x & 0x1F;    // Daten für A0 - A4 filtern
8
  LATA = Er_1 | Er_2;
9
10
  Er_1 = LATB & 0x1F;  // B0 - B4 aufheben
11
  Er_2 = x & 0xE0;  // Daten für B5 - B7 filtern
12
  LATB = Er_1 | Er_2;
13
}

Kurze erleuterung für die nachwelt.

B7      0
B6      0
B5      0
B4      1
B3   &  1 -> Momentane einstellung auf den Ports B0 - B4 aufheben in 
Er_1
B2      1
B1      1
B0      1

X7      1
X6      1
X5      1
X4      0
X3   &  0 -> Bestimmten bereich herrausfiltern und aufheben in Er_2
X2      0
X1      0
X0      0

PORTB = Er_1 | Er 2  -> Zusammenfutzeln und in PORTB schreiben



Das selbe Prinzip auc für den 2ten teil.

Ich wünsch euch nun noch eine schöne Wheinachtszeit!!!!!!!

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.