Forum: Mikrocontroller und Digitale Elektronik 8Bit Datenleitung auf 2 Ports splitten, für LCD, bidirektional


von Alex D. (t-g-m)


Angehängte Dateien:

Lesenswert?

Kennt jemand eine Lösung um ein Datenbyte gesplittet bidirektional von 2 
verschiedenen Ports zu senden bzw zu empfangen(z.B. von PortA[A7,A6] und 
von PortC[C7...C2]).
Steuerleitung geht ohne Probleme, aber 8Bit Datenleitung irgendwie 
nicht.

Dachte ich könnte das so lösen (geht aber nicht!):
----------------------------------- Code 
----------------------------------
void ausgabeP(unsigned char bitsVar) // Auslesen aus dem Byte und 
übergebe an PortC bzw. A
{unsigned char bitsA, bitsC;
  bitsA = bitsVar & 0b00000011; // Maske
  bitsA <<= 6;        // schiebe 6 mal nach links
  PORTA |= bitsA;
  bitsC = bitsVar & 0b11111100;
  PORTC |= bitsC;
}

unsigned char einlesenP(void) // einlesen in den Byte vom Port C und 
Port A
{
  unsigned char bitsVar, bitsA = PINA, bitsC = PINC;

  bitsA &= ~((1<<PA7)|(1<<PA6));
  bitsA >>= 6;

  bitsC &= 0b11111100;
  bitsVar =   (bitsA | bitsC);
   return bitsVar;

}
------------------------------ Ende Code 
---------------------------------------
Gibt es da anderen weg, weiß es nicht warum das so nicht geht...

Danke :)

von test (Gast)


Lesenswert?

Beim Einlesen machst du dir hier deine gewünschten Daten kaputt:
1
bitsA &= ~((1<<PA7)|(1<<PA6));

Beim schreiben musst du mal überlegen was passiert wenn im Vorfeld ein 
Bit im jeweiligen PORT-Register bereits gesetzt ist, du aber bei den 
neuen Daten eine 0 haben willst.

Schreib dir deine Befehle einfach mal an einem konkreten Beispiel auf 
ein Blatt Papier auf, da solltest du es schon sehen.

von Spess53 (Gast)


Lesenswert?

Hi

>Gibt es da anderen weg, weiß es nicht warum das so nicht geht...

Was geht nicht? JTAG abgeschaltet?

MfG Spess

von bitte löschen (Gast)


Lesenswert?

Ungetestet:
1
// schreiben:
2
PORTA = (PORTA & ~(3 << 6)) | (bitsVar << 6);
3
PORTC = (PORTC & 3) | (bitsVar & ~3);
4
5
// lesen:
6
return (PORTA >> 6) | (PORTC & ~3);

von Michael (Gast)


Lesenswert?

Viele LCD-Controller verfügen über einen 4-Bit Modus. Damit hättest du 
das Problem aus der Welt und vereinfachst dein Layout.

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

Entweder wie vorher, oder die belegung so umbauen dass du einen 
vollständigen Port zur Verfügung hast. PD würde sich anbieten.

von Alex D. (t-g-m)


Lesenswert?

test schrieb:
> Beim Einlesen machst du dir hier deine gewünschten Daten kaputt:bitsA &= 
~((1<<PA7)|(1<<PA6));

Da mach ich nur die überflüssigen Bits weg, die Beiden die mir wichtig 
sind bleiben doch erhalten....

Spess53 schrieb:
> Was geht nicht? JTAG abgeschaltet?

JTAG? warum spielt es da eine Rolle? Hab glaub ich abgeschaltet....

Philipp K. schrieb:
> Ungetestet:// schreiben:
> PORTA = (PORTA & ~(3 << 6)) | (bitsVar << 6);
> PORTC = (PORTC & 3) | (bitsVar & ~3);
>
> // lesen:
> return (PORTA >> 6) | (PORTC & ~3);

Sieht das ganze nur verkürzt aus...??? Stimmts?

Michael schrieb:
> Viele LCD-Controller verfügen über einen 4-Bit Modus. Damit hättest du
> das Problem aus der Welt und vereinfachst dein Layout.

Wie gesagt, wenn der PortC Ganz normal genutzt wird, also vollständig, 
dann Funktioniert es.
Hinzufügend: Es ist ein Grafik LCD, da gibt es leider den 4-Bit Modus 
nicht. Bzw. nicht bei dem LCD.

Michael Reinelt schrieb:
> Entweder wie vorher, oder die belegung so umbauen dass du einen
> vollständigen Port zur Verfügung hast. PD würde sich anbieten.

PD geht leider nicht wegen den 2 Externen Interrupts [Int0 und Int1], ja 
Sorry, sieht man nicht auf der Zeichnung, alle Pins mit Roten Markierung 
sind belegt oder reserviert. Und wenn ich Port C benutze, muss ich auf 
den I²C Bus verzichten... :(
Meinst du es geht gar nicht?

von Michael (Gast)


Lesenswert?

Alex Daimler schrieb:
> Hinzufügend: Es ist ein Grafik LCD, da gibt es leider den 4-Bit Modus
> nicht.

Das kann ja keiner ahnen ;-(

von Spess53 (Gast)


Lesenswert?

Hi

>JTAG? warum spielt es da eine Rolle? Hab glaub ich abgeschaltet....

Bei aktivierten JTAG kannst du auf PC2...5 nicht zugreifen.

>Meinst du es geht gar nicht?

Wieso nicht? Ist doch nur etwas Bitschubsen. Allerdings verlängert das 
die Ausgabe auf das Display.

MfG Spess

von Alex D. (t-g-m)


Lesenswert?

Spess53 schrieb:
> Bei aktivierten JTAG kannst du auf PC2...5 nicht zugreifen.

Gut, dann spielt es in meinem Fall keine Rolle, da ich nur PC6 und PC7 
benutze. :)

Spess53 schrieb:
> Wieso nicht? Ist doch nur etwas Bitschubsen. Allerdings verlängert das
> die Ausgabe auf das Display.

Ich habe mir auch bereits überlegt, dass es wegen der kurzen Rechenzeit 
nicht klappt, bin mir aber nicht so sicher. Ist ja nur eine Vermutung 
gewesen. Wahrscheinlicher ist es dass ich was falsch mache... :/

von test (Gast)


Lesenswert?

Alex Daimler schrieb:
> test schrieb:
>> Beim Einlesen machst du dir hier deine gewünschten Daten kaputt:bitsA &=
> ~((1<<PA7)|(1<<PA6));
>
> Da mach ich nur die überflüssigen Bits weg, die Beiden die mir wichtig
> sind bleiben doch erhalten....

Nein machst du eben nicht. Bit 7 und 6 sind ja die, um die es dir geht 
(mit den Pfeilen drunter).
Beispiel: (angenommen bitsA == 10100110):
                               ^^

((1<<PA7)|(1<<PA6))           --> 11000000
~((1<<PA7)|(1<<PA6))          --> 00111111
bitsA &= ~((1<<PA7)|(1<<PA6)) --> 10100110 & 00111111 = 00100110
bitsA >>= 6                   --> 00000000

von test (Gast)


Lesenswert?

Alex Daimler schrieb:
> Spess53 schrieb:
>> Bei aktivierten JTAG kannst du auf PC2...5 nicht zugreifen.
>
> Gut, dann spielt es in meinem Fall keine Rolle, da ich nur PC6 und PC7
> benutze. :)

Hä? Das sind eben genau die, die du benutzt. TMS,TCK,TDI,TDO

Da hängt ein großteil deiner Datenpins vom Display dran. Wenn JTAG an 
ist, kannst du die nicht nutzen.

von Alex D. (t-g-m)


Lesenswert?

test schrieb:
> Nein machst du eben nicht. Bit 7 und 6 sind ja die, um die es dir geht
>
> (mit den Pfeilen drunter).
>
> Beispiel: (angenommen bitsA == 10100110):
>
>                                ^^
>
>
>
> ((1<<PA7)|(1<<PA6))           --> 11000000
>
> ~((1<<PA7)|(1<<PA6))          --> 00111111
>
> bitsA &= ~((1<<PA7)|(1<<PA6)) --> 10100110 & 00111111 = 00100110
>
> bitsA >>= 6                   --> 00000000

Danke dir für deine Mühe, war mein Fehler, hab aber auch mit Binären 
Maske gemacht also;
 bitsA = BitsA & 0b11000000;

.. ging dennoch nicht.


-------------------

test schrieb:
> Hä? Das sind eben genau die, die du benutzt. TMS,TCK,TDI,TDO
>
>
>
> Da hängt ein großteil deiner Datenpins vom Display dran. Wenn JTAG an
>
> ist, kannst du die nicht nutzen.

XD, ich glaub ich hab dich verwirrt^^ Ja du hattes Recht hab da den Port 
C mit Port A verwechselt ;)

Mit JTag Häckchen bei Sec Bits würde das nicht funzen, ich habe keins 
gesetzt! Hab nachgeschaut und Probiert!
Also Liegt das irgendwie am verarbeiten von Signalen. Irgendwo ist etwas 
zu schnell oder etwas zu langsam.. Wenn die Logic richtig ist.

Grüße

von Frank K. (fchk)


Lesenswert?

Alex Daimler schrieb:

> Wie gesagt, wenn der PortC Ganz normal genutzt wird, also vollständig,
> dann Funktioniert es.
> Hinzufügend: Es ist ein Grafik LCD, da gibt es leider den 4-Bit Modus
> nicht. Bzw. nicht bei dem LCD.

Nimm ein 74HC164 Schieberegister und takte die Daten über PA6 und PA7 
raus.

Musst Du Daten zurücklesen? Dann nimm ein HC595 und ein HC597.

Ansonsten wäre einfach ein AVR mit mehr Pins die einfachste Lösung. Es 
gibt welche mit 100 Pins. Nur halt nicht im DIL-Gehäuse.

Alternative: I2C Port Extender wie z.B. Microchip MCP23017. Dann hast Du 
16 weitere Pins.

fchk

von Alex D. (t-g-m)


Lesenswert?

Frank K. schrieb:
> Nimm ein 74HC164 Schieberegister und takte die Daten über PA6 und PA7
>
> raus.
>
>
>
> Musst Du Daten zurücklesen? Dann nimm ein HC595 und ein HC597.
>
>
>
> Ansonsten wäre einfach ein AVR mit mehr Pins die einfachste Lösung. Es
>
> gibt welche mit 100 Pins. Nur halt nicht im DIL-Gehäuse.
>
>
>
> Alternative: I2C Port Extender wie z.B. Microchip MCP23017. Dann hast Du
>
> 16 weitere Pins.
>
>
>
> fchk

Danke, I2C Erweiterung mit 16 Ausgängen wäre meine Lösung als nächstes. 
Jetzt kenn ich zumindest die Bausteinbezeichnung für 16 Bit I2C 
Baustein. ;)

Wollte es einfach ohne zusätzliche Hardware Lösen, wenn du verstehst was 
ich meine ;)

von Alex D. (t-g-m)


Lesenswert?

So Liebe Leut jetzt geht es, nach allen möglichen Lösungen, funktioniert 
dieses hier (geht sicher kürzer, aber so ist übersichtlich, wer möcht 
kann es abkürzen):
1
  void ausgabeP(unsigned char bitsVar) // Auslesen aus dem Byte und übergebe an Port
2
{
3
PORTC = bitsVar & 0b11111100;
4
   
5
   switch (bitsVar & 0b00000011)
6
   {
7
   case 0:
8
     cbi(PORTA, PA7);
9
     cbi(PORTA, PA6);
10
     break;
11
   case 1:
12
     sbi(PORTA, PA6);
13
     cbi(PORTA, PA7);
14
     break;
15
   case 2:
16
     sbi(PORTA, PA7);
17
     cbi(PORTA, PA6);
18
     break;
19
   case 3:
20
     sbi(PORTA, PA7);
21
     sbi(PORTA, PA6);
22
     break;
23
         }
24
}
25
26
unsigned char einlesenP(void) // einlesen in den Byte vom Port
27
 {
28
   unsigned char bytee = PINC;
29
      
30
     if (PINA & (1<<PINA7))
31
     {
32
       sbi(bytee,1);
33
     } 
34
     else
35
     {
36
       cbi(bytee,1);
37
     }
38
    
39
    if (PINA & (1<<PINA6))
40
    {
41
      sbi(bytee,0);
42
    } 
43
    else
44
    {
45
      cbi(bytee,0);
46
    }
47
   return bytee;
48
}

MfG
Alex

von bitte löschen (Gast)


Lesenswert?

Alex Daimler schrieb:
> Philipp K. schrieb:
>> Ungetestet:// schreiben:
>> PORTA = (PORTA & ~(3 << 6)) | (bitsVar << 6);
>> PORTC = (PORTC & 3) | (bitsVar & ~3);
>>
>> // lesen:
>> return (PORTA >> 6) | (PORTC & ~3);
>
> Sieht das ganze nur verkürzt aus...??? Stimmts?

Verkürzt und korrigiert:
1. Schreiben: Die einzige Stelle, bei der bei Dir PORTC auftaucht, ist
1
PORTC |= bitsC;
Das setzt nur Bits, löscht aber keine. D.h., dass wenn Du beim letzten 
mal 111111xx in PORC geschrieben hattest, und Du willst nun 101010xx 
schreiben,  keine Änderung erfolgt. 111111xx | irgendwas = 111111xx
2. Lesen: Ooops, Asche auf mein Haupt! Da habe ich PORTx statt PINx 
geschrieben, aber sei's drum, Du weißt was ich meinte:
1
// lesen:
2
return (PINA >> 6) | (PINC & ~3);
Du schriebst ~((1<<PA7)|(1<<PA6)) als Maske, das ~ kannst Du weglassen, 
denn (1<<PA7)|(1<<PA6) = 11000000, und das ist das, was Du maskieren 
willst. Du kannst aber auch das Maskieren weglassen, weil die 6 rechten 
Bits mit "bitsA >>= 6" eh' verschwinden.

Du scheinst dazu zu neigen, beim Programmieren erst mal alles in die 
kleinsten Einzelschritte aufzuteilen, was grundsätzlich gut ist. Nur hat 
es den Vorteil, das andere Programmierer es besser lesen können, und 
dass Compiler besser optimieren können, wenn solche Einzelschritte 
danach zu kompakten Ausdrücken zusammengefasst werden, solange diese 
Ausdrücke überschaubar bleiben. Auch hier gilt: Alles in Maßen, und wenn 
die Sache so komplex wird, dass mittendrin x?y:z Ausdrücke auftauchen 
oder es über viele Zeilen geht, dann schreibt man doch lieber ein paar 
einzelne Anweisungen.

Dein zuletzt geposteter Code ist diesbezüglich nicht so optimal. Es ist 
möglich, dass ein bestmöglich optimierender Compiler Deine ganze 
switch-Anweisung wegoptimiert und am Ende Dein und Mein Code das gleiche 
Ergebnis produzieren, aber mein Code stiftet beim Lesen weniger 
Verwirrung und wird von einem anderen Bitfrunzel-Programmierer oder 
Jahre später von einem selbst in wenigen Sekunden verstanden. Um Deinen 
Code zu verstehen, muss man ihn erst mal im Kopf abarbeiten.

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.