Skip navigation
> RoadTest Reviews

STM32H7B3I-DK -  DISCOVERY KIT - Review

Scoring

Product Performed to Expectations: 9
Specifications were sufficient to design with: 8
Demo Software was of good quality: 9
Product was easy to use: 8
Support materials were available: 8
The price to performance ratio was good: 9
TotalScore: 51 / 60
  • RoadTest: STM32H7B3I-DK - DISCOVERY KIT
  • Buy Now
  • Evaluation Type: Development Boards & Tools
  • Was everything in the box required?: Yes
  • Comparable Products/Other parts you considered: STM32H747i-DISCO STM32H745i-DISCO Renesas EK-RA6M3G Evaluation Kit
  • What were the biggest problems encountered?: Inconsistencies in the documentation such as the User's Manual does not match the board Schematic. Also, there were issues creating a project in TouchGFX and them bringing it into STM32CubeIDE where the .ioc file used to define the project is missing from the STM32CubeIDE .project file thus it is not imported. This had to be added manually and the name of the generated .ioc file had to be changed. There is an option in the STM32CubeIDE CubeMX implementation where clock define issues can be resolved automatically, however selecting this option leave the board in a non boot condition.

  • Detailed Review:

    Overview

     

    The STMicroelectronics STM32H7B3i-DK is a nice board to evaluate the STM line of STM32H7 MCUs. It is an excellent platform for creating Human Machine Interfaces (HMI) for both local and remote control.  The added Wi-Fi modules brings the ability to send and receive data remotely without the need for a physical interface.  This could be used as an environmental control station where the board receives data from remote sensors as well as used to set temperatures or thresholds for the remote sensors.

      With regards to features, STM32H7B3i-DK is packed with a good number of peripheral options.

     

    Features

    • STM32H7B3LIH6QU Single Core 32-bit Arm® Cortex®-M7 280 MHz MCU
    • 4.3 TFT LCD Module with capacitive touch panel and RGB interface.
    • 128-Mbit SDRAM
    • 512-Mbit Octo-SPI NOR Flash memory
    • Wi-FI Module
    • USB OTS HS interface
    • USB STLINK-V3E debug interface

     

    Expansion Options

    • STMod+ expansion connector
      • STMod+ Fan-out board with Grove, microBUS and ESP-01 compatible connectors (Included)
    • Arduino compatible headers
    • Audio daughterboard expansion connector
    • External i2C expansion connector
    • microSD card slot
    • Stereo headset jack and microphone input
    • DCMI style camera connector; support for STM32F4DIS-CAM camera module.

      .. and more

     

    IDE Options

    • STM32CubeIDE
    • IAR EWARM
    • Keil MDK

     

    Graphical UI Options

    • TouchGFX
    • Embedded Wizard
    • STemWin

     

    Other tools used in RoadTest

    • MIKROE-3000 - H-Bridge 2 Click

        https://www.mikroe.com/h-bridge-2-click

        https://download.mikroe.com/documents/datasheets/MPC17510.pdf

     

    References

    • STM32H7B3i-DK Resource page

        https://www.st.com/en/evaluation-tools/stm32h7b3i-dk.html

        https://www.st.com/resource/en/user_manual/dm00610478-discovery-kit-with-stm32h7b3li-mcu-stmicroelectronics.pdf

        https://www.st.com/resource/en/schematic_pack/mb1332-h7b3i-b02_schematic.pdf

     

    • TouchGFX

        https://support.touchgfx.com/docs/development/board-bring-up/example-gpio/ http://thehackerworkshop.com/?p=1271

        https://support.touchgfx.com/docs/development/ui-development/software-architecture/screen-definition-and-mvp/

     

    • EmbeddedWizard

        https://www.embedded-wizard.de/

     

    Getting Started

     

    Video Overview of STM32H7B3i-DK

     

    Tool versions used

     

    ToolVersion
    STMCubeMX1.4.2
    STM32CubeIDE6.0.1
    STM32H71.8.0
    X-Cube-TouchGFX4.14.0
    CMSIS5.6.0

     

     

    There are a number of means to get started with the STM32H7B3i-SK, however for the purpose of this RoadTest, the approach was to start with TouchGFX and then edit the code and add additional logic in STM32CubeIDE.   The tools such as STM32H7, X-Cube-TouchGFX, and CMSIS can be install via STMCubeMX.  The STMCubeIDE can be downloaded from the STM website. There are many resources to cover the install of the tools, so this will not be covered in this posting.

     

     

     

    Install tools from STMCubeMX

    Ex:

     

      Create a Project in TouchGFX

    1. Launch TouchGFX

     

    Create a GUI interface in TouchGFX Designer

    1. Create a new Application

     

     

        2. Choose an Application Template

           a. Select STM32H7B3i-DK

     

        3. Set the Application Name and Application Directory

            a. The UI TEMPLATE can be selected at this point or left to the default Blank UI setting.

            b. Click CREATE to create the project

       4. Add Widgets and Screens and Interactions from the TouchGFX Designer. The Canvas area is the main location to place Widgets and Screens.

     

    5. On the left side of the Designer window various Widgets such as Buttons, Images, Containers and so on can be added

     

        6. Screens can be added to place the Widgets on as well as create multiple interface options.

     

        7. Custom Images can be added to the project and then added to a particular Widget. These are added by clicking on the Images icon at the top of the window and then the '+' symbol in the blue circle.  Here images were brought in for the Direction arrows and for the background.  The other images were provided by TouchGFX Designer

     

        8. If text is added to the GUI, the Texts option can be used to customize the settings such as Typology, Alignment, default values.

     

        9. On the right side of the Designer, there are options to customize the item placed on the Canvas such as Name, Locations, Style, Image, and so on.

            Here, the background_roadtest.png image was added to the backgroundImage Widget.

     

     

        10. Interactions can be added to created events such as "Button is clicked" Trigger with the upButton Widget. The Function Name textbox is used to add a name to the Interaction so it can be added to the code to handle an event from the GUI.

     

        11. Once the project is complete, click on Generate Code to create the code for the project.

        12.  The code will be located in the project folder

     

        12.  In the  gui_generated include folder, the gui_generated->main_screen folder should have a file MainViewBase.h file containing methods associated with the Interactions created in Designer. These are virtual methods that need to be added in the Main class to override them

     

    class MainViewBase : public touchgfx::View<MainPresenter>
    {
    public:
        MainViewBase();
        virtual ~MainViewBase() {}
        virtual void setupScreen();
    
        /*
         * Virtual Action Handlers
         */
        virtual void buttonUpClicked()
        {
            // Override and implement this function in Main
        }
    
        virtual void buttonDownClicked()
        {
            // Override and implement this function in Main
        }
    
        virtual void motorButtonClicked()
        {
            // Override and implement this function in Main
        }
    
        virtual void motorSpeedSliderChanged(int value)
        {
            // Override and implement this function in Main
        }
    
        virtual void motorSpeedChanged(int value)
        {
            // Override and implement this function in Main
        }
    
    protected:
        FrontendApplication& application() {
            return *static_cast<FrontendApplication*>(touchgfx::Application::getInstance());
        }
    

     

        13. These methods are placed in the TouchGFX\gui\src\main_screen\MainView.cpp file and associated .hpp file.

    void MainView::buttonUpClicked()
    {
        touchgfx_printf("buttonUpClicked\n");
        pwm += 100;
        if (pwm > 3906)
        {
            pwm = 3906;
        }
    #ifndef SIMULATOR
        //__HAL_TIM_SetCompare(&htim13, TIM_CHANNEL_1, pwm);  // update pwm value
        HAL_GPIO_WritePin(GPIOH, GPIO_PIN_8, GPIO_PIN_SET);  // DIR HIGH
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET);  // END HIGH
        HAL_Delay(5);
    #endif
    }
    void MainView::buttonDownClicked()
    {
        touchgfx_printf("buttonDownClicked\n");
        pwm -= 100;
        if (pwm < 0)
        {
            pwm = 0;
        }
    #ifndef SIMULATOR
        //__HAL_TIM_SetCompare(&htim13, TIM_CHANNEL_1, pwm);  // update pwm value
        //HAL_GPIO_WritePin(GPIOH, GPIO_PIN_8, GPIO_PIN_RESET);  // DIR HIGH
        HAL_GPIO_WritePin(GPIOH, GPIO_PIN_8, GPIO_PIN_RESET);  // DIR HIGH
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET);  // END HIGH
        HAL_Delay(5);
    #endif
    }
    
    void MainView::motorButtonClicked()
    {
        touchgfx_printf("motorButtonClicked\n");
        
        motor_state = !motor_state;
    #ifndef SIMULATOR
        if (motor_state)
        {
            HAL_GPIO_WritePin(GPIOH, GPIO_PIN_8, GPIO_PIN_SET);  // DIR HIGH
            HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET);  // END HIGH
            HAL_Delay(5);
        } else {
            HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET);  // END LOW
        }
    #endif
    }
    
    void MainView::motorSpeedSliderChanged(int value)
    {
        touchgfx_printf("motorSpeedChanged %d\n", value);
        presenter->setMotorSpeed(value);
    
    }
    
    void MainView::motorSpeedMsg()
    {
        touchgfx_printf("motorSpeedMsgReceived\n");
    }
    
    void MainView::motorSpeedChanged(int value)
    {
        Unicode::snprintf(textMotorSpeedBuffer, 4, "%d", value);
        textMotorSpeed.invalidate();
    
    }
    

     

        14. To test the code, the Run Simulator option can be used to run the code in a simulated environment.

               NOTE: Code that is not associated with the Simulator requires to be enclosed in "#ifndef SIMULATOR /#endif" tags to block out the code as seen in the previous code example.

        15. One particular issue with the TouchGFX STM32H7B3i-DK generated code is that the STM21CubeIDE code created by the Designer does not include the .ioc file for the project which is needed by CubeMX in STM32CubeIDE.  This reference needs to be added to the .project file and the .ioc file needs its name changed.

             The .project file is located under the STM32CubeIDE folder.

                 C:\TouchGFXProjects\RoadTest_Motor2\STM32CubeIDE

             The .ioc file is located under the project folder and needs to be copied to "STM32H7B3I_DISCO.ioc".

              Leave the STM32H7B3I-DK.ioc file as is since it is needed by the Simulator/

     

         Add the following to the .project file under the linkedResources tag

        16. Double click on the .cproject file located under the STM32CubeIDE folder to open the project in STM32CubeIDE.

     

     

    STM32CubeIDE

    1. Once the project is open in STM32CubeIDE, a few steps are required for the code to properly work on the STM32H7B3i-DK
    2. In the Project Explorer, double click on the STM32H7B3I_DISCO.ioc file to launch STM32CubeMX in the IDE

           NOTE: More than likely there will be an error seen since there is a mismatch between the STM32Cube FW_H7 from the TouchGFX project and that is installed in STM32CubeIDE.

           Click Migrate to update the TouchGFX generated code.

     

        An update progress window will be see.

        3. Once the process is complete, the MCU pinout screen will be seen

     

        4.  Save the project.  This should produce the following pop-up window.

            Click Yes

     

        5. Click Yes to change perspective

     

        6. A Warning Code Generation pop-up will appear regarding the Clock IPs.

           NOTE:Click Yes to generate the code.

     

        7. Once the code generation is complete, double click the .ioc file again to open the CubeMX perspective again,

            NOTE: This will produce the following Clock Configuration Pop-up.

                        DO NOT CLICK YES!  Click No. ( This may pop-up a second time but still select no.)

     

        8. This Clock Configuration window should appear.

     

        10. Click the Pinout & Configuration tab, select System Core, then RCC and in the Configuration Window, select Parameter Settings and Power Parameters.

            Change Power Regulator Voltage Scale from 2 to 0.

     

        11. Save the project and click Yes in the "Do you want to generate Code?" pop-up.

     

        12. Click yes on the Open Associated Perspective pop-up.

     

        13.  A clock warning may appear again.  Just click yes to generate the code.

        14.  Build the project.

     

       Run the code on the STM32H7B3i-DK

     

       1. Right click on the project in the Project Explorer and select Debug As - Debug Configuration

     

        2. Select STM32 Cortex-M C/C++ Application and then New launch configuration

     

        3. In the Debugger Tab, select the External loader, click Scan, and then find the loader associated with the STM32H7B3i-DK

    MX25LM51245G_STM32H7B3I_DISCO, 0x90000000, NOR_FLASH, MX25LM51245G_STM32H7B3I-DISCO.stldr
    

     

        4. Under GDB Server Command Line Options, set Reset Behavior to Software system reset

     

        5. Click Apply to run the debugger session

     

        6. Click the Resume button to run the code

    STMod MIKROE-3000 Configuration

     

    In order use the MIKROE-3000 H-Bridge with the STMod connection on the STM32H7B3i-DK, a few pins need to be configured and there are changes required on the STM32H7B3i-DK and the MIKROE-3000.

     

        1. For the STM32H7B3i-DK, SB6 (PA0) solder bridge needs to be closed.

     

     

        2. On the MIKROE-3000, move the VIN SEL zero ohm resistor to VIN so the power for the motors come from the external VIN on the board and not from the STM32H7B3i-DK.

     

        3. Mount the MIKROE-3000 on the STMod Fanout board

     

        4. In STM32CubeIDE, the following pin configurations are needed to control the MIKROE-3000.

     

        5. Pin Details:

    • GIN ( PA4) – Used to small motor between S1 and S2.
    • EN (END) ( PA0) – Used to enable the MPC17510 IC When high. Can be used as a brake
    • PWM ( PF8) – Routed to the 74LVC1G3157. Controls speed of motor

               Should be less than 200kHz.

    • DIR (RST) ( PH8) – Routed to 74LVC1G3157. Controls direction of motor

             If DIR is High, PWM is routed to IN2 of the MPC17510

             If DIR is Low (or float), PWM is routed to IN1 of MPC17510

     

     

    Motor Controller Project Configuration

     

        1. Open the previous TouchGFX project in STM32CubeIDE.

     

        2. Open the .ioc file..

     

        3. Search for PA4 (AN), PA0 (CS) PH8 (DIR) signals as GPIO

     

        4. Set PF8 (PWM) to TIM13_CH1 for the PWM signal.

     

       5. Configure TIM13 for PWM

     

       Set the following:

       Under Mode

    • Activated - Enabled
    • Channel1 - PWM Generation CH1

        Configuration - Parameter Settings

    • Prescalar - 15
    • Counter Mode - TIM_COUNTERDIVISION_DIV1
    • Period - 3905
    • Clock Division - TIM_CLOCKDIVISION_DIV1

     

        6. Click on the Pinout & Configuration Tab and select GPIO to change the names of the MikroBus signal names.

        Ex;

       

     

        7. Save the changes to generate the Code

     

        8. The GPIO configurations should be defined in the main.c file:

     

    CMSIS RTOS v2 FreeRTOS Task and Message Queue

    To control the MIKROE-3000 from the STM32H7B3i-DK GUI, a CMSIS (FreeRTOS) task and Message Queue were created.  This is used with the Slider from the TouchGFX GUI which sends a message to the Mortor Controller task via a Message Queue.

     

        1.  In STM32H7B3i-DK, open the .ioc file to access the CubeMX configuration.

             Click on Pinout & Configuration, then Middleware and select FREERTOS from the list.

     

        2. Under FREERTOS Mode and Configuration, in Configuration, select Tasks and Queue. Click Add to create a new task.

             The Task for the MotorSpeed Task is defined as follows.

     

        3. Under Queues, click Add to add a new message queue for the task.

             This is defined as follows

     

        4. Click save to save the changes and generate the code.

             This will create the code for both the Task and message queue in the main.c file

    /* Definitions for MotorSpeed_Task */
    osThreadId_t MotorSpeed_TaskHandle;
    const osThreadAttr_t MotorSpeed_Task_attributes = {
      .name = "MotorSpeed_Task",
      .priority = (osPriority_t) osPriorityNormal,
      .stack_size = 1024 * 4
    };
    /* Definitions for motorSpeedQueue */
    osMessageQueueId_t motorSpeedQueueHandle;
    const osMessageQueueAttr_t motorSpeedQueue_attributes = {
      .name = "motorSpeedQueue"
    };
    

     

        5. A motor_speed_task.c file was create for the MotorSpeed task and PWM configuration.

    /*
     * motor_speed_task.c
     *
     *  Created on: Sep 13, 2020
     *      Author: jomodev
     */
    
    #include "motor_speed_task.h"
    #include "cmsis_os2.h"
    #include "stm32h7xx_hal.h"
    #define LED3_Pin GPIO_PIN_11
    
    /* Definitions for motorSpeedQueue */
    //extern osMessageQueueId_t motorSpeedQueueHandle;
    extern osMessageQueueId_t motorSpeedQueueHandle;
    /*
    const osMessageQueueAttr_t motorSpeedQueue_attributes = {
      .name = "motorSpeedQueue"
    };
    */
    extern TIM_HandleTypeDef htim13;
    
    /* USER CODE BEGIN Header_Motor1PWM_Task */
    /* Create the queue(s) */
    /* creation of motorSpeedQueue */
    uint32_t num_msgs = 1;
    
    /**
    * @brief Function implementing the MotorSpeed_Task thread.
    * @param argument: Not used
    * @retval None
    */
    /* USER CODE END Header_Motor1PWM_Task */
    void Motor1PWM_Task(void *argument)
    {
      /* USER CODE BEGIN Motor1PWM_Task */
    
      uint16_t msg;
      volatile uint16_t motor_speed = 0; // Default motor_speed
      osStatus_t status;
    
      /*TIM13 define*/
    
      /* USER CODE BEGIN TIM13_Init 0 */
      TIM_ClockConfigTypeDef sClockSourceConfig;
      TIM_MasterConfigTypeDef sMasterConfig;
      /* USER CODE END TIM13_Init 0 */
    
      TIM_OC_InitTypeDef sConfigOC = {0};
    
      /* USER CODE BEGIN TIM13_Init 1 */
    
      /* USER CODE END TIM13_Init 1 */
      htim13.Instance = TIM13;
      //htim13.Init.Prescaler = 2800-1;
      htim13.Init.Prescaler = 15;
      htim13.Init.CounterMode = TIM_COUNTERMODE_UP;
      //htim13.Init.Period = 2000-1;
      htim13.Init.Period = 3906;
      htim13.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
      //htim13.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
    
      if (HAL_TIM_Base_Init(&htim13) != HAL_OK)
      {
        Error_Handler();
      }
    
      sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
      if (HAL_TIM_ConfigClockSource(&htim13, &sClockSourceConfig) != HAL_OK)
      {
         Error_Handler();
      }
      if (HAL_TIM_PWM_Init(&htim13) != HAL_OK)
      {
        Error_Handler();
      }
    
      sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
      sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
      if (HAL_TIMEx_MasterConfigSynchronization(&htim13, &sMasterConfig) != HAL_OK)
      {
        Error_Handler();
      }
    
      sConfigOC.OCMode = TIM_OCMODE_PWM1;
      //sConfigOC.Pulse = 1953;
      sConfigOC.Pulse = 0;
      sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
      sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
      if (HAL_TIM_PWM_ConfigChannel(&htim13, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
      {
        Error_Handler();
      }
      /* USER CODE BEGIN TIM13_Init 2 */
      HAL_TIM_Base_Start(&htim13);
      HAL_TIM_PWM_Start(&htim13, TIM_CHANNEL_1);
      /* USER CODE END TIM13_Init 2 */
      HAL_TIM_MspPostInit(&htim13);
      /* Infinite loop */
      for(;;)
      {
            // Assign motor_speed based on message in queue
            status = osMessageQueueGet(motorSpeedQueueHandle, &msg, NULL, 0);
    
            // If message was received, update delay
            if ( status == osOK )
            {
                motor_speed = msg;
    
    
                if (motor_speed < 3906 && motor_speed >= 0)
                //if (motor_speed > 500)
                {
                    __HAL_TIM_SetCompare(&htim13, TIM_CHANNEL_1, motor_speed);
                    HAL_GPIO_TogglePin(GPIOG, LED3_Pin); // GPIO_PIN_11
                    //HAL_GPIO_WritePin(GPIOG, LED3_Pin, GPIO_PIN_SET);
                } else {
                    HAL_GPIO_WritePin(GPIOG, LED3_Pin, GPIO_PIN_RESET);
                }
            }
    
        osDelay(100);
      }
    
      // In case we accidentally exit from the task loop
      osThreadTerminate(motorSpeedQueueHandle);
      /* USER CODE END Motor1PWM_Task */
    }
    
    
    

     

        6. If a Message is sent to the motorSpeedQueueHandle, the motor speed is sent to the value of 'msg'.  A user LED on the board is set to blink when a messages is seen.

      for(;;)
      {
            // Assign motor_speed based on message in queue
            status = osMessageQueueGet(motorSpeedQueueHandle, &msg, NULL, 0);
    
            // If message was received, update delay
            if ( status == osOK )
            {
                motor_speed = msg;
    
    
                if (motor_speed < 3906 && motor_speed >= 0)
                //if (motor_speed > 500)
                {
                    __HAL_TIM_SetCompare(&htim13, TIM_CHANNEL_1, motor_speed);
                    HAL_GPIO_TogglePin(GPIOG, LED3_Pin); // GPIO_PIN_11
                    //HAL_GPIO_WritePin(GPIOG, LED3_Pin, GPIO_PIN_SET);
                } else {
                    HAL_GPIO_WritePin(GPIOG, LED3_Pin, GPIO_PIN_RESET);
                }
            }
    
        osDelay(100);
      }
    

     

      NOTE: This uses the  TouchGFX Model-View-Presenter (MVP) pattern to pass messages between the TouchGFX GUI and the HAL layer.

     

    TouchGFX HAL Config

     

    In the TouchGFX code, the MainView.cpp file receives the messages from the GUI and handles the events associated with buttons and sliders.

     

        1. The button events are handled using the HAL GPIO options.

    #include <gui/main_screen/MainView.hpp>
    
    MainView::MainView()
    {
        pwm = 0;
        motor_state = 0;
    #ifndef SIMULATOR
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET);
    #endif
    }
    
    void MainView::setupScreen()
    {
        MainViewBase::setupScreen();
    }
    
    void MainView::tearDownScreen()
    {
        MainViewBase::tearDownScreen();
    }
    
    void MainView::buttonUpClicked()
    {
        touchgfx_printf("buttonUpClicked\n");
        pwm += 100;
        if (pwm > 3906)
        {
            pwm = 3906;
        }
    #ifndef SIMULATOR
        //__HAL_TIM_SetCompare(&htim13, TIM_CHANNEL_1, pwm);  // update pwm value
        HAL_GPIO_WritePin(GPIOH, GPIO_PIN_8, GPIO_PIN_SET);  // DIR HIGH
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET);  // END HIGH
        HAL_Delay(5);
    #endif
    }
    void MainView::buttonDownClicked()
    {
        touchgfx_printf("buttonDownClicked\n");
        pwm -= 100;
        if (pwm < 0)
        {
            pwm = 0;
        }
    #ifndef SIMULATOR
        //__HAL_TIM_SetCompare(&htim13, TIM_CHANNEL_1, pwm);  // update pwm value
        //HAL_GPIO_WritePin(GPIOH, GPIO_PIN_8, GPIO_PIN_RESET);  // DIR HIGH
        HAL_GPIO_WritePin(GPIOH, GPIO_PIN_8, GPIO_PIN_RESET);  // DIR HIGH
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET);  // END HIGH
        HAL_Delay(5);
    #endif
    }
    
    void MainView::motorButtonClicked()
    {
        touchgfx_printf("motorButtonClicked\n");
        
        motor_state = !motor_state;
    #ifndef SIMULATOR
        if (motor_state)
        {
            HAL_GPIO_WritePin(GPIOH, GPIO_PIN_8, GPIO_PIN_SET);  // DIR HIGH
            HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET);  // END HIGH
            HAL_Delay(5);
        } else {
            HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET);  // END LOW
        }
    #endif
    }
    

     

     

        2. For the Motor Speed slider, when a change is detected, the Presenter setMotorSpeed method is called with the value of the motor speed.

            Also, the value is passed back to the GUI to display it next to the slider.

    void MainView::motorSpeedSliderChanged(int value)
    {
        touchgfx_printf("motorSpeedChanged %d\n", value);
        presenter->setMotorSpeed(value);
    
    }
    
    void MainView::motorSpeedMsg()
    {
        touchgfx_printf("motorSpeedMsgReceived\n");
    }
    
    void MainView::motorSpeedChanged(int value)
    {
        Unicode::snprintf(textMotorSpeedBuffer, 4, "%d", value);
        textMotorSpeed.invalidate();
    
    }
    

     

     

        3. In MainPresenter.cpp, the model userSetMotorSpeed method is called with the speed value.

    void MainPresenter::setMotorSpeed(int value)
    {
        model->userSetMotorSpeed(value);
    }
    

     

        4. The value is sent to the Message Queue via the Model userSetMotorSpeed method using the CMSIS RTOS "osMessageQueuePut" method.

            NOTE: A reference to the "motorSpeedQueueHandle" is added using the 'extern "C"' option.

    #include <gui/model/Model.hpp>
    #include <gui/model/ModelListener.hpp>
    
    #ifndef SIMULATOR
    
        //#include "stm32f769i_discovery.h"
        #include "FreeRTOS.h"
        #include "touchgfx/Utils.hpp"
        #include "queue.h"
        #include "cmsis_os.h"
        #include "motor_speed_task.h"
    
    
        //*******************************************************
        //   Define Queue handles
        //*******************************************************
        //extern "C" xQueueHandle gui_msg_q; //From LEDTask
        extern "C" osMessageQueueId_t motorSpeedQueueHandle; // From motor_speed_task
        xQueueHandle gui_msg_q;
    
    #else
        #include <stdio.h>
    #endif
    
    Model::Model() : modelListener(0)
    {
        #ifndef SIMULATOR
        
        //*******************************************************
        // 
        //  Create GUI message queue
        //
        //  Check for messages from backend, with zero timeout
        //  Any time there's a message on this mailbox, react to it. value is meaningless in this case..
        //    
        //*******************************************************
        //
        gui_msg_q = xQueueGenericCreate(1, 1, 0);
        #endif
    }
    
    void Model::tick()
    {
    #ifndef SIMULATOR
    
        //*******************************************************
        // 
        //  HANDLE MESSAGES
        //
        //  Check for messages from backend, with zero timeout to 
        //  avoid blocking the UI. 
        // 
        //*******************************************************
        //
        
        uint8_t msg = 0;
        osStatus_t status;
        if (xQueueReceive(gui_msg_q, &msg, 0) == pdTRUE)
        {
          // Queue is used as a flag, so don't check msg.
        // Full = PRESSED, Empty = Do nothing.        
         //btnPressed();
            //touchgfx_printf("motorSpeedInQueued %d\n", msg);
        }
        /*
        status = osMessageQueueGet(motorSpeedQueueHandle, &msg, NULL, 0);
        if ( status == osOK )
        {
            motorSpeedSet();
        }
        */
    #endif
    
    }
    
    void Model:: motorSpeedSet()
    {
        modelListener->motorSpeedSet();
    }
    
    void Model::userSetMotorSpeed(int speed)
    {
        //struct Message msg;
        //msg.eventType = 
    
        //xQueueSend(gui_msg_q, &msg, 0);
        //touchgfx_printf("motorSpeedChanged %d\n", speed);
    #ifndef SIMULATOR
        int msg = 0;
        msg = speed * 30;
        osStatus_t status;
    
        status = osMessageQueuePut (motorSpeedQueueHandle, &msg, 0, 0);
    
        //if ( status == osOK )
        //{
    
        //}
    #endif
    }
    
    
    

     

     

        5. This is picked up by the Motor Speed task via the 'osMessageQueueGet' method defined previously where the speed value is sent to the STMod Fanout board and then the MIKROE-3000.

     

        6. Build and load the code

     

        7.  Install the STMod Fanout board with MIKROE-3000 to the STM32H7B3i-DK

     

       Wiring:

       VIN        - 5V Power Supply

       GND      - Ground of Power Supply

       M1-M2  - Motor

     

        8. Video of Motor Controll Demo

     

    Embeddded Wizard

     

    Useful Links


      Embedded Wizard is another tool that can be used to great a GUI Interface for the STM32H7B3i-DK.  There is a different approach with Embedded Wizard in that it has a built in Prototyer which provides a WYSIWYG interface where the GUI designed in the Embedded Wizard Studio is what will be seen when installed on the board.  Also, there are two versions of the Embedded Wizard - Free and Pro.  The Free version has limitations with regards to the GUI design that can be created where the Pro version is full-featured but requires a purchased license. 

        1. The first step is to download and install the Embedded Wizard.  The Free version was used in the RoadTest:

            https://www.embedded-wizard.de/download/download-free-edition

     

        2. Then open the Embedded Wizard Studio to create a GUI.

     

        3. There are multiple options to choose at this point.  In the right side of the screen there is an option to "Open an example project" to access the avaiable examples.

     

        4. The Quick Tour is a good place to start.

     

        5. From Embedded Wizard Studio, there are many options to edit a GUI.  Embedded Wizard uses a universal, target system imdependent programming language called Chora for creating the interfaces.

        See: https://doc.embedded-wizard.de/chora-reference?v=9.30

     

        6. For the RoadTest, a 'Hello' prjoject was created showing a basic screen with text in the middle.

     

        7. To load the code to the STM32H7B3i-DK, find the location of the Embedded Wizard project and copy the files in the Project folder and place them in the Application/GeneratedCode folder for the asscociated board.

       Ex:  Project location:

     

          Embedded Wizard STM32H7B30-Discovery folder:

     

        8. Under the STM32H7B30-Discovery folder, there is a file 'StartGccBuildEnvironment.bat'. This file has the settings for the target board and is where the STMCubeProgrammer tool location is defined.

     

        9. The 'devenv.cmd' file located under 'EmbeddedWizard\STM32H7B3-Discovery\Application\Project\GCC' defines the paths for the code, libraries and ST-LINK.

     

        10.  To build and install the application to the target, open a command window and navigate to the 'STM32H7B3-Discovery' folder.

               Run the 'StartGccBuildEnvironment.bat' script.  This will set the environment variables and place the cursor in the GCC folder.

     

        11.  Type 'make' to build the code.

     

        12. Ensure the board is connected and run 'make install' to load the code to the board.

     

        13. If all goes well, the code should be running on the board.

     

        14. Video of Embedded Wizard Hello code running

     

       Embedded Wizard MasterDemo

     

        This is an example of running the Embedded Wizard MasterDemo on the STM32H7B3i-DK

        1. Navigate to the 'EmbeddedWizard\STM32H7B3-Discovery\MasterDemo' folder and run the 'FlashMasterDemo.bat' script.

            This should build and flash the code to the board.

     

        2. MasterDemo running on the board

     

        3. Video of MasterDemo running

     

    Conclusion

     

    The STM32H7B3i-DK is a nice board with many features which were barely touched in this RoadTest. This is an excellent platform for evaluating the STM32H7 Single Core MCU as well as to get familiar with the STM GUI tools. Overall, outside of some issues between the STMCube software applications, the platform and tools were good to work with. I can see using this in a future project.


Comments

Also Enrolling

Enrollment Closes: Nov 23 
Enroll
Enrollment Closes: Nov 12 
Enroll
Enrollment Closes: Oct 29 
Enroll
Enrollment Closes: Nov 11 
Enroll
Enrollment Closes: Oct 29 
Enroll
Enrollment Closes: Oct 30 
Enroll