Forum: Mikrocontroller und Digitale Elektronik stm32f429 Expansion board


von Grundschüler (Gast)


Angehängte Dateien:

Lesenswert?

Dank bplaced.net habe ich den Einstieg in die M4-Welt geschafft - Leds 
blinken im Sekundentakt.

ich möchte über die DCMI-Schnittstelle Bilddaten an das sd-ram senden. 
Ich habe dcmi-D5 gegenüber Uwes Beispielcode von B6 auf D3 verlegt, da 
ich in erster Linie das sd-Ram nutzen will. Jetzt stört dcmi den 
RGB-TFT. Bei dem winzigen Bildschirm wäre spi völlig ausreichend. Wie 
stelle ich den Bildschirm von RGB auf SPI um?

von Bernd N (Gast)


Lesenswert?

Keil liefert ein entsprechendes Beispiel für die SPI Ansteuerung für 
dein Board.

von Grundschüler (Gast)


Lesenswert?

Bernd N schrieb:
> Keil

danke, werde ich suchen. Die hardware kann man auf der Unterseite 
sb22-25 einstellen. Es gibt vier spi-modi. Richtig müsste wohl 
4wire-8bit-sda sein: im1+im2 setzen.

von Uwe B. (derexponent)


Lesenswert?

Grundschüler schrieb:
> Bei dem winzigen Bildschirm wäre spi völlig ausreichend.

max SPI-Clock für das Display ist 10MHz
(so weit ich noch in Erinnerung habe)

320 x 240 Pixel und 16bit Farbe sind 153.600 Byte/Screen

per SPI dauert das ca. 120ms
der max refresh ist also ca. 8 Bilder/sec

reicht dir das ?!?

(per TFT-Bus geht das ca 100mal so schnell)


und eine fertige Lib für das ILI9341 (unter CoIDE) per SPI gibt es hier
da musst du nur die SPI Leitungen anpassen
(habe es aber auf dem STM32F429 nicht getestet)

http://mikrocontroller.bplaced.net/wordpress/?page_id=3071

: Bearbeitet durch User
von Grundschüler (Gast)


Lesenswert?

Uwe B. schrieb:
> ca. 8 Bilder/sec

das spi lcd läuft jetzt. Ich habe die Senderoutine etwas entschlackt:
1
uint8_t TM_SPI_Send(SPI_TypeDef* SPIx, uint8_t data) {
2
  //Fill output buffer with data
3
  SPIx->DR = data;
4
  //Wait for transmission to complete
5
//  while (!SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE));
6
  //Wait for received data to complete
7
//  while (!SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_RXNE));
8
  //Wait for SPI to be ready
9
  while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_BSY));
10
  //Return data from buffer
11
  return SPIx->DR;
12
}
läuft jetzt etwa so schnell wie beim M3, nicht ganz 2Bilder/sec. Viel 
mehr habe ich auch nicht erwartet. für Text aber völlig ausreichend.

Uwe B. schrieb:
> fertige Lib
habe ich auch versucht, Anpassung ist aber nicht ganz so einfach, weil 
es ein etwas anderer spi-modus iist.

von Grundschüler (Gast)


Lesenswert?

Bildaufbau lcd jetzt 4Bilder/sec,also alles ok und ausreichend schnell.

Problem bei der Einbindung des DCMI-Projekts:

Ich ziehe im Projekt-explorer z.B. die Datei stm32f4xx_fsmc.c in den 
cmsis_lib/source ordner. Es kommt eine Fehlermeldung weil FSMC_Bank3 
usw. nicht definiert ist.

ich benenne stm32f4xx_fsmc.c in stm32f4xx_fsmc_c.err um, weil ich den 
Fehler erst später suchen will. Die Fehlermeldung kommt weiter, d.h. die 
Datei wird trotz Umbenennung als c-Datei kompiliert. wenn ich die Datei 
nun im Windows-explorer suche, finde ich sie nicht obwohl sie im 
Projekt-explorer angezeigt wird.

Wie mache ich Coox klar, dass der Suchpfad genau so sein soll wie es der 
P-Explorer anzeigt?

von Uwe B. (derexponent)


Lesenswert?

beim STM32F429 gibt es kein FMSC sondern nur ein FMC !!

kann es sein das du das File für den STM32F407 benutzt ?
das funktioniert natürlich nicht

Die Peripheral-Repository darf beim STM32F429 NICHT benutzt werden !!


ich mache das immer so in der CoIDE :

1. per Win-Explorer die notwendigen Peripheral Files
(also hier stm32f4xx_fmc.c und stm32f4xx_fmc.h)
in den Projektordner kopieren . In den CMSIS_LIB Ordner

2. in CoIDE im Projekt-Explorer unter CMSIS_LIB per "Add Files"
die Files hinzufügen


Das funktioniert bei mir immer zuverlässig
und man hat alle notwendigen File im eigenen Projektordner

Uwe

: Bearbeitet durch User
von Grundschüler (Gast)


Lesenswert?

Uwe B. schrieb:
> Die Peripheral-Repository darf beim STM32F429 NICHT benutzt werden !!

danke, dann liegt der Fehler nicht bei mir.

von Grundschüler (Gast)


Lesenswert?

der M4 schreibt 1MByte in 130ms auf das SDRam - auf Anhieb ohne 
Änderungen an Uwes code. Langsam macht das mit dem Wechsel m3 zu m4 
Sinn.

Mit den Stm-Structuren habe ich noch Probleme. Ich möchte die DCMI 
Schnittstelle aktivieren, habe aber die Einstellung des pinouts noch 
nicht gefunden. Wäre für einen Tipp - insbesondere von Uwe - dankbar.

von Uwe B. (derexponent)


Lesenswert?

Grundschüler schrieb:
> habe aber die Einstellung des pinouts noch
> nicht gefunden

was meinst du mit "nicht gefunden" ?

wenn du die Pinbelegung an der CPU meinst,
gibt es hier eine Übersicht über alle Pins
vom STM32F429 (DCMI ist die Spalte ganz rechts)

http://mikrocontroller.bplaced.net/wordpress/wp-content/uploads/2013/10/Pinbelegung_f429_v100.html


> der M4 schreibt 1MByte in 130ms auf das SDRam

ich mache gerade tests für einen Logic-Analyzer
und da komme ich per DMA und (GPIO -> SDRAM)
auf ca. 48MByte/sec

bin aber noch nicht sicher ob die Daten konsistent sind :-)

Gruss Uwe

: Bearbeitet durch User
von Grundschüler (Gast)


Lesenswert?

ich habe jetzt das pinout in P_OV9655_InitIO entsprechend meiner 
20-pin-Schnittstelle angepasst. A8 liefert xClk. der ov7670 arbeitet und 
generiert Signale. Die Configuration des ov habe ich erst einmal 
weggelassen.

Ich müsste jetzt den DMA-Stream auf das SDram umleiten und dann vom 
sdram an das spi-lcd Schicken.
1
 DMA_InitStructure.DMA_PeripheralBaseAddr = OV9655_DCMI_REG_DR_ADDRESS;  
2
  DMA_InitStructure.DMA_Memory0BaseAddr = LCD_RAM_ADR;
3
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;

Wo finde ich die Adresse des SDRAM?

von Uwe B. (derexponent)


Lesenswert?

Grundschüler schrieb:
> Wo finde ich die Adresse des SDRAM?

die ergibt sich aus der Hardwarebeschaltung der Adress- und CS-Leitungen

#define SDRAM_START_ADR      ((uint32_t)0xD0000000)

: Bearbeitet durch User
von Grundschüler (Gast)


Lesenswert?

die Daten kommen bei den DCMI-Datainputpins an:
1
      tmp=(((GPIOC->IDR)&0x03c0)>>6)
2
    | (((GPIOE->IDR)&(1<<4))<<1)
3
    | (((GPIOD->IDR)&(1<<3))<<2)
4
    | (((GPIOD->IDR)&(32+64))<<1);
5
      lgi(11,1,tmp);
werden dann aber nicht in das DCMI-DR übernommen. Hier stehen immer 4 
bytes a 0b00000010.

von Grundschüler (Gast)


Lesenswert?

DR wird jetzt mit Werten gefüllt. Fehler war die Initialisierung für den 
ov7670:
1
  // DCMI init
2
  DCMI_InitStructure.DCMI_CaptureMode = DCMI_CaptureMode_Continuous;
3
  DCMI_InitStructure.DCMI_SynchroMode = DCMI_SynchroMode_Hardware;
4
  DCMI_InitStructure.DCMI_PCKPolarity = DCMI_PCKPolarity_Rising;
5
  //DCMI_InitStructure.DCMI_VSPolarity = DCMI_VSPolarity_Low;
6
  //DCMI_InitStructure.DCMI_HSPolarity = DCMI_HSPolarity_High;
7
  DCMI_InitStructure.DCMI_VSPolarity = DCMI_VSPolarity_High;
8
  DCMI_InitStructure.DCMI_HSPolarity = DCMI_HSPolarity_Low;
9
  DCMI_InitStructure.DCMI_CaptureRate = DCMI_CaptureRate_1of4_Frame;
10
  DCMI_InitStructure.DCMI_ExtendedDataMode = DCMI_ExtendedDataMode_8b; 
11
  DCMI_Init(&DCMI_InitStructure);
DCMI_VSPolarity /DCMI_HSPolarity anzugeben ist der Wert, bei dem nicht 
geschrieben wird.

von Grundschüler (Gast)


Lesenswert?

Auch die DMA scheint zu funktionieren mit:
1
      u8 *pt=((uint32_t)0xD0000000);
2
      lgi(16,1,*pt);lw("sd100");
3
      lgi(17,1,*pt+100);lw("sd100");
4
      lgi(18,1,*pt+1);lw("sd100");
 werden offensichtlich Sensorwerte angezeigt. Hier habe ich ein 
Verständnisproblem:
1
  // DMA init
2
  DMA_InitStructure.DMA_Channel = OV9655_DCMI_DMA_CHANNEL;  
3
  DMA_InitStructure.DMA_PeripheralBaseAddr = OV9655_DCMI_REG_DR_ADDRESS;  
4
//  DMA_InitStructure.DMA_Memory0BaseAddr = LCD_RAM_ADR;
5
#define SDRAM_START_ADRx      ((uint32_t)0xD0000000)
6
  DMA_InitStructure.DMA_Memory0BaseAddr = SDRAM_START_ADRx;
7
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
8
  DMA_InitStructure.DMA_BufferSize = 1;
9
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
10
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
11
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
12
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
13
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
14
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
15
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
16
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
17
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
18
  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;    
19
  DMA_Init(OV9655_DCMI_DMA_STREAM, &DMA_InitStructure);

Wieso ist das SDRam memory, es ist doch extern, also Peripheral?

Wieso werden die Daten nicht übereinander geschrieben da doch 
DMA_MemoryInc_Disable-d ist?

Wird das SDRam wie Memory behandelt?

von Uwe B. (derexponent)


Lesenswert?

"Peripheral" bedeutet nicht "extern" sondern
damit sind die einzelnen "Module" innerhalb der CPU gemeint

also "GPIO, TIMER, ADC, DCMI, DMA, UART" usw

"DMA_DIR_PeripheralToMemory" ist also hier schon richtig

die Ziel-Adresse entscheidet schlussendlich
ob internes oder externes RAM als "Memory" angesprochen wird

und "DMA_MemoryInc_Disable" ist meiner Meinung nach falsch

bist du dir sicher das die Daten richtig gespeichert werden ?

"Buffer_Size=1" und
"DMA_MemoryDataSize" != "DMA_PeripheralDataSize"
kommt mir auch komisch vor

: Bearbeitet durch User
von Grundschüler (Gast)


Lesenswert?

Das ist 100% dein Code mit geringen Änderungen für den ov7670 und der 
geänderten DestAdr. DataSize kann Sinn machen, weil DCMI immer 4Bytes 
ansammelt.

> bist du dir sicher das die Daten richtig gespeichert werden ?

Ziemlich sicher. Wenn ich den Sensor abdunkle, ändern sich alle drei 
Daten nicht mehr. Das lässt sich eigentlich nur so erklären, das die 
Daten ab SDRAM_START_ADR fortlaufend gespeichert werden. Als nächstes 
werde ich die Daten vom Ram in das Lcd einlesen. Ich bin guter Hoffnung, 
dass dann ein brauchbares Bild rauskommt.

von Uwe B. (derexponent)


Lesenswert?

Grundschüler schrieb:
> Das ist 100% dein Code

das kann ja sein....aber "mein" Code hat die Daten der Camera nicht
in ein RAM kopiert sondern an ein LCD gesendet

und das LCD inkrementiert seinen internen Adresspointer
nach jedem Schreibzugriff

daher das "DMA_MemoryInc_Disable"

warum das beim SDRAM auch funktioniert ist mir nicht ganz klar
(aber man muss auch nicht alles verstehen ;.)

Gruss Uwe

von Grundschüler (Gast)


Angehängte Dateien:

Lesenswert?

nach einigen Versuchen tauchte völlig unerwartet eine Schrift auf dem 
Bildschirm auf. Es funktioniert. Danke für Uwes Unterstützung. Schluss 
für heute.

von Grundschüler (Gast)


Lesenswert?

Grundschüler schrieb:
> Es funktioniert.

zu früh gefreut. Dieses merkwürdige Testbild stammt nicht vom ov7670.

Die DCMI-DMA funktioniert, allerdings werden nur die ersten 4bytes des 
SDRAM beschrieben. Macht eigentlich auch Sinn, denn der DMA-Transfer 
läuft immer für 4Bytes ab. Dann fängt er anscheinend mit der angegebenen 
DestAdr für das nächste int wieder von vorne an. Dest-Increment ist 
eanabled, ansonsten wird nur das erste Byte beschrieben.

Die DestAdr muss also incrementiert werden oder die Daten müssen aus der 
DestAdr abgeholt und auf das SDRam verteilt werden.

Kann ich DestAdr mittels Zeiger auf eine Adresse verweisen, die mittels 
px-interrupt hochgezählt wird?

Kann ich DestAdr  direkt durch einen px-interrupt hochzählen?

Muss ich den Inhalt von DestAdr mittels m2m-DMA auf das sdram verteilen?

Irgendwelche andere Ideen?

von Uwe B. (derexponent)


Lesenswert?

Grundschüler schrieb:
> Grundschüler schrieb:
>
> Kann ich DestAdr mittels Zeiger auf eine Adresse verweisen, die mittels
> px-interrupt hochgezählt wird?
>
> Kann ich DestAdr  direkt durch einen px-interrupt hochzählen?
>

das hochzählen vom Adresspointer macht der DMA...dafür ist der da

stellt mal "DMA_InitStructure.DMA_BufferSize"
auf die Größe von einem Bild der Camera ein
also : X-Auflösung * Y-Auflösung

dann sollten zumindest alle Bildpunkte der Camera im SDRAM landen
und nicht nur einer

von Grundschüler (Gast)


Lesenswert?

Uwe B. schrieb:
> stellt mal "DMA_InitStructure.DMA_BufferSize"
> auf die Größe von einem Bild der Camera ein
> also : X-Auflösung * Y-Auflösung

es tut sich was. es wird zwar nicht der ganze Bildschirm gefüllt - 
640*480/jedes 4.pixel _ gefüllt, aber es wird zumindest incrementiert.

Jetzt kann ich über den Zeilen-Intrrupt die DestAdr  nach jeder Zeile 
neu festsetzen. Das ist das nächste, was ich versuche.

von Uwe B. (derexponent)


Lesenswert?

Grundschüler schrieb:

> 640*480

stell doch erstmal in der Kamera eine Auflösung ein die
1. das Display auch anzeigen kann und
2. der DMA in einem Rutsch kopieren kann

also z.B. QQVGA mit 160×120 Pixel
(das sind 19200 Transfers)

da kannst du den DMA einmal Triggern und wenn er fertig
ist gemütlich die Daten ans Display senden
ohne groß Klimzüge machen zu müssen

und für die max Auflösung vom Display (320 x 240)
kannst den DMA auf "double Buffer-Mode" stellen
und zweimal 36400 Pixel transferieren...das sollte auch gehen

von Grundschüler (Gast)


Lesenswert?

QVGA ist kein Problem. das habe ich auch mit dem m3 geschafft. Es geht 
nur um größere Auflösungen.

Uwe B. schrieb:
> "double Buffer-Mode"

da scheint die Lösung hin zu gehen:
https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=%2Fpublic%2FSTe2ecommunities%2Fmcu%2FLists%2Fcortex_mx_stm32%2FDCMI%20Camera%20interface%20-%20max%20Resolution%20Camera&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B&currentviews=2990

den dort geposteten code werde ich jetzt einmal ausprobieren.

von Grundschüler (Gast)


Angehängte Dateien:

Lesenswert?

"double Buffer-Mode" speichert it dieser routine
1
void DMA2_Stream1_IRQHandler(void){
2
  if(DMA_GetITStatus(DMA2_Stream1, DMA_IT_TCIF1)){//TransferComplete
3
    DMA_ClearITPendingBit(DMA2_Stream1, DMA_IT_TCIF1);
4
    zl_Hline+=8;
5
//if(zl_Hline<600){
6
    pixel_cursorDB+=H_PX<<3;//*8
7
    if((zl_Hline)%16){//line0 ready - start line1
8
      DMA2_Stream1->M0AR=0xD0000000+4*H_PX*zl_Hline;
9
    }else{//line1 ready - start line0
10
      DMA2_Stream1->M1AR=0xD0000000+4*H_PX*zl_Hline;
11
    }
12
 //}/**/
13
  }
14
}
den DCMI-frame auf dem sdram.

Verbleibendes Problem ist, dass vom ov7670 noch keine brauchbaren 
rgb-daten kommen. Der SCCB-Bus scheint noch nicht zu funktionieren.

von Grundschüler (Gast)


Angehängte Dateien:

Lesenswert?

geschafft, 640x480px auf sdram und von da verkleinert auf das tft.

Nichts ist einfach. Selbst der SCCB-Code bereitet Schwierigkeiten, die 
es bei NXP und AVR nicht gab.

Danke nochmals für Uwes Unterstützung. Als nächstes kommt die SD-Karte 
und dann Ethernet.

von Grundschüler (Gast)


Angehängte Dateien:

Lesenswert?

Der ov3640 läuft jetzt mit XGA, wahrscheinlich auch mit mehr. Hier der 
DCMI-Code in der Endfassung.

von dummy (Gast)


Lesenswert?

Funktionen in einer Headerdatei. Wie grottig.

von Grundschüler (Gast)


Lesenswert?

dummy schrieb:
> Funktionen in einer Headerdatei. Wie grottig.

Das ist Grotten-C. DA macht man das so, weil es einfacher ist.

von STM32F429 (Gast)


Lesenswert?

Hallo Grundschüler,

mit welcher IDE hast du Programmiert? Würdest du das komplette Projekt 
zur Verfügung stellen?

Gruß

von Grundschüler (Gast)


Lesenswert?

STM32F429 schrieb:
> mit welcher IDE hast du Programmiert?

das ist - wie hier im thread beschrieben - ub_coox. Sehr zu empfehlen.

Du kannst den kompletten Code gerne haben, ich möchte nur vorher den 
sccb-Teil neu strukturieren, bevor ich ihn hier einstelle.

von Grundschüler (Gast)


Angehängte Dateien:

Lesenswert?

Der  Projektcode mit dem Sensor OV3640-XGA. Der OV7670 müsste auch noch 
gehen, habe ich aber nicht mehr getestet. Wie man sieht, ist ein 
Stepdown-Wandler erforderlich, da die 2,9Volt vom board für den OV3640 
und für den ENC nicht ausreichen. Die Enbindung des ENC steht noch an. 
Wäre hier für Unterstützung dankbar.  Nochmals Dank an Uwe für seine 
tolle Projektseite, die den Einstieg in die STM-Welt -mit all ihren 
Structure-Merkwürdigkeiten - sehr erleichtert hat.

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.