元驭机器人元驭机器人Hall 传感器教学下载原文件
1/*!2    \file  system_gd32e23x.c3    \brief CMSIS Cortex-M23 Device Peripheral Access Layer Source File for4           GD32E23x Device Series5*/67/* Copyright (c) 2012 ARM LIMITED8   Copyright (c) 2026, GigaDevice Semiconductor Inc.910   All rights reserved.11   Redistribution and use in source and binary forms, with or without12   modification, are permitted provided that the following conditions are met:13   - Redistributions of source code must retain the above copyright14     notice, this list of conditions and the following disclaimer.15   - Redistributions in binary form must reproduce the above copyright16     notice, this list of conditions and the following disclaimer in the17     documentation and/or other materials provided with the distribution.18   - Neither the name of ARM nor the names of its contributors may be used19     to endorse or promote products derived from this software without20     specific prior written permission.21   *22   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"23   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE24   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE25   ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE26   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR27   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF28   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS29   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN30   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)31   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE32   POSSIBILITY OF SUCH DAMAGE.33   ---------------------------------------------------------------------------*/3435/* This file refers the CMSIS standard, some adjustments are made according to GigaDevice chips */3637#include "gd32e23x.h"3839/* system frequency define */40#define __IRC8M           (IRC8M_VALUE)            /* internal 8 MHz RC oscillator frequency */41#define __HXTAL           (HXTAL_VALUE)            /* high speed crystal oscillator frequency */42#define __SYS_OSC_CLK     (__IRC8M)                /* main oscillator frequency */4344#define VECT_TAB_OFFSET  (uint32_t)0x00            /* vector table base offset */4546/* select a system clock by uncommenting the following line */47/* 本板 OSCIN/OSCOUT(PF0/PF1)未接晶振。使用 HXTAL 会在等时钟稳定时死循环。 */48//#define __SYSTEM_CLOCK_8M_HXTAL              (__HXTAL)49//#define __SYSTEM_CLOCK_8M_IRC8M              (__IRC8M)50//#define __SYSTEM_CLOCK_72M_PLL_HXTAL         (uint32_t)(72000000)51#define __SYSTEM_CLOCK_72M_PLL_IRC8M_DIV2    (uint32_t)(72000000)5253/* The following is to prevent Vcore fluctuations caused by frequency switching.54   It is strongly recommended to include it to avoid issues caused by self-removal.55*/56#define RCU_MODIFY(__delay)     do{                                     \57                                    volatile uint32_t i,reg;            \58                                    if(0U != (__delay)){                   \59                                        reg = RCU_CFG0;                 \60                                        reg &= ~(RCU_CFG0_AHBPSC);      \61                                        /* CK_AHB = SYSCLK/2 */         \62                                        reg |= RCU_AHB_CKSYS_DIV2;      \63                                        RCU_CFG0 = reg;                 \64                                        for(i=0U; i<(__delay); i++){       \65                                        }                               \66                                        reg = RCU_CFG0;                 \67                                        reg &= ~(RCU_CFG0_AHBPSC);      \68                                        reg |= RCU_AHB_CKSYS_DIV4;      \69                                        /* CK_AHB = SYSCLK/4 */         \70                                        RCU_CFG0 = reg;                 \71                                        for(i=0U; i<(__delay); i++){       \72                                        }                               \73                                    }                                   \74                                }while(0U)7576#define RCU_MODIFY_UP_2(__delay)     do{                                    \77                                        volatile uint32_t i,reg;            \78                                        if(0U != (__delay)){                   \79                                            for(i=0U; i<(__delay); i++){       \80                                            }                               \81                                            reg = RCU_CFG0;                 \82                                            reg &= ~(RCU_CFG0_AHBPSC);      \83                                            reg |= RCU_AHB_CKSYS_DIV2;      \84                                            RCU_CFG0 = reg;                 \85                                            for(i=0U; i<(__delay); i++){       \86                                            }                               \87                                            reg = RCU_CFG0;                 \88                                            reg &= ~(RCU_CFG0_AHBPSC);      \89                                            reg |= RCU_AHB_CKSYS_DIV1;      \90                                            RCU_CFG0 = reg;                 \91                                    }                                       \92                                }while(0U)9394#define SEL_IRC8M       0x00U95#define SEL_HXTAL       0x01U96#define SEL_PLL         0x02U9798/* set the system clock frequency and declare the system clock configuration function */99#ifdef __SYSTEM_CLOCK_8M_HXTAL100uint32_t SystemCoreClock = __SYSTEM_CLOCK_8M_HXTAL;101static void system_clock_8m_hxtal(void);102103#elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL)104uint32_t SystemCoreClock = __SYSTEM_CLOCK_72M_PLL_HXTAL;105static void system_clock_72m_hxtal(void);106107#elif defined (__SYSTEM_CLOCK_72M_PLL_IRC8M_DIV2)108uint32_t SystemCoreClock = __SYSTEM_CLOCK_72M_PLL_IRC8M_DIV2;109static void system_clock_72m_irc8m(void);110111#else112uint32_t SystemCoreClock = __SYSTEM_CLOCK_8M_IRC8M;113static void system_clock_8m_irc8m(void);114#endif /* __SYSTEM_CLOCK_8M_HXTAL */115116/* configure the system clock */117static void system_clock_config(void);118static void _soft_delay_(uint32_t time);119120/* software delay to prevent the impact of Vcore fluctuations.121   It is strongly recommended to include it to avoid issues caused by self-removal. */122static void _soft_delay_(uint32_t time)123{124    __IO uint32_t i;125    for(i=0U; i<time*10U; i++){126    }127}128129/*!130    \brief      setup the microcontroller system, initialize the system131    \param[in]  none132    \param[out] none133    \retval     none134    \note       This function contains scenarios leading to an infinite loop.135                Modify according to the use's actual usage scenarios.136*/137void SystemInit(void)138{139    /* enable IRC8M */140    RCU_CTL0 |= RCU_CTL0_IRC8MEN;141    while(0U == (RCU_CTL0 & RCU_CTL0_IRC8MSTB)){142    }143    if(((RCU_CFG0 & RCU_CFG0_SCSS) == RCU_SCSS_PLL)){144        RCU_MODIFY(0x80U);145    }146    RCU_CFG0 &= ~RCU_CFG0_SCS;147    _soft_delay_(100U);148    RCU_CTL0 &= ~(RCU_CTL0_HXTALEN | RCU_CTL0_CKMEN | RCU_CTL0_PLLEN | RCU_CTL0_HXTALBPS);149    /* reset RCU */150    RCU_CFG0 &= ~(RCU_CFG0_SCS | RCU_CFG0_AHBPSC | RCU_CFG0_APB1PSC | RCU_CFG0_APB2PSC |\151                  RCU_CFG0_ADCPSC | RCU_CFG0_CKOUTSEL | RCU_CFG0_CKOUTDIV | RCU_CFG0_PLLDV);152    RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PLLMF | RCU_CFG0_PLLMF4 | RCU_CFG0_PLLDV);153    RCU_CFG1 &= ~(RCU_CFG1_PREDV);154    RCU_CFG2 &= ~(RCU_CFG2_USART0SEL | RCU_CFG2_ADCSEL);155    RCU_CFG2 &= ~RCU_CFG2_IRC28MDIV;156    RCU_CFG2 &= ~RCU_CFG2_ADCPSC2;157    RCU_CTL1 &= ~RCU_CTL1_IRC28MEN;158    RCU_INT = 0x00000000U;159160    /* configure system clock */161    system_clock_config();162    163#ifdef VECT_TAB_SRAM164    nvic_vector_table_set(NVIC_VECTTAB_RAM,VECT_TAB_OFFSET);165#else166    nvic_vector_table_set(NVIC_VECTTAB_FLASH,VECT_TAB_OFFSET);167#endif168}169170/*!171    \brief      configure the system clock172    \param[in]  none173    \param[out] none174    \retval     none175*/176static void system_clock_config(void)177{178#ifdef __SYSTEM_CLOCK_8M_HXTAL179    system_clock_8m_hxtal();180#elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL)181    system_clock_72m_hxtal();182#elif defined (__SYSTEM_CLOCK_72M_PLL_IRC8M_DIV2)183    system_clock_72m_irc8m();184#elif defined (__SYSTEM_CLOCK_72M_PLL_IRC48M_DIV2)185    system_clock_72m_irc48m();186#else187    system_clock_8m_irc8m();188#endif /* __SYSTEM_CLOCK_8M_HXTAL */189}190191#ifdef __SYSTEM_CLOCK_8M_HXTAL192/*!193    \brief      configure the system clock to 8M by HXTAL194    \param[in]  none195    \param[out] none196    \retval     none197    \note       This function contains scenarios leading to an infinite loop.198                Modify according to the use's actual usage scenarios.199*/200static void system_clock_8m_hxtal(void)201{202    uint32_t timeout = 0U;203    uint32_t stab_flag = 0U;204    __IO uint32_t reg_temp;205206    /* enable HXTAL */207    RCU_CTL0 |= RCU_CTL0_HXTALEN;208    209    /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */210    do{211        timeout++;212        stab_flag = (RCU_CTL0 & RCU_CTL0_HXTALSTB);213    }214    while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout));    215    /* if fail */216    if(0U == (RCU_CTL0 & RCU_CTL0_HXTALSTB)){217        while(1){218        }219    }220    221    /* HXTAL is stable */222    /* AHB = SYSCLK */223    RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;224    /* APB2 = AHB */225    RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;226    /* APB1 = AHB */227    RCU_CFG0 |= RCU_APB1_CKAHB_DIV1;228229    reg_temp = RCU_CFG0;230    /* select HXTAL as system clock */231    reg_temp &= ~RCU_CFG0_SCS;232    reg_temp |= RCU_CKSYSSRC_HXTAL;233    RCU_CFG0 = reg_temp;234    235    /* wait until HXTAL is selected as system clock */236    while(RCU_SCSS_HXTAL != (RCU_CFG0 & RCU_CFG0_SCSS)){237    }238}239240#elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL)241/*!242    \brief      configure the system clock to 72M by PLL which selects HXTAL as its clock source243    \param[in]  none244    \param[out] none245    \retval     none246    \note       This function contains scenarios leading to an infinite loop.247                Modify according to the use's actual usage scenarios.248*/249static void system_clock_72m_hxtal(void)250{251    uint32_t timeout = 0U;252    uint32_t stab_flag = 0U;253    __IO uint32_t reg_temp;254    255    /* enable HXTAL */256    RCU_CTL0 |= RCU_CTL0_HXTALEN;257258    /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */259    do{260        timeout++;261        stab_flag = (RCU_CTL0 & RCU_CTL0_HXTALSTB);262    }263    while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout));264    /* if fail */265    if(0U == (RCU_CTL0 & RCU_CTL0_HXTALSTB)){266        while(1){267        }268    }269    270    FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | WS_WSCNT_2;271    272    /* HXTAL is stable */273    /* AHB = SYSCLK/4 */274    RCU_CFG0 |= RCU_AHB_CKSYS_DIV4;275    /* APB2 = AHB */276    RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;277    /* APB1 = AHB */278    RCU_CFG0 |= RCU_APB1_CKAHB_DIV1;279280    /* PLL = HXTAL * 9 = 72 MHz */281    RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PLLMF | RCU_CFG0_PLLDV);282    RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL9);283284    /* enable PLL */285    RCU_CTL0 |= RCU_CTL0_PLLEN;286287    /* wait until PLL is stable */288    while(0U == (RCU_CTL0 & RCU_CTL0_PLLSTB)){289    }290291    reg_temp = RCU_CFG0;292    /* select PLL as system clock */293    reg_temp &= ~RCU_CFG0_SCS;294    reg_temp |= RCU_CKSYSSRC_PLL;295    RCU_CFG0 = reg_temp;296297    /* wait until PLL is selected as system clock */298    while(RCU_SCSS_PLL != (RCU_CFG0 & RCU_CFG0_SCSS)){299    }300301    RCU_MODIFY_UP_2(0x80U);302}303304#elif defined (__SYSTEM_CLOCK_72M_PLL_IRC8M_DIV2)305/*!306    \brief      configure the system clock to 72M by PLL which selects IRC8M/2 as its clock source307    \param[in]  none308    \param[out] none309    \retval     none310    \note       This function contains scenarios leading to an infinite loop.311                Modify according to the use's actual usage scenarios.312*/313static void system_clock_72m_irc8m(void)314{315    uint32_t timeout = 0U;316    uint32_t stab_flag = 0U;317    __IO uint32_t reg_temp;318    319    /* enable IRC8M */320    RCU_CTL0 |= RCU_CTL0_IRC8MEN;321322    /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */323    do{324        timeout++;325        stab_flag = (RCU_CTL0 & RCU_CTL0_IRC8MSTB);326    }327    while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout));328329    /* if fail */330    if(0U == (RCU_CTL0 & RCU_CTL0_IRC8MSTB)){331        while(1){332        }333    }334335    FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | WS_WSCNT_2;336    337    /* AHB = SYSCLK/4 */338    RCU_CFG0 |= RCU_AHB_CKSYS_DIV4;339    /* APB2 = AHB */340    RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;341    /* APB1 = AHB */342    RCU_CFG0 |= RCU_APB1_CKAHB_DIV1;343    /* PLL = (IRC8M/2) * 18 = 72 MHz */344    RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PLLMF);345    RCU_CFG0 |= (RCU_PLLSRC_IRC8M_DIV2 | RCU_PLL_MUL18);346    347    /* enable PLL */348    RCU_CTL0 |= RCU_CTL0_PLLEN;349350    /* wait until PLL is stable */351    while(0U == (RCU_CTL0 & RCU_CTL0_PLLSTB)){352    }353354    reg_temp = RCU_CFG0;355    /* select PLL as system clock */356    reg_temp &= ~RCU_CFG0_SCS;357    reg_temp |= RCU_CKSYSSRC_PLL;358    RCU_CFG0 = reg_temp;359360    /* wait until PLL is selected as system clock */361    while(RCU_SCSS_PLL != (RCU_CFG0 & RCU_CFG0_SCSS)){362    }363364    RCU_MODIFY_UP_2(0x80);365}366367#else368/*!369    \brief      configure the system clock to 8M by IRC8M370    \param[in]  none371    \param[out] none372    \retval     none373    \note       This function contains scenarios leading to an infinite loop.374                Modify according to the use's actual usage scenarios.375*/376static void system_clock_8m_irc8m(void)377{378    uint32_t timeout = 0U;379    uint32_t stab_flag = 0U;380    __IO uint32_t reg_temp;381    382    /* enable IRC8M */383    RCU_CTL0 |= RCU_CTL0_IRC8MEN;384385    /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */386    do{387        timeout++;388        stab_flag = (RCU_CTL0 & RCU_CTL0_IRC8MSTB);389    }390    while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout));391392    /* if fail */393    if(0U == (RCU_CTL0 & RCU_CTL0_IRC8MSTB)){394        while(1){395        }396    }397398    /* AHB = SYSCLK */399    RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;400    /* APB2 = AHB */401    RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;402    /* APB1 = AHB */403    RCU_CFG0 |= RCU_APB1_CKAHB_DIV1;404    405    reg_temp = RCU_CFG0;406    /* select IRC8M as system clock */407    reg_temp &= ~RCU_CFG0_SCS;408    reg_temp |= RCU_CKSYSSRC_IRC8M;409    RCU_CFG0 = reg_temp;410    411    /* wait until IRC8M is selected as system clock */412    while(RCU_SCSS_IRC8M != (RCU_CFG0 & RCU_CFG0_SCSS)){413    }414}415#endif /* __SYSTEM_CLOCK_8M_HXTAL */416417/*!418    \brief      update the SystemCoreClock with current core clock retrieved from cpu registers419    \param[in]  none420    \param[out] none421    \retval     none422*/423void SystemCoreClockUpdate (void)424{425    uint32_t sws = 0U;426    uint32_t pllmf = 0U, pllmf4 = 0U, pllsel = 0U, prediv = 0U, idx = 0U, clk_exp = 0U;427    /* exponent of AHB clock divider */428    const uint8_t ahb_exp[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};429430    sws = GET_BITS(RCU_CFG0, 2, 3);431    switch(sws){432    /* IRC8M is selected as CK_SYS */433    case SEL_IRC8M:434        SystemCoreClock = IRC8M_VALUE;435        break;436    /* HXTAL is selected as CK_SYS */437    case SEL_HXTAL:438        SystemCoreClock = HXTAL_VALUE;439        break;440    /* PLL is selected as CK_SYS */441    case SEL_PLL:442        /* get the value of PLLMF[3:0] */443        pllmf = GET_BITS(RCU_CFG0, 18, 21);444        pllmf4 = GET_BITS(RCU_CFG0, 27, 27);445        /* high 16 bits */446        if(1U == pllmf4){447            pllmf += 17U;448        }else if(15U == pllmf){449            pllmf = 16U;450        } else {451            pllmf += 2U;452        }453        454        /* PLL clock source selection, HXTAL or IRC8M/2 */455        pllsel = GET_BITS(RCU_CFG0, 16, 16);456        if(0U != pllsel){457            prediv = (GET_BITS(RCU_CFG1, 0, 3) + 1U);458            SystemCoreClock = (HXTAL_VALUE / prediv) * pllmf;459        } else {460            SystemCoreClock = (IRC8M_VALUE >> 1) * pllmf;461        }462        break;463    /* IRC8M is selected as CK_SYS */464    default:465        SystemCoreClock = IRC8M_VALUE;466        break;467    }468    /* calculate AHB clock frequency */469    idx = GET_BITS(RCU_CFG0, 4, 7);470    clk_exp = ahb_exp[idx];471    SystemCoreClock >>= clk_exp;472}473474#ifdef __FIRMWARE_VERSION_DEFINE475/*!476    \brief      get firmware version477    \param[in]  none478    \param[out] none479    \retval     firmware version480*/481uint32_t gd32e23x_firmware_version_get(void)482{483    return (uint32_t)__GD32E23x_STDPERIPH_VERSION;484}485#endif /* __FIRMWARE_VERSION_DEFINE */