Forum: Mikrocontroller und Digitale Elektronik LCD über GPIOs ansteuern


von Marco (Gast)


Lesenswert?

Hi,

ich möchte gern mein neues LCD Display (mit einem integrierten ST7529)
mit einem STM32 Prozessor ansteuern, welcher allerdings keinen
Daten/Adressbus besitzt. Daher muss ich normale GPIOs verwenden.

Ist meine Schreibroutine (Displaydaten und Initialisierungsdaten) so
richtig?
1
void write_lcd(unsigned char addr, unsigned char data)
2
{
3
  // addr (Displaydaten = 1 oder InitDaten = 0) setzen    
4
  GPIOC->ODR = ((GPIOC->ODR & 0x10) | (addr << 4));
5
6
  // daten setzen 
7
  GPIOB->ODR = ((GPIOB->ODR & 0xFFFF) | data);
8
     
9
  // cs auf low setzen
10
  GPIOC->BRR = (1 << 8);
11
12
  // r/w auf low setzen
13
  GPIOC->BRR = (1 << 5);
14
15
  delay(100); 
16
17
  /* beide wieder auf high ziehen */
18
  GPIOC->BSRR = (1 << 8);
19
  GPIOC->BSRR = (1 << 5);
20
21
}


Gruß
Marco

von (prx) A. K. (prx)


Lesenswert?

Marco schrieb:

>   GPIOC->ODR = ((GPIOC->ODR & 0x10) | (addr << 4));

Sollen die Bits 5..15 von ODR wirklich alle gelöscht werden? Wenn man
nicht wirklich alle Pins ansprochen will, dann sollte man unbedingt
BRR/BSRR statt ODR verwenden. Spätestens wenn ein Interrupt-Handler 
ebenfalls den Port anspricht wird das wichtig.

So kann man beispielsweise die Pins 4..7 gezielt auf einen Wert setzen, 
ohne den Rest zu verändern:
  GPIOC->BSRR = (0x00F0 << 16) | (addr << 4);

Von Operationen der Art
  GPIOx->ODR &= ...;
  GPIOx->ODR |= ...;
  GPIOx->ODR = (GPIOx->ODR & ...) | ...;
ist grundsätzlich abzuraten.

von Marco (Gast)


Lesenswert?

Danke für den Hinweis mit dem ODR Register. Warum sollte man dieses 
nicht direkt verwenden?
1
GPIOC->BSRR = (0xFF << 16) | (data);

Irgendwas mach ich hier noch falsch, wenn ich die Bits [0, 7] setzen 
möchte... Wenn data z.B. 0x30 ist, dann ist das dritte und vierte Bit 
gesetzt...

von (prx) A. K. (prx)


Lesenswert?

Marco schrieb:

> Danke für den Hinweis mit dem ODR Register. Warum sollte man dieses
> nicht direkt verwenden?

http://www.mikrocontroller.net/articles/Interrupt#Interruptfeste_Programmierung

> Irgendwas mach ich hier noch falsch, wenn ich die Bits [0, 7] setzen
> möchte... Wenn data z.B. 0x30 ist, dann ist das dritte und vierte Bit
> gesetzt...

Zählst du die Bits von links nach rechts?

0x30 setzt das 5. und 6. Bit von rechts. Die übrigen Bits in [0,7] 
werden gelöscht. [8,15] bleibt unverändert. Wo ist das Problem?

von Marco (Gast)


Lesenswert?

A. K. schrieb:
> 0x30 setzt das 5. und 6. Bit von rechts. Die übrigen Bits in [0,7] sind
> gelöscht. [8,15] bleibt unverändert. Wo ist das Problem?

ok, dann ist mein Problem noch irgendwo anders. Weil bis jetzt das 3. 
und 4. Bit von rechts gesetzt werden und die anderen sind 0.

von Marco (Gast)


Lesenswert?

kann es sein, dass es daran liegt, wie ich die I/Os für den Datenbus 
konfiguriere? Bis jetzt versuche ich lediglich ein paar Werte ans 
Display zu senden.
1
//datenbus I/Os 
2
GPIOB->CRL &= ~0xFFFFFFFF; 
3
GPIOB->CRL |=  0x22222222;   //push-pull output

von (prx) A. K. (prx)


Lesenswert?

Wenn du die Pins 4 und 5 einschaltest und die Pins 2 und 3 werden aktiv, 
dann ist nicht die Pinkonfiguration falsch, sondern die Hardware (oder 
deine Zählweise beim Anschluss - alles schon mal dagewesen).

Schieb doch mal Einsen durch die Portpins, also erst Pin 0, dann Pin 1, 
etc. Du merkst dann, welcher Pin wo sitzt.

von Marco (Gast)


Lesenswert?

ich hab den Fehler gefunden. Ich muss die beiden Pins PB3 und PB4 
remappen, weil diese momentan vom JTAG Interface in Anspruch genommen 
werden.

(Seite 35 sind die beiden Pins)
http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/DATASHEET/CD00191185.pdf

Hierzu muss ich das AFIO_MAPR Register laut UserManual entsprechend 
programmieren. Hier gibt es allerdings mehrere Möglichkeiten, die ich 
noch nicht ganz verstehe:

GPIO_Remap_SWJ_Disable
GPIO_Remap_SWJ_NoJTRST
GPIO_Remap_SWJ_JTAGDisable

Und vor allem, kann ich den Prozessor anschließend immer noch ohne 
Probleme neu programmieren?

von (prx) A. K. (prx)


Lesenswert?

JTAG/SWJ remappen geht nicht, abschalten geht. Nur ist dann natürlich 
kein Debugging möglich. Programmieren per JTAG/SWJ geht m.E. schon, denn 
nach dem Hardware-Reset ist das ja wieder drauf. Ausserdem kann man per 
Bootloader programmieren.

SWJ geht auch ohne diese beiden Pins, die werden nur fürs komplette JTAG 
verwendet. Siehe Table 37 (9.3.5) in der Reference.

von Marco (Gast)


Lesenswert?

ok, es funktioniert!

Eine Frage hab ich noch: wenn ich Daten vom Display Lesen möchte, muss 
ich dann die Datenbus I/Os als Input mit Pullup/down oder als floating 
Input installieren?

von (prx) A. K. (prx)


Lesenswert?

Marco schrieb:

> Eine Frage hab ich noch: wenn ich Daten vom Display Lesen möchte, muss
> ich dann die Datenbus I/Os als Input mit Pullup/down oder als floating
> Input installieren?

Das ist im Grunde egal. Floating input reicht aus.

von Marco (Gast)


Lesenswert?

Danke A.K.

Das Display bekomm ich bereits angesteuert.

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.