Forum: Mikrocontroller und Digitale Elektronik Verständnissfrage zu FSMC und LCD bei STM32


von Patrick B. (p51d)


Lesenswert?

Hallo
Ich stehe gerade etwas auf dem Schlauch: Das LCD hat ein eigenes RAM 
(daher ja der Betrieb über den FSMC). Kann man jetzt darauf schreiben 
und lesen, wie ein normales RAM?
Konkret geht es um eine kleine Anwendung, bei der eine Kamera 
eingelesen, und das Bild vorläufig auf dem LCD angezeigt wird. Dann soll 
aus dem Farbbild ein Binärbild erstellt werden, welches auf dem PC 
weiterverarbeitet wird. Die Lösung soll wiederum auf dem LCD angezeigt 
werden.
Wenn ich jetzt Daten vom LCD lesen und schreiben könnte, würde ein 
zusätzliches RAM wegfallen.

Es soll eine kleine Schularbeit (Fächer Bildverarbeitung und 
Programmieren) mit einem STM32F4-Discovery und basisboard werden.

Besten Dank, Gruss
Patrick

von Mehmet K. (mkmk)


Lesenswert?

Dıese Thematık wurde hier in der Vergangenheit bereits in einem Beitrag 
angesprochen. Die Antwort ist: "yes, we can".

von Patrick B. (p51d)


Lesenswert?

Noch eine ergänzende Frage:
Gibt es Displays, die über das FSMC angesteuert werden können, die eine 
grössere Auflösung als 320x240 haben? Die Demo-Boards und Eval-Boards 
mit einer Kamera (meistens OV9055) könnten ja ohne Probleme 640x480 oder 
noch höher im RGB565 Format generieren. Nur finde ich keine Displays.
Ebenso wird in einer AppNote (AN2790) darauf verwiesen, dass nur ein 
Display mit QVGA unterstützt wird, obwohl die Bank theorierisch 4x64MB 
hat. Jedenfalls finde ich weder Evalboards noch sonst was, dass eine 
höhere Displayauflösung bietet (auch keine Displays mit einem 
entsprechenden Anschluss).

Ich stehe gerade etwas im Regen. Kann mir jemand weiterhelfen (vieleicht 
auch gleich einen Display-Tip geben?)?

Besten Dank, Gruss

von Uwe Bonnes (Gast)


Lesenswert?

Warum nicht F429 Discovery? Hatt Ram und LCD...

von Patrick B. (p51d)


Lesenswert?

Habe ich mir auch angeschaut.
Dann müsste ich das Bild ins RAM schieben, und dann verkleinert 
(irgendwie dem DMA sagen, dass er jedes 2. oder 3. Pixel nimmt) an das 
Display weiter geben.
Prinzipiell eigentlich nicht verkehrt. So könnte ich das Bild (welches 
dann am PC sowieso bearbeitet wird) komplett abspeichern und dann die 
Lösung an das LCD senden.

Dann müsste der DMA aber inteligenet sein und die Adressen der Quelle 
nicht nur um 1 inkrementieren (damit das Bild im ersten Fall auch auf 
dem Display ist).

: Bearbeitet durch User
von grundschüler (Gast)


Lesenswert?

Patrick B. schrieb:
> DMA aber inteligenet sein und die Adressen der Quelle
> nicht nur um 1 inkrementieren

mit dem double-buffer-mode geht das möglicherweise:
Beitrag "Re: stm32f429 Expansion board"

Du kannst aber die Pixel vollständig im RAM speichern und dann nur z.B. 
jedes 2.Pixel /jede 2.Zeile auf dem Lcd anzeigen. das ist auch ohne DMA 
schnell genug.

von Patrick B. (p51d)


Lesenswert?

Ich habe mir mal das 429i-Disco etwas genauer angeschaut und muss sagen, 
dass ich von ST entäuscht bin. Hätten die nicht für 2 Cent das grössere 
Gehäuse nehmen können? So sind praktisch alle Peripherie-Schnittstellen 
schon für LCD und SDRAM belegt.

So wie ich das sehe, besteht die einzige Möglichkeit darin, dass LCD 
abwechselnd mit dem DCMI zu betreiben (sofern dies überhaupt möglich 
ist), da die wichtigen Pins wie PXCLK und HSYNC auf das LCD gelegt 
wurden.
Oder kann das LCD auch rein mit SPI (wie im verlinkten Artikel) ohne das 
Parallelinterface betrieben werden?

von DD4DA (Gast)


Lesenswert?

Ja, geht - ich benutze gerade ein 5" Display mit 800x480 Pixel mit 
SSD1963 am FSMC des STM32F407VG (Discovery4 board). Das funktioniert 
flüssig und ohne weitere Probleme.
Das FSMC_timing ist halt sehr wichtig damit das Display nicht überfahren 
wird oder Schnecken-Lahm wird.
Es gibt keine kardinalwerte die immer funktionieren. Das Timing ist 
wesentlich von der Verkabelung des Displays zum Host-Prozessor abhängig.
Je kürzer die Leitungswege sind, desto kürzer darf die Setup- und 
Hold-Zeit der Daten und Adresssignale sein - also ein langsameres oder 
schnelleres Display.
Ich benutze die Standard-Peripherie-Driver Library bei meinen Projekten. 
Es eine sehr übersichtliche Methode zur Programmierung der Kontroller.
Für Puristen ist dass allerdings nicht zu gebrauchen denn die wollen ja 
die Register selber anfassen - bitte sehr. Man darf jedoch nicht 
unterstellen dass die in der Lib zusammengefassten Funktionen immer 100% 
ok sind, sondern bei unerwartetem Verhalten man mal ein Blick in die 
Quellen wirft und auf Fehlerfreiheit prüft.
Um noch ein Beispiel für mein Timing am STM32407VG (Disco4 Board) an 
einem SSD1963 gestütztem 5" TFT Display beizusteuern, habe ich meine 
INIT-Werte mal angehangen. Sie dienen dazu, das Display für den Betrieb 
mit der Segger emWIN5.24b GUI-Lib vorzubereiten.

// Bit Banding
// Zeiger auf fixe Speicheradressen im Bereich des FSMA
// Register und Frame-Memory des SSD1963 werden in BANK 1 ab $6000:0000 
in den SRAM eingeblendet

#define LCD_REG16  (* ( (volatile unsigned short *) 0x60000000 ) ) /* RS 
= 0 */
#define LCD_RAM16  (* ( (volatile unsigned short *) 0x60020000 ) ) /* RS 
= 1 */



/*********************************************************************
*
*       LCD_X_Init
*
* Purpose:
*   This routine should be called from your application program
*   to set port pins to their initial values
*/

// NOTE: the RCC_AHB1Periph_CRC Clock path should be enable to work with 
emWIN5.xx libray - see AN4323 the note in Page 6
void LCD_CtrlLinesConfig ( void )
 {
 GPIO_InitTypeDef  GPIO_InitStructure;
 RCC_AHB1PeriphClockCmd ( RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOG | 
RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_GPIOF | RCC_AHB1Periph_CRC , 
ENABLE );
 RCC_AHB3PeriphClockCmd ( RCC_AHB3Periph_FSMC , ENABLE );

 GPIO_PinAFConfig ( GPIOD, GPIO_PinSource0,  GPIO_AF_FSMC );  // D2
 GPIO_PinAFConfig ( GPIOD, GPIO_PinSource1,  GPIO_AF_FSMC );  // D3
 GPIO_PinAFConfig ( GPIOD, GPIO_PinSource4,  GPIO_AF_FSMC );  // NOE -> 
RD
 GPIO_PinAFConfig ( GPIOD, GPIO_PinSource5,  GPIO_AF_FSMC );  // NWE -> 
WR
 GPIO_PinAFConfig ( GPIOD, GPIO_PinSource7,  GPIO_AF_FSMC );  // NE1 -> 
CS
 GPIO_PinAFConfig ( GPIOD, GPIO_PinSource8,  GPIO_AF_FSMC );  // D13
 GPIO_PinAFConfig ( GPIOD, GPIO_PinSource9,  GPIO_AF_FSMC );  // D14
 GPIO_PinAFConfig ( GPIOD, GPIO_PinSource10, GPIO_AF_FSMC );  // D15
 GPIO_PinAFConfig ( GPIOD, GPIO_PinSource11, GPIO_AF_FSMC );  // A16 -> 
RS
 GPIO_PinAFConfig ( GPIOD, GPIO_PinSource14, GPIO_AF_FSMC );  // D0
 GPIO_PinAFConfig ( GPIOD, GPIO_PinSource15, GPIO_AF_FSMC );  // D1

 GPIO_InitStructure.GPIO_Pin     = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 
| GPIO_Pin_5 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | 
GPIO_Pin_11 | GPIO_Pin_14 | GPIO_Pin_15;
 GPIO_InitStructure.GPIO_Mode    = GPIO_Mode_AF;
 GPIO_InitStructure.GPIO_Speed   = GPIO_Speed_100MHz;
 GPIO_InitStructure.GPIO_OType   = GPIO_OType_PP;
 GPIO_InitStructure.GPIO_PuPd    = GPIO_PuPd_NOPULL;
 GPIO_Init ( GPIOD , &GPIO_InitStructure );

 GPIO_PinAFConfig ( GPIOE, GPIO_PinSource7, GPIO_AF_FSMC );  // D4
 GPIO_PinAFConfig ( GPIOE, GPIO_PinSource8, GPIO_AF_FSMC );  // D5
 GPIO_PinAFConfig ( GPIOE, GPIO_PinSource9, GPIO_AF_FSMC );  // D6
 GPIO_PinAFConfig ( GPIOE, GPIO_PinSource10, GPIO_AF_FSMC );  // D7
 GPIO_PinAFConfig ( GPIOE, GPIO_PinSource11, GPIO_AF_FSMC );  // D8
 GPIO_PinAFConfig ( GPIOE, GPIO_PinSource12, GPIO_AF_FSMC );  // D9
 GPIO_PinAFConfig ( GPIOE, GPIO_PinSource13, GPIO_AF_FSMC );  // D10
 GPIO_PinAFConfig ( GPIOE, GPIO_PinSource14, GPIO_AF_FSMC );  // D11
 GPIO_PinAFConfig ( GPIOE, GPIO_PinSource15, GPIO_AF_FSMC );  // D12

 GPIO_InitStructure.GPIO_Pin     = GPIO_Pin_0 | GPIO_Pin_7 | GPIO_Pin_8 
| GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | 
GPIO_Pin_14 | GPIO_Pin_15;
 GPIO_InitStructure.GPIO_Mode    = GPIO_Mode_AF;
 GPIO_InitStructure.GPIO_Speed   = GPIO_Speed_100MHz;
 GPIO_InitStructure.GPIO_OType   = GPIO_OType_PP;
 GPIO_InitStructure.GPIO_PuPd    = GPIO_PuPd_NOPULL;
 GPIO_Init ( GPIOE , &GPIO_InitStructure );

 }




void LCD_FSMCConfig ( void )
 {
 FSMC_NORSRAMInitTypeDef FSMC_NORSRAMInitStructure;
 FSMC_NORSRAMTimingInitTypeDef   FSMC_NORSRAMTimingInitStructure;
 FSMC_NORSRAMTimingInitStructure.FSMC_AddressSetupTime          = 15; 
// 15
 FSMC_NORSRAMTimingInitStructure.FSMC_AddressHoldTime = 0;     // 0
 FSMC_NORSRAMTimingInitStructure.FSMC_DataSetupTime   = 13;   // 13
 FSMC_NORSRAMTimingInitStructure.FSMC_BusTurnAroundDuration  = 0;
 FSMC_NORSRAMTimingInitStructure.FSMC_CLKDivision  = 0;
 FSMC_NORSRAMTimingInitStructure.FSMC_DataLatency  = 0;
 FSMC_NORSRAMTimingInitStructure.FSMC_AccessMode   = FSMC_AccessMode_A;
 FSMC_NORSRAMInitStructure.FSMC_Bank               = 
FSMC_Bank1_NORSRAM1;
 FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = 
FSMC_DataAddressMux_Disable;
 FSMC_NORSRAMInitStructure.FSMC_MemoryType      = FSMC_MemoryType_SRAM;
 FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = 
FSMC_MemoryDataWidth_16b;
 FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = 
FSMC_BurstAccessMode_Disable;
 FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = 
FSMC_WaitSignalPolarity_Low;
 FSMC_NORSRAMInitStructure.FSMC_WrapMode        = FSMC_WrapMode_Disable;
 FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive= 
FSMC_WaitSignalActive_BeforeWaitState;
 FSMC_NORSRAMInitStructure.FSMC_WriteOperation  = 
FSMC_WriteOperation_Enable;
 FSMC_NORSRAMInitStructure.FSMC_WaitSignal                      = 
FSMC_WaitSignal_Disable;
 FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait                = 
FSMC_AsynchronousWait_Disable;
 FSMC_NORSRAMInitStructure.FSMC_ExtendedMode                    = 
FSMC_ExtendedMode_Disable;
 FSMC_NORSRAMInitStructure.FSMC_WriteBurst                      = 
FSMC_WriteBurst_Enable;
 FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct           = 
&FSMC_NORSRAMTimingInitStructure;
 FSMC_NORSRAMInit ( &FSMC_NORSRAMInitStructure );


 FSMC_NORSRAMTimingInitStructure.FSMC_AddressSetupTime          = 15; 
// 15
 FSMC_NORSRAMTimingInitStructure.FSMC_AddressHoldTime           = 0; 
// not supported
 FSMC_NORSRAMTimingInitStructure.FSMC_DataSetupTime              = 13; 
// 13
 FSMC_NORSRAMTimingInitStructure.FSMC_BusTurnAroundDuration     = 0;
 FSMC_NORSRAMTimingInitStructure.FSMC_CLKDivision               = 0;
 FSMC_NORSRAMTimingInitStructure.FSMC_DataLatency               = 0;
 FSMC_NORSRAMTimingInitStructure.FSMC_AccessMode                = 
FSMC_AccessMode_A;
 FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct               = 
&FSMC_NORSRAMTimingInitStructure;

 FSMC_NORSRAMInit ( &FSMC_NORSRAMInitStructure );

 FSMC_NORSRAMCmd ( FSMC_Bank1_NORSRAM1, ENABLE );
 }




/*********************************************************************** 
********
* Function Name  : LCD_Configuration
* Description    : Configure the LCD Control pins by FSMC Parallel 
interface and
*                : TFT register init.
* The LCD's bus and register init call is handled by this routine - 
sepperate init
* at startup (main) for Display and FSMC is not required.
* Input          : None
* Output         : None
* Return         : None
* Attention     : requires delay between the hardware I/O-Register and 
FSMC init
************************************************************************ 
*******/

void LCD_X_Init ( void )
 {
 LCD_CtrlLinesConfig();        // Configure the LCD Control pins 
------------------
 delay_ms (100);
 LCD_FSMCConfig();         // Configure the 16 Bit FSMC Parallel 
interface ----
 delay_ms (100);
 }

von DD4DA (Gast)


Lesenswert?

Das STM32F429 Disco hat kein besonders großes Display - externes 
Anschließen ist nicht so ohne weiteres möglich. Der Vorteil des on-Board 
Memories in Kombination mit dem on-Chip Display Controllers geht beim 
Disco-Board wegen des gelöteten Displays verloren. Es ist ja nur zum 
Probieren gedacht und nicht als Applikation.
Ich würde dazu tendieren ein eigenes Board mit dem STM32F429 plus DRAM 
und diskretem Display zu bauen, wenn es unbedingt dieses Controllers 
bedarf.
Das Ding ist jedem TFT-Modul mit On-Board Controller erdrückend 
überlegen. Das liegt einfach daran, dass man den Bildwiederholspeicher 
direkt und ohne Umwege mit dem Core oder DMA direkt manipulieren kann. 
Das alles zu Programmieren ist allerdings auch recht komplex und ist ja 
nicht der Selbstzweck sondern nur eine Teilaufgabe.
Der FSMC am STM32F407VG ist schon recht schnell und man kann schon 
ausreichend flüssig dargestellte Grafiken anzeigen lassen. Es hängt im 
wesentlichen von der Programmierweise ab wie gut das Ergebnis wird.
Das geht auch ganz ohne die Nutzung von DMA-Unterstützung. Segger zeigt 
es mit seiner emWIN GUI-Lib wie sowas aussehen kann.

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.