Hallo,
ich habe mir grade ein STM32F103VET Board mit TFT von Pollin zugelegt.
Das LCD besitzt einen ILI9325 Display-Controller und ist über 16 Bit
FSMC angebunden. Hierzu habe ich mir entsprechende Bibliotheken
zusammengeführt um die volle Funktionalität zu erzielen.
Soweit so gut:
Ich kann Texte schreiben, Graphen zeichnen und Bildchen anzeigen. (Alles
was man sich so wünscht). Touch gibts auch!
Aber:
Funktionen wie "LCD_Clear" benötigen ca.32 ms für die 320x240 Pixel.
Damit ist keine vernüftige Bildrate umzusetzen. Der Grund dafür ist
recht einfach - in sämmtlichen Bibliotheken wird eine for-Schleife für
die 320x240=76800 Pixel genutzt und jedes mit einer entsprechenden Farbe
gefüllt. Mit einer Taktfrequenz von 72 MHz weiß man dann schnell wo die
32 ms herkommen.
Da ich ein großer Fan von DMA bin dachte ich mir, dass ich diesen doch
nutzen könnte um die Pixel im Hintergrund und wesentlich schnell zu
füllen. Ebenso könnte man so schnell kleine Bildchen/Icons aus einem
Puffer ausgeben.
Leider scheitere ich momentan an dieser Aufgabe: Der DMA scheint ein
Timing-Problem mit dem FSMC zu haben - zwar kommen Daten an - diese sind
jedoch fehlerhaft. Die ersten 10-20 Pixel sind müll, während die
nachfolgenden Pixel eine kontinuierliche, falsche Farbe haben (rot statt
gelb).
Der Code dafür sieht so aus:
1 | uint16_t ColorDMA = Color;
|
2 |
|
3 | LCD_SetCursor( 0, 0 );
|
4 | LCD_WriteRAM_Prepare(); /* Prepare to write GRAM */
|
5 |
|
6 | RCC_AHBPeriphClockCmd( RCC_AHBPeriph_DMA1, ENABLE );
|
7 |
|
8 | DMA_InitTypeDef DMA_InitStructure;
|
9 |
|
10 | DMA_StructInit( &DMA_InitStructure );
|
11 |
|
12 |
|
13 | DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t) &(ColorDMA);
|
14 | DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
|
15 | DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
|
16 |
|
17 | DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) 0x60020000;
|
18 | DMA_InitStructure.DMA_PeripheralDataSize = DMA_MemoryDataSize_HalfWord;
|
19 | DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
|
20 |
|
21 | DMA_InitStructure.DMA_M2M = DMA_M2M_Enable;
|
22 | DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;//DMA_DIR_PeripheralSRC;
|
23 |
|
24 | DMA_InitStructure.DMA_BufferSize = 3000; // max 65535
|
25 |
|
26 | DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
|
27 | DMA_InitStructure.DMA_Priority = DMA_Priority_Low;
|
28 |
|
29 | DMA_DeInit( DMA1_Channel1 );
|
30 | DMA_Init( DMA1_Channel1, &DMA_InitStructure );
|
31 |
|
32 | DMA_ITConfig( DMA1_Channel1, DMA_IT_TC, ENABLE );
|
33 |
|
34 | NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
|
35 |
|
36 | DMA_Cmd( DMA1_Channel1, ENABLE );
|
37 |
|
38 | while(!(DMA_GetITStatus(DMA1_IT_TC1)));
|
39 | DMA_ClearFlag(DMA1_FLAG_TC1);
|
Der Code sollte eigentlich die ersten 3000 Pixel in der vorgebenen Farbe
füllen. Stattdessen sind die ersten 10-20 Pixel schwarz und die
restlichen rot statt gelb.
Was mir auch vollständig unerklärlich ist: warum nutzt keine der
Bibliotheken den DMA für solche Funktionen? Eigentlich liegt das doch
auf der Hand... Laut STM32 Datenblättern sollte der DMA auf FSMC
zugreifen können...
Ich hoffe hier kann mir jemand helfen!
Gruß Erik