第一次写博客,我以为会是点灯的,没想到留给了GUI,但是第一次写,可能写的不够好欢迎大家批评指正。

最近由于比赛的要求,需要给自己的LCD设计GUI界面,在查了一些资料后,决定先学STemwin然后学习移植LVGL,也参考了很多博客,走了很多弯路,花了两天时间最后终于成功了,最后把这一点经验分享给大家,然后也是在未来说不定自己还需要重新复习一下(手动狗头)

1.第一步 首先是上效果

最开始就通过GUIBuilder生成这样的一个简单的界面,学会我这个之后自己可以操作生成更好看的界面了

1.正式第一步,通过cubemx对stm32f407芯片进行配置

最基本的RCC,SYS就不必说了,配置的最基本的,然后是时钟线配置的是8Mhz,HCLK是168mhz,主要的是FSMC,按照下图配置,有关lcd的原理可以自行查资料,网上的很多

然后是开启LCD背光,我用的是正点原子系列的开发板,因此不一样的就需要看自己板子的原理图,我们这里这里配置的PB15端口,要是想要测试代码的可以自行配置一下串口,LED灯啥的,我这里为了测试代码就配置了一个USART1,然后就可以生成代码了。

最重要的一步!!!千万记得开启CRC。如果不开启CRC,是没办法移植STemwin的!

最后cubemx生成代码模板

​​​​​​​

第二步:添加显示屏驱动文件

我这里是用的正点原子官方例程改的测试代码,然后测试一下LCD驱动代码有没有问题,

#include "main.h"
#include "crc.h"
#include "dma.h"
#include "usart.h"
#include "gpio.h"
#include "fsmc.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include  "ILI93xx.h"
//#include "sram.h"
//#include "malloc.h"
#include "GUI.h"
#include "UART_DMA.h"
extern void MainTask1(void);
extern void MainTask2(void);/* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD *//* USER CODE END PTD *//* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD *//* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*//* USER CODE BEGIN PV *//* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP *//* USER CODE END PFP *//* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 *//* USER CODE END 0 */int main(void)
{HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_DMA_Init();MX_USART1_UART_Init();MX_FSMC_Init();     MX_CRC_Init();TFTLCD_Init();
POINT_COLOR=BLACK;
LCD_ShowString(10,10,300,24,24,"LCD");while (1){}}

下载到开发板上有现象,说明驱动代码没有问题,这就可以开始下一步了。驱动代码可以在网上找得到,我是根据这篇博客来的,大佬写的很好,通俗易懂,可以参考一下。我用的是ILI9341驱动的屏,这里记得改一下你显示屏的驱动文件名,因为后面的STemwin会包含LCD的驱动文件,为了防止重定义(30条消息) STM32CubeMX实战教程(七)——TFT_LCD液晶显示(附驱动代码)_会开发的喵的博客-CSDN博客_lcd register select

第三步,通过GUIBder生成一个看得过去的界面

STemwin是ST公司自己开发的GUI图形用户界面,具体驱动文件是cubemx每次更新都会自行下载的,具体的位置可以找你cubemx下载的默认位置,但是你还是需要下载一个GUIBuilder(emwin),然后通过GUIBuilder配置好界面就可以生成一个.c文件。

GUIBuider界面如下

首先是新建一个Framewin,然后在左下方那个类似表格的位置,你可以调整相应的参数,进行设置,

Name顾名思义,就是这个Framewin的名字,xPos就是页面的x轴位置,然后yPos就是位置,这里应该统一设置成为0,0。xSize和ySize就是界面大小的设置,这个根据你自己的显示屏进行设置

同样这个界面你也可以设置标题,设置方法:

画红圈出右键,你可以看待加入标题,标题颜色,标题位置以及字体等功能,我在这里就不赘述了,大家可以自行尝试,最后在左上角保存就可以生成相应的.c文件,这里有关界面设置的就介绍到这里,上面有很多功能软件,需要大家自己去探索。

第四步:真正到了移植部分了,移植STemwin

首先找到安装包所在的位置,我用的是v1.13.0版本,具体这里看一下我的文件位置,每一个文件文位置都是差不多的格式。

需要复制的文件夹有Config,Inc,Lib,OS

这里简单介绍一下各个文件夹的文件作用

​​​​​​​

复制完毕后,我们需要用的文件是

这里面借用了正点原子的图,前面的文件夹不用管,除了GUI_X_Touch.Analog.c文件,其他都是需要的,GUI_X.c是无操作系统的,如果是有操作系统的,就需要另外的一个文件,在OS文件夹里 ,EMWIN_LIB我用的是keil,如果用上了操作系统则需要添加带有OS的,还需要的文件是CMSIS的Lib

小伙伴们可以根据自己生成的文件去寻找,选择最后一个,

这一个文件夹里,我们选择的也是最后一个。

然后是修改文件,第一个是GUIConf.c,这里是分配内存,GUI_NUMBYTES 就是内存大小,具体的要看芯片内存大小,

/*********************************************************************
*          Portions COPYRIGHT 2016 STMicroelectronics                *
*          Portions SEGGER Microcontroller GmbH & Co. KG             *
*        Solutions for real time microcontroller applications        *
**********************************************************************
*                                                                    *
*        (c) 1996 - 2015  SEGGER Microcontroller GmbH & Co. KG       *
*                                                                    *
*        Internet: www.segger.com    Support:  support@segger.com    *
*                                                                    *
************************************************************************ emWin V5.32 - Graphical user interface for embedded applications **
All  Intellectual Property rights  in the Software belongs to  SEGGER.
emWin is protected by  international copyright laws.  Knowledge of the
source code may not be used to write a similar product.  This file may
only be used in accordance with the following terms:The  software has  been licensed  to STMicroelectronics International
N.V. a Dutch company with a Swiss branch and its headquarters in Plan-
les-Ouates, Geneva, 39 Chemin du Champ des Filles, Switzerland for the
purposes of creating libraries for ARM Cortex-M-based 32-bit microcon_
troller products commercialized by Licensee only, sublicensed and dis_
tributed under the terms and conditions of the End User License Agree_
ment supplied by STMicroelectronics International N.V.
Full source code is available at: www.segger.comWe appreciate your understanding and fairness.
----------------------------------------------------------------------
File        : GUIConf.c
Purpose     : Display controller initialization
---------------------------END-OF-HEADER------------------------------
*//********************************************************************************* @attention** Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");* You may not use this file except in compliance with the License.* You may obtain a copy of the License at:**        http://www.st.com/software_license_agreement_liberty_v2** Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.********************************************************************************/#include "GUI.h"/*********************************************************************
*
*       Defines
*
**********************************************************************
*/
//
// Define the available number of bytes available for the GUI
//
#define GUI_NUMBYTES 10*1024/*********************************************************************
*
*       Public code
*
**********************************************************************
*/
/*********************************************************************
*
*       GUI_X_Config
*
* Purpose:
*   Called during the initialization process in order to set up the
*   available memory for the GUI.
*/
void GUI_X_Config(void) {//// 32 bit aligned memory area//static U32 aMemory[GUI_NUMBYTES / 4];//// Assign memory to emWin//GUI_ALLOC_AssignMemory(aMemory, GUI_NUMBYTES);//// Set default font//GUI_SetDefaultFont(GUI_FONT_6X8);
}/*************************** End of file ****************************/

然后是GUIDRV_Template.c,首先需要引用显示屏驱动文件,然后修改四个函数,

static void _SetPixelIndex(GUI_DEVICE * pDevice, int x, int y, int PixelIndex) 
static unsigned int _GetPixelIndex(GUI_DEVICE * pDevice, int x, int y) 
static void _FillRect(GUI_DEVICE * pDevice, int x0, int y0, int x1, int y1) 
static void _DrawBitLine16BPP(GUI_DEVICE * pDevice, int x, int y, U16 const GUI_UNI_PTR * p, int xsize)

这四个函数中的画点函数都用显示屏驱动函数就可以了

static void _SetPixelIndex(GUI_DEVICE * pDevice, int x, int y, int PixelIndex) {LCD_Fast_DrawPoint(x, y, PixelIndex);
}//??
static unsigned int _GetPixelIndex(GUI_DEVICE * pDevice, int x, int y) {unsigned int PixelIndex;//// Convert logical into physical coordinates (Dep. on LCDConf.h)//#if (LCD_MIRROR_X == 1) || (LCD_MIRROR_Y == 1) || (LCD_SWAP_XY == 1)int xPhys, yPhys;xPhys = LOG2PHYS_X(x, y);yPhys = LOG2PHYS_Y(x, y);#else#define xPhys x#define yPhys y#endifGUI_USE_PARA(pDevice);GUI_USE_PARA(x);GUI_USE_PARA(y);{//// Write into hardware ... Adapt to your system//// TBD by customer...//PixelIndex = LCD_ReadPoint(x, y);}#if (LCD_MIRROR_X == 0) && (LCD_MIRROR_Y == 0) && (LCD_SWAP_XY == 0)#undef xPhys#undef yPhys#endifreturn PixelIndex;
}static void _FillRect(GUI_DEVICE * pDevice, int x0, int y0, int x1, int y1) {LCD_Fill(x0, y0, x1, y1, LCD_COLORINDEX);
}static void _DrawBitLine16BPP(GUI_DEVICE * pDevice, int x, int y, U16 const GUI_UNI_PTR * p, int xsize) {LCD_PIXELINDEX pixel;LCD_SetCursor(x, y);*(vu16 *)(0x6001FFFE) = lcddev.wramcmd;   for (;xsize > 0; xsize--, x++, p++) {pixel = *p;_SetPixelIndex(pDevice, x, y, pixel);}
}

然后是修改FlexColor_Template.c,这里我们需要修改LCD_X_Config(),这里的第一个定义是定义你的显示屏宽度和长度(分辨率),我们用的也是LCD的显示屏驱动函数

#include "GUI.h"
#include "GUIDRV_FlexColor.h"
#include "ILI93xx.h"
/*********************************************************************
*
*       Layer configuration (to be modified)
*
**********************************************************************
*///
// Physical display size
//
#define XSIZE_PHYS 800// To be adapted to x-screen size
#define YSIZE_PHYS  480 // To be adapted to y-screen size
//#define lcddev.dir 1;
/*********************************************************************
*
*       Configuration checking
*
**********************************************************************
*/
#ifndef   VXSIZE_PHYS#define VXSIZE_PHYS XSIZE_PHYS
#endif
#ifndef   VYSIZE_PHYS#define VYSIZE_PHYS YSIZE_PHYS
#endif
#ifndef   XSIZE_PHYS#error Physical X size of display is not defined!
#endif
#ifndef   YSIZE_PHYS#error Physical Y size of display is not defined!
#endif
#ifndef   GUICC_565#error Color conversion not defined!
#endif
#ifndef   GUIDRV_FLEXCOLOR#error No display driver defined!
#endif/*********************************************************************
*
*       Local functions
*
**********************************************************************
*/
/********************************************************************
*
*       LcdWriteReg
*
* Function description:
*   Sets display register
*///static void LcdWriteReg(uint16_t Data) {
//  // ... TBD by user
//  LCD_WRITE_REG = Data;
//}/********************************************************************
*
*       LcdWriteData
*
* Function description:
*   Writes a value to a display register
*/
//static void LcdWriteData(U16 Data) {
//  // ... TBD by user
//}/********************************************************************
*
*       LcdWriteDataMultiple
*
* Function description:
*   Writes multiple values to a display register.
*/
//static void LcdWriteDataMultiple(U16 * pData, int NumItems) {
//  while (NumItems--) {
//    // ... TBD by user
//  }
//}/********************************************************************
*
*       LcdReadDataMultiple
*
* Function description:
*   Reads multiple values from a display register.
*/
//static void LcdReadDataMultiple(U16 * pData, int NumItems) {
//  while (NumItems--) {
//    // ... TBD by user
//  }
//}/*********************************************************************
*
*       Public functions
*
**********************************************************************
*/
/*********************************************************************
*
*       LCD_X_Config
*
* Function description:
*   Called during the initialization process in order to set up the
*   display driver configuration.
*
*/
void LCD_X_Config(void) {//// Set display driver and color conversion///* GUIDRV_Template_API ?????API??, ?????4???????????????*/GUI_DEVICE_CreateAndLink(&GUIDRV_Template_API, GUICC_M565, 0, 0);//// Display driver configuration, required for Lin-driver//LCD_SetSizeEx (0, lcddev.width , lcddev.height);LCD_SetVSizeEx(0, lcddev.width, lcddev.height);/*GUIÏÔʾÆÁ·½Ïò*///    {
//      if(lcddev.dir == 0) //ÊúÆÁ  // 2001:3520 6352
//          {                       // 9147:3832 6288
//          GUI_TOUCH_Calibrate(GUI_COORD_X,0,480,0,479);
//          GUI_TOUCH_Calibrate(GUI_COORD_Y,0,800,0,799);
//      }else //ºáÆÁ
//      {
//          //GUI_TOUCH_SetOrientation(GUI_SWAP_XY|GUI_MIRROR_Y);
//          GUI_TOUCH_Calibrate(GUI_COORD_X,0,480,0,479);
//          GUI_TOUCH_Calibrate(GUI_COORD_Y,0,800,0,799);
//      }//  if(lcddev.dir == 0) //??
//  {
//    GUI_TOUCH_Calibrate(GUI_COORD_X,0,320,0,319);
//    GUI_TOUCH_Calibrate(GUI_COORD_Y,0,480,0,479);
//  }else //??
//  {
//    GUI_TOUCH_Calibrate(GUI_COORD_X,0,480,0,479);
//    GUI_TOUCH_Calibrate(GUI_COORD_Y,0,320,0,319);
//  }
}
/*********************************************************************
*
*       LCD_X_DisplayDriver
*
* Function description:
*   This function is called by the display driver for several purposes.
*   To support the according task the routine needs to be adapted to
*   the display controller. Please note that the commands marked with
*   'optional' are not cogently required and should only be adapted if
*   the display controller supports these features.
*
* Parameter:
*   LayerIndex - Index of layer to be configured
*   Cmd        - Please refer to the details in the switch statement below
*   pData      - Pointer to a LCD_X_DATA structure
*
* Return Value:
*   < -1 - Error
*     -1 - Command not handled
*      0 - Ok
*/
int LCD_X_DisplayDriver(unsigned LayerIndex, unsigned Cmd, void * pData) {int r;(void) LayerIndex;(void) pData;switch (Cmd) {case LCD_X_INITCONTROLLER: {//// Called during the initialization process in order to set up the// display controller and put it into operation. If the display// controller is not initialized by any external routine this needs// to be adapted by the customer...//// ...TFTLCD_Init();return 0;}default:r = -1;}return r;
}/*************************** End of file ****************************/

最重要的是,GUI_X.c中的

volatile GUI_TIMER_TIME OS_TimeMS;
这个是STemwin的心跳,我们要让emwin动起来,就一定要让心脏跳动起来,我这里放到了系统时钟里,在stm32f4xx_it.c加上这一段代码

void SysTick_Handler(void)
{/* USER CODE BEGIN SysTick_IRQn 0 */
extern volatile GUI_TIMER_TIME OS_TimeMS;
OS_TimeMS++;/* USER CODE END SysTick_IRQn 0 */HAL_IncTick();HAL_SYSTICK_IRQHandler();/* USER CODE BEGIN SysTick_IRQn 1 *//* USER CODE END SysTick_IRQn 1 */
}

这样就移植的差不多了,然后需要做的就是添加文件路径。

第五步,修改FramewinDLG.c,然后添加文件定义,使我们可以使用DSP库和FPU。

为了使用stm32f4的FPU,在SystemInit()函数里有具体要求,具体在system_stm32f4xx.h文件里,我们需要加入定义

USE_STDPERIPH_DRIVER,__FPU_PRESENT = 1,__FPU_USED=1,ARM_MATH_CM4,__CC_ARM

最后就在framewinDLG.c最后添加一段代码

void MainTask1(void)
{GUI_Init();WM_MULTIBUF_Enable(1);CreateFramewin();while(1){GUI_Delay(100);}}

报错的话记得引用GUI.h

在main函数里调用,就大功告成了!

/* USER CODE BEGIN Header */
/********************************************************************************* @file           : main.c* @brief          : Main program body******************************************************************************* @attention** Copyright (c) 2022 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "crc.h"
#include "dma.h"
#include "usart.h"
#include "gpio.h"
#include "fsmc.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include  "ILI93xx.h"
#include "GUI.h"
#include "UART_DMA.h"
extern void MainTask1(void);
extern void MainTask2(void);/* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD *//* USER CODE END PTD *//* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD *//* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*//* USER CODE BEGIN PV *//* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP *//* USER CODE END PFP *//* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 *//* USER CODE END 0 *//*** @brief  The application entry point.* @retval int*/
int main(void)
{/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BE GIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_DMA_Init();MX_USART1_UART_Init();MX_FSMC_Init();     MX_CRC_Init();/* USER CODE BEGIN 2 */
TFTLCD_Init();StartUartRxDMA();
GUI_Init();GUI_SetFont(&GUI_Font24_ASCII);MainTask1();//POINT_COLOR=BLACK;
//LCD_ShowString(10,10,300,24,24,"LCD");/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}

最终完成移植!!!大功告成!

参考博客:

(30条消息) STM32f407ZGT6 HAL + ili9341 + FreeRTOS + emWin5.44移植_cp_srd的博客-CSDN博客

超详细!!!STM32F407ZGT6HAL库移植STemwin(基于正点原子最小系统板+GUIBuilder)相关推荐

  1. GUI——LVGL移植+STM32f407zgt6(正点原子最小系统板+GUI Guider

    写在前面,写这篇blog的目的也是为了提醒自己how to移植LVGL,所以写的不够好,也可能不是会很详细,大佬勿喷 准备工作,下载lvgl源码,Github源码,很容易. 一.GUI Guider的 ...

  2. 基于正点原子F103精英板和CubeIDE的Hal库LCD驱动移植(从零开始)

    最近在学习王维波老师的<STM32Cube高效开发教程>,王老师移植的是普中科技的驱动,而我手动移植了一下正点原子的lcd驱动,看了网上的诸多教程,有的博客存在一些bug,于是乎手动整理了 ...

  3. 基于正点原子Linux开发板(ALIENTEK I.MX6U ALPHA V2.2)的个人自学记录

    基于正点原子Linux开发板(ALIENTEK I.MX6U ALPHA V2.2)的个人自学记录 硬件环境 正点原子Linux开发板(ALIENTEK I.MX6U ALPHA V2.2) 底板+核 ...

  4. stm32f407 6路串口dma如何配置_stm32cubeMX学习十、扫码模块程序开发(基于正点原子STM32F407开发板)...

    本程序编写基于正点原子STM32F407开发板. 本文使用的扫码模块是下面这个品牌. 扫码模块的应用场景非常广泛,我们可以上百度搜索一下: 等等. 今天就来说说如何在开发板上实现控制它吧,打开数据手册 ...

  5. 基于正点原子STM32F103精英板IIC实验的MS5611气压计的使用

    MS5611是一款气压计,能够提供高精度的气压值与温度值,这次做项目正好需要用到这款传感器,包括之前也没好好学习用过IIC,所以写下博客记录一下. 如果有需要使用的朋友可以去https://downl ...

  6. Linux platform 设备驱动实验-基于正点原子IMX6ULL开发板

    我们以前的设备驱动都非常的简单,都是对IO进行最简单的读写操作.像I2C. SPI.LCD 这些复杂外设的驱动就不能这么去写了,Linux 系统要考虑到驱动的可重用性,因此提出了驱动的分离与分层这样的 ...

  7. Linux 设备树下的 platform 驱动实验基于正点原子IMX6ULL开发板

    1 设备树下的 platform 驱动简介 platform 驱动框架分为总线.设备和驱动,其中总线不需要我们这些驱动程序员去管理,这个是 Linux 内核提供的,我们在编写驱动的时候只要关注于设备和 ...

  8. Linux MISC 驱动实验-基于正点原子IMX6ULL开发板

    misc 的意思是混合.杂项的,因此 MISC 驱动也叫做杂项驱动,也就是当我们板子上的某些外设无法进行分类的时候就可以使用 MISC 驱动.MISC 驱动其实就是最简单的字符设备驱动,通常嵌套在 p ...

  9. stm32f103r6最小系统原理图_PCB stm32的最小系统原理图 基于STM32F103VBT6的最小系统板 - 下载 - 搜珍网...

    PCB板(许荣盛)/History/CFB80610/Miscellaneous Devices.~(1).PcbLib.Zip PCB板(许荣盛)/History/CFB80610/Miscella ...

最新文章

  1. 【 Vivado 】Performing System-Level Design Entry(总览)
  2. 双系统环境下解决wine的字体为方块的问题
  3. shell 提示符个性化设置
  4. eclipse启动出现“An Error has Occurred. See the log file”解决方法
  5. react 遍历对象_React 源码系列 | React Children 详解
  6. Qt工作笔记-Qt元对象系统解析【2合1】
  7. Oracle取同一类别中某属性最大或者最小值的一条
  8. Hive on Spark与SparkSql的区别
  9. 自定义IE地址栏图标
  10. 服务器防火墙如何开放端口?常见的服务器端口有哪些?
  11. 疫情之下要不要转行?
  12. ​华为回应出售手机业务传闻:假消息;微软将ChatGPT整合到更多工具中:不用写代码就能开发应用;苹果更新Mac产品线|极客头条...
  13. 黑苹果 MAC Monterey 在睡眠后 bluetoothd 占用很高的cpu解决方案
  14. java p2p开发项目实战(完整)
  15. Proxmox VE(PVE)+ceph+物理网络规划-超融合生产环境安装部署案例
  16. 高级操作!用 Python 在 Excel 里画出蒙娜丽莎
  17. STM32CubeMX学习--ThreadX_UART
  18. python plot设置坐标轴_python中plot怎么设置横纵坐标名称
  19. oracle 导出身份证号_ORACLE对身份证号码处理相关的SQL汇总
  20. deepin、UOS 安装wine

热门文章

  1. mib2c : You didn‘t give mib2c a valid OID to start with.解决
  2. 雨水弃流装置详细说明
  3. 我国传统长度单位c语言,标准长度单位换算c程序设计方案书.doc
  4. storage/emulated/0.到底在哪儿
  5. Java程序员进阶全过程
  6. DSP-FTU实现DNP3.0
  7. STM32F103频率计
  8. GitHub置顶半个月!78w字百亿级并发设计(全彩PDF),竟出自京东
  9. 行业前沿|无人机视觉自主导航发展及视觉智能开发支撑平台介绍
  10. onedrive电脑手机不同步_onedrive无法同步