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?
Keil liefert ein entsprechendes Beispiel für die SPI Ansteuerung für dein Board.
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.
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
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.
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?
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
Uwe B. schrieb: > Die Peripheral-Repository darf beim STM32F429 NICHT benutzt werden !! danke, dann liegt der Fehler nicht bei mir.
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.
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
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?
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
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.
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.
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?
"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
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.
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
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.
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?
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
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.
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
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¤tviews=2990 den dort geposteten code werde ich jetzt einmal ausprobieren.
"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.
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.
Der ov3640 läuft jetzt mit XGA, wahrscheinlich auch mit mehr. Hier der DCMI-Code in der Endfassung.
dummy schrieb: > Funktionen in einer Headerdatei. Wie grottig. Das ist Grotten-C. DA macht man das so, weil es einfacher ist.
Hallo Grundschüler, mit welcher IDE hast du Programmiert? Würdest du das komplette Projekt zur Verfügung stellen? Gruß
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.