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
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.
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);
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
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ß
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.
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
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 );
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.....
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.
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.
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
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.