Forum: Mikrocontroller und Digitale Elektronik Ausgabe-HexWert an 8 Pins?


von Andreas (Gast)


Lesenswert?

Hallo,

ich möchte einen Hex Wert an die die Ports D0-D7 meines LCDs senden. 
Enable und CS funktionieren allerdings stehe ich wie der OChs vorm Berg 
beim Schreiben einer Funktion die mir z.B den Wert 3F an 8 Pins meines 
Kontrollers schickt (Atmel-ARM)!

ICh will keine Lösung, aber wenn mir jemand den grundsäztlichen Ablauf 
erklären könnte wäre das Super, danke!

Gruß


Andreas

von Karl H. (kbuchegg)


Lesenswert?

Andreas wrote:
> Hallo,
>
> ich möchte einen Hex Wert an die die Ports D0-D7 meines LCDs senden.
> Enable und CS funktionieren allerdings stehe ich wie der OChs vorm Berg
> beim Schreiben einer Funktion die mir z.B den Wert 3F an 8 Pins meines
> Kontrollers schickt

Du bruachst nichts spezielles zu tun. Gib einfach die 0x3f an
den Port aus und deine Portpins werden den Zustand
     0011 1111
annehmen.

Binär, Hex, Dezimal sind nur verschiedene Schreibweisen für
Zahlen. Das ändert aber an der Zahl nichts.

von Andreas (Gast)


Lesenswert?

Hallo,


das dachte ich auch! allerdings bekomme ich an allen Pins ein High!
so sieht meine Funktion dazu aus:

void ks0108_write_data (uint8_t data, uint8_t chip) {

  AT91F_PIO_ClearOutput (pPIO, LCD_DATA | LCD_RW | LCD_CS1 | LCD_CS2);
  AT91F_PIO_SetOutput (pPIO, LCD_RW);
  data &= 0xff;

  if (chip == left)  {
    AT91F_PIO_ClearOutput (pPIO, LCD_CS2);
    AT91F_PIO_SetOutput (pPIO, LCD_CS1);
      //pPIO->PIO_SODR = LCD_DATA & (data << LCD_SHIFT);
      pPIO->PIO_SODR = ((uint32_t)data<<LCD_PIN0);
  }
  if (chip == right)  {
    AT91F_PIO_ClearOutput (pPIO, LCD_CS1);
    AT91F_PIO_SetOutput (pPIO, LCD_CS2);
void ks0108_write_data (uint8_t data, uint8_t chip) {

  AT91F_PIO_ClearOutput (pPIO, LCD_DATA | LCD_RW | LCD_CS1 | LCD_CS2);
  AT91F_PIO_SetOutput (pPIO, LCD_RW);
  data &= 0xff;

  if (chip == left)  {
    AT91F_PIO_ClearOutput (pPIO, LCD_CS2);
    AT91F_PIO_SetOutput (pPIO, LCD_CS1);
      //pPIO->PIO_SODR = LCD_DATA & (data << LCD_SHIFT);
      pPIO->PIO_SODR = LCD_DATA & data;
  }
  if (chip == right)  {
    AT91F_PIO_ClearOutput (pPIO, LCD_CS1);
    AT91F_PIO_SetOutput (pPIO, LCD_CS2);
      pPIO->PIO_SODR = LCD_DATA & data;
  }
  ks0108_en();

}
  }
  ks0108_en();

}

LCD_DATA entspricht den Ausgabeports D0-D7 und an allen liegt ein High 
an.
Irgendeine Idee?

Gruß

Andreas

von Andreas (Gast)


Lesenswert?

ups.....ich  verunnde das nicht sondern ich mach ein "oder" dazwischen, 
dann liegt an allen Pins ein High an!

So meinte ich das:

pPIO->PIO_SODR = (LCD_DATA | data);

von Karl H. (kbuchegg)


Lesenswert?

Andreas wrote:
> ups.....ich  verunnde das nicht sondern ich mach ein "oder" dazwischen,
> dann liegt an allen Pins ein High an!
>
> So meinte ich das:
>
> pPIO->PIO_SODR = (LCD_DATA | data);

Welchen Wert hat LCD_DATA
Welchen Wert hat data

Wenn du die beiden vorODERst, dann kriegst du ueberall dort
eine 1 wo entweder in LCD_DATA oder in data eine 1 ist.

Wenn also an allen Pins eine 1 messbar ist, dann wird wohl
aus der Veroderung von LCD_DATA und data der Wert 0xFF folgen.

http://www.mikrocontroller.net/articles/AVR-Tutorial:_Logik

von Andreas (Gast)


Lesenswert?

LCD_Data setze ich mit dem Befehl:

AT91F_PIO_ClearOutput (pPIO, LCD_DATA | LCD_RW | LCD_CS1 | LCD_CS2);

auf 0 am Ausgang.

Die nächste relevante Zeile für LCD_DATA ist dann zum Beispiel folgende:

pPIO->PIO_SODR = (LCD_DATA | data);

danach erscheint an den Ausgängen =0xFF. data beinhaltet 0x3F.
Im Debugmodus habe ich mich versichert das dem auch so ist.


In anderen Beispielel habe ich solche Lösungen gesehen:

      pPIO->PIO_SODR = ((uint32_t)data<<LCD_PIN0);

Wobei LCD_PIN0 D0 repräsentieren soll, kommt aber im Endeffekt das 
Gleiche raus, alle Ausgänge High.

irgendeine Idee?

Gruß

von Karl H. (kbuchegg)


Lesenswert?

Andreas wrote:
> LCD_Data setze ich mit dem Befehl:
>
> AT91F_PIO_ClearOutput (pPIO, LCD_DATA | LCD_RW | LCD_CS1 | LCD_CS2);
>

Nochmal:

Welcher   W E R T   (also welche Zahl) steht hinter LCD_DATA.

LCD_DATA ist ein Makro, dass irgendwo in deinem Code vorkommt.
Irgendwo muss stehen

#define LCD_DATA  xxx

und das xxx ist das Interessante.

> irgendeine Idee?

Ja. Lerne C beginnend mit den Grundlagen. Programmieren lernen
nach dem Muster: Ich probier einfach mal jedes Zeichen das ich
irgendwo gesehen oder von dem ich gehört habe, funktioniert
einfach nicht.

von Andreas (Gast)


Lesenswert?

das steht hinter LCD_Data:

#define LCD_DATA 
(LCD_D0|LCD_D1|LCD_D2|LCD_D3|LCD_D4|LCD_D5|LCD_D6|LCD_D7)

das steht hinter LCD_Dx:

#define LCD_D0 (1<<23)          // P23
#define LCD_D1 (1<<25)          // P25
#define LCD_D2 (1<<26)          // P26
#define LCD_D3 (1<<27)          // P27
#define LCD_D4 (1<<28)          // P28
#define LCD_D5 (1<<29)          // P29
#define LCD_D6 (1<<30)          // P30
#define LCD_D7 (1<<31)          // P31

Gruß

von Karl H. (kbuchegg)


Lesenswert?

Andreas wrote:
> das steht hinter LCD_Data:
>
> #define LCD_DATA
> (LCD_D0|LCD_D1|LCD_D2|LCD_D3|LCD_D4|LCD_D5|LCD_D6|LCD_D7)
>
> das steht hinter LCD_Dx:
>
> #define LCD_D0 (1<<23)          // P23
> #define LCD_D1 (1<<25)          // P25
> #define LCD_D2 (1<<26)          // P26
> #define LCD_D3 (1<<27)          // P27
> #define LCD_D4 (1<<28)          // P28
> #define LCD_D5 (1<<29)          // P29
> #define LCD_D6 (1<<30)          // P30
> #define LCD_D7 (1<<31)          // P31
>


Da darfst du dich jetzt aber nicht wundern, dass alle Ausgabepins
1 sind.

LCD_DATA ist eine 32 Bit Zahl in der 8 Stück 1-en gesetzt sind.
d.h. binär so
    1111 1111 0000 0000 0000 0000

wenn du das jetzt mit 0x3F veroderst

        1111 1111 0000 0000 0000 0000 0000 0000
oder    0000 0000 0000 0000 0000 0000 0011 1111

dann kriegst du als Ergebnis

        1111 1111 0000 0000 0000 0000 0011 1111

        |+++++++|

und wenn es der markierte Bitbereich ist, den du an
den Ausgangspins misst, dann ist der klarerweise immer
alle Bits 1

Du musst logischerweise deine 0x3F erst mal soweit
nach links schieben, dass sie auch uber den 'Ausgangsbits'
liegen.

     data << LCD_D0

oder da es anscheinend dafür ein Makro gibt

     data << LCD_PIN0

(was wahrscheinlich dasselbe ist)
damit wird aus den 0x3F

      0011 1111 0000 0000 0000 0000 0000 0000

und das dann mit LCD_DATA verodert

        1111 1111 0000 0000 0000 0000 0000 0000
oder    0011 1111 0000 0000 0000 0000 0000 0000

ergibt immer noch

        1111 1111 0000 0000 0000 0000 0000 0000

also alle Bits 1, weil Oder die falsche Operation ist.

Aber

        1111 1111 0000 0000 0000 0000 0000 0000
und     0011 1111 0000 0000 0000 0000 0000 0000

ergibt

        0011 1111 0000 0000 0000 0000 0000 0000

und das willst du haben.

In C
    pPIO->PIO_SODR = ((uint32_t)data<<LCD_PIN0) & LCD_DATA;

Wozu das & (die UND Operation).
Angenommen deine Zahl wäre nicht so schön, wei hier und
da wären an anderer Stelle noch ein paar 1-en

        1111 1111 0000 0000 0000 0000 0000 0000
und     0011 1111 0000 0000 1001 0010 0010 0000

dann lautet das Ergebnis wieder
        0011 1111 0000 0000 0000 0000 0000 0000

weil durch die UND-Operation nur dort im Ergebnis eine 1 auftauchen
kann, wo in der Maske (in LCD_DATA) eine 1 steht. Dort wo in der
Maske eine 0 ist, ist auch im Ergebnis auf jeden Fall eine 0.

http://www.mikrocontroller.net/articles/AVR-Tutorial:_Logik

von Karl H. (kbuchegg)


Lesenswert?

Moment mal:

Ist LCD_D0 sicher  1 << 23 und nicht 1 << 24
(Sorry, habs jetzt erst gesehen, damit ist das meiste
aus dem letzten Post hinfällig)

Wer denkt sich denn sowas aus? Ist doch Schwachsinn die
Datenbits auseinanderzureissen. Das gibt dich nur Ärger
oder zumindest unnötig komplizierten Code. Dann geht das
mit einer einzelnen Schiebe und Maskier- Operation nämlich
sowieso nicht.

Dann muss das heissen:
#define LCD_DATA_REST  LCD_D1 | LCD_D2 | LCD_D3 | LCD_D4 \
                       LCD_D5 | LCD_D6 | LCD_D7

    pPIO->PIO_SODR = ( ((uint32_t)data << LCD_D0) & LCD_D0 ) |
                     ( ((uint32_t)data << (LCD_D1-1)) & LCD_DATA_REST );

von Andreas (Gast)


Lesenswert?

Oh....Danke für dein Input!

Das wichtigste vorweg....es klappt immer noch nicht. Alle Ausgänge sind 
LOW.
Das mit dem shiften habe ich mir schon gedacht, allerdings war ich noch 
zu sehr in der 8Bit Welt vom Studium.

Das mit den PA 23 PA25 PA26 usw ist wirklich sehr doof, allerdings 
benutzte ich ein EK Board von OLIMEX und das hat max. 7 
aufeinanderfolgen Ports mit einem Anschlußpin auf dem Board, wenn ich 
Port 24 benutzen möchte dann müßte direkt an den Kontroller (Pin23) 
gehen. Andere Ausgänge wie SPI, I²C UART werden schon benutzt und fallen 
somit weg.

Mit deiner schnellen Lösung zu dem Problem kann ich im Debugmodus sehen, 
daß er gar nicht mehr in die Funktion pPIO->PIO_SODR springt, sondern 
sie einfach übergeht!

Eine Warnung bekomme ich auch beim kompilieren:

warning: left shift count >= width of type

aber die ignoriere ich ersteinmal.....

von Karl H. (kbuchegg)


Lesenswert?

Andreas wrote:
> Oh....Danke für dein Input!
>
>> Eine Warnung bekomme ich auch beim kompilieren:
>
> warning: left shift count >= width of type
>
> aber die ignoriere ich ersteinmal.....

Die solltest du nicht ignorieren. Die ist nämlich fatal.
Wo genau kriegst du sie?

Im #define steckt übrigens noch ein Fehler:

#define LCD_DATA_REST  ( LCD_D1 | LCD_D2 | LCD_D3 | LCD_D4 \
                         LCD_D5 | LCD_D6 | LCD_D7 )

Auch diese Klammern sind wichtig.

von Karl H. (kbuchegg)


Lesenswert?

Wenn du so nicht weiter kommst, dann drösle das ganze
mal auf:

   uint32_t value1, value2;

   value1 = (((uint32_t)data) << LCD_D0;
   value1 = value & LCD_D0;

   value2 = (((uint32_t)data) << (LCD_D1-1);
   value2 = value2 & LCD_DATA_REST;

   value1 = value1 | value2;
   pPIO->PIO_SODR = value1;


und sieh nach wo was verloren geht und wo noch casts
oder Klammern hinmuessen.

von Andreas (Gast)


Lesenswert?

Habe jetzt mal einiges probiert aber im Endeffekt änder sich nichts, zur 
Zeit zumindest:

//      value1 = (data << LCD_D0);  // nach dieser Zeile value1 = 0
//   value1 = value1 | LCD_D0;    // nach dieser Zeile value1 = 8388608 
=>                          100000000000000000000000
//   value2 = (((uint32_t)data) << ((LCD_D1-1)-3));    // nach dieser 
Zeile value2 = 0
//   value2 = value2 | LCD_DATA_REST;        // nach dieser Zeile value2 
= 4261412864  =>  11111110000000000000000000000000
//
//   value1 = value1 | value2;          //nach dieser Zeile value1 = 
4269801472      => 11111110100000000000000000000000
//   pPIO->PIO_SODR = value1;            // alle Pins am Ausgang auf 
High!  gewünscht=> 00111111000000000000000000000000
                          //
                          //

von Andreas (Gast)


Lesenswert?

kleine Korrektur:


//      value1 = (data << LCD_D0);  // nach dieser Zeile value1 = 0
//   value1 = value1 | LCD_D0;    // nach dieser Zeile value1 = 8388608
=>                          100000000000000000000000
//   value2 = (((uint32_t)data) << (LCD_D1-1));    // nach dieser
Zeile value2 = 0
//   value2 = value2 | LCD_DATA_REST;        // nach dieser Zeile value2
= 4261412864  =>  11111110000000000000000000000000
//
//   value1 = value1 | value2;          //nach dieser Zeile value1 =
4269801472      => 11111110100000000000000000000000
//   pPIO->PIO_SODR = value1;            // alle Pins am Ausgang auf
High!  gewünscht=> 00111111000000000000000000000000
                          //
                          //

von Andreas (Gast)


Lesenswert?

Guten Morgen,

momentaner Stand ist, daß ich herausgefunden habe das der ARM sich nicht 
für das Interessiert was ich ausgeben möchte.
egal ob 0x00 oder 0xff es ist immer das gleiche ergebniss!
Mal schauen wie ich weiterkomme

von Obelix (Gast)


Lesenswert?

Was sagt senn dein Debugger?

von maddin (Gast)


Lesenswert?

oh leute...

schreine doch einfach mal direkt was an deinen port, ohne defines, ohne 
shift ops, soweit das möglich ist...  und dann step bei step aufbohren, 
wenn der arm das macht was du erwartest..

gruß,
m.

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.