本帖最后由 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 ...
|