网站设计与建设课程,久久建筑网101图集下载,上海建设工程咨询网官网,编程基础知识入门文章目录 一、前言二、差异性三、软件移植部分1.前期准备1.1 安装GD32固件库1.2 选择所用芯片 2.修改程序2.1 启动时间#xff08;内部时钟可不改#xff09;2.2 主频2.2.1 系统时钟配置2.2.2 108MHz宏定义第一处第二处第三处第四处第五处 2.2.3 串口2.2.4 FLASH 四、总结 一… 文章目录 一、前言二、差异性三、软件移植部分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内核程序存储容量256KB256KBRAM总容量48KB48KBGPIO端口数量8080工作电压范围2V~3.6V2.6V~3.6V内核的供电电压1.2V1.8VCPU最大主频72MHz108MHz程序存储器类型FLASHFLASH工作温度范围-40℃~85℃-40℃~85℃ADC(位数)12bit12bitDAC(位数)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 0x05002.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要配置108MHZPLL时钟倍频因子需要配置为PLL源时钟x27由于我们在RCC_PLLConfig函数选择RCC_PLLSource_HSI_Div2HSI刚好是8MHZ一半的HSI是4MHZ4x27108MHZ
PLLMF[3:0]为第21位到18位PLL源时钟 x 27为11010第一个1其实是第27位所以时钟配置寄存器 0RCU_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 */}
}
#endif2.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的工程移植经验分享附件是移植好的工程。感谢你的观看谢谢