Wir machen Beispiele für STM32, die in verschiedenen Entwicklungsumgebungen gesammelt wurden

Wie ich bereits in früheren Artikeln erwähnt habe, bin ich einer der Entwickler des All-Hardware-Dienstes, über den jeder remote mit verschiedenen Debug-Boards arbeiten kann, die dort von Mikrocontroller-Herstellern veröffentlicht werden. Standardmäßig wird eine Beispiel-Demo-Anwendung auf jede Karte geladen. Das Projekt zur Selbstorganisation dieser Anwendung kann heruntergeladen werden, um Experimente von Grund auf neu zu starten. Alles wäre in Ordnung, aber unterschiedliche Benutzer bevorzugen unterschiedliche Entwicklungsumgebungen. Natürlich ist es unmöglich, die gesamte Vielfalt abzudecken, aber zumindest Eclipse, was bedeutet, dass GNU im Allgemeinen (im Fall von STM32 ist es eher eine spezielle Baugruppe der STM32-Cube-IDE) und Keil mit IAR, es wert ist. Eigentlich wurde ich angewiesen, zumindest einige Demoprojekte für STM32-Boards zu vereinheitlichen. In diesem Artikel werde ich Ihnen zunächst erklären, wie Sie ein einfacher Benutzer sein können.Wer ging zum Dienst und lud das Beispiel herunter. Was muss getan werden, um es zu sammeln? Nun, und nur dann wird es einige Memoiren geben, die die gewählte Entscheidung rechtfertigen und einfach die Eindrücke der Arbeit beschreiben.







1. Welche Art von Anwendungen



Schauen wir uns zunächst an, welche Apps angeboten werden. Wir betreten die Website https://all-hw.com/ .



Sie müssen sich dort anmelden (die Registrierung ist kostenlos). Danach wird eine Liste der verfügbaren Boards angezeigt. Der erste von ihnen hat keinen Bildschirm, daher ist er als Illustration für den Artikel unpraktisch. Der zweite ist banal, jeder hat ihn, es ist einfach nicht interessant, darüber zu sprechen. Ich werde die dritte wählen - STM32F469I Discovery . Nachdem ich einige Schritte durchlaufen habe, befinde ich mich auf der folgenden Seite: Links sehen wir die Tafel, die die Kamera entfernt. Und genau diese Anwendung funktioniert dort. Der Zähler tickt nur. Wenn Sie im Terminal rechts eine Zeile eingeben, wird diese auf dem Bildschirm angezeigt, da das Terminal mit dem UART-Debug-Port verbunden ist. Nun, hier habe ich Just Test eingegeben.



























Es scheint, dass eine Anwendung für einen Controller zur Implementierung dieser Funktionalität nicht kompliziert ist, aber ... Aber ... Aber ich wiederhole, wir nehmen die Anzahl der Arten von ST-Karten und multiplizieren sie mit mindestens drei. Und wieder eine sehr wichtige Bedingung: Die Entwicklungszeit dieser Anwendung sollte nicht lang sein. Wir müssen es so schnell wie möglich entwickeln. Und es muss von mindestens drei Compilern kompiliert werden.



2. Mögliche Wege



Das erste, was mir in den Sinn kommt, ist die Entwicklung einer typischen Anwendung im STM32Cube MX. Dort können Sie alles für drei Entwicklungsumgebungen generieren und schnell Standardgeräte hinzufügen. So ist es, aber:



  1. Wenn Sie sich die Beispiele für die Arbeit mit Anwendungen ansehen, die mit CubeMX erstellt wurden, sehen Sie, dass Sie dort nach der automatischen Erstellung noch viel mit einer Datei verfeinern müssen. Das heißt, obwohl Zeit gespart wird, ist sie immer noch nicht maximal.
  2. , .
  3. Cube MX STemWin, ( , , , ST STemWin TouchGFX, – ).


Tatsächlich reicht dies aus, um eine solche Option in der Reserve zu verschieben und zu prüfen, ob es einfachere Lösungen gibt ... Es stellt sich heraus, dass es solche gibt, und sie beziehen sich auch auf den Cube MX. Jeder, der mit dieser Umgebung gearbeitet hat, weiß, dass sie aus Kerncode und Paketen besteht, die eine bestimmte Familie von Controllern bedienen. Was ist das Paket? Dies ist eine ZIP-Datei. Lassen Sie es uns herunterladen und entpacken. Nehmen Sie zum Beispiel ein Paket für einen brandneuen STM32H747. Ich habe diese Datei en.stm32cubeh7_v1-8-0.zip.



Und wir sehen einen solchen Reichtum darin:







Dies sind typische Lösungen für verschiedene Prototyping-Boards mit diesem Controllertyp. Okay. Wir geben unseren Katalog STM32H747I-DISCO ein... Es gibt separat vorgefertigte Anwendungen und separat - Beispiele für die Arbeit mit Steuerblöcken. Hier gibt es nichts Interessantes für diejenigen, die nur ein Beispiel erstellen möchten, aber Entwickler einer typischen Demo-Anwendung sollten den Inhalt des UART-Verzeichnisses studieren.







Und von Anwendungen natürlich STemWin. Und das einfachste. Hallo Welt. Das Verzeichnis, in dem es sich befindet, ist für alle Benutzer von Interesse.







Wir werden unser Beispiel basierend auf dieser Anwendung machen. Warum? Wir betreten das Verzeichnis STemWin_HelloWorld und sehen:







ST-Programmierer haben alles für uns getan. Sie erstellten Quellen, die aus Keil, IAR und Eclipse (in der Tat Cube-IDE) kompiliert werden können. Es reicht also aus, diese Quellen zu korrigieren, und die Aufgabe wird gelöst, ohne die Dateien zu bearbeiten, die von den Entwicklungsumgebungen abhängen! Nun, und das Hello World-Projekt zeigt auch Texte auf dem Bildschirm an. Es reicht aus, UART-Unterstützung hinzuzufügen, und alles wird funktionieren. Aus diesem Grund habe ich oben erwähnt, dass das UART-Beispiel auch für Entwickler nützlich ist.



Und in diesem speziellen Fall trete ich meinem eigenen Lied auf die Kehle. Wenn jemand meine vorherigen Artikel gelesen hat, weiß er, dass ich HAL hasse. HAL und Optimierung sind zwei inkompatible Dinge. In realen Projekten verwende ich entweder die direkte Arbeit mit Hardware oder die Treiber von Konstantin Chizhov (mcucpp-Bibliothek). In diesem speziellen Fall ist dies jedoch überhaupt nicht der Fall. Wir machen nur ein Programm, das Texte anzeigt und mit einem COM-Port arbeitet. Auf einem Controller mit einer Taktfrequenz von Hunderten von Megahertz. Um ehrlich zu sein, kam zur Zeit von Ona die übliche BK-shka damit zurecht, deren Prozessor bei einer Frequenz von 3 MHz arbeitete. Darüber hinaus hatte der BK-shki keine RISC-Befehle, es gab nicht einmal eine Pipeline. Es gab jedoch einen Multiplexbus (dh mehrere Takte pro Zyklus) und einen asynchronen DRAM ohne Caching. Zusamenfassend,Die Leistung betrug nur 300.000 Register-Register-Operationen pro Sekunde. Und dies war genug, um das Problem der Textausgabe zu lösen und mit UART (über den IRPS-Block) zu arbeiten. Das heißt, die Optimalität des HAL-Codes für diese Aufgabe auf modernen STM32s reicht auch für die anstehenden Aufgaben völlig aus. Die Entwicklungsgeschwindigkeit bei Verwendung von HAL ist jedoch am höchsten.



Es wird ein neues Board angezeigt, an das definitiv eine HAL mit einheitlichen Anrufen angehängt ist. Wir werden die Initialisierung im typischen Beispiel gemäß dem beigefügten UART-Beispiel korrigieren, und die Arbeit wird immer dieselbe sein. Die Entwicklungsgeschwindigkeit beträgt mehrere zehn Minuten. Nicht einmal eine Uhr. Das heißt, um dieses Problem zu lösen, ist es definitiv am besten, HAL zu verwenden, obwohl ich es für Kampffälle nicht mag.



Alle. Das Minimum an Theorie, ohne das es unmöglich ist, zur Praxis überzugehen, sagte ich. Ich werde Ihnen nach der Laborarbeit detailliertere theoretische Dinge erzählen. Fahren wir also mit den Experimenten fort.



3. Was sollte der Endbenutzer tun?



3.1 Laden Sie das Paket herunter



Damit. Sie werden nicht sofort etwas Eigenes erstellen, sondern zunächst mit einem vorgefertigten Beispiel aus der All-Hardware-Website spielen. Was brauchst du, um es zu erstellen und auszuführen? Zunächst müssen Sie Bibliotheken für eine bestimmte Karte herunterladen. Bei der Arbeit mit Open Source-Lösungen bin ich bereits auf die Tatsache gestoßen, dass es nicht ausreicht, ein Projekt herunterzuladen. Wir müssen noch 100.500 Tools installieren und 100.500 Bibliotheken von Drittanbietern herunterladen. Hier müssen Sie nur eine Datei herunterladen und entpacken. Es stimmt, seine Größe ist gigantisch. Aber der Inhalt ist einfach toll. Damit. Wir benötigen Pakete für STM32 CubeMX. Nun sieht ein direkter Link zu ihrem Repository folgendermaßen aus:



www.st.com/de/development-tools/stm32cubemx.html#tools-software



Welches Paket heruntergeladen werden soll, ist in der folgenden Tabelle aufgeführt.

Zahlen Paket
STM32F429I-Erkennung STM32CubeF4
STM32F469I Erkennung STM32CubeF4
STM32G474RE DPOW1-Erkennung (kein Bildschirm) STM32CubeG4
STM32F746G-Erkennung STM32CubeF7
STM32H747I Erkennung STM32CubeH7


3.2 Projekt kopieren und an die Arbeit gehen



Die Struktur der Pakete ist im Inneren dieselbe, daher

wechseln wir in das Verzeichnis mit der folgenden Hierarchie: <Paketname> \ Projekte \ <Boardname> \ Anwendungen \ STemWin.



Kopieren Sie dort das Verzeichnis mit dem Beispiel. Wir bekommen so etwas:





Der Speicherort des Verzeichnisses ist wichtig, da die Pfade zu den Bibliotheken in einem relativen Format geschrieben sind. Wenn das Projekt aufgrund der großen Anzahl fehlender Dateien nicht erstellt wird, raten Sie nicht, wo es sich in der Verzeichnishierarchie befindet.
Wir betreten den Katalog, wählen eine Projektvariante für eine der Entwicklungsumgebungen aus, öffnen das Projekt, arbeiten damit ... Ende der Anleitung!







3.3 Funktion der STM32G474RE DPOW1 Discovery-Karte



Diese Karte hat keinen Bildschirm, was bedeutet, dass das proprietäre Paket keinen STemWin-Katalog enthält. Daher sollte das Projekt auf die nächste Ebene gestellt werden:



\ STM32Cube_FW_G4_V1.3.0 \ Projects \ B-G474E-DPOW1 \ Examples \ UART



4. Wie Projekte erstellt werden



Es ist klar, wie einfach es ist, ein Beispiel zusammenzustellen. Schauen wir uns nun an, wie diese Beispiele gemacht werden. Vielleicht sind diese Informationen nützlich für diejenigen, die etwas anderes tun möchten, als nur Texte auf dem Bildschirm anzuzeigen. Nun, wenn in ein paar Monaten das nächste Board implementiert werden muss und ich bereits alles vergessen habe, werde ich diesen Artikel selbst öffnen, um die Anweisungen in meinem Gedächtnis zu aktualisieren.



4.1 UART hinzufügen und initialisieren



Dem typischen STemWin Hello World-Beispiel fehlt vorhersehbar ein UART. Es muss hinzugefügt werden. Es scheint, dass wir den Beispielcode nehmen und hinzufügen. Leider ist das Leben komplizierter. In einer Arbeitsfunktion machen wir das so. Bei der Initialisierung gibt es jedoch einige Nuancen. Zunächst haben verschiedene Prototyping-Boards unterschiedliche Ports, die an den im JTAG-Adapter integrierten USB-UART-Adapter angeschlossen sind. Welches angeschlossen ist, müssen Sie in der Beschreibung für die Karte suchen. Normalerweise natürlich USART1, aber es ist besser, es noch einmal zu überprüfen.



Ferner wird die Vielfalt durch die Tatsache eingeführt, dass während der Entwicklung von Steuerungen verschiedene nützliche Funktionen zu den UART-Geräten hinzugefügt werden. Sie müssen auch in der HAL der neuen Boards initialisiert werden. Insbesondere die Arbeit mit FIFO.



Daher schlage ich die folgenden typischen Schritte vor:



  1. Fügen Sie ein Port-Handle hinzu.
  2. Fügen Sie die UART-Hardware-Initialisierung hinzu.
  3. Initialisierung der UART-Pins hinzufügen.
  4. UART-Interrupt-Handler hinzufügen.


Mit dem Griff ist alles klar und universell. Es wird ungefähr so ​​aussehen:



UART_HandleTypeDef huart1;


Der Rest befindet sich im Beispiel des Verzeichnisses \ <Paketname> \ Projects \ <Boardname> \ Examples \ UART .



Beispiel: Projekt \ STM32Cube_FW_H7_V1.8.0 \ Projekte \ STM32H747I-DISCO \ Beispiele \ UART \ UART_WakeUpFromStopUsingFIFO .



Die main () - Funktion enthält die Initialisierung des UART selbst (Sie müssen nur sicherstellen, dass die Geschwindigkeit 9600 beträgt. Wenn nicht, geben Sie sie ein). Die Verbindung mit den Beinen wird in einer anderen Datei in der

Void- Funktion HAL_UART_MspInit (UART_HandleTypeDef * huart) konfiguriert .



Ich ziehe es vor, alles in einer Funktion zusammenzufassen. Da die Zeit begrenzt ist, habe ich nicht versucht, eine solche Funktion aus diesen Materialien zu kompilieren, sie in die Datei main.c zu stellen und nicht zu vergessen, sie über die Funktion main () aufzurufen.



static void MX_USART1_UART_Init(void)
{

  /* USER CODE BEGIN USART1_Init 0 */
	  GPIO_InitTypeDef  GPIO_InitStruct;


  /* USER CODE END USART1_Init 0 */

  /* USER CODE BEGIN USART1_Init 1 */

//	__HAL_RCC_LPUART1_CLK_ENABLE();
	__HAL_RCC_USART1_CLK_ENABLE();

  /* USER CODE END USART1_Init 1 */
  huart1.Instance = USART1;
  huart1.Init.BaudRate = 115200;
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
  huart1.Init.StopBits = UART_STOPBITS_1;
  huart1.Init.Parity = UART_PARITY_NONE;
  huart1.Init.Mode = UART_MODE_TX_RX;
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
  huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart1) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetTxFifoThreshold(&huart1, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetRxFifoThreshold(&huart1, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_EnableFifoMode(&huart1) != HAL_OK)
  {
    Error_Handler();
  }

  /* Enable the UART RX FIFO threshold interrupt */
  __HAL_UART_ENABLE_IT(&huart1, UART_IT_RXFT);

  /* Enable the UART wakeup from stop mode interrupt */
  __HAL_UART_ENABLE_IT(&huart1, UART_IT_WUF);

  /* USER CODE BEGIN USART3_Init 2 */
	__HAL_RCC_GPIOA_CLK_ENABLE();

  /*##-2- Configure peripheral GPIO ##########################################*/
  /* UART TX GPIO pin configuration  */
  GPIO_InitStruct.Pin       = GPIO_PIN_9;
  GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull      = GPIO_PULLUP;
  GPIO_InitStruct.Speed     = GPIO_SPEED_FREQ_VERY_HIGH;
  GPIO_InitStruct.Alternate = GPIO_AF7_USART1;

  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /* UART RX GPIO pin configuration  */
  GPIO_InitStruct.Pin = GPIO_PIN_10;
  GPIO_InitStruct.Alternate = GPIO_AF7_USART1;

  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  
  /* NVIC for USART */
  HAL_NVIC_SetPriority(USART1_IRQn, 0, 1);
  HAL_NVIC_EnableIRQ(USART1_IRQn);
	

  /* USER CODE END USART1_Init 2 */

}




, , JTAG. . — , JTAG , . .
Interrupts sind einfach. Wir suchen im Beispiel nach einer Datei mit dem Suffix _it.c und übertragen die UART-Zeilen in die Datei mit dem Suffix _it unseres Projekts.



In diesem Fall wird aus der Datei

\ STM32Cube_FW_H7_V1.8.0 \ Projects \ STM32H747I-DISCO \ Examples \ UART \ UART_WakeUpFromStopUsingFIFO \ CM7 \ Src \ stm32h7xx_it.c



in die Datei

\ STM32Cube_FW_H7_V1.8.0 \ STM32Cube_FW_H7_V1.8.0 \ STM32Cube_FW_H7_V1.8.0 \ STemWin \ Demo_H747 \ CM7 \ Core \ Src \ stm32h7xx_it.c



Übertragen Sie das Fragment:



extern UART_HandleTypeDef huart1;
void USART1_IRQHandler(void)
{
 HAL_UART_IRQHandler(&huart1);
}


Alle.



4.2 Hauptarbeitsfunktion bearbeiten



Mit der Hauptarbeitsfunktion ist im Prinzip alles einfacher. Obwohl nicht im Prinzip und insbesondere - nicht ganz, aber wir werden weiter unten darüber sprechen. Lassen Sie uns zunächst sehen, welche Funktion am Ende der Hauptfunktion aufgerufen wird. In diesem Fall sind dies:



  MainTask();


Dies bedeutet, dass die Hauptarbeit darin erledigt wird. Wir ersetzen nur den Körper durch ein typisches Beispiel aus unserer Website.



4.3 Wie geht es weiter?



Außerdem können Sie Beispiele für andere Geräte ziehen, wie wir es gerade mit den UART-Geräten getan haben. Die Kontrolle über den Betrieb dieses Geräts geht zwar über den Rahmen dieses Artikels hinaus. Wie Sie sehen können, gilt das typische Steuerelement auf der WEB-Seite nur für das Bild und für einen UART. Der Rest wird etwas schwieriger weitergeleitet. Trotzdem kann ich nicht anders, als Ihnen zu sagen, wie ich einmal angewiesen wurde, an einem Abend einen Morsecode-Generator auf der Basis des STM32G474RE DPOW1 Discovery- Boards herzustellen . Wenn Sie sich eines Abends auf einem unbekannten Board von Grund auf neu entwickeln, können Sie nicht Hunderte von Dokumentationsseiten lesen. Wenn das Projekt über Jahrhunderte durchgeführt würde, würde ich dem Management einfach beweisen, dass es nicht richtig ist und dass alles sorgfältig untersucht werden sollte. Das Projekt hatte aber auch einen kurzen Lebenszyklus. Also beschloss ich, den Weg des Herausziehens von Beispielen zu beschreiten.



Für Morsecode benötigen Sie also einen Sinus mit einer Frequenz von 1 kHz ... Entpacken Sie mit der üblichen Handbewegung die Datei en.stm32cubeg4_v1-3-0.zip und untersuchen Sie das Verzeichnis D: \ tmp \ STM32Cube_FW_G4_V1.3.0 \ Projects \ B-G474E-DPOW1 \ Beispiele ... und nichts Gutes nicht gefunden ...







Das DAC-Verzeichnis enthält nichts Nützliches.







Ist das das Ende? Nicht wirklich. Schauen wir uns Beispiele von anderen Boards mit demselben Kristall an (wenn auch in unterschiedlichen Paketen) ... Und das ist die Schönheit, die wir für das Nucleo-Board finden!







Das Schöne ist, dass sich in der Datei main.c eine Tabelle zum Generieren des Sinus befindet:



/* Sine wave values for a complete symbol */
uint16_t sinewave[60] = {
0x07ff,0x08cb,0x0994,0x0a5a,0x0b18,0x0bce,0x0c79,0x0d18,0x0da8,0x0e29,0x0e98,0x0ef4,0x0f3e,0x0f72,0x0f92,0x0f9d,
0x0f92,0x0f72,0x0f3e,0x0ef4,0x0e98,0x0e29,0x0da8,0x0d18,0x0c79,0x0bce,0x0b18,0x0a5a,0x0994,0x08cb,0x07ff,0x0733,
0x066a,0x05a4,0x04e6,0x0430,0x0385,0x02e6,0x0256,0x01d5,0x0166,0x010a,0x00c0,0x008c,0x006c,0x0061,0x006c,0x008c,
0x00c0,0x010a,0x0166,0x01d5,0x0256,0x02e6,0x0385,0x0430,0x04e6,0x05a4,0x066a,0x0733};


Wir prüfen und stellen sicher, dass ja. In diesem Beispiel wird am DAC-Ausgang ein Sinus oder Dreieck generiert. Und das nur mit einer Frequenz von 1 KHz. Das ist großartig! Da die Zeit begrenzt war, habe ich mir nicht einmal die Mühe gemacht, eine Theorie zu lesen. Ich habe nur sichergestellt, dass die gesamte Formation auf Hardware-Ebene stattfindet, indem ich mir den Code kurz angesehen habe. Danach habe ich im Projekt den Controller durch den in der erforderlichen Platine ersetzt, zusammengebaut, ausgefüllt, gestartet und nach dem Laufenlassen der Oszilloskopsonde entlang der Beine den gefunden, auf dem dieser Sinus vorhanden ist. Dann habe ich es an den Eingang der Lautsprecher angeschlossen, die Erzeugung eines Sinus oder eines Dreiecks durch die Erzeugung eines Sinus oder einer Stille ersetzt (ja, ich habe eine andere Tabelle nur aus Nullen erstellt) ... Nun, das Schreiben eines angewendeten Teils mit Morsecode war so einfach wie das Schälen von Birnen. Ich erinnerte mich an meine Jugend, die Militärabteilung, Oberst Pawlow ...



Im Allgemeinen ist die Technik "Finden Sie ein Beispiel, fügen Sie es in Ihren Code ein" sehr effektiv. Und der Ansatz „ein typisches Beispiel erstellen - eine riesige Bibliothek herunterladen“ trägt dazu bei, da all diese Markenbeispiele Teil davon sind.



5. Probleme bei der Vereinigung



Ein Kollege von mir zitiert gerne die folgende philosophische Aussage:



„Theoretisch gibt es keinen Unterschied zwischen Theorie und Praxis. In der Praxis ist es das. "



Bei der Arbeit mit verschiedenen STM32 habe ich mich regelmäßig daran erinnert. Ich habe bereits über unvermeidlich unterschiedliche UARTs gesprochen, aber es scheint, dass der einheitliche StemWin keine Überraschungen bieten sollte ... Präsentiert!



5.1 STM32H747



Hallo Welt ist gezeichnet. Aber wenn ich den Arbeitscode übertrage, sehe ich einen blauen Bildschirm. Es ist nur so, dass wir zuerst einen roten Bildschirm für eine Sekunde zeichnen, dann einen grünen Bildschirm für eine Sekunde, dann einen blauen Bildschirm für eine Sekunde, dann beginnt die Arbeit. Wenn Sie unmittelbar nach der Initialisierung einen Haltepunkt setzen, noch bevor eine Zeichnung ausgelöst wird, werden die Timer-Messwerte vom letzten Start auf dem Bildschirm angezeigt. Dann werden sie von demselben blauen Bildschirm überschrieben. Was?



Ich entferne die Ausgabe von drei Farben pro Sekunde und füge sofort die Arbeit hinzu. Es funktioniert, aber es friert schnell für immer ein. Allmählich finde ich heraus, was nach 37 Millisekunden einfriert. Was für eine magische Zeit ist das? Eine Millisekunde ist klar. System-Tick. Aber 37. Ja, zumindest etwas Rundes, Nahes ...



Wie lang, kurz, aber ich finde heraus, dass alles im Interrupt-Handler angezeigt wirdHAL_DSI_IRQHandler (DSI_HandleTypeDef * hdsi) . Es wird aufgerufen, alles wird angezeigt, danach werden die Anrufe beendet. Alles wird im Puffer gebildet, aber nicht auf dem Bildschirm angezeigt. Genauer gesagt, im Leben des Programms erscheint alles zweimal auf dem Bildschirm. Bei der Initialisierung (das gleiche Artefakt aus einem früheren Leben) und nach 37 ms. Alles, was dazwischen war, wird niemand sehen.



Im Kopf - Sie müssen die Dokumentation studieren und herausfinden, was was ist. Aber in der Tat - die Zeit für die Aufgabe ist nicht wenig, aber sehr wenig. Es ist klar, dass die Unterbrechung provoziert werden muss, aber wie? Ich versuche ehrlich, GUI_Exec () aufzurufen, obwohl GUI_Delay () dort sowieso aufgerufen wird ... Hilft nicht.



Das Beispiel ist tot. Eher ist es dort lustig. Hello World wird wie in den ersten 37 ms gedruckt. Und dann - ein totes Beispiel. Ok, ich nehme ein Beispiel mit Animation aus demselben Katalog. Es funktioniert. Allmählich finde ich heraus, was herausgezogen werden muss, damit unser Beispiel funktioniert ... So sieht unser typischer Code aus:



  	GUI_SetBkColor(GUI_RED);
        GUI_Clear();
  	GUI_Delay(1000);
  	GUI_SetBkColor(GUI_GREEN);
  	GUI_Clear();
  	GUI_Delay(1000);
  	GUI_SetBkColor(GUI_BLUE);
  	GUI_Clear();
  	GUI_Delay(1000);


Nun, es ist logisch! Und es funktioniert! .. Auf anderen Boards ... Aber nach einer solchen Bearbeitung hat es sich irgendwie auf dem H747 bewegt:







Der gleiche Text.
	GUI_MULTIBUF_Begin();
  	GUI_SetBkColor(GUI_RED);
        GUI_Clear();
	GUI_MULTIBUF_End();
  	GUI_Delay(1000);
	GUI_MULTIBUF_Begin();
  	GUI_SetBkColor(GUI_GREEN);
  	GUI_Clear();
	GUI_MULTIBUF_End();
  	GUI_Delay(1000);
	GUI_MULTIBUF_Begin();
  	GUI_SetBkColor(GUI_BLUE);
  	GUI_Clear();
	GUI_MULTIBUF_End();
  	GUI_Delay(1000);




Aber im Allgemeinen funktioniert es und im Besonderen - der rote und der grüne Bildschirm halten eine Sekunde lang an, der blaue flackert und der Arbeitsbildschirm wird sofort angezeigt. Nach einer kleinen Anzahl von Experimenten stellte sich heraus, dass in dieser Form alles voll funktioniert:



	GUI_MULTIBUF_Begin();
  	GUI_SetBkColor(GUI_RED);
        GUI_Clear();
	GUI_MULTIBUF_End();
	GUI_MULTIBUF_Begin();
	GUI_MULTIBUF_End();
	GUI_MULTIBUF_Begin();
	GUI_MULTIBUF_End();
  	GUI_Delay(1000);
	GUI_MULTIBUF_Begin();
  	GUI_SetBkColor(GUI_GREEN);
  	GUI_Clear();
	GUI_MULTIBUF_End();
	GUI_MULTIBUF_Begin();
	GUI_MULTIBUF_End();
	GUI_MULTIBUF_Begin();
	GUI_MULTIBUF_End();
  	GUI_Delay(1000);
	GUI_MULTIBUF_Begin();
  	GUI_SetBkColor(GUI_BLUE);
  	GUI_Clear();
	GUI_MULTIBUF_End();
	GUI_MULTIBUF_Begin();
	GUI_MULTIBUF_End();
	GUI_MULTIBUF_Begin();
	GUI_MULTIBUF_End();
  	GUI_Delay(1000);


Soviel zur Vereinigung ... Es bestand der Verdacht, dass die Einstellung schuld war:



/* Define the number of buffers to use (minimum 1) */
#define NUM_BUFFERS  3


Experimente zur Korrektur ergaben jedoch kein ideales Ergebnis, und die Zeit erlaubte es nicht, die Details zu untersuchen. Vielleicht sagt Ihnen jemand in den Kommentaren, wie Sie richtig handeln sollen, und dieser Abschnitt zeigt, wie Sie in einer begrenzten Zeit für die Entwicklung handeln können. In der Zwischenzeit ist der Code in einem so schrecklichen Zustand geblieben. Glücklicherweise ist dies kein Tutorial, sondern nur ein Beispiel für Arbeitscode.



5.2 STM32F429



Dieses Board ist alt, was könnte daran falsch sein? Grundlagen! An der alten Tafel kommen Auswüchse heraus, die existieren, aber schon lange nicht mehr funktionieren. Führen Sie das Hello World-Beispiel aus und sehen Sie:







Das Bild wird relativ zum typischen um 90 Grad gedreht. Was könnte einfacher sein? Als ich 2016 die Firmware des MZ3D 3D-Druckers von Arduinka auf STM32F429 zog, drehte ich das Bild persönlich mit einfachen Einstellungen. Komm schon. Wie läuft es hier? Und hier sind die Einstellungen!



#define LCD_SWAP_XY  1 
#define LCD_MIRROR_Y 1


Der Versuch, sie zu ändern, hilft nicht. Überprüfen, wo sie verwendet werden ... Aber nirgendwo! Sie werden gerade angekündigt. Ich vermute, dass sie die Verarbeitung gestoppt haben, als DMA2D implementiert wurde, aber ich werde nicht dafür bürgen. Es gibt jedoch die gleiche Funktion. Hier finden Sie Ratschläge aus Dutzenden von Foren. Ich habe diese Funktion im Jahr 2016 verwendet:



GUI_SetOrientation(GUI_SWAP_XY)


Einige fügen noch eine Spiegelungskonstante hinzu ... Aber nicht der Punkt. Diese Funktion funktioniert 2020 nicht! Funktioniert nicht und das wars! Und die Bibliothek wird in Objektform geliefert, warum es nicht funktioniert - niemand wird es sagen.



Nun, ich verstehe immer noch Bildschirme. Ich gehe zur Datei \ STM32F429-DISC1 \ Drivers \ BSP \ Components \ ili9341 \ ili9341.c (ja, sie ist schreibgeschützt, aber leicht zu entfernen). Dort wird der Grafikchip konfiguriert. Wir verändern uns.







Der gleiche Text.
  ili9341_WriteReg(LCD_MAC);
  ili9341_WriteData(0xC8);




auf





Der gleiche Text.
  ili9341_WriteReg(LCD_MAC);
  ili9341_WriteData(0x48|0x20);




Das Bild dreht sich natürlich ... Aber der Puffer ist eindeutig etwas falsch konfiguriert:







Dies sind die Abmessungen:



#define XSIZE_PHYS 240
#define YSIZE_PHYS 320


beeinflussen auch nicht die Arbeit in irgendeiner Weise. Gleiches gilt für diese Seite:



#define  ILI9341_LCD_PIXEL_WIDTH    ((uint16_t)240)
#define  ILI9341_LCD_PIXEL_HEIGHT   ((uint16_t)320)


Aber die Seite ist interessanter:



  if (LCD_GetSwapXYEx(0)) {
    LCD_SetSizeEx (0, YSIZE_PHYS, XSIZE_PHYS);
    LCD_SetVSizeEx(0, YSIZE_PHYS * NUM_VSCREENS, XSIZE_PHYS);
  } else {
    LCD_SetSizeEx (0, XSIZE_PHYS, YSIZE_PHYS);
    LCD_SetVSizeEx(0, XSIZE_PHYS, YSIZE_PHYS * NUM_VSCREENS);
  }


Ich habe Negation zum Spaß hinzugefügt:







Der gleiche Text.
  if (!LCD_GetSwapXYEx(0)) {
    LCD_SetSizeEx (0, YSIZE_PHYS, XSIZE_PHYS);
    LCD_SetVSizeEx(0, YSIZE_PHYS * NUM_VSCREENS, XSIZE_PHYS);
  } else {
    LCD_SetSizeEx (0, XSIZE_PHYS, YSIZE_PHYS);
    LCD_SetVSizeEx(0, XSIZE_PHYS, YSIZE_PHYS * NUM_VSCREENS);
  }




Ich habe diese Schönheit.







Ich habe in anderen Experimenten eine ähnliche, aber nicht genau die gleiche Schönheit erhalten, ich erinnere mich nicht mehr ... Kurz gesagt, wir kommen alle zu dem gleichen enttäuschenden Ergebnis. Wir müssen uns hinsetzen und es klären ... Aber es ist keine Zeit für den Prozess vorgesehen. Was zu tun ist? Glücklicherweise konnte ich die Antwort auf diese Frage von Google erhalten. Infolgedessen sieht der typische Code in der Demo-Anwendung folgendermaßen aus:



  GUI_DispStringHCenterAt("www.all-hw.com",   xSize / 2, 20);


Und für F429 muss es auf diese Form reduziert werden:

  GUI_RECT Rect = {20-10, 0, 20+10, xSize};		
  GUI_DispStringInRectEx("www.all-hw.com", &Rect, 
      GUI_TA_HCENTER | GUI_TA_VCENTER,
      20, GUI_ROTATE_CCW);	


Die Funktion zum Ausgeben von gedrehtem Text wird verwendet. Dazu müssen Sie jedoch die Entität "Rechteck" hinzufügen. Was kannst du tun? Und der Zähler muss nicht durch die Funktion des Druckens einer Zahl angezeigt werden, sondern zuerst durch Bilden einer Zeichenfolge und erst dann durch Anzeigen in gedrehter Form. Ansonsten war alles fast universell. Im Gegenteil, es ist sogar möglich, Texte überall auf diese Weise anzuzeigen, aber nicht überall die Rotationsflagge anzuzeigen. Aber es scheint mir, dass dies bereits eine Perversion sein wird.



6. Fazit



Wir haben die Methode zur Entwicklung typischer Programme für verschiedene STM32-Boards untersucht, sowohl aus Sicht des Entwicklers als auch aus Sicht des Benutzers, der einfach die Demo-Anwendung für sein Board heruntergeladen hat und sie nur erstellen möchte, ohne an Physik zu denken. Wir haben uns auch Beispiele angesehen, die zeigen, dass der Grad der Code-Vereinheitlichung leider hoch ist, aber nicht hundertprozentig erreicht. Das gewonnene Wissen kann überprüft werden, indem über den All-Hardware-Service abwechselnd mit verschiedenen Boards gearbeitet wird, ohne Geld für deren Kauf auszugeben.



Der Artikel zeigt, wie man Dinge eher oberflächlich regelt. Auf diese Weise können Sie schnell ein bestimmtes Board beherrschen. Aber je länger Sie mit ihr zu tun haben, desto tieferes Wissen erhalten Sie natürlich. Bei der Lösung realer Probleme ist dies äußerst wichtig, da komplexe Programme, in denen der Autor die Physik von Prozessen nicht versteht, ein Weg zu Fehlern in Algorithmen sind. Ich möchte, dass jeder alles tief genug beherrscht. Ja, mit der Hardware des All Hardware-Dienstes.



All Articles