1. أي نوع من التطبيقات
دعنا أولاً نلقي نظرة على التطبيقات المعروضة. ندخل الموقع https://all-hw.com/ .
تحتاج إلى تسجيل الدخول هناك (التسجيل مجاني). بعد ذلك ، سيتم عرض قائمة باللوحات المتاحة. أولهم لا يحتوي على شاشة ، لذلك فهو غير مريح كتوضيح للمقال. الثانية مبتذلة ، الجميع يمتلكها ، ليس من المثير الحديث عنها. سأختار الثالث - اكتشاف STM32F469I . بعد اجتياز بضع خطوات ، أجد نفسي في الصفحة التالية: في الواقع ، على اليسار نرى اللوحة التي تزيلها الكاميرا. وهذا التطبيق بالذات يعمل هناك. العداد يدق فقط. وإذا قمت بإدخال خط في الجهاز على اليمين ، فسيتم عرضه على الشاشة ، نظرًا لأن الجهاز متصل بمنفذ تصحيح الأخطاء UART. حسنًا ، لقد دخلت هنا في Just Test.
يبدو أن تطبيقًا لوحدة تحكم لتنفيذ هذه الوظيفة ليس معقدًا ، ولكن ... لكن ... لكني أكرر ، نأخذ عدد أنواع لوحات ST ونضربها بثلاثة على الأقل. ومرة أخرى ، هناك شرط مهم للغاية: يجب ألا يكون وقت تطوير هذا التطبيق طويلاً. نحن بحاجة إلى تطويره في أسرع وقت ممكن. ويجب أن يتم تجميعها بواسطة ثلاثة مجمعين على الأقل.
2. السبل الممكنة
أول ما يتبادر إلى الذهن هو تطوير تطبيق نموذجي في STM32Cube MX. هناك ، يمكنك إنشاء كل شيء لثلاث بيئات تطوير وإضافة أجهزة قياسية بسرعة. هذا هو الحال ، ولكن:
- إذا نظرت إلى أمثلة العمل مع التطبيقات التي تم إنشاؤها من خلال CubeMX ، يمكنك أن ترى أنه بعد الإنشاء التلقائي ، ما زلت بحاجة إلى تحسين الكثير باستخدام ملف. أي على الرغم من توفير الوقت ، إلا أنه لا يزال غير الحد الأقصى.
- , .
- Cube MX STemWin, ( , , , ST STemWin TouchGFX, – ).
في الواقع ، هذا يكفي لتأجيل مثل هذا الخيار في الاحتياطي ومعرفة ما إذا كانت هناك حلول أبسط ... اتضح أن هناك ، وهي مرتبطة أيضًا بـ Cube MX. يعرف أي شخص عمل مع هذه البيئة أنها تتكون من كود وحزم أساسية تخدم عائلة محددة من وحدات التحكم. ما هي الباقة؟ هذا ملف مضغوط. لنقم بتنزيله وتفريغه. خذ ، على سبيل المثال ، حزمة لجهاز STM32H747 الجديد تمامًا. لدي هذا الملف en.stm32cubeh7_v1-8-0.zip.
ونرى مثل هذا الثراء فيه:
هذه حلول نموذجية لألواح النماذج الأولية المختلفة مع هذا النوع من وحدات التحكم. حسنا. ندخل الكتالوج الخاص بنا STM32H747I-DISCO... هناك تطبيقات جاهزة منفصلة ومنفصلة - أمثلة للعمل مع كتل أجهزة التحكم. لا يوجد شيء مثير للاهتمام هنا لأولئك الذين يرغبون فقط في بناء مثال ، ولكن مطوري التطبيق التجريبي النموذجي يجب أن يدرسوا محتويات دليل UART.
ومن التطبيقات ، حسنًا ، بالطبع ، STemWin. والأبسط. مرحبا بالعالم. سيكون الدليل الذي يقع فيه موضع اهتمام جميع المستخدمين.
سنجعل مثالنا بناءً على هذا التطبيق. لماذا ا؟ ندخل دليل STemWin_HelloWorld ونرى:
فعل مبرمجو ST كل شيء من أجلنا. لقد أنشأوا مصادر يمكن تجميعها من Keil ومن IAR ومن Eclipse (وهو في الواقع Cube-IDE). وبالتالي ، يكفي تصحيح هذه المصادر ، وسيتم حل المهمة دون تحرير الملفات التي تعتمد على بيئات التطوير! حسنًا ، ومشروع Hello World ، يعرض أيضًا نصوصًا على الشاشة. يكفي إضافة دعم UART إليها ، وسيعمل كل شيء. لهذا السبب أشرت أعلاه إلى أن مثال UART مفيد أيضًا للمطورين.
وفي هذه الحالة بالذات ، أخطو على حنجرة أغنيتي الخاصة. إذا قرأ أي شخص مقالاتي السابقة ، فإنهم يعلمون أنني أكره هال. HAL والتحسين هما شيئان غير متوافقين. في المشاريع الحقيقية ، أستخدم إما العمل المباشر مع الأجهزة ، أو برامج تشغيل Konstantin Chizhov (مكتبة mcucpp). لكن في هذه الحالة بالذات ، هذا ليس هو الحال على الإطلاق. نحن فقط نصنع برنامجًا يعرض النصوص ويعمل مع منفذ COM. على وحدة تحكم بتردد ساعة يصل إلى مئات ميغا هرتز. لكي نكون صادقين ، في وقت Ona ، تعامل BK-shka المعتاد مع هذا ، حيث كان المعالج يعمل بتردد 3 ميجاهرتز. علاوة على ذلك ، لم يكن لدى BK-shki أوامر RISC ، ولم يكن هناك حتى خط أنابيب. ولكن كان هناك ناقل متعدد الإرسال (أي عدة ساعات في كل دورة) وذاكرة DRAM غير متزامنة بدون تخزين مؤقت. بالمختصر،كان الأداء 300 ألف عملية تسجيل فقط في الثانية. وكان هذا كافياً لحل مشكلة إخراج النصوص والعمل مع UART (من خلال كتلة IRPS). وهذا يعني أن أفضلية كود HAL لهذه المهمة في STM32s الحديثة كافية أيضًا للمهام المطروحة. لكن سرعة التطوير عند استخدام HAL ستكون الأعلى.
ستظهر لوحة جديدة ، وستحتوي بالتأكيد على HAL مع إرفاق مكالمات موحدة بها. سنقوم بتصحيح التهيئة في المثال النموذجي ، وفقًا لمثال UART المرفق ، والعمل ، سيكون دائمًا هو نفسه. سرعة التطوير عشرات الدقائق. ولا حتى ساعة. أي لحل هذه المشكلة ، من الأفضل بالتأكيد استخدام HAL ، على الرغم من أنني لا أحبها في حالات القتال.
الكل. قلت الحد الأدنى من النظرية ، والتي بدونها من المستحيل الانتقال إلى الممارسة. سأخبرك بمزيد من التفاصيل النظرية بعد العمل المخبري. لذلك دعنا ننتقل إلى التجارب.
3. ما يجب أن يفعله المستخدم النهائي
3.1 تنزيل الحزمة
وبالتالي. لن تقوم على الفور بإنشاء شيء خاص بك ، ولكنك تريد أولاً أن تلعب بمثال جاهز مأخوذ من موقع All-Hardware على الويب. ماذا تحتاج لبناء وتشغيل؟ أولاً ، تحتاج إلى تنزيل مكتبات للوحة معينة. من خلال العمل مع حلول مفتوحة المصدر ، صادفت بالفعل حقيقة أنه لا يكفي تنزيل مشروع. ما زلنا بحاجة إلى تثبيت 100500 أداة وتنزيل 100500 مكتبة تابعة لجهات خارجية. هنا ما عليك سوى تنزيل ملف واحد وفك ضغطه. صحيح أن حجمه ضخم. لكن المحتوى رائع فقط. وبالتالي. نحتاج إلى حزم لـ STM32 CubeMX. الآن يبدو الرابط المباشر إلى المستودع الخاص بهم على النحو التالي :
www.st.com/en/development-tools/stm32cubemx.html#tools-software تظهر
الحزمة التي يجب تنزيلها في الجدول أدناه.
| دفع | صفقة |
|---|---|
| اكتشاف STM32F429I | STM32CubeF4 |
| اكتشاف STM32F469I | STM32CubeF4 |
| اكتشاف STM32G474RE DPOW1 (بدون شاشة) | STM32CubeG4 |
| اكتشاف STM32F746G | STM32CubeF7 |
| اكتشاف STM32H747I | STM32CubeH7 |
3.2 نسخ المشروع والبدء في العمل
بنية الحزم هي نفسها من الداخل ، لذلك نذهب إلى الدليل بالتسلسل الهرمي التالي:
<اسم الحزمة> \ المشاريع \ <اسم اللوحة> \ التطبيقات \ STemWin.
انسخ الدليل مع المثال هناك. نحصل على شيء مثل هذا:
يعتبر موقع الدليل مهمًا لأن المسارات إلى المكتبات مكتوبة بتنسيق نسبي. إذا لم يتم بناء المشروع بسبب العدد الهائل من الملفات المفقودة ، فأنت لا تخمن موقعه في التسلسل الهرمي للدليل.ندخل إلى الكتالوج ، ونختار نوعًا مختلفًا من المشروع لإحدى بيئات التطوير ، ونفتح المشروع ، ونعمل معه ... نهاية التعليمات!
3.3 سمة من سمات لوحة اكتشاف STM32G474RE DPOW1
لا تحتوي هذه اللوحة على شاشة ، مما يعني أنه لا يوجد كتالوج STemWin في حزمة الملكية الخاصة به. لذلك ، يجب وضع المشروع في المستوى التالي:
\ STM32Cube_FW_G4_V1.3.0 \ Projects \ B-G474E-DPOW1 \ Examples \ UART
4. كيف يتم إنشاء المشاريع
ما مدى سهولة تجميع مثال واضح. الآن دعونا نلقي نظرة على كيفية عمل هذه الأمثلة. ربما تكون هذه المعلومات مفيدة لأولئك الذين يريدون القيام بشيء آخر غير مجرد عرض النصوص على الشاشة. حسنًا ، عندما يكون من الضروري تقديم اللوحة التالية في غضون بضعة أشهر ، وقد نسيت كل شيء بالفعل ، سأفتح هذه المقالة لتحديث التعليمات الموجودة في ذاكرتي.
4.1 إضافة UART وتهيئته
من المتوقع أن المثال النموذجي لـ STemWin Hello World يفتقر إلى UART. يجب إضافته. يبدو أننا نأخذ نموذج الكود ونضيفه. للأسف ، الحياة أكثر تعقيدًا. في دالة العمل ، نقوم بذلك بهذه الطريقة. ولكن هناك بعض الفروق الدقيقة أثناء التهيئة. بادئ ذي بدء ، تحتوي لوحات النماذج المختلفة على منافذ مختلفة متصلة بمحول USB-UART المدمج في محول JTAG. أيهما متصل ، عليك أن تبحث في الوصف على السبورة. عادة ، بالطبع ، USART1 ، لكن من الأفضل إعادة التحقق.
علاوة على ذلك ، يتم تقديم التنوع من خلال حقيقة أنه مع تطور وحدات التحكم ، تتم إضافة وظائف مفيدة متنوعة إلى معدات UART. يجب أيضًا تهيئتهم في HAL للوحات الجديدة. على وجه الخصوص ، العمل مع FIFO.
لذلك ، أقترح الخطوات النموذجية التالية:
- أضف مقبض المنفذ.
- إضافة تهيئة الأجهزة UART.
- أضف تهيئة دبابيس UART.
- إضافة معالج المقاطعة UART.
مع المقبض ، كل شيء واضح وعالمي. سيبدو شيئا من هذا القبيل:
UART_HandleTypeDef huart1;
الباقي موجود في مثال الدليل \ <Package Name> \ Projects \ <Board Name> \ Examples \ UART .
على سبيل المثال ، مشروع \ STM32Cube_FW_H7_V1.8.0 \ Projects \ STM32H747I-DISCO \ Examples \ UART \ UART_WakeUpFromStopUsingFIFO .
في الوظيفة الرئيسية () ، هناك تهيئة لـ UART نفسها (تحتاج فقط للتأكد من أن السرعة هي 9600 ، إذا لم تكن كذلك ، أدخلها). تم تكوين الاتصال بالأرجل في ملف آخر ، في
وظيفة HAL_UART_MspInit (UART_HandleTypeDef * huart) الفارغة .
أفضل أن أضعها كلها في وظيفة واحدة. نظرًا لأن الوقت محدود ، لم أنظر إلى تجميع مثل هذه الوظيفة من هذه المواد ، ووضعها في ملف main.c وعدم نسيان الاتصال بها من الوظيفة الرئيسية ().
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 , . .حسنًا ، المقاطعات بسيطة. نحن نبحث عن ملف له لاحقة _it.c في المثال ونقل خطوط UART إلى الملف مع اللاحقة _it من مشروعنا.
في هذه الحالة ، من الملف
\ STM32Cube_FW_H7_V1.8.0 \ Projects \ STM32H747I-DISCO \ Examples \ UART \ UART_WakeUpFromStopUsingFIFO \ CM7 \ Src \ stm32h7xx_it.c
إلى الملف
\ STM32Cube_FW_H7_V1.8_V1.8 \ STemWin \ Demo_H747 \ CM7 \ Core \ Src \ stm32h7xx_it.c انقل
الجزء:
extern UART_HandleTypeDef huart1;
…
void USART1_IRQHandler(void)
{
HAL_UART_IRQHandler(&huart1);
}
الكل.
4.2 تحرير وظيفة العمل الرئيسية
مع وظيفة العمل الرئيسية ، من حيث المبدأ ، كل شيء أبسط. على الرغم من أنه ليس من حيث المبدأ ، وعلى وجه الخصوص - ليس تمامًا ، لكننا سنتحدث عن هذا أدناه. الآن ، دعنا نرى فقط الوظيفة التي يتم استدعاؤها في نهاية الوظيفة الرئيسية. في هذه الحالة ، هذه هي:
MainTask();
هذا يعني أن العمل الرئيسي يتم فيه. نحن فقط نستبدل جسمه بمثال نموذجي مأخوذ من موقعنا.
4.3 ماذا بعد؟
علاوة على ذلك - يمكنك أن تحمل أمثلة على معدات أخرى ، كما فعلنا للتو مع معدات UART. صحيح أن التحكم في تشغيل هذا الجهاز خارج نطاق هذه المقالة. كما ترى ، فإن عنصر التحكم النموذجي على صفحة الويب مخصص فقط للصورة ولجهاز UART واحد. يتم إعادة توجيه الباقي أكثر صعوبة. ومع ذلك ، لا يسعني إلا أن أخبرك كيف تلقيت تعليمات ذات مرة لإنشاء مولد شفرة مورس استنادًا إلى لوحة اكتشاف STM32G474RE DPOW1 في إحدى الأمسيات . ذات مساء لتطوير من الصفر على لوحة غير مألوفة لا يجعلك تقرأ مئات الصفحات من الوثائق. إذا تم تنفيذ المشروع لعدة قرون ، فسأبدأ ببساطة في إثبات للإدارة أنه ليس صحيحًا وأنه يجب دراسة كل شيء بعناية. لكن المشروع كان أيضًا ذا دورة حياة قصيرة. لذلك قررت أن أسير في طريق أخذ الأمثلة.
لذلك ، بالنسبة إلى شفرة مورس ، فأنت بحاجة إلى جيب بتردد 1 كيلو هرتز ... مع الحركة المعتادة لليد ، قم بفك ضغط الملف en.stm32cubeg4_v1-3-0.zip وفحص الدليل D: \ tmp \ STM32Cube_FW_G4_V1.3.0 \ Projects \ B-G474E-DPOW1 \ أمثلة ... غير موجود ...
لا يوجد شيء مفيد في دليل DAC.
هل هذه النهاية؟ ليس صحيحا. دعونا نلقي نظرة على أمثلة من لوحات أخرى بنفس البلورة (وإن كانت في عبوات مختلفة) ... وهذا هو الجمال الذي نجده في لوحة Nucleo!
الجميل أنه يوجد داخل الملف main.c جدول لتوليد الجيب:
/* 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};
نتحقق ونتأكد من ذلك نعم. يولد هذا المثال جيبًا أو مثلثًا عند إخراج DAC. وفقط بتردد 1 كيلو هرتز. هذا رائع! منذ أن كان الوقت محدودًا ، لم أكلف نفسي عناء قراءة أي نظرية. لقد تأكدت للتو من أن جميع التشكيلات تتم على مستوى الأجهزة من خلال إلقاء نظرة سريعة على الكود. بعد ذلك ، في المشروع ، استبدلت وحدة التحكم بالوحدة الموجودة على اللوحة المطلوبة ، وقمت بتجميعها وملؤها وتشغيلها ، وبعد تشغيل مسبار الذبذبات على طول الأرجل ، وجدت الجهاز الذي يوجد عليه هذا الجيب. ثم قمت بتوصيله بإدخال مكبرات الصوت ، واستبدلت جيل الجيب أو المثلث بتوليد الجيب أو الصمت (نعم ، لقد صنعت جدولًا آخر من الأصفار فقط) ... حسنًا ، كانت كتابة جزء مطبق باستخدام شفرة مورس سهلة مثل تقشير الكمثرى. تذكرت شبابي ، القسم العسكري ، العقيد بافلوف ...
بشكل عام ، تعتبر تقنية "العثور على مثال ، أدخله في التعليمات البرمجية الخاصة بك" فعالة للغاية. ويساهم نهج "بناء مثال نموذجي - تنزيل مكتبة ضخمة" في ذلك ، لأن كل هذه الأمثلة ذات العلامات التجارية هي جزء منه.
5. مشاكل في التوحيد
يحب أحد زملائي الاقتباس من العبارة الفلسفية التالية:
"من الناحية النظرية ، لا يوجد فرق بين النظرية والممارسة. من الناحية العملية ، هو كذلك ".
عند العمل مع مجموعة من أجهزة STM32 المختلفة ، كنت أتذكرها بانتظام. لقد قلت بالفعل عن UART مختلفة لا محالة ، ولكن يبدو أن StemWin الموحدة لا ينبغي أن تقدم أي مفاجآت ... مقدمة!
5.1 STM32H747
تم رسم عنوان Hello World. لكن عندما أقوم بنقل رمز العمل ، أرى شاشة زرقاء. كل ما في الأمر أننا نرسم أولاً شاشة حمراء لمدة ثانية ، ثم خضراء لمدة ثانية ، ثم زرقاء لمدة ثانية ، ثم يبدأ العمل. إذا وضعت نقطة توقف مباشرة بعد التهيئة ، حتى قبل أي رسم ، عند تشغيله ، فإن قراءات العداد من البداية الأخيرة تكون مرئية على الشاشة. ثم يتم استبدالها بنفس الشاشة الزرقاء. ماذا؟
أزل ناتج ثلاثة ألوان في الثانية ، وأضيف العمل على الفور. إنه يعمل ، لكنه يتجمد بسرعة إلى الأبد. تدريجيًا اكتشفت ما يتجمد بعد 37 مللي ثانية. أي نوع من الوقت السحري هذا؟ واحد مللي ثانية واضح. علامة النظام. لكن 37. نعم ، على الأقل شيء مستدير ، قريب ...
كم من الوقت أو قصير ، لكني اكتشفت أن كل شيء معروض في معالج المقاطعةHAL_DSI_IRQHandler (DSI_HandleTypeDef * hdsi) . يطلق عليه ، يتم عرض كل شيء ، وبعد ذلك يتم إنهاء مكالماته. يتكون كل شيء في المخزن المؤقت ، لكنه لا يظهر على الشاشة. بتعبير أدق ، كل شيء يضرب الشاشة مرتين في عمر البرنامج. عند التهيئة (نفس الأداة من حياة سابقة) وبعد 37 مللي ثانية. كل ما كان بين ، لن يرى أحد.
في ذهنك - تحتاج إلى دراسة الوثائق ومعرفة ماذا. لكن في الحقيقة - وقت المهمة ليس قليلًا ، ولكنه قليل جدًا. واضح ان الانقطاع لا بد من استفزازه ولكن كيف؟ أحاول بصدق الاتصال بـ GUI_Exec () ، على الرغم من استدعاء GUI_Delay () هناك على أي حال ... لا يساعد.
المثال مات. بل إنه أمر مضحك هناك. Hello World هو الإخراج كما هو الحال في أول 37 مللي ثانية. وبعد ذلك - مثال ميت. حسنًا ، سآخذ مثالاً للرسوم المتحركة من نفس الكتالوج. هو يعمل. تدريجيًا ، اكتشفت ما يجب سحبه منه حتى يعمل مثالنا ... هكذا تبدو الكود النموذجي لدينا:
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);
حسنًا ، هذا منطقي! وهو يعمل! .. على لوحات أخرى ... ولكن بعد هذا التعديل ، انتقل بطريقة ما إلى H747:
نفس النص.
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);
لكنها تعمل بشكل عام ، وبشكل خاص - تدوم الشاشات الحمراء والخضراء لثانية واحدة ، وتومض الشاشة الزرقاء وتظهر شاشة العمل على الفور. بعد عدد قليل من التجارب ، اتضح أن كل شيء يبدأ في العمل بشكل كامل بهذا الشكل:
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);
الكثير من أجل التوحيد ... كان هناك شك في أن اللوم هو المكان:
/* Define the number of buffers to use (minimum 1) */
#define NUM_BUFFERS 3
لكن التجارب في تصحيحها لم تعط نتيجة مثالية ، ولم يسمح الوقت بدراسة التفاصيل. ربما يخبرك أحد الأشخاص في التعليقات بكيفية التصرف بشكل صحيح ، ويوضح هذا القسم كيف يمكنك التصرف في وقت محدود من أجل التطوير. في غضون ذلك ، ظل الكود في مثل هذه الحالة الرهيبة. لحسن الحظ ، هذا ليس برنامجًا تعليميًا ، ولكنه مجرد مثال على رمز العمل.
5.2 STM32F429
هذا اللوح قديم ، ما الخطأ فيه؟ اساسيات! في اللوحة القديمة ، تظهر الثمرات الموجودة ، ولكنها توقفت منذ فترة طويلة عن العمل. قم بتشغيل مثال Hello World وانظر:
تم تدوير الصورة 90 درجة بالنسبة للصورة النموذجية. ما الذي يمكن أن يكون أسهل؟ مرة أخرى في عام 2016 ، أثناء سحب البرنامج الثابت للطابعة MZ3D 3D من Arduinka إلى STM32F429 ، قمت شخصيًا بتحويل الصورة بإعدادات بسيطة. هيا. كيف تسير الامور هنا؟ وها هي الإعدادات!
#define LCD_SWAP_XY 1
#define LCD_MIRROR_Y 1
محاولة تغييرها ، لا يساعد. التحقق من مكان استخدامها ... ولكن في أي مكان! أعلنوا للتو. أظن أنه لم تعد تتم معالجتها عند تنفيذ DMA2D ، لكنني لن أضمن ذلك. ومع ذلك ، هناك نفس الوظيفة. هذه نصيحة من عشرات المنتديات. لقد استخدمت هذه الوظيفة في عام 2016:
GUI_SetOrientation(GUI_SWAP_XY)
لا يزال البعض يضيف ثابت الانعكاس ... لكن ليس النقطة. هذه الوظيفة لا تعمل في 2020! لا يعمل وهذا كل شيء! ويتم تسليم المكتبة في شكل كائن ، لماذا لا تعمل - لن يخبر أحد.
حسنًا ، ما زلت أفهم الشاشات. أذهب إلى الملف \ STM32F429-DISC1 \ Drivers \ BSP \ Components \ ili9341 \ ili9341.c (نعم ، إنه محمي ضد الكتابة ، لكن من السهل إزالته). تم تكوين شريحة الرسومات هناك. نحن نتغير.
نفس النص.
ili9341_WriteReg(LCD_MAC);
ili9341_WriteData(0xC8);
على
نفس النص.
ili9341_WriteReg(LCD_MAC);
ili9341_WriteData(0x48|0x20);
الصورة ، بالطبع ، تدور ... لكن من الواضح أن المخزن المؤقت تم تكوينه بشكل غير صحيح إلى حد ما:
هذه هي الأبعاد:
#define XSIZE_PHYS 240
#define YSIZE_PHYS 320
أيضا لا تؤثر على العمل بأي شكل من الأشكال. الأمر نفسه ينطبق على هذا الموقع:
#define ILI9341_LCD_PIXEL_WIDTH ((uint16_t)240)
#define ILI9341_LCD_PIXEL_HEIGHT ((uint16_t)320)
لكن الموقع أكثر إثارة للاهتمام:
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);
}
أضفت النفي للمتعة:
نفس النص.
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);
}
حصلت على هذا الجمال.
لقد حصلت على جمال مشابه ، ولكن ليس تمامًا في تجارب أخرى ، لم أعد أتذكره ... باختصار ، توصلنا جميعًا إلى نفس النتيجة المخيبة للآمال. يجب أن نجلس ونحل الأمور ... لكن لا يوجد وقت مخصص للمحاكمة. ماذا أفعل؟ لحسن الحظ ، تمكنت من الحصول على إجابة لهذا السؤال من Google. نتيجة لذلك ، يبدو الرمز النموذجي في التطبيق التجريبي كما يلي:
GUI_DispStringHCenterAt("www.all-hw.com", xSize / 2, 20);
وبالنسبة لـ F429 يجب اختزاله إلى هذا النموذج:
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);
يتم استخدام وظيفة إخراج النص المستدير. ومع ذلك ، لهذا عليك إضافة الكيان "المستطيل". حسنا، ماذا يمكنك أن تفعل. ولا يجب عرض العداد من خلال وظيفة طباعة رقم ، ولكن أولاً عن طريق تكوين سلسلة ، وبعد ذلك فقط من خلال عرضه في شكل مستدير. لكن بخلاف ذلك ، تحول كل شيء تقريبًا على مستوى العالم. من الممكن ، على العكس من ذلك ، عرض النصوص في كل مكان بهذه الطريقة ، ولكن ليس في كل مكان تشير إلى علم الاستدارة. لكن يبدو لي أن هذا سيكون بالفعل تحريفًا.
6. الخلاصة
لقد درسنا منهجية تطوير البرامج النموذجية للوحات STM32 المختلفة ، سواء من وجهة نظر المطور أو من وجهة نظر المستخدم الذي قام ببساطة بتنزيل تطبيق تجريبي للوحة الخاصة به ويريد فقط بنائه دون التفكير في الفيزياء. نظرنا أيضًا إلى أمثلة توضح ، للأسف ، أن درجة توحيد الشفرة عالية ، لكنها لا تصل إلى مائة بالمائة. يمكن التحقق من المعرفة المكتسبة من خلال العمل بالتناوب مع لوحات مختلفة من خلال خدمة All-Hardware ، دون إنفاق الأموال على شرائها.
يوضح المقال كيفية فرز الأشياء بشكل سطحي إلى حد ما. هذا يسمح لك بإتقان لوحة معينة بسرعة. لكن ، بالطبع ، كلما طالت مدة التعامل معها ، زادت المعرفة العميقة التي تحصل عليها. عند حل المشكلات الحقيقية ، يعد هذا أمرًا مهمًا للغاية ، لأن البرامج المعقدة ، التي لا يفهم فيها المؤلف فيزياء العمليات ، هي طريق للأخطاء في الخوارزميات. أتمنى أن يتقن الجميع كل شيء بعمق كافٍ. نعم ، باستخدام الأجهزة من خدمة All Hardware.