3969|3

13

帖子

0

TA的资源

一粒金砂(中级)

楼主
 

3D打印机控制器项目报告 [复制链接]

  本帖最后由 caxfan 于 2022-11-5 20:28 编辑

#


3D打印机控制器项目

                                            caxfan

 


作品简介

基于开源3D打印机系统Smoothieware V2.0移植到STM32F7508-DK的项目。硬件采用STM32F7508-DK作为主控制器及UI显示,ESP32作为WIFI设备通过USART进行通讯的3D打印机控制系统。具有高度模块化,可根据需求改变附件实现CNC,激光雕刻,绘图等多种功能。


###系统框图

###程序框架

##各部分功能说明

###硬件

1.STM32F7508-DK探索板是为基于STMicroelectronics Arm® Cortex®-M7内核的STM32F750N8H6微控制器而设计的一个完整的演示和开发平台。该微控制器具有

- 四个I2C、六个具有三个复用单工I2S的SPI、SDMMC、四个USART、四个UART、两个CAN、三个12位ADC、两个12位DAC、两个SAI、8到14位的数字相机模块接口、
- 内部320+16+4-Kb的SRAM和64-Kb的闪存、
- USB OTG HS和FS、以太网MAC、FMC接口、Quad-SPI接口、SWD调试支持。
板上的全系列硬件特性可帮助用户评估几乎所有外设
- USB OTG HS和FS、
- 10/100-Mbit以太网、
- microSD™卡、
- USART、
- 带音频输入和输出插孔的SAI立体声音频DAC、
- ST-MEMS数字麦克风、
- SDRAM(美光128Mb的MT48LC4M32B2,能够使用8MB)、
- Quad-SPI闪存(美光16MB的N25Q128A)、
- 带电容式多点触摸板的4.3英寸彩色LCD-TFT(480X272)、
- SPDIF RCA输入等)和开发其应用。
- Arduino™ Uno V3连接器可轻松连接用于用户特定应用的扩展板或子板。
- 集成的ST-LINK/V2-1提供了用于STM32的嵌入式在线调试器和编程器。

  ![](RackMultipart20221105-1-q1d30a_html_6df8b06766c23fda.jpg) ![](RackMultipart20221105-1-q1d30a_html_2eab6bdf2d6accc1.jpg)

2.ESP32-S3 是一款低功耗的 MCU 系统级芯片 (SoC),支持 2.4 GHz Wi-Fi 和低功耗蓝牙 (Bluetooth® LE) 双模无线通信。芯片集成了 Xtensa® 32 位 LX7 双核处理器、超低功耗协处理器、Wi-Fi 基带、蓝牙基带、RF 模块以及外设。芯片的功能框图如下图所示。

![](RackMultipart20221105-1-q1d30a_html_a51e12b51938fd56.jpg)

###软件

#### Smoothie简介

Smoothie原平台是使用STM32H745芯片基于FreeRTOS嵌入式操作系统的GCC平台软件,包含FatFS文件系统,PID温度控制,开源,高度模块化,高性能G代码解释器和用面向对象的C++编写的CNC,3D打印机,激光切割控制器。具有可伸缩灵活配置,可靠,易维护的特点。

![](RackMultipart20221105-1-q1d30a_html_4966360998a3800e.jpg)

#### FreeRTOS简介

FreeRTOS是一个迷你的实时操作系统内核。作为一个轻量级的操作系统,功能包括:任务管理、时间管理、信号量、消息队列、内存管理、记录功能、软件定时器、协程等,可基本满足较小系统的需要。

![](RackMultipart20221105-1-q1d30a_html_80926dd8f37ced64.jpg)

#### LVGL简介

LVGL(轻量级和通用图形库)是一个免费和开源的图形库,它提供了创建嵌入式GUI所需的一切,具有易于使用的图形元素,美丽的视觉效果和低内存占用。LVGL的项目作者是来自匈牙利首都布达佩斯的 Gábor Kiss-Vámosi 。Kiss 在2016年将其并发布在 GitHub 上。当时叫 LittlevGL而不是LVGL,后来作者统一修改为 LVGL。 像一般的开源项目的那样,它是作为一个人的项目开始的。 从那时起,陆续有近 100 名贡献者参与了项目开发,使得 LVGL 逐渐成为最受欢迎的嵌入式图形库之一。

![](RackMultipart20221105-1-q1d30a_html_2f84067360621f4b.jpg)

由于STM32F7508N芯片内部FLASH只有区区的64KB,而且内置RAM只有320K,对于项目来说,两者都不够,必须使用外部FLASH及外部SDRAM。本来尝试过混合模式,对于单单FreeRTOS+LVGL还可以成功,但是增加Smooth模块后内置FLASH空间就不够了,估计是C++的支持运行库太大。只能采用Bootloader加APP方式,Bootloader放在内部FLASH,APP放在外置FLASH中。不过这种方式在开发中也遇到好几个大坑,足足耽误了一个月时间,还好最终还是成功了。

###启动程序

由于STM32F7508-DK采用的芯片STM32F750N8H6属于STMicroelectronics Arm® Cortex®-M7内核,内置FLASH只有64K,所以启动程序必须精简,提供必要的功能。故需要使用QSPI,SDRAM模块

#### QSPI

QSPI 即 Quad SPI,是一种专用的通信接口,连接单、双或四(条数据线)SPI FLASH 存储
器。STM32F7 具有 QSPI 接口,支持如下三种工作模式:间接模式,状态轮询模式,内存映射模式。
 QSPI启动后,需要设置内存映射模式

```
/**
  * @brief  Initializes and configure the QSPI interface.
  * @retval QSPI memory status
  */
uint32_t QSPI_Startup(void)
{
  QSPIHandle.Instance = QUADSPI;

  /* Call the DeInit function to reset the driver */
  if (HAL_QSPI_DeInit(&QSPIHandle) != HAL_OK)
  {
    return MEMORY_ERROR;
  }

  /* System level initialization */
  QSPI_MspInit();

  /* sCommand initialize common parameter */
  sCommand.AddressMode       = QSPI_ADDRESS_NONE;
  sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
  sCommand.DataMode          = QSPI_DATA_NONE;
  sCommand.DummyCycles       = 0;
  sCommand.DdrMode           = QSPI_DDR_MODE_DISABLE;
  sCommand.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
  sCommand.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;
  sCommand.AddressSize       = QSPI_ADDRESS_24_BITS;

  /* sConfig initialize common parameter */
  sConfig.MatchMode       = QSPI_MATCH_MODE_AND;
  sConfig.StatusBytesSize = 1;
  sConfig.Interval        = 0x10;
  sConfig.AutomaticStop   = QSPI_AUTOMATIC_STOP_ENABLE;

  /* QSPI initialization */
  /* QSPI freq = SYSCLK /(1 + ClockPrescaler) = 216 MHz/(1+1) = 108 Mhz */
  QSPIHandle.Init.ClockPrescaler     = 1;   /* QSPI freq = 216 MHz/(1+1) = 108 Mhz */
  QSPIHandle.Init.FifoThreshold      = 4;
  QSPIHandle.Init.SampleShifting     = QSPI_SAMPLE_SHIFTING_HALFCYCLE;
  QSPIHandle.Init.FlashSize          = POSITION_VAL(N25Q128A_FLASH_SIZE) - 1;
  QSPIHandle.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_6_CYCLE; /* Min 30ns for nonRead */
  QSPIHandle.Init.ClockMode          = QSPI_CLOCK_MODE_0;
  QSPIHandle.Init.FlashID            = QSPI_FLASH_ID_1;
  QSPIHandle.Init.DualFlash          = QSPI_DUALFLASH_DISABLE;

  if (HAL_QSPI_Init(&QSPIHandle) != HAL_OK)
  {
    return MEMORY_ERROR;
  }

  /* QSPI memory reset */
  if (QSPI_ResetMemory(&QSPIHandle))
  {
    return MEMORY_ERROR;
  }

#if (CODE_AREA == USE_QSPI)
  /* Put QSPI memory in QPI mode */
  if( QSPI_EnterMemory_QPI( &QSPIHandle )!=MEMORY_OK )
  {
    return MEMORY_ERROR;
  }

  /* Configuration of the dummy cycles on QSPI memory side */
  if (QSPI_DummyCyclesCfg(&QSPIHandle) != MEMORY_OK)
  {
    return MEMORY_ERROR;
  }

  /* Enable MemoryMapped mode */
  if( QSPI_EnableMemoryMappedMode( &QSPIHandle ) != MEMORY_OK )
  {
    return MEMORY_ERROR;
  }
#elif (BINARY_AREA == USE_SPI_NOR)
  if (QSPI_Copy(APPLICATION_ADDRESS, BINARY_BASE_OFFSET, BINARY_SIZE) != MEMORY_OK)
  {
    return MEMORY_ERROR;
  }

  if (QSPI_Shutdown() != MEMORY_OK)
  {
    return MEMORY_ERROR;
  }
#endif /* (CODE_AREA == USE_QSPI) */

  return MEMORY_OK;
}

static uint32_t QSPI_ResetMemory(QSPI_HandleTypeDef *hqspi)
{
  /* Send command RESET command in SPI mode */
  /* Initialize the reset enable command */
  sCommand.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
  sCommand.Instruction       = RESET_ENABLE_CMD;
  sCommand.DataMode          = QSPI_DATA_NONE;
  /* Send the command */
  if (HAL_QSPI_Command(hqspi, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
  {
    return MEMORY_ERROR;
  }

  /* Send the reset memory command */
  sCommand.Instruction = RESET_MEMORY_CMD;
  if (HAL_QSPI_Command(hqspi, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
  {
    return MEMORY_ERROR;
  }

  return MEMORY_OK;
}

static uint32_t QSPI_EnableMemoryMappedMode(QSPI_HandleTypeDef *hqspi)
{
  QSPI_MemoryMappedTypeDef s_mem_mapped_cfg;

  /* Configure the command for the read instruction */
  sCommand.InstructionMode   = QSPI_INSTRUCTION_4_LINES;
  sCommand.Instruction       = QUAD_INOUT_FAST_READ_CMD;
  sCommand.AddressMode       = QSPI_ADDRESS_4_LINES;
  sCommand.DataMode          = QSPI_DATA_4_LINES;
  sCommand.DummyCycles       = N25Q128A_DUMMY_CYCLES_READ_QUAD;

  /* Configure the memory mapped mode */
  s_mem_mapped_cfg.TimeOutActivation = QSPI_TIMEOUT_COUNTER_DISABLE;
  s_mem_mapped_cfg.TimeOutPeriod     = 0;

  if (HAL_QSPI_MemoryMapped(hqspi, &sCommand, &s_mem_mapped_cfg) != HAL_OK)
  {
    return MEMORY_ERROR;
  }

  return MEMORY_OK;
}

```

####SDRAM

通过 STM32F750 的 FMC 接口驱动美光MT48LC4M32B2,容量16MB,但是由于FMC接口引脚原因,只能使用8MB。

```
/**
  * @brief  Initializes the SDRAM device.
  * @retval SDRAM status
  */
uint32_t SDRAM_Startup(void)
{
  SDRAM_HandleTypeDef      sdramHandle;
  FMC_SDRAM_TimingTypeDef  Timing;
  FMC_SDRAM_CommandTypeDef Command; 
  __IO uint32_t            tmpmrd = 0;
  
  /* SDRAM device configuration */
  sdramHandle.Instance = FMC_SDRAM_DEVICE;
    
  /* Timing configuration for 100Mhz as SDRAM clock frequency (System clock is up to 200Mhz) */
  Timing.LoadToActiveDelay    = 2;
  Timing.ExitSelfRefreshDelay = 7;
  Timing.SelfRefreshTime      = 4;
  Timing.RowCycleDelay        = 7;
  Timing.WriteRecoveryTime    = 3;
  Timing.RPDelay              = 2;
  Timing.RCDDelay             = 2;
    
  sdramHandle.Init.SDBank             = FMC_SDRAM_BANK1;
  sdramHandle.Init.ColumnBitsNumber   = FMC_SDRAM_COLUMN_BITS_NUM_8;
  sdramHandle.Init.RowBitsNumber      = FMC_SDRAM_ROW_BITS_NUM_12;
  sdramHandle.Init.MemoryDataWidth    = SDRAM_MEMORY_WIDTH;
  sdramHandle.Init.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4;
  sdramHandle.Init.CASLatency         = FMC_SDRAM_CAS_LATENCY_2;
  sdramHandle.Init.WriteProtection    = FMC_SDRAM_WRITE_PROTECTION_DISABLE;
  sdramHandle.Init.SDClockPeriod      = SDCLOCK_PERIOD;
  sdramHandle.Init.ReadBurst          = FMC_SDRAM_RBURST_ENABLE;
  sdramHandle.Init.ReadPipeDelay      = FMC_SDRAM_RPIPE_DELAY_0;

  /* SDRAM controller initialization */
  SDRAM_MspInit();

  if (HAL_SDRAM_Init(&sdramHandle, &Timing) != HAL_OK)
  {
    return MEMORY_ERROR;
  }

/* SDRAM initialization sequence */
  /* Step 1: Configure a clock configuration enable command */
  Command.CommandMode            = FMC_SDRAM_CMD_CLK_ENABLE;
  Command.CommandTarget          = FMC_SDRAM_CMD_TARGET_BANK1;
  Command.AutoRefreshNumber      = 1;
  Command.ModeRegisterDefinition = 0;

  /* Send the command */
  HAL_SDRAM_SendCommand(&sdramHandle, &Command, SDRAM_TIMEOUT);

  /* Step 2: Insert 100 us minimum delay */ 
  /* Inserted delay is equal to 1 ms due to systick time base unit (ms) */
  HAL_Delay(1);
    
  /* Step 3: Configure a PALL (precharge all) command */ 
  Command.CommandMode            = FMC_SDRAM_CMD_PALL;
  Command.CommandTarget          = FMC_SDRAM_CMD_TARGET_BANK1;
  Command.AutoRefreshNumber      = 1;
  Command.ModeRegisterDefinition = 0;

  /* Send the command */
  HAL_SDRAM_SendCommand(&sdramHandle, &Command, SDRAM_TIMEOUT);  
  
  /* Step 4: Configure an Auto Refresh command */ 
  Command.CommandMode            = FMC_SDRAM_CMD_AUTOREFRESH_MODE;
  Command.CommandTarget          = FMC_SDRAM_CMD_TARGET_BANK1;
  Command.AutoRefreshNumber      = 8;
  Command.ModeRegisterDefinition = 0;

  /* Send the command */
  HAL_SDRAM_SendCommand(&sdramHandle, &Command, SDRAM_TIMEOUT);
  
  /* Step 5: Program the external memory mode register */
  tmpmrd = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_1          |\
                     SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL   |\
                     SDRAM_MODEREG_CAS_LATENCY_2           |\
                     SDRAM_MODEREG_OPERATING_MODE_STANDARD |\
                     SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;
  
  Command.CommandMode            = FMC_SDRAM_CMD_LOAD_MODE;
  Command.CommandTarget          = FMC_SDRAM_CMD_TARGET_BANK1;
  Command.AutoRefreshNumber      = 1;
  Command.ModeRegisterDefinition = tmpmrd;

  /* Send the command */
  HAL_SDRAM_SendCommand(&sdramHandle, &Command, SDRAM_TIMEOUT);
  
  /* Step 6: Set the refresh rate counter */
  /* Set the device refresh rate */
  HAL_SDRAM_ProgramRefreshRate(&sdramHandle, REFRESH_COUNT); 

  return MEMORY_OK;
}

```

####程序入口

配置好外置FLASH和SDRAM后,进行初始化后,设置APP的堆栈指针,和Reset\_Handler地址
然后跳入APP执行程序,完成BOOT引导过程。

```
/**
  * @brief  Main program
  * @param  None
  * @retval None
  */
int main(void)
{
  /* Configure MPU to allow non aligned access */
  MPU_Config();

  /* Enable the CPU Cache */
  CPU_CACHE_Enable();

  /* STM32F7xx HAL library initialization:
       - Configure the Flash ART accelerator on ITCM interface
       - Configure the Systick to generate an interrupt each 1 msec
       - Set NVIC Group Priority to 4
       - Low Level Initialization
     */
  HAL_Init();

  /* Configure the system clock to 200 MHz */
  /* Configure the Systick to generate an interrupt each 1 msec */
  SystemClock_Config();

  /*##-1- Configure Required Memory #########################################*/
  if(Memory_Startup() != MEMORY_OK)
  {
    Error_Handler();
  }

  /* Disable CPU L1 cache before jumping to the QSPI code execution */
  CPU_CACHE_Disable();
  /* Disable Systick interrupt */
  DISABLE_INT();
  HAL_RCC_DeInit();
  SysTick->CTRL = 0;
  SysTick->LOAD = 0;
  SysTick->VAL = 0;
  
  for (int i = 0; i < 8; i++)
  {
      NVIC->ICER=0xFFFFFFFF;
      NVIC->ICPR=0xFFFFFFFF;
  }
  ENABLE_INT();
  __set_CONTROL(0);

  /* Initialize user application's Stack Pointer & Jump to user application */
  JumpToApplication = (pFunction) (*(__IO uint32_t*) (APPLICATION_ADDRESS + 4));
  __set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);
  JumpToApplication();

  /* We should never get here as execution is now on user application */
  while(1)
  {
  }
}

```

###主程序
## 框架概述
  由于STM32F750的硬件限制,需要将主程序放在外置FLASH。所以程序可使用BOOT+APP程序模式,BOOT程序在芯片内置FLASH启动后,加载外置FLASH,SDRAM驱动程序,跳转到主程序的Reset_Handler入口函数,所以主程序的入口偏移地址必须和BOOT程序的跳转指针地址一致。
  主程序在外置FLASH上运行,而且需要使用外部SDRAM,同时还有使用内部RAM,最好采用分散文件管理内存布局。
```
; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************

LR_IROM1 0x90000000 0x0800000
{    ; load region size_region
    ER_IROM1 0x90000000 0x0800000
    {  ; load address = execution address
        *.o (RESET, +First)
        *(InRoot$$Sections)
        *(Veneer$$Code)
        .ANY (+RO)
    }
    RW_IRAM1 0x20000000 0x00050000
    {  ; RW data
        *.o(registmodules)
        ;*.o(.dtram_bss)    
        *.o(.data*)
        *.o(.bss.*)
        *.o(.bss)
        *.o(.dtcm_bss)
        .ANY (+RW +ZI)
    }
    RW_SRAM1 0xC0000000 0x00100000
    {
        *.o(.lvgl_bss)        
    }
    RW_SRAM2 0xC0100000 0x00100000
    {
        *.o(.sram_bss)
        ;*.o(.sram_1_bss)
        *.o(.first_data) 
    }
    RW_ITCM 0x00000000 0x00010000 
    {   ; ITCM
        *.o(.ramfunctions)
    }
    ARM_LIB_HEAP ImageLimit(RW_IRAM1) EMPTY 0x20040000-ImageLimit(RW_IRAM1)
    {
    }
    ARM_LIB_STACK 0x20050000 EMPTY -0x10000
    {
    }
}
```
程序入口地址需要修改成LR_IROM1地址即0x90000000。
```
#define VECT_TAB_BASE_ADDRESS   QSPI_BASE

static void SystemClock_Config(void)
{
    RCC_OscInitTypeDef RCC_OscInitStruct = { 0 };
    RCC_ClkInitTypeDef RCC_ClkInitStruct = { 0 };

    /** Configure LSE Drive Capability
    */
    HAL_PWR_EnableBkUpAccess();

    /** Configure the main internal regulator output voltage
    */
    __HAL_RCC_PWR_CLK_ENABLE();
    __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

    /** Initializes the RCC Oscillators according to the specified parameters
    * in the RCC_OscInitTypeDef structure.
    */
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI | RCC_OSCILLATORTYPE_HSE;
    RCC_OscInitStruct.HSEState = RCC_HSE_ON;
    RCC_OscInitStruct.LSIState = RCC_LSI_ON;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
    RCC_OscInitStruct.PLL.PLLM = 25;
// #if (DATA_AREA == USE_EXTERNAL_SDRAM) || (CODE_AREA == USE_EXTERNAL_SDRAM)
    RCC_OscInitStruct.PLL.PLLN = 360;
// #else
//     RCC_OscInitStruct.PLL.PLLN = 432;
// #endif
    RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
    RCC_OscInitStruct.PLL.PLLQ = 8;
    if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
    {
        Error_Handler();
    }

    /** Activate the Over-Drive mode
    */
    if (HAL_PWREx_EnableOverDrive() != HAL_OK)
    {
        Error_Handler();
    }

    /** Initializes the CPU, AHB and APB buses clocks
      */
    RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
                                | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

    if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_6) != HAL_OK)
    {
        Error_Handler();
    }
    RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = { 0 };

    /** Initializes the peripherals clock
    */
    PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LTDC | RCC_PERIPHCLK_SAI2
                                | RCC_PERIPHCLK_SDMMC1 | RCC_PERIPHCLK_CLK48;
    PeriphClkInitStruct.PLLSAI.PLLSAIN = 384;
    PeriphClkInitStruct.PLLSAI.PLLSAIR = 5;
    PeriphClkInitStruct.PLLSAI.PLLSAIQ = 2;
    PeriphClkInitStruct.PLLSAI.PLLSAIP = RCC_PLLSAIP_DIV8;
    PeriphClkInitStruct.PLLSAIDivQ = 1;
    PeriphClkInitStruct.PLLSAIDivR = RCC_PLLSAIDIVR_2;
    PeriphClkInitStruct.Sai2ClockSelection = RCC_SAI2CLKSOURCE_PLLSAI;
    PeriphClkInitStruct.Clk48ClockSelection = RCC_CLK48SOURCE_PLLSAIP;
    PeriphClkInitStruct.Sdmmc1ClockSelection = RCC_SDMMC1CLKSOURCE_CLK48;
    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
    {
        Error_Handler();
    }

    /* Enable SYSCFG clock mondatory for I/O Compensation Cell */
    __HAL_RCC_SYSCFG_CLK_ENABLE();

    /* Enables the I/O Compensation Cell */
    HAL_EnableCompensationCell();
}


// called from main, but it is HAL so we put it here
void main_system_setup()
{
    //MPU_Config();
    // Enable the CPU Cache
    CPU_CACHE_Enable();
    // stm32h7xx HAL library initialization
    if (HAL_Init() != HAL_OK) {
        Error_Handler();
    }
    // Configure the system clock to 200 MHz
    SystemClock_Config();
}

int main(int argc, char *argv[])
{
    // 设置时钟和缓存等(在 HAL 中)
    main_system_setup();
    setup_memory_pool();

    Board_LED_Init();
    // led 4 表示启动阶段 1 开始
    Board_LED_Set(0, true);

    std::ios_base::sync_with_stdio(false);

    benchmark_timer_init();

    setup_xprintf();

    if(setup_uart() < 0) {
        printf("FATAL: UART setup failed\n");
    }
    if(rtc_init() != 1) {
        printf("ERROR: Failed to init RTC\n");
    }
    // 启动启动线程,该线程将成为执行所有传入命令的命令线程

     xTaskCreate(led_startup, "LedThread", 256, NULL, (tskIDLE_PRIORITY + DISP_PRI), (TaskHandle_t *)NULL);
    xTaskCreate(lvglui_startup, "LvglThread", 2048, NULL, (tskIDLE_PRIORITY + DISP_PRI), (TaskHandle_t *)&LVGLTask_Handler);
    xTaskCreate(smoothie_startup, "CommandThread", 8192, NULL, (tskIDLE_PRIORITY + CMDTHRD_PRI), (TaskHandle_t *)&CommTask_Handler);
    /* 启动调度程序 */
    vTaskStartScheduler();

    while (1)
    {
    }
    // 永远不要到这里
    return 1;
}

```
##界面
界面采用LVGL,实现功能界面的切换,包括按钮,开关等控件实现对3D打印机功能的调用完成打印任务。除界面外,还需要实现触摸功能,显示功能。
###显示功能接口
STM32F7508-DK采用的是ROCKTECH带电容式触摸屏的4.3英寸480x272彩色LCD-TFT,型号RK043FN48H-CT672B,需要驱动LCD-TFT 控制器 (LTDC),同时要使LVGL接口进行对接。
```
/**
 * Initialize your display here
 */

void tft_init(void)
{
    /* There is only one display on STM32 */
    if(our_disp != NULL)
        abort();
    /* LCD Initialization */
    LCD_Init();

    /* LCD Initialization */
    LCD_LayerRgb565Init((uint32_t)my_fb);

    /* Enable the LCD */
    LCD_DisplayOn();

    DMA_Config();

   /*-----------------------------
    * Create a buffer for drawing
    *----------------------------*/

   /* LittlevGL requires a buffer where it draws the objects. The buffer's has to be greater than 1 display row*/

    static lv_disp_draw_buf_t disp_buf_1;
    static lv_color_t buf1_1[TFT_HOR_RES * TFT_VER_RES]  __attribute__((section(".lvgl_bss"), aligned(32)));
    static lv_color_t buf1_2[TFT_HOR_RES * TFT_VER_RES]  __attribute__((section(".lvgl_bss"), aligned(32)));
    lv_disp_draw_buf_init(&disp_buf_1, buf1_1, buf1_2, TFT_HOR_RES * TFT_VER_RES);   /*Initialize the display buffer*/


    /*-----------------------------------
    * Register the display in LittlevGL
    *----------------------------------*/

    lv_disp_drv_init(&disp_drv);                    /*Basic initialization*/

    /*Set up the functions to access to your display*/

    /*Set the resolution of the display*/
    disp_drv.hor_res = 480;
    disp_drv.ver_res = 272;

    /*Used to copy the buffer's content to the display*/
    disp_drv.flush_cb = ex_disp_flush;
    disp_drv.clean_dcache_cb = ex_disp_clean_dcache;

    /*Set a display buffer*/
    disp_drv.draw_buf = &disp_buf_1;


    /*Finally register the driver*/
    our_disp = lv_disp_drv_register(&disp_drv);
}


/**
 * @brief Configure LCD pins, and peripheral clocks.
 */
static void LCD_MspInit(void)
{
    GPIO_InitTypeDef gpio_init_structure;

    /* Enable the LTDC and DMA2D clocks */
    __HAL_RCC_LTDC_CLK_ENABLE();
    __HAL_RCC_DMA2D_CLK_ENABLE();
    /* Enable GPIOs clock */
    __HAL_RCC_GPIOE_CLK_ENABLE();
    __HAL_RCC_GPIOG_CLK_ENABLE();
    __HAL_RCC_GPIOI_CLK_ENABLE();
    __HAL_RCC_GPIOJ_CLK_ENABLE();
    __HAL_RCC_GPIOK_CLK_ENABLE();
    LCD_DISP_GPIO_CLK_ENABLE();
    LCD_BL_CTRL_GPIO_CLK_ENABLE();

    /*** LTDC Pins configuration ***/
    /* GPIOE configuration */
    gpio_init_structure.Pin       = GPIO_PIN_4;
    gpio_init_structure.Mode      = GPIO_MODE_AF_PP;
    gpio_init_structure.Pull      = GPIO_NOPULL;
    gpio_init_structure.Speed     = GPIO_SPEED_FAST;
    gpio_init_structure.Alternate = GPIO_AF14_LTDC;
    HAL_GPIO_Init(GPIOE, &gpio_init_structure);

    /* GPIOG configuration */
    gpio_init_structure.Pin       = GPIO_PIN_12;
    gpio_init_structure.Mode      = GPIO_MODE_AF_PP;
    gpio_init_structure.Alternate = GPIO_AF9_LTDC;
    HAL_GPIO_Init(GPIOG, &gpio_init_structure);

    /* GPIOI LTDC alternate configuration */
    gpio_init_structure.Pin       = GPIO_PIN_9 | GPIO_PIN_10 | \
            GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
    gpio_init_structure.Mode      = GPIO_MODE_AF_PP;
    gpio_init_structure.Alternate = GPIO_AF14_LTDC;
    HAL_GPIO_Init(GPIOI, &gpio_init_structure);

    /* GPIOJ configuration */
    gpio_init_structure.Pin       = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | \
            GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7 | \
            GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | \
            GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
    gpio_init_structure.Mode      = GPIO_MODE_AF_PP;
    gpio_init_structure.Alternate = GPIO_AF14_LTDC;
    HAL_GPIO_Init(GPIOJ, &gpio_init_structure);

    /* GPIOK configuration */
    gpio_init_structure.Pin       = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_4 | \
            GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7;
    gpio_init_structure.Mode      = GPIO_MODE_AF_PP;
    gpio_init_structure.Alternate = GPIO_AF14_LTDC;
    HAL_GPIO_Init(GPIOK, &gpio_init_structure);

    /* LCD_DISP GPIO configuration */
    gpio_init_structure.Pin       = LCD_DISP_PIN;     /* LCD_DISP pin has to be manually controlled */
    gpio_init_structure.Mode      = GPIO_MODE_OUTPUT_PP;
    HAL_GPIO_Init(LCD_DISP_GPIO_PORT, &gpio_init_structure);

    /* LCD_BL_CTRL GPIO configuration */
    gpio_init_structure.Pin       = LCD_BL_CTRL_PIN;  /* LCD_BL_CTRL pin has to be manually controlled */
    gpio_init_structure.Mode      = GPIO_MODE_OUTPUT_PP;
    HAL_GPIO_Init(LCD_BL_CTRL_GPIO_PORT, &gpio_init_structure);
}

/**
 * @brief Configure LTDC PLL.
 */
static void LCD_ClockConfig(void)
{
    static RCC_PeriphCLKInitTypeDef  periph_clk_init_struct;

    /* RK043FN48H LCD clock configuration */
    /* PLLSAI_VCO Input = HSE_VALUE/PLL_M = 1 Mhz */
    /* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN = 192 Mhz */
    /* PLLLCDCLK = PLLSAI_VCO Output/PLLSAIR = 192/5 = 38.4 Mhz */
    /* LTDC clock frequency = PLLLCDCLK / LTDC_PLLSAI_DIVR_4 = 38.4/4 = 9.6Mhz */
    periph_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_LTDC;
    periph_clk_init_struct.PLLSAI.PLLSAIN = 192;
    periph_clk_init_struct.PLLSAI.PLLSAIR = RK043FN48H_FREQUENCY_DIVIDER;
    periph_clk_init_struct.PLLSAIDivR = RCC_PLLSAIDIVR_4;
    HAL_RCCEx_PeriphCLKConfig(&periph_clk_init_struct);
}

/**
  * @brief  Initializes the LCD.
  * @retval LCD state
  */
static uint8_t LCD_Init(void)
{
    /* Select the used LCD */

    /* The RK043FN48H LCD 480x272 is selected */
    /* Timing Configuration */
    hLtdcHandler.Init.HorizontalSync = (RK043FN48H_HSYNC - 1);
    hLtdcHandler.Init.VerticalSync = (RK043FN48H_VSYNC - 1);
    hLtdcHandler.Init.AccumulatedHBP = (RK043FN48H_HSYNC + RK043FN48H_HBP - 1);
    hLtdcHandler.Init.AccumulatedVBP = (RK043FN48H_VSYNC + RK043FN48H_VBP - 1);
    hLtdcHandler.Init.AccumulatedActiveH = (RK043FN48H_HEIGHT + RK043FN48H_VSYNC + RK043FN48H_VBP - 1);
    hLtdcHandler.Init.AccumulatedActiveW = (RK043FN48H_WIDTH + RK043FN48H_HSYNC + RK043FN48H_HBP - 1);
    hLtdcHandler.Init.TotalHeigh = (RK043FN48H_HEIGHT + RK043FN48H_VSYNC + RK043FN48H_VBP + RK043FN48H_VFP - 1);
    hLtdcHandler.Init.TotalWidth = (RK043FN48H_WIDTH + RK043FN48H_HSYNC + RK043FN48H_HBP + RK043FN48H_HFP - 1);

    /* LCD clock configuration */
    LCD_ClockConfig();

    /* Initialize the LCD pixel width and pixel height */
    hLtdcHandler.LayerCfg->ImageWidth  = RK043FN48H_WIDTH;
    hLtdcHandler.LayerCfg->ImageHeight = RK043FN48H_HEIGHT;

    /* Background value */
    hLtdcHandler.Init.Backcolor.Blue = 0;
    hLtdcHandler.Init.Backcolor.Green = 0;
    hLtdcHandler.Init.Backcolor.Red = 0;

    /* Polarity */
    hLtdcHandler.Init.HSPolarity = LTDC_HSPOLARITY_AL;
    hLtdcHandler.Init.VSPolarity = LTDC_VSPOLARITY_AL;
    hLtdcHandler.Init.DEPolarity = LTDC_DEPOLARITY_AL;
    hLtdcHandler.Init.PCPolarity = LTDC_PCPOLARITY_IPC;
    hLtdcHandler.Instance = LTDC;

    if(HAL_LTDC_GetState(&hLtdcHandler) == HAL_LTDC_STATE_RESET)
    {
        /* Initialize the LCD Msp: this __weak function can be rewritten by the application */
        LCD_MspInit();
    }
    HAL_LTDC_Init(&hLtdcHandler);

    /* Assert display enable LCD_DISP pin */
    HAL_GPIO_WritePin(LCD_DISP_GPIO_PORT, LCD_DISP_PIN, GPIO_PIN_SET);

    /* Assert backlight LCD_BL_CTRL pin */
    HAL_GPIO_WritePin(LCD_BL_CTRL_GPIO_PORT, LCD_BL_CTRL_PIN, GPIO_PIN_SET);

    uint32_t i;
    for(i = 0; i < (TFT_HOR_RES * TFT_VER_RES) ; i++)
    {
        my_fb = 0;
    }

    return LCD_OK;
}

static void LCD_LayerRgb565Init(uint32_t FB_Address)
{
    LTDC_LayerCfgTypeDef  layer_cfg;

    /* Layer Init */
    layer_cfg.WindowX0 = 0;
    layer_cfg.WindowX1 = TFT_HOR_RES;
    layer_cfg.WindowY0 = 0;
    layer_cfg.WindowY1 = TFT_VER_RES;

#if LV_COLOR_DEPTH == 16
    layer_cfg.PixelFormat = LTDC_PIXEL_FORMAT_RGB565;
#elif LV_COLOR_DEPTH == 24 || LV_COLOR_DEPTH == 32
    layer_cfg.PixelFormat = LTDC_PIXEL_FORMAT_ARGB8888;
#else
#error Unsupported color depth (see tft.c)
#endif
    layer_cfg.FBStartAdress = FB_Address;
    layer_cfg.Alpha = 255;
    layer_cfg.Alpha0 = 0;
    layer_cfg.Backcolor.Blue = 0;
    layer_cfg.Backcolor.Green = 0;
    layer_cfg.Backcolor.Red = 0;
    layer_cfg.BlendingFactor1 = LTDC_BLENDING_FACTOR1_PAxCA;
    layer_cfg.BlendingFactor2 = LTDC_BLENDING_FACTOR2_PAxCA;
    layer_cfg.ImageWidth = TFT_HOR_RES;
    layer_cfg.ImageHeight = TFT_VER_RES;

    HAL_LTDC_ConfigLayer(&hLtdcHandler, &layer_cfg, 0);
}

static void LCD_DisplayOn(void)
{
    /* Display On */
    __HAL_LTDC_ENABLE(&hLtdcHandler);
    HAL_GPIO_WritePin(LCD_DISP_GPIO_PORT, LCD_DISP_PIN, GPIO_PIN_SET);        /* Assert LCD_DISP pin */
    HAL_GPIO_WritePin(LCD_BL_CTRL_GPIO_PORT, LCD_BL_CTRL_PIN, GPIO_PIN_SET);  /* Assert LCD_BL_CTRL pin */
}

static void DMA_Config(void)
{
    /*## -1- Enable DMA2 clock #################################################*/
    __HAL_RCC_DMA2_CLK_ENABLE();

    /*##-2- Select the DMA functional Parameters ###############################*/
    DmaHandle.Init.Channel = CPY_BUF_DMA_CHANNEL;                   /* DMA_CHANNEL_0                    */
    DmaHandle.Init.Direction = DMA_MEMORY_TO_MEMORY;                /* M2M transfer mode                */
    DmaHandle.Init.PeriphInc = DMA_PINC_ENABLE;                     /* Peripheral increment mode Enable */
    DmaHandle.Init.MemInc = DMA_MINC_ENABLE;                        /* Memory increment mode Enable     */
    DmaHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;   /* Peripheral data alignment : 16bit */
    DmaHandle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;      /* memory data alignment : 16bit     */
    DmaHandle.Init.Mode = DMA_NORMAL;                               /* Normal DMA mode                  */
    DmaHandle.Init.Priority = DMA_PRIORITY_HIGH;                    /* priority level : high            */
    DmaHandle.Init.FIFOMode = DMA_FIFOMODE_ENABLE;                  /* FIFO mode enabled                */
    DmaHandle.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_1QUARTERFULL; /* FIFO threshold: 1/4 full   */
    DmaHandle.Init.MemBurst = DMA_MBURST_SINGLE;                    /* Memory burst                     */
    DmaHandle.Init.PeriphBurst = DMA_PBURST_SINGLE;                 /* Peripheral burst                 */

    /*##-3- Select the DMA instance to be used for the transfer : DMA2_Stream0 #*/
    DmaHandle.Instance = CPY_BUF_DMA_STREAM;

    /*##-4- Initialize the DMA stream ##########################################*/
    if(HAL_DMA_Init(&DmaHandle) != HAL_OK)
    {
        while(1)
        {
        }
    }

    /*##-5- Select Callbacks functions called after Transfer complete and Transfer error */
    HAL_DMA_RegisterCallback(&DmaHandle, HAL_DMA_XFER_CPLT_CB_ID, DMA_TransferComplete);
    HAL_DMA_RegisterCallback(&DmaHandle, HAL_DMA_XFER_ERROR_CB_ID, DMA_TransferError);

    /*##-6- Configure NVIC for DMA transfer complete/error interrupts ##########*/
    NVIC_SetPriority(CPY_BUF_DMA_STREAM_IRQ, 7);
    NVIC_EnableIRQ(CPY_BUF_DMA_STREAM_IRQ);
}

```
###触摸功能
```
/**
 * Initialize your input devices here
 */
void touchpad_init(void)
{
    BSP_TS_Init(TFT_HOR_RES, TFT_VER_RES);

    static lv_indev_drv_t indev_drv;                       /*Descriptor of an input device driver*/
    lv_indev_drv_init(&indev_drv);                  /*Basic initialization*/
    indev_drv.type = LV_INDEV_TYPE_POINTER;         /*The touchpad is pointer type device*/
    indev_drv.read_cb = touchpad_read;

    lv_indev_drv_register(&indev_drv);
}

/**
 * Read an input device
 * @param indev_id id of the input device to read
 * @param x put the x coordinate here
 * @param y put the y coordinate here
 * @return true: the device is pressed, false: released
 */
static void touchpad_read(lv_indev_drv_t *indev, lv_indev_data_t *data)
{
    /* Read your touchpad */
    static int16_t last_x = 0;
    static int16_t last_y = 0;
    //BSP_LED_Toggle(LED1);

    BSP_TS_GetState(&TS_State);
    if(TS_State.touchDetected) {
            data->point.x = TS_State.touchX[0];
            data->point.y = TS_State.touchY[0];
            last_x = data->point.x;
            last_y = data->point.y;
            data->state = LV_INDEV_STATE_PRESSED;
    } else {
            data->point.x = last_x;
            data->point.y = last_y;
            data->state = LV_INDEV_STATE_RELEASED;
    }
}
```

####界面

```
void ui_init(void)
{
    lv_disp_t * dispp = lv_disp_get_default();
    lv_theme_t * theme = lv_theme_default_init(dispp, lv_palette_main(LV_PALETTE_BLUE), lv_palette_main(LV_PALETTE_RED),
                                               false, LV_FONT_DEFAULT);
    lv_disp_set_theme(dispp, theme);
    ui_Screen_1_Print_screen_init();
    ui_Screen_2_Move_screen_init();
    ui_Screen_3_Setting_screen_init();
    lv_disp_load_scr(ui_Screen_1_Print);
}

///////////////////// SCREENS ////////////////////
void ui_Screen_1_Print_screen_init(void)
{

    // ui_Screen_1_Print

    ui_Screen_1_Print = lv_obj_create(NULL);

    lv_obj_set_style_bg_color(ui_Screen_1_Print, lv_color_hex(0x191D26), LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_opa(ui_Screen_1_Print, 255, LV_PART_MAIN | LV_STATE_DEFAULT);

    // ui_Background

    ui_Background = lv_img_create(ui_Screen_1_Print);
    lv_img_set_src(ui_Background, &ui_img_3d_printer_bg_png);

    lv_obj_set_width(ui_Background, 480);
    lv_obj_set_height(ui_Background, 272);

    lv_obj_set_x(ui_Background, 0);
    lv_obj_set_y(ui_Background, 0);

    lv_obj_set_align(ui_Background, LV_ALIGN_CENTER);

    lv_obj_add_flag(ui_Background, LV_OBJ_FLAG_ADV_HITTEST);

    // ui_Panel_Header

    ui_Panel_Header = lv_obj_create(ui_Screen_1_Print);

    lv_obj_set_width(ui_Panel_Header, 400);
    lv_obj_set_height(ui_Panel_Header, 22);

    lv_obj_set_x(ui_Panel_Header, -18);
    lv_obj_set_y(ui_Panel_Header, 0);

    lv_obj_set_align(ui_Panel_Header, LV_ALIGN_TOP_RIGHT);

    lv_obj_clear_flag(ui_Panel_Header, LV_OBJ_FLAG_SCROLLABLE);

    lv_obj_set_style_bg_color(ui_Panel_Header, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_opa(ui_Panel_Header, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_main_stop(ui_Panel_Header, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_grad_stop(ui_Panel_Header, 255, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_border_width(ui_Panel_Header, 0, LV_PART_MAIN | LV_STATE_DEFAULT);

    // ui_Label_Header

    ui_Label_Header = lv_label_create(ui_Panel_Header);

    lv_obj_set_width(ui_Label_Header, LV_SIZE_CONTENT);
    lv_obj_set_height(ui_Label_Header, LV_SIZE_CONTENT);

    lv_obj_set_x(ui_Label_Header, 0);
    lv_obj_set_y(ui_Label_Header, 0);

    lv_obj_set_align(ui_Label_Header, LV_ALIGN_LEFT_MID);

    lv_label_set_text(ui_Label_Header, "The #ffffff squareline.gcode# word file is being printed");
    lv_label_set_recolor(ui_Label_Header, "true");

    lv_obj_set_style_text_color(ui_Label_Header, lv_color_hex(0x9098AA), LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_text_opa(ui_Label_Header, 255, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_text_font(ui_Label_Header, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT);

    // ui_IMG_Wifi

    ui_IMG_Wifi = lv_img_create(ui_Panel_Header);
    lv_img_set_src(ui_IMG_Wifi, &ui_img_icn_wifi_png);

    lv_obj_set_width(ui_IMG_Wifi, LV_SIZE_CONTENT);
    lv_obj_set_height(ui_IMG_Wifi, LV_SIZE_CONTENT);

    lv_obj_set_x(ui_IMG_Wifi, 0);
    lv_obj_set_y(ui_IMG_Wifi, 0);

    lv_obj_set_align(ui_IMG_Wifi, LV_ALIGN_RIGHT_MID);

    lv_obj_add_flag(ui_IMG_Wifi, LV_OBJ_FLAG_ADV_HITTEST);

    // ui_IMG_PC

    ui_IMG_PC = lv_img_create(ui_Panel_Header);
    lv_img_set_src(ui_IMG_PC, &ui_img_icn_pc_png);

    lv_obj_set_width(ui_IMG_PC, LV_SIZE_CONTENT);
    lv_obj_set_height(ui_IMG_PC, LV_SIZE_CONTENT);

    lv_obj_set_x(ui_IMG_PC, -25);
    lv_obj_set_y(ui_IMG_PC, 0);

    lv_obj_set_align(ui_IMG_PC, LV_ALIGN_RIGHT_MID);

    lv_obj_add_flag(ui_IMG_PC, LV_OBJ_FLAG_ADV_HITTEST);

    // ui_IMG_USB

    ui_IMG_USB = lv_img_create(ui_Panel_Header);
    lv_img_set_src(ui_IMG_USB, &ui_img_icn_usb_png);

    lv_obj_set_width(ui_IMG_USB, LV_SIZE_CONTENT);
    lv_obj_set_height(ui_IMG_USB, LV_SIZE_CONTENT);

    lv_obj_set_x(ui_IMG_USB, -50);
    lv_obj_set_y(ui_IMG_USB, 0);

    lv_obj_set_align(ui_IMG_USB, LV_ALIGN_RIGHT_MID);

    lv_obj_add_flag(ui_IMG_USB, LV_OBJ_FLAG_ADV_HITTEST);

    // ui_BTN_Menu_Print_S1

    ui_BTN_Menu_Print_S1 = lv_img_create(ui_Screen_1_Print);
    lv_img_set_src(ui_BTN_Menu_Print_S1, &ui_img_btn_print_png);

    lv_obj_set_width(ui_BTN_Menu_Print_S1, 47);
    lv_obj_set_height(ui_BTN_Menu_Print_S1, 91);

    lv_obj_set_x(ui_BTN_Menu_Print_S1, 0);
    lv_obj_set_y(ui_BTN_Menu_Print_S1, 0);

    lv_obj_add_flag(ui_BTN_Menu_Print_S1, LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_ADV_HITTEST);
    lv_obj_clear_flag(ui_BTN_Menu_Print_S1, LV_OBJ_FLAG_SCROLLABLE);

    // ui_BTN_Menu_Move_S1

    ui_BTN_Menu_Move_S1 = lv_img_create(ui_Screen_1_Print);
    lv_img_set_src(ui_BTN_Menu_Move_S1, &ui_img_btn_move_png);

    lv_obj_set_width(ui_BTN_Menu_Move_S1, 47);
    lv_obj_set_height(ui_BTN_Menu_Move_S1, 91);

    lv_obj_set_x(ui_BTN_Menu_Move_S1, 0);
    lv_obj_set_y(ui_BTN_Menu_Move_S1, 0);

    lv_obj_set_align(ui_BTN_Menu_Move_S1, LV_ALIGN_LEFT_MID);

    lv_obj_add_flag(ui_BTN_Menu_Move_S1, LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_ADV_HITTEST);
    lv_obj_clear_flag(ui_BTN_Menu_Move_S1, LV_OBJ_FLAG_SCROLLABLE);

    lv_obj_add_event_cb(ui_BTN_Menu_Move_S1, ui_event_BTN_Menu_Move_S1, LV_EVENT_ALL, NULL);
    lv_obj_set_style_opa(ui_BTN_Menu_Move_S1, 0, LV_PART_MAIN | LV_STATE_DEFAULT);

    // ui_BTN_Menu_Setting_S1

    ui_BTN_Menu_Setting_S1 = lv_img_create(ui_Screen_1_Print);
    lv_img_set_src(ui_BTN_Menu_Setting_S1, &ui_img_btn_setting_png);

    lv_obj_set_width(ui_BTN_Menu_Setting_S1, 47);
    lv_obj_set_height(ui_BTN_Menu_Setting_S1, 90);

    lv_obj_set_x(ui_BTN_Menu_Setting_S1, 0);
    lv_obj_set_y(ui_BTN_Menu_Setting_S1, 0);

    lv_obj_set_align(ui_BTN_Menu_Setting_S1, LV_ALIGN_BOTTOM_LEFT);

    lv_obj_add_flag(ui_BTN_Menu_Setting_S1, LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_ADV_HITTEST);
    lv_obj_clear_flag(ui_BTN_Menu_Setting_S1, LV_OBJ_FLAG_SCROLLABLE);

    lv_obj_add_event_cb(ui_BTN_Menu_Setting_S1, ui_event_BTN_Menu_Setting_S1, LV_EVENT_ALL, NULL);
    lv_obj_set_style_opa(ui_BTN_Menu_Setting_S1, 0, LV_PART_MAIN | LV_STATE_DEFAULT);

    // ui_S1_Content_Panel

    ui_S1_Content_Panel = lv_obj_create(ui_Screen_1_Print);

    lv_obj_set_width(ui_S1_Content_Panel, 432);
    lv_obj_set_height(ui_S1_Content_Panel, 245);

    lv_obj_set_x(ui_S1_Content_Panel, 0);
    lv_obj_set_y(ui_S1_Content_Panel, 0);

    lv_obj_set_align(ui_S1_Content_Panel, LV_ALIGN_BOTTOM_RIGHT);

    lv_obj_clear_flag(ui_S1_Content_Panel, LV_OBJ_FLAG_SCROLLABLE);

    lv_obj_set_style_bg_color(ui_S1_Content_Panel, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_opa(ui_S1_Content_Panel, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_main_stop(ui_S1_Content_Panel, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_grad_stop(ui_S1_Content_Panel, 255, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_border_width(ui_S1_Content_Panel, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_pad_left(ui_S1_Content_Panel, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_pad_right(ui_S1_Content_Panel, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_pad_top(ui_S1_Content_Panel, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_pad_bottom(ui_S1_Content_Panel, 0, LV_PART_MAIN | LV_STATE_DEFAULT);

    // ui_Slider_Print_View

    ui_Slider_Print_View = lv_slider_create(ui_S1_Content_Panel);
    lv_slider_set_range(ui_Slider_Print_View, 0, 100);
    lv_slider_set_value(ui_Slider_Print_View, 70, LV_ANIM_OFF);
    if(lv_slider_get_mode(ui_Slider_Print_View) == LV_SLIDER_MODE_RANGE) lv_slider_set_left_value(ui_Slider_Print_View, 0,
                                                                                                      LV_ANIM_OFF);

    lv_obj_set_width(ui_Slider_Print_View, 199);
    lv_obj_set_height(ui_Slider_Print_View, 225);

    lv_obj_set_x(ui_Slider_Print_View, 0);
    lv_obj_set_y(ui_Slider_Print_View, -6);

    lv_obj_set_align(ui_Slider_Print_View, LV_ALIGN_LEFT_MID);

    lv_obj_add_event_cb(ui_Slider_Print_View, ui_event_Slider_Print_View, LV_EVENT_ALL, NULL);
    lv_obj_set_style_radius(ui_Slider_Print_View, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_color(ui_Slider_Print_View, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_opa(ui_Slider_Print_View, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_main_stop(ui_Slider_Print_View, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_grad_stop(ui_Slider_Print_View, 255, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_img_src(ui_Slider_Print_View, &ui_img_print_view_bg_png, LV_PART_MAIN | LV_STATE_DEFAULT);

    lv_obj_set_style_radius(ui_Slider_Print_View, 0, LV_PART_INDICATOR | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_color(ui_Slider_Print_View, lv_color_hex(0xFFFFFF), LV_PART_INDICATOR | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_opa(ui_Slider_Print_View, 0, LV_PART_INDICATOR | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_main_stop(ui_Slider_Print_View, 0, LV_PART_INDICATOR | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_grad_stop(ui_Slider_Print_View, 255, LV_PART_INDICATOR | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_img_src(ui_Slider_Print_View, &ui_img_print_view_front_png, LV_PART_INDICATOR | LV_STATE_DEFAULT);

    lv_obj_set_style_bg_color(ui_Slider_Print_View, lv_color_hex(0xFFFFFF), LV_PART_KNOB | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_opa(ui_Slider_Print_View, 0, LV_PART_KNOB | LV_STATE_DEFAULT);

    // ui_Number_Print

    ui_Number_Print = lv_label_create(ui_Slider_Print_View);

    lv_obj_set_width(ui_Number_Print, LV_SIZE_CONTENT);
    lv_obj_set_height(ui_Number_Print, LV_SIZE_CONTENT);

    lv_obj_set_x(ui_Number_Print, 0);
    lv_obj_set_y(ui_Number_Print, -20);

    lv_obj_set_align(ui_Number_Print, LV_ALIGN_BOTTOM_MID);

    lv_label_set_text(ui_Number_Print, "70%");

    lv_obj_set_style_text_color(ui_Number_Print, lv_color_hex(0x00D2FF), LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_text_opa(ui_Number_Print, 255, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_text_font(ui_Number_Print, &lv_font_montserrat_16, LV_PART_MAIN | LV_STATE_DEFAULT);

    // ui_Display_Time_S1

    ui_Display_Time_S1 = lv_obj_create(ui_S1_Content_Panel);

    lv_obj_set_width(ui_Display_Time_S1, 210);
    lv_obj_set_height(ui_Display_Time_S1, 45);

    lv_obj_set_x(ui_Display_Time_S1, -16);
    lv_obj_set_y(ui_Display_Time_S1, 17);

    lv_obj_set_align(ui_Display_Time_S1, LV_ALIGN_TOP_RIGHT);

    lv_obj_clear_flag(ui_Display_Time_S1, LV_OBJ_FLAG_SCROLLABLE);

    lv_obj_set_style_bg_color(ui_Display_Time_S1, lv_color_hex(0x191D26), LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_opa(ui_Display_Time_S1, 255, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_main_stop(ui_Display_Time_S1, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_grad_stop(ui_Display_Time_S1, 255, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_border_width(ui_Display_Time_S1, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_outline_color(ui_Display_Time_S1, lv_color_hex(0x414B62), LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_outline_opa(ui_Display_Time_S1, 100, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_outline_width(ui_Display_Time_S1, 4, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_outline_pad(ui_Display_Time_S1, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_pad_left(ui_Display_Time_S1, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_pad_right(ui_Display_Time_S1, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_pad_top(ui_Display_Time_S1, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_pad_bottom(ui_Display_Time_S1, 0, LV_PART_MAIN | LV_STATE_DEFAULT);

    // ui_DT1

    ui_DT1 = lv_obj_create(ui_Display_Time_S1);

    lv_obj_set_width(ui_DT1, lv_pct(50));
    lv_obj_set_height(ui_DT1, lv_pct(100));

    lv_obj_set_x(ui_DT1, 0);
    lv_obj_set_y(ui_DT1, 0);

    lv_obj_set_align(ui_DT1, LV_ALIGN_LEFT_MID);

    lv_obj_clear_flag(ui_DT1, LV_OBJ_FLAG_SCROLLABLE);

    lv_obj_set_style_bg_color(ui_DT1, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_opa(ui_DT1, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_main_stop(ui_DT1, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_grad_stop(ui_DT1, 255, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_border_width(ui_DT1, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_pad_left(ui_DT1, 6, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_pad_right(ui_DT1, 6, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_pad_top(ui_DT1, 12, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_pad_bottom(ui_DT1, 12, LV_PART_MAIN | LV_STATE_DEFAULT);

    // ui_Label_Printing_Time_1

    ui_Label_Printing_Time_1 = lv_label_create(ui_DT1);

    lv_obj_set_width(ui_Label_Printing_Time_1, LV_SIZE_CONTENT);
    lv_obj_set_height(ui_Label_Printing_Time_1, LV_SIZE_CONTENT);

    lv_obj_set_x(ui_Label_Printing_Time_1, 0);
    lv_obj_set_y(ui_Label_Printing_Time_1, -7);

    lv_obj_set_align(ui_Label_Printing_Time_1, LV_ALIGN_TOP_MID);

    lv_label_set_text(ui_Label_Printing_Time_1, "Printing Time");
    lv_label_set_recolor(ui_Label_Printing_Time_1, "true");

    lv_obj_set_style_text_color(ui_Label_Printing_Time_1, lv_color_hex(0x9098AA), LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_text_opa(ui_Label_Printing_Time_1, 255, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_text_font(ui_Label_Printing_Time_1, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT);

    // ui_IMG_Tine_1

    ui_IMG_Tine_1 = lv_img_create(ui_DT1);
    lv_img_set_src(ui_IMG_Tine_1, &ui_img_icn_time_1_png);

    lv_obj_set_width(ui_IMG_Tine_1, LV_SIZE_CONTENT);
    lv_obj_set_height(ui_IMG_Tine_1, LV_SIZE_CONTENT);

    lv_obj_set_x(ui_IMG_Tine_1, 5);
    lv_obj_set_y(ui_IMG_Tine_1, 6);

    lv_obj_set_align(ui_IMG_Tine_1, LV_ALIGN_LEFT_MID);

    lv_obj_add_flag(ui_IMG_Tine_1, LV_OBJ_FLAG_ADV_HITTEST);

    // ui_Label_Time_1

    ui_Label_Time_1 = lv_label_create(ui_DT1);

    lv_obj_set_width(ui_Label_Time_1, LV_SIZE_CONTENT);
    lv_obj_set_height(ui_Label_Time_1, LV_SIZE_CONTENT);

    lv_obj_set_x(ui_Label_Time_1, 35);
    lv_obj_set_y(ui_Label_Time_1, 7);

    lv_obj_set_align(ui_Label_Time_1, LV_ALIGN_LEFT_MID);

    lv_label_set_text(ui_Label_Time_1, "10:52");

    lv_obj_set_style_text_color(ui_Label_Time_1, lv_color_hex(0xDBE6FF), LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_text_opa(ui_Label_Time_1, 255, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_text_font(ui_Label_Time_1, &lv_font_montserrat_16, LV_PART_MAIN | LV_STATE_DEFAULT);

    // ui_Panel3

    ui_Panel3 = lv_obj_create(ui_Display_Time_S1);

    lv_obj_set_width(ui_Panel3, 2);
    lv_obj_set_height(ui_Panel3, 28);

    lv_obj_set_x(ui_Panel3, 0);
    lv_obj_set_y(ui_Panel3, 0);

    lv_obj_set_align(ui_Panel3, LV_ALIGN_CENTER);

    lv_obj_set_style_bg_color(ui_Panel3, lv_color_hex(0x3A3F4B), LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_opa(ui_Panel3, 255, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_main_stop(ui_Panel3, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_grad_stop(ui_Panel3, 255, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_border_width(ui_Panel3, 0, LV_PART_MAIN | LV_STATE_DEFAULT);

    // ui_DT2

    ui_DT2 = lv_obj_create(ui_Display_Time_S1);

    lv_obj_set_width(ui_DT2, lv_pct(50));
    lv_obj_set_height(ui_DT2, lv_pct(100));

    lv_obj_set_x(ui_DT2, 0);
    lv_obj_set_y(ui_DT2, 0);

    lv_obj_set_align(ui_DT2, LV_ALIGN_RIGHT_MID);

    lv_obj_clear_flag(ui_DT2, LV_OBJ_FLAG_SCROLLABLE);

    lv_obj_set_style_bg_color(ui_DT2, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_opa(ui_DT2, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_main_stop(ui_DT2, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_grad_stop(ui_DT2, 255, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_border_width(ui_DT2, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_pad_left(ui_DT2, 6, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_pad_right(ui_DT2, 6, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_pad_top(ui_DT2, 12, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_pad_bottom(ui_DT2, 12, LV_PART_MAIN | LV_STATE_DEFAULT);

    // ui_Label_Printing_Time_2

    ui_Label_Printing_Time_2 = lv_label_create(ui_DT2);

    lv_obj_set_width(ui_Label_Printing_Time_2, LV_SIZE_CONTENT);
    lv_obj_set_height(ui_Label_Printing_Time_2, LV_SIZE_CONTENT);

    lv_obj_set_x(ui_Label_Printing_Time_2, 0);
    lv_obj_set_y(ui_Label_Printing_Time_2, -6);

    lv_obj_set_align(ui_Label_Printing_Time_2, LV_ALIGN_TOP_MID);

    lv_label_set_text(ui_Label_Printing_Time_2, "Printing Time");
    lv_label_set_recolor(ui_Label_Printing_Time_2, "true");

    lv_obj_set_style_text_color(ui_Label_Printing_Time_2, lv_color_hex(0x9098AA), LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_text_opa(ui_Label_Printing_Time_2, 255, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_text_font(ui_Label_Printing_Time_2, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT);

    // ui_IMG_Tine_2

    ui_IMG_Tine_2 = lv_img_create(ui_DT2);
    lv_img_set_src(ui_IMG_Tine_2, &ui_img_icn_time_2_png);

    lv_obj_set_width(ui_IMG_Tine_2, LV_SIZE_CONTENT);
    lv_obj_set_height(ui_IMG_Tine_2, LV_SIZE_CONTENT);

    lv_obj_set_x(ui_IMG_Tine_2, 11);
    lv_obj_set_y(ui_IMG_Tine_2, 7);

    lv_obj_set_align(ui_IMG_Tine_2, LV_ALIGN_LEFT_MID);

    lv_obj_add_flag(ui_IMG_Tine_2, LV_OBJ_FLAG_ADV_HITTEST);

    // ui_Label_Time_2

    ui_Label_Time_2 = lv_label_create(ui_DT2);

    lv_obj_set_width(ui_Label_Time_2, LV_SIZE_CONTENT);
    lv_obj_set_height(ui_Label_Time_2, LV_SIZE_CONTENT);

    lv_obj_set_x(ui_Label_Time_2, 36);
    lv_obj_set_y(ui_Label_Time_2, 8);

    lv_obj_set_align(ui_Label_Time_2, LV_ALIGN_LEFT_MID);

    lv_label_set_text(ui_Label_Time_2, "08:25");

    lv_obj_set_style_text_color(ui_Label_Time_2, lv_color_hex(0xDBE6FF), LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_text_opa(ui_Label_Time_2, 255, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_text_font(ui_Label_Time_2, &lv_font_montserrat_16, LV_PART_MAIN | LV_STATE_DEFAULT);

    // ui_Display_Heat_S1

    ui_Display_Heat_S1 = lv_obj_create(ui_S1_Content_Panel);

    lv_obj_set_width(ui_Display_Heat_S1, 210);
    lv_obj_set_height(ui_Display_Heat_S1, 45);

    lv_obj_set_x(ui_Display_Heat_S1, -16);
    lv_obj_set_y(ui_Display_Heat_S1, 74);

    lv_obj_set_align(ui_Display_Heat_S1, LV_ALIGN_TOP_RIGHT);

    lv_obj_clear_flag(ui_Display_Heat_S1, LV_OBJ_FLAG_SCROLLABLE);

    lv_obj_set_style_bg_color(ui_Display_Heat_S1, lv_color_hex(0x191D26), LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_opa(ui_Display_Heat_S1, 255, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_main_stop(ui_Display_Heat_S1, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_grad_stop(ui_Display_Heat_S1, 255, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_border_width(ui_Display_Heat_S1, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_outline_color(ui_Display_Heat_S1, lv_color_hex(0x414B62), LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_outline_opa(ui_Display_Heat_S1, 100, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_outline_width(ui_Display_Heat_S1, 4, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_outline_pad(ui_Display_Heat_S1, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_pad_left(ui_Display_Heat_S1, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_pad_right(ui_Display_Heat_S1, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_pad_top(ui_Display_Heat_S1, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_pad_bottom(ui_Display_Heat_S1, 0, LV_PART_MAIN | LV_STATE_DEFAULT);

    // ui_DT3

    ui_DT3 = lv_obj_create(ui_Display_Heat_S1);

    lv_obj_set_width(ui_DT3, lv_pct(50));
    lv_obj_set_height(ui_DT3, lv_pct(100));

    lv_obj_set_x(ui_DT3, 0);
    lv_obj_set_y(ui_DT3, 0);

    lv_obj_set_align(ui_DT3, LV_ALIGN_LEFT_MID);

    lv_obj_clear_flag(ui_DT3, LV_OBJ_FLAG_SCROLLABLE);

    lv_obj_set_style_bg_color(ui_DT3, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_opa(ui_DT3, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_main_stop(ui_DT3, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_grad_stop(ui_DT3, 255, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_border_width(ui_DT3, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_pad_left(ui_DT3, 6, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_pad_right(ui_DT3, 6, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_pad_top(ui_DT3, 12, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_pad_bottom(ui_DT3, 12, LV_PART_MAIN | LV_STATE_DEFAULT);

    // ui_Label_Printing_Head_Temp

    ui_Label_Printing_Head_Temp = lv_label_create(ui_DT3);

    lv_obj_set_width(ui_Label_Printing_Head_Temp, LV_SIZE_CONTENT);
    lv_obj_set_height(ui_Label_Printing_Head_Temp, LV_SIZE_CONTENT);

    lv_obj_set_x(ui_Label_Printing_Head_Temp, 0);
    lv_obj_set_y(ui_Label_Printing_Head_Temp, -6);

    lv_obj_set_align(ui_Label_Printing_Head_Temp, LV_ALIGN_TOP_MID);

    lv_label_set_text(ui_Label_Printing_Head_Temp, "Head Temp.");
    lv_label_set_recolor(ui_Label_Printing_Head_Temp, "true");

    lv_obj_set_style_text_color(ui_Label_Printing_Head_Temp, lv_color_hex(0x9098AA), LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_text_opa(ui_Label_Printing_Head_Temp, 255, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_text_font(ui_Label_Printing_Head_Temp, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT);

    // ui_IMG_Head

    ui_IMG_Head = lv_img_create(ui_DT3);
    lv_img_set_src(ui_IMG_Head, &ui_img_icn_head_png);

    lv_obj_set_width(ui_IMG_Head, LV_SIZE_CONTENT);
    lv_obj_set_height(ui_IMG_Head, LV_SIZE_CONTENT);

    lv_obj_set_x(ui_IMG_Head, 7);
    lv_obj_set_y(ui_IMG_Head, 9);

    lv_obj_set_align(ui_IMG_Head, LV_ALIGN_LEFT_MID);

    lv_obj_add_flag(ui_IMG_Head, LV_OBJ_FLAG_ADV_HITTEST);

    // ui_Label_Head_Temp

    ui_Label_Head_Temp = lv_label_create(ui_DT3);

    lv_obj_set_width(ui_Label_Head_Temp, LV_SIZE_CONTENT);
    lv_obj_set_height(ui_Label_Head_Temp, LV_SIZE_CONTENT);

    lv_obj_set_x(ui_Label_Head_Temp, 22);
    lv_obj_set_y(ui_Label_Head_Temp, 7);

    lv_obj_set_align(ui_Label_Head_Temp, LV_ALIGN_LEFT_MID);

    lv_label_set_text(ui_Label_Head_Temp, "195°");

    lv_obj_set_style_text_color(ui_Label_Head_Temp, lv_color_hex(0xDBE6FF), LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_text_opa(ui_Label_Head_Temp, 255, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_text_font(ui_Label_Head_Temp, &lv_font_montserrat_16, LV_PART_MAIN | LV_STATE_DEFAULT);

    // ui_Label_Printing_Head_Temp_2

    ui_Label_Printing_Head_Temp_2 = lv_label_create(ui_DT3);

    lv_obj_set_width(ui_Label_Printing_Head_Temp_2, LV_SIZE_CONTENT);
    lv_obj_set_height(ui_Label_Printing_Head_Temp_2, LV_SIZE_CONTENT);

    lv_obj_set_x(ui_Label_Printing_Head_Temp_2, 55);
    lv_obj_set_y(ui_Label_Printing_Head_Temp_2, 7);

    lv_obj_set_align(ui_Label_Printing_Head_Temp_2, LV_ALIGN_LEFT_MID);

    lv_label_set_text(ui_Label_Printing_Head_Temp_2, "/ 195°");
    lv_label_set_recolor(ui_Label_Printing_Head_Temp_2, "true");

    lv_obj_set_style_text_color(ui_Label_Printing_Head_Temp_2, lv_color_hex(0x9098AA), LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_text_opa(ui_Label_Printing_Head_Temp_2, 255, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_text_font(ui_Label_Printing_Head_Temp_2, &ui_font_Small_Font, LV_PART_MAIN | LV_STATE_DEFAULT);

    // ui_Panel1

    ui_Panel1 = lv_obj_create(ui_Display_Heat_S1);

    lv_obj_set_width(ui_Panel1, 2);
    lv_obj_set_height(ui_Panel1, 28);

    lv_obj_set_x(ui_Panel1, 0);
    lv_obj_set_y(ui_Panel1, 0);

    lv_obj_set_align(ui_Panel1, LV_ALIGN_CENTER);

    lv_obj_set_style_bg_color(ui_Panel1, lv_color_hex(0x3A3F4B), LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_opa(ui_Panel1, 255, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_main_stop(ui_Panel1, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_grad_stop(ui_Panel1, 255, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_border_width(ui_Panel1, 0, LV_PART_MAIN | LV_STATE_DEFAULT);

    // ui_DT3_copy

    ui_DT3_copy = lv_obj_create(ui_Display_Heat_S1);

    lv_obj_set_width(ui_DT3_copy, lv_pct(50));
    lv_obj_set_height(ui_DT3_copy, lv_pct(100));

    lv_obj_set_x(ui_DT3_copy, 0);
    lv_obj_set_y(ui_DT3_copy, 0);

    lv_obj_set_align(ui_DT3_copy, LV_ALIGN_RIGHT_MID);

    lv_obj_clear_flag(ui_DT3_copy, LV_OBJ_FLAG_SCROLLABLE);

    lv_obj_set_style_bg_color(ui_DT3_copy, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_opa(ui_DT3_copy, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_main_stop(ui_DT3_copy, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_grad_stop(ui_DT3_copy, 255, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_border_width(ui_DT3_copy, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_pad_left(ui_DT3_copy, 6, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_pad_right(ui_DT3_copy, 6, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_pad_top(ui_DT3_copy, 12, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_pad_bottom(ui_DT3_copy, 12, LV_PART_MAIN | LV_STATE_DEFAULT);

    // ui_Label_Printing_Bed_Temp

    ui_Label_Printing_Bed_Temp = lv_label_create(ui_DT3_copy);

    lv_obj_set_width(ui_Label_Printing_Bed_Temp, LV_SIZE_CONTENT);
    lv_obj_set_height(ui_Label_Printing_Bed_Temp, LV_SIZE_CONTENT);

    lv_obj_set_x(ui_Label_Printing_Bed_Temp, 0);
    lv_obj_set_y(ui_Label_Printing_Bed_Temp, -5);

    lv_obj_set_align(ui_Label_Printing_Bed_Temp, LV_ALIGN_TOP_MID);

    lv_label_set_text(ui_Label_Printing_Bed_Temp, "Bed Temp.");
    lv_label_set_recolor(ui_Label_Printing_Bed_Temp, "true");

    lv_obj_set_style_text_color(ui_Label_Printing_Bed_Temp, lv_color_hex(0x9098AA), LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_text_opa(ui_Label_Printing_Bed_Temp, 255, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_text_font(ui_Label_Printing_Bed_Temp, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT);

    // ui_IMG_Head1

    ui_IMG_Head1 = lv_img_create(ui_DT3_copy);
    lv_img_set_src(ui_IMG_Head1, &ui_img_icn_bed_png);

    lv_obj_set_width(ui_IMG_Head1, LV_SIZE_CONTENT);
    lv_obj_set_height(ui_IMG_Head1, LV_SIZE_CONTENT);

    lv_obj_set_x(ui_IMG_Head1, 10);
    lv_obj_set_y(ui_IMG_Head1, 10);

    lv_obj_set_align(ui_IMG_Head1, LV_ALIGN_LEFT_MID);

    lv_obj_add_flag(ui_IMG_Head1, LV_OBJ_FLAG_ADV_HITTEST);

    // ui_Label_Bed_Temp

    ui_Label_Bed_Temp = lv_label_create(ui_DT3_copy);

    lv_obj_set_width(ui_Label_Bed_Temp, LV_SIZE_CONTENT);
    lv_obj_set_height(ui_Label_Bed_Temp, LV_SIZE_CONTENT);

    lv_obj_set_x(ui_Label_Bed_Temp, 32);
    lv_obj_set_y(ui_Label_Bed_Temp, 7);

    lv_obj_set_align(ui_Label_Bed_Temp, LV_ALIGN_LEFT_MID);

    lv_label_set_text(ui_Label_Bed_Temp, "65°");

    lv_obj_set_style_text_color(ui_Label_Bed_Temp, lv_color_hex(0xDBE6FF), LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_text_opa(ui_Label_Bed_Temp, 255, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_text_font(ui_Label_Bed_Temp, &lv_font_montserrat_16, LV_PART_MAIN | LV_STATE_DEFAULT);

    // ui_Label_Printing_Bed_Temp1

    ui_Label_Printing_Bed_Temp1 = lv_label_create(ui_DT3_copy);

    lv_obj_set_width(ui_Label_Printing_Bed_Temp1, LV_SIZE_CONTENT);
    lv_obj_set_height(ui_Label_Printing_Bed_Temp1, LV_SIZE_CONTENT);

    lv_obj_set_x(ui_Label_Printing_Bed_Temp1, 59);
    lv_obj_set_y(ui_Label_Printing_Bed_Temp1, 7);

    lv_obj_set_align(ui_Label_Printing_Bed_Temp1, LV_ALIGN_LEFT_MID);

    lv_label_set_text(ui_Label_Printing_Bed_Temp1, "/ 65°");
    lv_label_set_recolor(ui_Label_Printing_Bed_Temp1, "true");

    lv_obj_set_style_text_color(ui_Label_Printing_Bed_Temp1, lv_color_hex(0x9098AA), LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_text_opa(ui_Label_Printing_Bed_Temp1, 255, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_text_font(ui_Label_Printing_Bed_Temp1, &ui_font_Small_Font, LV_PART_MAIN | LV_STATE_DEFAULT);

    // ui_Panel_Buttons_S1

    ui_Panel_Buttons_S1 = lv_obj_create(ui_S1_Content_Panel);

    lv_obj_set_width(ui_Panel_Buttons_S1, 228);
    lv_obj_set_height(ui_Panel_Buttons_S1, 114);

    lv_obj_set_x(ui_Panel_Buttons_S1, 0);
    lv_obj_set_y(ui_Panel_Buttons_S1, 0);

    lv_obj_set_align(ui_Panel_Buttons_S1, LV_ALIGN_BOTTOM_RIGHT);

    lv_obj_clear_flag(ui_Panel_Buttons_S1, LV_OBJ_FLAG_SCROLLABLE);

    lv_obj_set_style_bg_color(ui_Panel_Buttons_S1, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_opa(ui_Panel_Buttons_S1, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_main_stop(ui_Panel_Buttons_S1, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_grad_stop(ui_Panel_Buttons_S1, 255, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_border_width(ui_Panel_Buttons_S1, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_pad_left(ui_Panel_Buttons_S1, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_pad_right(ui_Panel_Buttons_S1, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_pad_top(ui_Panel_Buttons_S1, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_pad_bottom(ui_Panel_Buttons_S1, 0, LV_PART_MAIN | LV_STATE_DEFAULT);

    // ui_BTN_Pause

    ui_BTN_Pause = lv_img_create(ui_Panel_Buttons_S1);
    lv_img_set_src(ui_BTN_Pause, &ui_img_btn_print_down_png);

    lv_obj_set_width(ui_BTN_Pause, LV_SIZE_CONTENT);
    lv_obj_set_height(ui_BTN_Pause, LV_SIZE_CONTENT);

    lv_obj_set_x(ui_BTN_Pause, 10);
    lv_obj_set_y(ui_BTN_Pause, 0);

    lv_obj_set_align(ui_BTN_Pause, LV_ALIGN_LEFT_MID);

    lv_obj_add_flag(ui_BTN_Pause, LV_OBJ_FLAG_ADV_HITTEST);

    // ui_BTN_Pause_Top

    ui_BTN_Pause_Top = lv_img_create(ui_BTN_Pause);
    lv_img_set_src(ui_BTN_Pause_Top, &ui_img_btn_print_top_off_png);

    lv_obj_set_width(ui_BTN_Pause_Top, LV_SIZE_CONTENT);
    lv_obj_set_height(ui_BTN_Pause_Top, LV_SIZE_CONTENT);

    lv_obj_set_x(ui_BTN_Pause_Top, 0);
    lv_obj_set_y(ui_BTN_Pause_Top, 0);

    lv_obj_set_align(ui_BTN_Pause_Top, LV_ALIGN_CENTER);

    lv_obj_add_flag(ui_BTN_Pause_Top, LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_CHECKABLE | LV_OBJ_FLAG_ADV_HITTEST);

    lv_obj_set_style_radius(ui_BTN_Pause_Top, 18, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_main_stop(ui_BTN_Pause_Top, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_grad_stop(ui_BTN_Pause_Top, 255, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_shadow_color(ui_BTN_Pause_Top, lv_color_hex(0x00D2FF), LV_PART_MAIN | LV_STATE_CHECKED);
    lv_obj_set_style_shadow_opa(ui_BTN_Pause_Top, 255, LV_PART_MAIN | LV_STATE_CHECKED);
    lv_obj_set_style_shadow_width(ui_BTN_Pause_Top, 12, LV_PART_MAIN | LV_STATE_CHECKED);
    lv_obj_set_style_shadow_spread(ui_BTN_Pause_Top, 5, LV_PART_MAIN | LV_STATE_CHECKED);
    lv_obj_set_style_shadow_ofs_x(ui_BTN_Pause_Top, 0, LV_PART_MAIN | LV_STATE_CHECKED);
    lv_obj_set_style_shadow_ofs_y(ui_BTN_Pause_Top, 0, LV_PART_MAIN | LV_STATE_CHECKED);
    lv_obj_set_style_shadow_color(ui_BTN_Pause_Top, lv_color_hex(0x00D2FF), LV_PART_MAIN | LV_STATE_PRESSED);
    lv_obj_set_style_shadow_opa(ui_BTN_Pause_Top, 255, LV_PART_MAIN | LV_STATE_PRESSED);
    lv_obj_set_style_shadow_width(ui_BTN_Pause_Top, 10, LV_PART_MAIN | LV_STATE_PRESSED);
    lv_obj_set_style_shadow_spread(ui_BTN_Pause_Top, 5, LV_PART_MAIN | LV_STATE_PRESSED);
    lv_obj_set_style_shadow_ofs_x(ui_BTN_Pause_Top, 0, LV_PART_MAIN | LV_STATE_PRESSED);
    lv_obj_set_style_shadow_ofs_y(ui_BTN_Pause_Top, 0, LV_PART_MAIN | LV_STATE_PRESSED);
    lv_obj_set_style_img_recolor(ui_BTN_Pause_Top, lv_color_hex(0x67799B), LV_PART_MAIN | LV_STATE_PRESSED);
    lv_obj_set_style_img_recolor_opa(ui_BTN_Pause_Top, 255, LV_PART_MAIN | LV_STATE_PRESSED);

    // ui_Image_Pause

    ui_Image_Pause = lv_img_create(ui_BTN_Pause_Top);
    lv_img_set_src(ui_Image_Pause, &ui_img_icn_pause_png);

    lv_obj_set_width(ui_Image_Pause, LV_SIZE_CONTENT);
    lv_obj_set_height(ui_Image_Pause, LV_SIZE_CONTENT);

    lv_obj_set_x(ui_Image_Pause, 0);
    lv_obj_set_y(ui_Image_Pause, 0);

    lv_obj_set_align(ui_Image_Pause, LV_ALIGN_CENTER);

    lv_obj_add_flag(ui_Image_Pause, LV_OBJ_FLAG_ADV_HITTEST);

    lv_obj_set_style_img_recolor(ui_Image_Pause, lv_color_hex(0x000000), LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_img_recolor_opa(ui_Image_Pause, 0, LV_PART_MAIN | LV_STATE_DEFAULT);

    // ui_BTN_Cancel

    ui_BTN_Cancel = lv_img_create(ui_Panel_Buttons_S1);
    lv_img_set_src(ui_BTN_Cancel, &ui_img_btn_print_down_png);

    lv_obj_set_width(ui_BTN_Cancel, LV_SIZE_CONTENT);
    lv_obj_set_height(ui_BTN_Cancel, LV_SIZE_CONTENT);

    lv_obj_set_x(ui_BTN_Cancel, -18);
    lv_obj_set_y(ui_BTN_Cancel, 0);

    lv_obj_set_align(ui_BTN_Cancel, LV_ALIGN_RIGHT_MID);

    lv_obj_add_flag(ui_BTN_Cancel, LV_OBJ_FLAG_ADV_HITTEST);

    // ui_BTN_Cancel_Top

    ui_BTN_Cancel_Top = lv_img_create(ui_BTN_Cancel);
    lv_img_set_src(ui_BTN_Cancel_Top, &ui_img_btn_print_top_off_png);

    lv_obj_set_width(ui_BTN_Cancel_Top, LV_SIZE_CONTENT);
    lv_obj_set_height(ui_BTN_Cancel_Top, LV_SIZE_CONTENT);

    lv_obj_set_x(ui_BTN_Cancel_Top, 0);
    lv_obj_set_y(ui_BTN_Cancel_Top, 0);

    lv_obj_set_align(ui_BTN_Cancel_Top, LV_ALIGN_CENTER);

    lv_obj_add_flag(ui_BTN_Cancel_Top, LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_ADV_HITTEST);

    lv_obj_add_event_cb(ui_BTN_Cancel_Top, ui_event_BTN_Cancel_Top, LV_EVENT_ALL, NULL);
    lv_obj_set_style_radius(ui_BTN_Cancel_Top, 18, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_main_stop(ui_BTN_Cancel_Top, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_grad_stop(ui_BTN_Cancel_Top, 255, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_shadow_color(ui_BTN_Cancel_Top, lv_color_hex(0x00D2FF), LV_PART_MAIN | LV_STATE_CHECKED);
    lv_obj_set_style_shadow_opa(ui_BTN_Cancel_Top, 255, LV_PART_MAIN | LV_STATE_CHECKED);
    lv_obj_set_style_shadow_width(ui_BTN_Cancel_Top, 12, LV_PART_MAIN | LV_STATE_CHECKED);
    lv_obj_set_style_shadow_spread(ui_BTN_Cancel_Top, 5, LV_PART_MAIN | LV_STATE_CHECKED);
    lv_obj_set_style_shadow_ofs_x(ui_BTN_Cancel_Top, 0, LV_PART_MAIN | LV_STATE_CHECKED);
    lv_obj_set_style_shadow_ofs_y(ui_BTN_Cancel_Top, 0, LV_PART_MAIN | LV_STATE_CHECKED);
    lv_obj_set_style_shadow_color(ui_BTN_Cancel_Top, lv_color_hex(0x00D2FF), LV_PART_MAIN | LV_STATE_PRESSED);
    lv_obj_set_style_shadow_opa(ui_BTN_Cancel_Top, 255, LV_PART_MAIN | LV_STATE_PRESSED);
    lv_obj_set_style_shadow_width(ui_BTN_Cancel_Top, 12, LV_PART_MAIN | LV_STATE_PRESSED);
    lv_obj_set_style_shadow_spread(ui_BTN_Cancel_Top, 5, LV_PART_MAIN | LV_STATE_PRESSED);
    lv_obj_set_style_img_recolor(ui_BTN_Cancel_Top, lv_color_hex(0x67799B), LV_PART_MAIN | LV_STATE_PRESSED);
    lv_obj_set_style_img_recolor_opa(ui_BTN_Cancel_Top, 255, LV_PART_MAIN | LV_STATE_PRESSED);

    // ui_Image_Cancel

    ui_Image_Cancel = lv_img_create(ui_BTN_Cancel_Top);
    lv_img_set_src(ui_Image_Cancel, &ui_img_icn_stop_png);

    lv_obj_set_width(ui_Image_Cancel, LV_SIZE_CONTENT);
    lv_obj_set_height(ui_Image_Cancel, LV_SIZE_CONTENT);

    lv_obj_set_x(ui_Image_Cancel, 0);
    lv_obj_set_y(ui_Image_Cancel, 0);

    lv_obj_set_align(ui_Image_Cancel, LV_ALIGN_CENTER);

    lv_obj_add_flag(ui_Image_Cancel, LV_OBJ_FLAG_ADV_HITTEST);

    lv_obj_set_style_img_recolor(ui_Image_Cancel, lv_color_hex(0x000000), LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_img_recolor_opa(ui_Image_Cancel, 0, LV_PART_MAIN | LV_STATE_DEFAULT);

}
```
3D打印机控制器基本功能是通过解释G代码程序,生成各种命令序列,控制打印机的XYZ(笛卡尔型)或ABC(Delta型)等等的步进电机进行移动,还要控制挤出机温度,通过PID算法,调节加热器保持温度稳定。高级功能需要通过网络接口,WIFI接口,USB设备等实现文件传输,远程控制,甚至云操作。
整体结构是在FreeRTOS平台基础上,创建LVGL和Command进程分别对应界面和主功能。在命令进程中根据SD卡的配置文件,解析并配置各功能模块,分配引脚,初始化参数。完成后根据用户的操作开启命令子进程完成业务,退出时回收资源。LVGL界面进程则通过用户触摸LCD,动画反馈操作,并通过消息命令队列与命令进程进行通讯,类似于Windows系统的消息,最终实现用户需要的功能。
由于平台的差异性需要移植的模块有SD,ADC,USART,PWM,TIM等等,特别是SD模块基于FATFS而Smooth采用的是标准文件系统,需要对接底层函数,网上介绍资料很少,通过不断调试找到方案,重写_sys_open等函数。
###SD模块
驱动
```
/**
  *@brief 初始化 SD MSP.
  *@param HSD SD 句柄
  *@retval 无
  */
static void SD_MspInit(SD_HandleTypeDef *hsd)
{
    GPIO_InitTypeDef gpio_init_structure;

    if(hsd == &hsd_sdmmc[0]) {
        /* 启用 SDIO 时钟 */
        __HAL_RCC_SDMMC1_CLK_ENABLE();
        /* 启用 DMA 时钟 */
        __HAL_RCC_DMA2_CLK_ENABLE();

        /* 启用 GPIO 时钟 */
        __HAL_RCC_GPIOC_CLK_ENABLE();
        __HAL_RCC_GPIOD_CLK_ENABLE();

        /* 常见 GPIO 配置 */
        gpio_init_structure.Mode      = GPIO_MODE_AF_PP;
        gpio_init_structure.Pull      = GPIO_NOPULL;
        gpio_init_structure.Speed     = GPIO_SPEED_FREQ_HIGH; // GPIO_SPEED_FREQ_VERY_HIGH;
        /* D0(PC8), D1(PC9), D2(PC10), D3(PC11), CK(PC12), CMD(PD2) */
        /* 常见 GPIO 配置 */
        gpio_init_structure.Alternate = GPIO_AF12_SDMMC1;
        /* GPIOC 配置 */
        gpio_init_structure.Pin = GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12;
        HAL_GPIO_Init(GPIOC, &gpio_init_structure);
        /* GPIOD 配置 */
        gpio_init_structure.Pin = GPIO_PIN_2;
        HAL_GPIO_Init(GPIOD, &gpio_init_structure);

        allocate_hal_pin(GPIOC, GPIO_PIN_8);
        allocate_hal_pin(GPIOC, GPIO_PIN_9);
        allocate_hal_pin(GPIOC, GPIO_PIN_10);
        allocate_hal_pin(GPIOC, GPIO_PIN_11);
        allocate_hal_pin(GPIOC, GPIO_PIN_12);
        allocate_hal_pin(GPIOD, GPIO_PIN_2);

        __HAL_RCC_SDMMC1_FORCE_RESET();
        __HAL_RCC_SDMMC1_RELEASE_RESET();

        /* SDIO 中断的 NVIC 配置   */
        NVIC_SetPriority(SDMMC1_IRQn, BSP_SD_IT_PRIORITY);
        NVIC_EnableIRQ(SDMMC1_IRQn);
        
          /* 配置 DMA Rx 参数 */
        dma_rx_handle.Instance                 = DMA2_Stream3;
        dma_rx_handle.Init.Channel             = DMA_CHANNEL_4;
        dma_rx_handle.Init.Direction           = DMA_PERIPH_TO_MEMORY;
        dma_rx_handle.Init.PeriphInc           = DMA_PINC_DISABLE;
        dma_rx_handle.Init.MemInc              = DMA_MINC_ENABLE;
        dma_rx_handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
        dma_rx_handle.Init.MemDataAlignment    = DMA_MDATAALIGN_WORD;
        dma_rx_handle.Init.Mode                = DMA_PFCTRL;
        dma_rx_handle.Init.Priority            = DMA_PRIORITY_VERY_HIGH;
        dma_rx_handle.Init.FIFOMode            = DMA_FIFOMODE_ENABLE;
        dma_rx_handle.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
        dma_rx_handle.Init.MemBurst            = DMA_MBURST_INC4;
        dma_rx_handle.Init.PeriphBurst         = DMA_PBURST_INC4;

        /* Associate the DMA handle */
        __HAL_LINKDMA(hsd, hdmarx, dma_rx_handle);

        /* Deinitialize the stream for new transfer */
        HAL_DMA_DeInit(&dma_rx_handle);

        /* 配置 the DMA stream */
        HAL_DMA_Init(&dma_rx_handle);

        /* 配置 DMA Tx parameters */
        dma_tx_handle.Instance                 = DMA2_Stream6;
        dma_tx_handle.Init.Channel             = DMA_CHANNEL_4;
        dma_tx_handle.Init.Direction           = DMA_MEMORY_TO_PERIPH;
        dma_tx_handle.Init.PeriphInc           = DMA_PINC_DISABLE;
        dma_tx_handle.Init.MemInc              = DMA_MINC_ENABLE;
        dma_tx_handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
        dma_tx_handle.Init.MemDataAlignment    = DMA_MDATAALIGN_WORD;
        dma_tx_handle.Init.Mode                = DMA_PFCTRL;
        dma_tx_handle.Init.Priority            = DMA_PRIORITY_VERY_HIGH;
        dma_tx_handle.Init.FIFOMode            = DMA_FIFOMODE_ENABLE;
        dma_tx_handle.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
        dma_tx_handle.Init.MemBurst            = DMA_MBURST_INC4;
        dma_tx_handle.Init.PeriphBurst         = DMA_PBURST_INC4;

        /* Associate the DMA handle */
        __HAL_LINKDMA(hsd, hdmatx, dma_tx_handle);

        /* Deinitialize the stream for new transfer */
        HAL_DMA_DeInit(&dma_tx_handle);

        /* 配置 the DMA stream */
        HAL_DMA_Init(&dma_tx_handle); 

        /* NVIC configuration for DMA transfer complete interrupt */
        NVIC_SetPriority(DMA2_Stream3_IRQn, BSP_SD_IT_PRIORITY+1);
        NVIC_EnableIRQ(DMA2_Stream3_IRQn);

        /* NVIC configuration for DMA transfer complete interrupt */
        NVIC_SetPriority(DMA2_Stream6_IRQn, BSP_SD_IT_PRIORITY+1);
        NVIC_EnableIRQ(DMA2_Stream6_IRQn);
    }
}

/**
  *@brief DeInitializes SD MSP.
  *@param HSD SD 句柄
  *@retval 无
  */
static void SD_MspDeInit(SD_HandleTypeDef *hsd)
{
    GPIO_InitTypeDef gpio_init_structure;

    if(hsd == &hsd_sdmmc[0])
    {
          /* Disable NVIC for DMA transfer complete interrupts */
        HAL_NVIC_DisableIRQ(DMA2_Stream3_IRQn);
        HAL_NVIC_DisableIRQ(DMA2_Stream6_IRQn);

        /* Deinitialize the stream for new transfer */
        HAL_DMA_DeInit(&dma_rx_handle);
        /* Deinitialize the stream for new transfer */
        HAL_DMA_DeInit(&dma_tx_handle);
        /* 禁用 NVIC 以进行 SDIO 中断   */
        HAL_NVIC_DisableIRQ(SDMMC1_IRQn);

        /* GPIOB 配置   */
        gpio_init_structure.Pin = GPIO_PIN_8 | GPIO_PIN_9;
        HAL_GPIO_DeInit(GPIOB, gpio_init_structure.Pin);

        /* GPIOC 配置   */
        gpio_init_structure.Pin = GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12;
        HAL_GPIO_DeInit(GPIOC, gpio_init_structure.Pin);

        /* GPIOC 配置   */
        gpio_init_structure.Pin = GPIO_PIN_6 | GPIO_PIN_7;
        HAL_GPIO_DeInit(GPIOC, gpio_init_structure.Pin);

        /* GPIOD 配置   */
        gpio_init_structure.Pin = GPIO_PIN_2;
        HAL_GPIO_DeInit(GPIOD, gpio_init_structure.Pin);

        /* 禁用 SDMMC1 时钟   */
        __HAL_RCC_SDMMC1_CLK_DISABLE();            
    }
}


主程序中
int setup_sdmmc()
{
    // 链接微型 SD 磁盘 I/O 驱动程序
    if(FATFS_LinkDriver(&SD_Driver, SDPath) != 0) {
        printf("Error: setup_sdmmc - link driver failed\n");
        return 0;
    }
    return 1;
}

if(!setup_sdmmc())
{
    printf("ERROR: setting up sdmmc\n");
    break;
}
        
// TODO 检查卡是否插入闪烁 4LED(如果不是)
int ret = f_mount(&fatfs, "sd", 1);
if(FR_OK != ret)
{
    printf("ERROR: mounting: /sd: %d\n", ret);
    break;
}

std::fstream fs;
fs.open("/sd/config.ini", std::fstream::in);
if(!fs.is_open())
{
    printf("ERROR: opening file: /sd/config.ini\n");
    break;
}
```
底层接口函数
```
const char __stdin_name[] =  ":tt";
const char __stdout_name[] =  ":tt";
const char __stderr_name[] =  ":tt";
 
FILEHANDLE _sys_open(const char *name, int openmode)
{
#if FATFS_EN
  BYTE mode;
  FIL *fp;
  FRESULT fr;
#endif
  
  if (name == __stdin_name)
    return STDIN;
  else if (name == __stdout_name)
  {
    setup_uart(); // 初始化串口 (在main函数执行前执行)
    return STDOUT;
  }
  else if (name == __stderr_name)
    return STDERR;
  
#if FATFS_EN
  if (sizeof(FILEHANDLE) < sizeof(void *))
  {
    usart_send_string("sizeof(FILEHANDLE) should be no less than sizeof(void *)!\n", -1);
    return -1;
  }
  
  fp = malloc(sizeof(FIL));
  if (fp == NULL)
    return -1;
  
  if (openmode & OPEN_W)
  {
    mode = FA_CREATE_ALWAYS | FA_WRITE;
    if (openmode & OPEN_PLUS)
      mode |= FA_READ;
  }
  else if (openmode & OPEN_A)
  {
    mode = FA_OPEN_APPEND | FA_WRITE;
    if (openmode & OPEN_PLUS)
      mode |= FA_READ;
  }
  else
  {
    mode = FA_READ;
    if (openmode & OPEN_PLUS)
      mode |= FA_WRITE;
  }
  
  fr = f_open(fp, name, mode);
  if (fr == FR_OK)
    return (uintptr_t)fp;
  
  free(fp);
#endif
  
  return -1;
}
 
int _sys_close(FILEHANDLE fh)
{
#if FATFS_EN
  FRESULT fr;
#endif
  
  if (IS_STD(fh))
  {
    if (fh == STDOUT)
      stop_uart();
    return 0;
  }
  
#if FATFS_EN
  fr = f_close((FIL *)fh);
  if (fr == FR_OK)
  {
    free((void *)fh);
    return 0;
  }
#endif
  
  return -1;
}
```
###USART
```
void Configure_USART(void)
{
    LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
    RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
    rxrb = CreateRingBuffer(128);

    /* (1) 启用 GPIO 时钟并配置 USART 引脚 *********************/
    PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USART1;
    PeriphClkInitStruct.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;
    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
    {
        Error_Handler();
    }

    /* 启用 GPIO 端口的外设时钟 */
    LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_USART1);

    LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOB);
    LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOA);

    /*
    PB7   ------> USART1_RX
    PA9   ------> USART1_TX
    */
    GPIO_InitStruct.Pin = LL_GPIO_PIN_7;
    GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
    GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
    GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
    GPIO_InitStruct.Alternate = LL_GPIO_AF_7;
    LL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = LL_GPIO_PIN_9;
    GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
    GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
    GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
    GPIO_InitStruct.Alternate = LL_GPIO_AF_7;
    LL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* (2) USART 中断的 NVIC 配置 */
    /*  - 设置 USARTx_IRQn 优先级 */
    /*  - 启用 USARTx_IRQn */
    NVIC_SetPriority(USART1_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY+8);
    NVIC_EnableIRQ(USART1_IRQn);

    /* (3) 启用 USART 外设时钟和时钟源 ***********************/
    /* 设置时钟源 */
    LL_RCC_SetUSARTClockSource(LL_RCC_USART1_CLKSOURCE_PCLK2);

    /* (4) 配置 USART 功能参数 ********************************/

    /* 在修改配置寄存器之前禁用 USART */
    /* 注意:注释为与重置值相对应 */
    LL_USART_Disable(USART1);

    /* 设置初始化结构的字段                   */
    /*  - 预标定器 : LL_USART_PRESCALER_DIV1         */
    /*  - 波特率 : 115200                          */
    /*  - 数据宽度 : LL_USART_DATAWIDTH_8B           */
    /*  - 停止位 : LL_USART_STOPBITS_1             */
    /*  - 奇偶校验 : LL_USART_PARITY_NONE            */
    /*  - 传输方向 : LL_USART_DIRECTION_TX_RX        */
    /*  - 硬件流控制:LL_USART_HWCONTROL_NONE         */
    /*  - 过采样:LL_USART_OVERSAMPLING_16        */
    LL_USART_InitTypeDef usart_initstruct;
    usart_initstruct.BaudRate            = 115200;
    usart_initstruct.DataWidth           = LL_USART_DATAWIDTH_8B;
    usart_initstruct.StopBits            = LL_USART_STOPBITS_1;
    usart_initstruct.Parity              = LL_USART_PARITY_NONE;
    usart_initstruct.TransferDirection   = LL_USART_DIRECTION_TX_RX;
    usart_initstruct.HardwareFlowControl = LL_USART_HWCONTROL_NONE;
    usart_initstruct.OverSampling        = LL_USART_OVERSAMPLING_16;

    /* 根据初始化结构中定义的参数初始化 USART 实例 */
    LL_USART_Init(USART1, &usart_initstruct);
    LL_USART_ConfigAsyncMode(USART1);
    /* (5) 启用 USART *********************************************************/
    CLEAR_BIT(USART1->CR3, USART_CR3_OVRDIS);
    LL_USART_Enable(USART1);

    /* 轮询 USART 初始化 */
//    while((!(LL_USART_IsActiveFlag_TEACK(USART1))) || (!(LL_USART_IsActiveFlag_REACK(USART1)))) {
//    }

    /* 启用 RXNE 和错误中断 */
    LL_USART_EnableIT_RXNE(USART1);
    //LL_USART_EnableIT_ERROR(USART1);
    LL_USART_DisableIT_ERROR(USART1);

    allocate_hal_pin(USARTx_TX_GPIO_PORT, USARTx_TX_PIN);
    allocate_hal_pin(USARTx_RX_GPIO_PORT, USARTx_RX_PIN);
}

size_t read_uart(char * buf, size_t length)
{
    size_t cnt = 0;
    for (int i = 0; i < length; ++i)
    {
        if(RingBufferEmpty(rxrb)) break;
        uint8_t ch;
        RingBufferGet(rxrb, &ch);
        buf = ch;
        ++cnt;
    }
    return cnt;
}

size_t write_uart(const char *buf, size_t length)
{
    for (int i = 0; i < length; ++i)
    {
        LL_USART_TransmitData8(USART1, buf);
        while (!LL_USART_IsActiveFlag_TXE(USART1)) { }
        LL_USART_ClearFlag_TC(USART1);
    }
    return length;
}

```


##作品源码

##作品功能演示视频

###运行输出结果

![](RackMultipart20221105-1-q1d30a_html_d2d7eb9f29d96760.jpg)

###界面运行效果

https://bbs.eeworld.com.cn/forum.php?mod=attachment&aid=NjUwNDQ0fDQ3MjRlMDhifDE2NjczOTgzNTF8NzUwODY4fDEyMjIxMTg%3D

##项目总结

首先感谢电子工程世界组织了这次活动,得捷电子提供此次物料,使我能够初步的实现3D打印机控制器基本功能。在此次开发中,由于踩坑填坑花费太多时间,代码还有很多缺陷,有待完善。但是从开发中也学习了很多原先没有接触过的外设驱动如QSPI,SDRAM,MPU等等知识,对以后的工作肯定大有裨益。
下一步计划是完善代码,把USB,网路,wifi功能实现出来,再在此基础上探索S曲线控制算法。

 

 

3D打印机控制器项目报告.do ...

3D打印机控制器项目报告.docx

23.21 MB, 下载次数: 210

最新回复

您好,是否用下图中的markdown发帖,如果直接复制到编辑器会按照普通文本方式展示 [attach]657314[/attach]     详情 回复 发表于 2022-11-15 17:38
点赞 关注(1)
 
 

回复
举报

6828

帖子

0

TA的资源

五彩晶圆(高级)

沙发
 

很赞 

 
 
 

回复

13

帖子

0

TA的资源

一粒金砂(中级)

板凳
 
 
 

回复

9185

帖子

6

TA的资源

管理员

4
 

您好,是否用下图中的markdown发帖,如果直接复制到编辑器会按照普通文本方式展示

 

加EE小助手好友,
入技术交流群
EE服务号
精彩活动e手掌握
EE订阅号
热门资讯e网打尽
聚焦汽车电子软硬件开发
认真关注技术本身
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/7 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表