GD32移植STM32工程(因为懒,所以移植)

文章目录

  • 一、前言
  • 二、差异性
  • 三、软件移植部分
    • 1.前期准备
      • 1.1 安装GD32固件库
      • 1.2 选择所用芯片
    • 2.修改程序
      • 2.1 启动时间(内部时钟可不改)
      • 2.2 主频
        • 2.2.1 系统时钟配置
        • 2.2.2 108MHz宏定义
          • 第一处
          • 第二处
          • 第三处
          • 第四处
          • 第五处
        • 2.2.3 串口
        • 2.2.4 FLASH
  • 四、总结


一、前言

在一个慵懒的日子里,我因为不想花费太多时间和精力,直接将原来为STM32编写的工程进行了修改,使其适用于GD32工程。这个过程并不复杂,只需要对一些特定的代码进行替换和调整,以适应GD32的硬件架构和指令集。然而,由于我对STM32和GD32之间的差异了解不够深入,这个过程也让我犯了一些错误。最终,经过一番努力,我终于成功地将工程从STM32移植到了GD32。

经过这次移植的经历,我深刻体会到了GD32和STM32之间的差异,并积累了一定的经验。因此,我决定将这次移植的经验分享出来,希望能够帮助更多的人在面对类似移植问题时能够更加顺利地完成移植工作。

在这里插入图片描述

二、差异性

可以从下面表格看出主要的硬件差异是供电以及主频大小等。

MCUSTM32F103VCT6GD32F103VCT6
内核Cortex-M3内核Cortex-M3内核
程序存储容量256KB256KB
RAM总容量48KB48KB
GPIO端口数量8080
工作电压范围2V~3.6V2.6V~3.6V
内核的供电电压1.2V1.8V
CPU最大主频72MHz108MHz
程序存储器类型FLASHFLASH
工作温度范围-40℃~+85℃-40℃~+85℃
ADC(位数)12bit12bit
DAC(位数)12bit12bit

三、软件移植部分

这里我使用的GD芯片是GD32F103VCT6,移植的程序来源自STM32F103VCT6,采用的是STM32的标准库。

1.前期准备

1.1 安装GD32固件库

进入兆易创新GD32 MCU官网下载keil支持包,下载完成后双击进行安装。
在这里插入图片描述

1.2 选择所用芯片

这里我用的是keil5,所以我选择安装 GigaDevice.GD32F10x_DFP.2.1.0 pack Keil5 在线支持包,安装完成后点击keil的魔术棒会出现GD32F10x Series。

在这里插入图片描述

最后,选择我们需要的MCU型号,前期准备工作完成,接下来开始移植程序。

在这里插入图片描述

2.修改程序

2.1 启动时间(内部时钟可不改)

HSE_STARTUP_TIMEOUT是用于定义外部高速时钟(HSE)启动的超时时间。我用的是内部时钟,所以也可以不改。

代码如下(示例):

/*** @brief In the following line adjust the External High Speed oscillator (HSE) Startup Timeout value */
#define HSE_STARTUP_TIMEOUT   ((uint16_t)0xFFFF) /*!< Time out for HSE start up */ //STM32 0x0500

2.2 主频

2.2.1 系统时钟配置

通过上面的差异性比较,我们知道GD32的最高主频为108MHZ,那么在STM32工程中要有哪些修改呢?

请接着往下看

1.在SystemClock_Config系统时钟配置函数中选择我们需要的时钟,这里用的是内部时钟HSI,有同学可能对底下这个宏定义 #define RCC_PLLMul_27 ((uint32_t)0x08280000)感到疑惑,下面就解释下。

根据官方GD32F10x User Manual 2.6版本用户手册的资料显示(中文P84-P87,英文P87-P91),要配置108MHZ,PLL时钟倍频因子需要配置为PLL源时钟x27,由于我们在RCC_PLLConfig函数选择RCC_PLLSource_HSI_Div2,HSI刚好是8MHZ,一半的HSI是4MHZ,4x27=108MHZ

PLLMF[3:0]为第21位到18位,(PLL源时钟 x 27)为11010,第一个1其实是第27位,所以时钟配置寄存器 0(RCU_CFG0)最后的值为0x0000 1000 0010 1000 XXXX(补零)=0x08280000

在这里插入图片描述
代码如下(示例):

 #define RCC_PLLMul_27                   ((uint32_t)0x08280000)/******************************************************************************** 函数名:SystemClock_Config* 描述  :系统时钟配置* 输入  :void* 输出  :void* 调用  :初始化* 备注  :
*******************************************************************************/
void SystemClock_Config(void)
{/* SYSCLK, HCLK, PCLK2 and PCLK1 configuration -----------------------------*/   /* RCC system reset(for debug purpose) */RCC_DeInit();/* Enable HSI */RCC_HSICmd(ENABLE);/* Wait till HSI is ready */while (RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET){}/* Enable Prefetch Buffer */FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);/* Flash 2 wait state */FLASH_SetLatency(FLASH_Latency_2);/* HCLK = SYSCLK */RCC_HCLKConfig(RCC_SYSCLK_Div1); /* PCLK2 = HCLK */RCC_PCLK2Config(RCC_HCLK_Div1); /* PCLK1 = HCLK/2 */RCC_PCLK1Config(RCC_HCLK_Div2);
#ifdef STM32F10X_CL/* Configure PLLs *********************************************************//* PLL2 configuration: PLL2CLK = (HSI / 2) * 4 = 16 MHz */RCC_PREDIV2Config(RCC_PREDIV2_Div2);RCC_PLL2Config(RCC_PLL2Mul_4);/* Enable PLL2 */RCC_PLL2Cmd(ENABLE);/* Wait till PLL2 is ready */while (RCC_GetFlagStatus(RCC_FLAG_PLL2RDY) == RESET){}/* PLL configuration: PLLCLK = (PLL2 / 5) * 9 = 72 MHz */ RCC_PREDIV1Config(RCC_PREDIV1_Source_PLL2, RCC_PREDIV1_Div5);RCC_PLLConfig(RCC_PLLSource_PREDIV1, RCC_PLLMul_9);
#else/* PLLCLK = 4MHz * 27 = 72 MHz */RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_27); // HSI is divided by 2 to have 4MHz then multiply by 27 to have 108MHz
#endif/* Enable PLL */ RCC_PLLCmd(ENABLE);/* Wait till PLL is ready */while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET){}/* Select PLL as system clock source */RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);/* Wait till PLL is used as system clock source */while(RCC_GetSYSCLKSource() != 0x08){}
}
2.2.2 108MHz宏定义

在system_stm32f10x.c文件中找到SYSCLK_FREQ_72MHz的位置,一共有5处,全部注释掉,并且换成SYSCLK_FREQ_108MHz。

代码如下(示例):

第一处
#if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
/* #define SYSCLK_FREQ_HSE    HSE_VALUE */#define SYSCLK_FREQ_24MHz  24000000
#else
/* #define SYSCLK_FREQ_HSE    HSE_VALUE */
/* #define SYSCLK_FREQ_24MHz  24000000 */ 
/* #define SYSCLK_FREQ_36MHz  36000000 */
/* #define SYSCLK_FREQ_48MHz  48000000 */
/* #define SYSCLK_FREQ_56MHz  56000000 */
/* #define SYSCLK_FREQ_72MHz  72000000 */#define SYSCLK_FREQ_108MHz  108000000
#endif
第二处
/*******************************************************************************
*  Clock Definitions
*******************************************************************************/
#ifdef SYSCLK_FREQ_HSEuint32_t SystemCoreClock         = SYSCLK_FREQ_HSE;        /*!< System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_24MHzuint32_t SystemCoreClock         = SYSCLK_FREQ_24MHz;        /*!< System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_36MHzuint32_t SystemCoreClock         = SYSCLK_FREQ_36MHz;        /*!< System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_48MHzuint32_t SystemCoreClock         = SYSCLK_FREQ_48MHz;        /*!< System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_56MHzuint32_t SystemCoreClock         = SYSCLK_FREQ_56MHz;        /*!< System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_72MHzuint32_t SystemCoreClock         = SYSCLK_FREQ_72MHz;        /*!< System Clock Frequency (Core Clock) */#elif defined SYSCLK_FREQ_108MHzuint32_t SystemCoreClock         = SYSCLK_FREQ_108MHz;        /*!< System Clock Frequency (Core Clock) */
#else /*!< HSI Selected as System Clock source */uint32_t SystemCoreClock         = HSI_VALUE;        /*!< System Clock Frequency (Core Clock) */
#endif
第三处
#ifdef SYSCLK_FREQ_HSEstatic void SetSysClockToHSE(void);
#elif defined SYSCLK_FREQ_24MHzstatic void SetSysClockTo24(void);
#elif defined SYSCLK_FREQ_36MHzstatic void SetSysClockTo36(void);
#elif defined SYSCLK_FREQ_48MHzstatic void SetSysClockTo48(void);
#elif defined SYSCLK_FREQ_56MHzstatic void SetSysClockTo56(void);  
#elif defined SYSCLK_FREQ_72MHzstatic void SetSysClockTo72(void);
#elif defined SYSCLK_FREQ_108MHzstatic void SetSysClockTo108(void);	
#endif
第四处
/*** @brief  Configures the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers.* @param  None* @retval None*/
static void SetSysClock(void)
{
#ifdef SYSCLK_FREQ_HSESetSysClockToHSE();
#elif defined SYSCLK_FREQ_24MHzSetSysClockTo24();
#elif defined SYSCLK_FREQ_36MHzSetSysClockTo36();
#elif defined SYSCLK_FREQ_48MHzSetSysClockTo48();
#elif defined SYSCLK_FREQ_56MHzSetSysClockTo56();  
#elif defined SYSCLK_FREQ_72MHzSetSysClockTo72();
#elif defined SYSCLK_FREQ_108MHzSetSysClockTo108();
#endif 
}
第五处
#elif defined SYSCLK_FREQ_108MHz
/*** @brief  Sets System clock frequency to 72MHz and configure HCLK, PCLK2 *         and PCLK1 prescalers. * @note   This function should be used only after reset.* @param  None* @retval None*/
static void SetSysClockTo108(void)
{__IO uint32_t StartUpCounter = 0, HSEStatus = 0;  /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/    /* Enable HSE */    RCC->CR |= ((uint32_t)RCC_CR_HSEON); /* Wait till HSE is ready and if Time out is reached exit */do{HSEStatus = RCC->CR & RCC_CR_HSERDY;StartUpCounter++;  } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));if ((RCC->CR & RCC_CR_HSERDY) != RESET){HSEStatus = (uint32_t)0x01;}else{HSEStatus = (uint32_t)0x00;}  if (HSEStatus == (uint32_t)0x01){/* Enable Prefetch Buffer */FLASH->ACR |= FLASH_ACR_PRFTBE;/* Flash 2 wait state */FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;     /* HCLK = SYSCLK */RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;      /* PCLK2 = HCLK */RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;    /* PCLK1 = HCLK/2 */RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
#ifdef STM32F10X_CL/* Configure PLLs ------------------------------------------------------*//* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz *//* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */        RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 |RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);  /* Enable PLL2 */RCC->CR |= RCC_CR_PLL2ON;/* Wait till PLL2 is ready */while((RCC->CR & RCC_CR_PLL2RDY) == 0){}    /* PLL configuration: PLLCLK = PREDIV1 * 9 = 72 MHz */ RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 | RCC_CFGR_PLLMULL9); 
#else    /*  PLL configuration: PLLCLK = HSE/2 * 27 = 108 MHz */RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |RCC_CFGR_PLLMULL));RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSI_Div2 | RCC_CFGR_PLLMULL27);
#endif /* STM32F10X_CL *//* Enable PLL */RCC->CR |= RCC_CR_PLLON;/* Wait till PLL is ready */while((RCC->CR & RCC_CR_PLLRDY) == 0){}    /* Select PLL as system clock source */RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;    /* Wait till PLL is used as system clock source */while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08){}}else{ /* If HSE fails to start-up, the application will have wrong clock configuration. User can add here some code to deal with this error */}
}
#endif
2.2.3 串口

一开始我改完时钟108MHZ,试了串口,然后发现乱码,后面查了资料,才知道在stm32f10x_rcc.c文件中RCC_GetClocksFreq函数要新增以下代码。

if(RCC->CFGR & 0x08000000)这行代码用于检查RCC->CFGR寄存器中特定位(第27位)的值。如果该位为1,就会执行pllmull += 15;,即将pllmull变量的值增加15,变成27倍频刚好对应上面的108MHZ。

代码如下(示例):

/*** @brief  Returns the frequencies of different on chip clocks.* @param  RCC_Clocks: pointer to a RCC_ClocksTypeDef structure which will hold*         the clocks frequencies.* @note   The result of this function could be not correct when using *         fractional value for HSE crystal.  * @retval None*/
void RCC_GetClocksFreq(RCC_ClocksTypeDef* RCC_Clocks)
{uint32_t tmp = 0, pllmull = 0, pllsource = 0, presc = 0;#ifdef  STM32F10X_CLuint32_t prediv1source = 0, prediv1factor = 0, prediv2factor = 0, pll2mull = 0;
#endif /* STM32F10X_CL */#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL)uint32_t prediv1factor = 0;
#endif    /* Get SYSCLK source -------------------------------------------------------*/tmp = RCC->CFGR & CFGR_SWS_Mask;switch (tmp){case 0x00:  /* HSI used as system clock */RCC_Clocks->SYSCLK_Frequency = HSI_VALUE;break;case 0x04:  /* HSE used as system clock */RCC_Clocks->SYSCLK_Frequency = HSE_VALUE;break;case 0x08:  /* PLL used as system clock *//* Get PLL clock source and multiplication factor ----------------------*/pllmull = RCC->CFGR & CFGR_PLLMull_Mask;pllsource = RCC->CFGR & CFGR_PLLSRC_Mask;      
#ifndef STM32F10X_CL      pllmull = ( pllmull >> 18) + 2;      if(RCC->CFGR & 0x08000000)//取27位{pllmull += 15;}						if (pllsource == 0x00){/* HSI oscillator clock divided by 2 selected as PLL clock entry */RCC_Clocks->SYSCLK_Frequency = (HSI_VALUE >> 1) * pllmull;}else{#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL)prediv1factor = (RCC->CFGR2 & CFGR2_PREDIV1) + 1;/* HSE oscillator clock selected as PREDIV1 clock entry */RCC_Clocks->SYSCLK_Frequency = (HSE_VALUE / prediv1factor) * pllmull; #else/* HSE selected as PLL clock entry */if ((RCC->CFGR & CFGR_PLLXTPRE_Mask) != (uint32_t)RESET){/* HSE oscillator clock divided by 2 */RCC_Clocks->SYSCLK_Frequency = (HSE_VALUE >> 1) * pllmull;}else{RCC_Clocks->SYSCLK_Frequency = HSE_VALUE * pllmull;}#endif}
#elsepllmull = pllmull >> 18;      if (pllmull != 0x0D){pllmull += 2;}else{ /* PLL multiplication factor = PLL input clock * 6.5 */pllmull = 13 / 2; }            if (pllsource == 0x00){/* HSI oscillator clock divided by 2 selected as PLL clock entry */RCC_Clocks->SYSCLK_Frequency = (HSI_VALUE >> 1) * pllmull;}else{/* PREDIV1 selected as PLL clock entry */        /* Get PREDIV1 clock source and division factor */prediv1source = RCC->CFGR2 & CFGR2_PREDIV1SRC;prediv1factor = (RCC->CFGR2 & CFGR2_PREDIV1) + 1;        if (prediv1source == 0){ /* HSE oscillator clock selected as PREDIV1 clock entry */RCC_Clocks->SYSCLK_Frequency = (HSE_VALUE / prediv1factor) * pllmull;          }else{/* PLL2 clock selected as PREDIV1 clock entry */          /* Get PREDIV2 division factor and PLL2 multiplication factor */prediv2factor = ((RCC->CFGR2 & CFGR2_PREDIV2) >> 4) + 1;pll2mull = ((RCC->CFGR2 & CFGR2_PLL2MUL) >> 8 ) + 2; RCC_Clocks->SYSCLK_Frequency = (((HSE_VALUE / prediv2factor) * pll2mull) / prediv1factor) * pllmull;                         }}
#endif /* STM32F10X_CL */ break;default:RCC_Clocks->SYSCLK_Frequency = HSI_VALUE;break;}/* Compute HCLK, PCLK1, PCLK2 and ADCCLK clocks frequencies ----------------*//* Get HCLK prescaler */tmp = RCC->CFGR & CFGR_HPRE_Set_Mask;tmp = tmp >> 4;presc = APBAHBPrescTable[tmp];/* HCLK clock frequency */RCC_Clocks->HCLK_Frequency = RCC_Clocks->SYSCLK_Frequency >> presc;/* Get PCLK1 prescaler */tmp = RCC->CFGR & CFGR_PPRE1_Set_Mask;tmp = tmp >> 8;presc = APBAHBPrescTable[tmp];/* PCLK1 clock frequency */RCC_Clocks->PCLK1_Frequency = RCC_Clocks->HCLK_Frequency >> presc;/* Get PCLK2 prescaler */tmp = RCC->CFGR & CFGR_PPRE2_Set_Mask;tmp = tmp >> 11;presc = APBAHBPrescTable[tmp];/* PCLK2 clock frequency */RCC_Clocks->PCLK2_Frequency = RCC_Clocks->HCLK_Frequency >> presc;/* Get ADCCLK prescaler */tmp = RCC->CFGR & CFGR_ADCPRE_Set_Mask;tmp = tmp >> 14;presc = ADCPrescTable[tmp];/* ADCCLK clock frequency */RCC_Clocks->ADCCLK_Frequency = RCC_Clocks->PCLK2_Frequency / presc;
}
2.2.4 FLASH

因为GD的Flash是自己的专利技术,而ST的Flash则是由第三方提供的,所以,当进行Flash取值操作时,GD32F10X芯片可以达到零等待周期的响应时间,而ST芯片则需要等待两个周期。另一方面,GD芯片的Flash擦除和编程时间可能会比ST芯片长一些。

所以针对这个不同需要增加两个空循环__NOP();指令进行等待。

代码如下(示例):

/*** @brief  Erases the FLASH option bytes.* @note   This functions erases all option bytes except the Read protection (RDP). * @note   This function can be used for all STM32F10x devices.* @param  None* @retval FLASH Status: The returned value can be: FLASH_ERROR_PG,*         FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.*/
FLASH_Status FLASH_EraseOptionBytes(void)
{uint16_t rdptmp = RDP_Key;FLASH_Status status = FLASH_COMPLETE;/* Get the actual read protection Option Byte value */ if(FLASH_GetReadOutProtectionStatus() != RESET){rdptmp = 0x00;  }/* Wait for last operation to be completed */status = FLASH_WaitForLastOperation(EraseTimeout);if(status == FLASH_COMPLETE){/* Authorize the small information block programming */FLASH->OPTKEYR = FLASH_KEY1;FLASH->OPTKEYR = FLASH_KEY2;    __NOP();__NOP();    /* if the previous operation is completed, proceed to erase the option bytes */FLASH->CR |= CR_OPTER_Set;FLASH->CR |= CR_STRT_Set;/* Wait for last operation to be completed */status = FLASH_WaitForLastOperation(EraseTimeout);    if(status == FLASH_COMPLETE){/* if the erase operation is completed, disable the OPTER Bit */FLASH->CR &= CR_OPTER_Reset;       /* Enable the Option Bytes Programming operation */FLASH->CR |= CR_OPTPG_Set;/* Restore the last read protection Option Byte value */OB->RDP = (uint16_t)rdptmp; /* Wait for last operation to be completed */status = FLASH_WaitForLastOperation(ProgramTimeout);if(status != FLASH_TIMEOUT){/* if the program operation is completed, disable the OPTPG Bit */FLASH->CR &= CR_OPTPG_Reset;}}else{if (status != FLASH_TIMEOUT){/* Disable the OPTPG Bit */FLASH->CR &= CR_OPTPG_Reset;}}  }/* Return the erase status */return status;
}

除了FLASH_EraseOptionBytes函数外,还有下面三个函数也需要增加 __NOP();

FLASH_Status FLASH_ProgramOptionByteData(uint32_t Address, uint8_t Data);
FLASH_Status FLASH_EnableWriteProtection(uint32_t FLASH_Pages);
FLASH_Status FLASH_ReadOutProtection(FunctionalState NewState);

GD芯片的Flash擦除和编程时间可能会比ST芯片长一些,所以把擦除和编程时间变长些。

/* Delay definition */   
#define EraseTimeout          ((uint32_t)0x000fffff)//0x000B0000   
#define ProgramTimeout        ((uint32_t)0x0000ffff)//0x00002000

四、总结

今天是STM32到GD32的工程移植经验分享,附件是移植好的工程。感谢你的观看,谢谢!

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/577313.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

等级保护的网络安全技术措施

目录 结构安全 访问控制 ​编辑 安全审计 边界完整性检查 入侵防范 恶意代码防范 网络设备防护 结构安全 访问控制 安全审计 边界完整性检查 入侵防范 恶意代码防范 网络设备防护 ~over~

date-fns v3 发布——这个由 200 个函数组成的 JavaScript 日期处理套件

date-fns v3 发布——这个由 200 个函数组成的 JavaScript 日期处理套件已经在 TypeScript 中重写&#xff0c;重新引入了 String 日期参数&#xff0c;在 Node 上支持 ESM&#xff0c;并且所有函数现在都可以通过命名导出导出。 经过几个月的开发&#xff0c;v3 终于出来了&a…

力扣经典面试题——搜索旋转排序数组及最小值(二分搜索旋转数组系列一次搞定)

我们先来看看一个常规的二分搜索是如何进行的&#xff1f; 例如要找一个有序数组的某个数 【1&#xff0c;2&#xff0c;4&#xff0c;5&#xff0c;9&#xff0c;11&#xff0c;15&#xff0c;19】 我们要找11&#xff0c;每次我们分割半边判断然后看到底在哪一边。 这里为什么…

Neovim+ctag浏览、编辑源代码

Neovimctag浏览、编辑源代码 一 配置安装vim及 ctags vim应该可以不用装&#xff0c;直接装neovim&#xff0c;这里我是先装了vim再装的neovim Ctags必须装&#xff0c;后面用neovim telescope索引函数时才有效 vim复制系统粘贴板&#xff1a;vim输入模式下&#xff0c;按shi…

[kubernetes]Kube-APIServer

API Server API Server是什么 提供集群管理的REST API接口&#xff0c;包括认证授权、数据校验以及集群状态变更等提供其他模块之间的数据交互和通信的枢纽&#xff08;其他模块通过API Server查询或修改数据&#xff0c;只有API Server才直接操作etcd&#xff09; 访问控制…

开源自托管导航页配置服务Dashy本地搭建结合内网穿透远程访问

开源自托管导航页配置服务Dashy本地搭建结合内网穿透远程访问 简介1. 安装Dashy2. 安装cpolar3.配置公网访问地址4. 固定域名访问 简介 Dashy 是一个开源的自托管的导航页配置服务&#xff0c;具有易于使用的可视化编辑器、状态检查、小工具和主题等功能。你可以将自己常用的一…

Mongodb基础介绍与应用场景

NoSql 解决方案第二种 Mongodb MongoDB 是一款开源 高性能 无模式的文档型数据库 当然 它是NoSql数据库中的一种 是最像关系型数据库的 非关系型数据库 首先 最需要注意的是 无模式的文档型数据库 这个需要后面我们看到它的数据才能明白 其次是 最像关系型数据库的非关系型数据…

RK3588平台开发系列讲解(AI 篇)RKNN 数据结构详解

文章目录 一、rknn_sdk_version二、rknn_input_output_num三、rknn_tensor_attr四、rknn_perf_detail五、rknn_perf_run六、rknn_mem_size七、rknn_tensor_mem八、rknn_input九、rknn_output沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇章主要讲解 RKNN 相关的数…

Autosar CAN开发02(入门Autosar)

Autosar架构 想起当时刚毕业进入公司之后&#xff0c;我的岗位是Autosar Bsw软件工程师。 看着这个什么“Autosar”&#xff0c;真的是一脸懵。 后来才知道&#xff0c;按照我的理解&#xff1a;Autosar就是一个软件架构。它分为ASW和BSW。ASW负责实现应用层功能&#xff08…

“React学习之旅:从入门到精通的点滴感悟“

在探索和学习React的过程中&#xff0c;我逐渐领悟到了前端开发的魅力与挑战。React&#xff0c;作为Facebook推出的开源JavaScript库&#xff0c;以其独特的思维方式和强大的功能&#xff0c;引领着前端开发的潮流。在这篇文章中&#xff0c;我将分享我的React学习心得&#x…

test assert-01-Google Truth 断言

Truth Truth 是用于Java测试的断言框架&#xff0c;灵感来自于FEST&#xff0c;并受到一些可扩展性需求的驱动&#xff0c;几乎完全由谷歌员工在业余时间编写&#xff0c;或者作为Java核心图书馆管理员的身份做出贡献。 作用 作为工程师&#xff0c;我们花费大部分的时间来阅…

《C++避坑神器·二十四》简单搞懂json文件的读写之根据键值对读写Json

c11 json解析库nlohmann/json.hpp文件整个代码由一个头文件组成 json.hpp&#xff0c;没有子项目&#xff0c;没有依赖关系&#xff0c;没有复杂的构建系统&#xff0c;使用起来非常方便。 json.hpp库在文章末尾下载 读写主要有两种方式&#xff0c;第一种根据键值对读写&…

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之Progress进度条组件

鸿蒙&#xff08;HarmonyOS&#xff09;项目方舟框架&#xff08;ArkUI&#xff09;之Progress进度条组件 一、操作环境 操作系统: Windows 10 专业版、IDE:DevEco Studio 3.1、SDK:HarmonyOS 3.1 二、Progress组件 进度条也是UI开发最常用的组件之一&#xff0c;进度条组件…

OpenAI换血大震动始末:“ChatGPT之父”奥特曼,缘何被“扫地出门”?

近期&#xff0c;AI业界发生了一场“大地震”。作为聊天机器人ChatGPT的开发者&#xff0c;OpenAI无疑是最受关注的人工智能公司之一。就是这家公司的联合创始人、CEO、有“ChatGPT之父”之称的阿尔特曼在“疯狂的5天”里&#xff0c;经历了被闪电免职、加入微软、最终又官复原…

影响嵌入式项目成功的一些要素

选择了嵌入式开发这个技术领域&#xff0c;就相当于选择了一条充满挑战的技术开发道路。 对于工程师而言&#xff0c;项目的成功和失败对他们十分重要。因为一行行代码他们不知道熬了多少个通宵&#xff0c;脑细胞死了多少而写出来的。 如果项目失败了&#xff0c;就意味着辛辛…

移动开发新的风口?Harmony4.0鸿蒙应用开发基础+实践案例

前段时间鸿蒙4.0引发了很多讨论&#xff0c;不少业内人士认为&#xff0c;鸿蒙将与iOS、安卓鼎足而三了。 事实上&#xff0c;从如今手机操作系统竞赛中不难看出&#xff0c;安卓与iOS的形态、功能逐渐趋同化&#xff0c;两大系统互相取长补短&#xff0c;综合性能等差距越来越…

【Element】el-select下拉框实现选中图标并回显图标

一、背景 需求&#xff1a;在下拉框中选择图标&#xff0c;并同时显示图标和文字&#xff0c;以便用户可以直观地选择所需的图标。 二、功能实现 <template><div><el-table ref"table" :data"featureCustom2List" height"200"…

分享71个Java源码总有一个是你想要的

分享71个Java源码总有一个是你想要的 学习知识费力气&#xff0c;收集整理更不易。 知识付费甚欢喜&#xff0c;为咱码农谋福利。 链接&#xff1a;https://pan.baidu.com/s/1frK-W3GT8WrydSlQ-E3o6A?pwd6666 提取码&#xff1a;6666 UI代码 def __init__(self):import …

Text2SQL学习整理(五)将Text-to-SQL任务与基本语言模型结合

导语 上篇博客&#xff1a;Text2SQL学习整理&#xff08;四&#xff09;将预训练语言模型引入WikiSQL任务简要介绍了两个借助预训练语言模型BERT来解决WIkiSQL数据集挑战的方法&#xff1a;SQLOVA和X-SQL模型。其中&#xff0c;借助预训练语言模型的强大表示能力&#xff0c;S…

【Gitlab】CICD流水线自动化部署教程

第一步&#xff0c;准备 GitLab 仓库 这个不用多说&#xff0c;得先保证你的项目已经托管在一个 GitLab 仓库中。 第二步&#xff0c;定义 .gitlab-ci.yml 文件 在你的项目根目录中创建一个 .gitlab-ci.yml 文件。这个文件将定义所有 CI/CD 的工作流程&#xff0c;包括构建、测…