基于air105_project的库函数寄存器芯片数据手册_1.1.pdf手册

Air105的时钟高频震荡源* 芯片支持使用内部震荡源,或外接12MHz晶振* 芯片上电复位后ROM启动过程以内部12MHz震荡为基准* 精度芯片内部集成的12MHz晶振源为±2%,一般精度*使用外部12MHz晶振,需要软件切换,144MHz、156MHz、168MHz、180MHz、192MHz、204MHz

目录Air105的时钟高频振荡源通过PLL倍频为系统提供输入倍频的PLL时钟频率,可以通过寄存器进行配置。可选频率有:108MHz、120MHz、132MHz、144MHz、156MHz、180MHz、192MHz、204MHz分频结构FCLK/CPU_CLKHCLKPCLKQSPI低频振荡源时钟结构时钟设置

以下代码基于air105_project的库函数

注册

注册手册 Air105 芯片数据表_1.1.pdf

寄存器的基地址,定义在air105.h

#define AIR105_FLASH_BASE                       (0x01000000UL)                /*!< (FLASH     ) Base Address */
#define AIR105_SRAM_BASE                        (0x20000000UL)                /*!< (SRAM      ) Base Address */
#define AIR105_PERIPH_BASE                      (0x40000000UL)                /*!< (Peripheral) Base Address */
#define AIR105_AHB_BASE                         (AIR105_PERIPH_BASE)
#define AIR105_APB0_BASE                        (AIR105_PERIPH_BASE + 0x10000)
#define SYSCTRL_BASE                            (AIR105_APB0_BASE + 0xF000)

SYSCTRL_BASE

时钟振荡器源

振荡源选择

SYSCTRL_SYSCLKSourceSelect(SELECT_EXT12M);

图片[1]-基于air105_project的库函数寄存器芯片数据手册_1.1.pdf手册-唐朝资源网

12MHz时钟源选择:0:片外XTAL,1:片内OSC

void SYSCTRL_SYSCLKSourceSelect(SYSCLK_SOURCE_TypeDef source)
{
    assert_param(IS_SYSCLK_SOURCE(source));
    
    switch (source)
    {
    case SELECT_EXT12M:
        // FREQ_SEL 是一个32bit的寄存器, 先与补码(清零第12位), 然后写入值(0)
        SYSCTRL->FREQ_SEL = ((SYSCTRL->FREQ_SEL & (~SYSCTRL_FREQ_SEL_CLOCK_SOURCE_Mask)) | SYSCTRL_FREQ_SEL_CLOCK_SOURCE_EXT);
        break;
    
    case SELECT_INC12M:
        // 先与补码(清零第12位), 然后写入值(1)
        SYSCTRL->FREQ_SEL = ((SYSCTRL->FREQ_SEL & (~SYSCTRL_FREQ_SEL_CLOCK_SOURCE_Mask)) | SYSCTRL_FREQ_SEL_CLOCK_SOURCE_INC);
        break;
    }

图片[2]-基于air105_project的库函数寄存器芯片数据手册_1.1.pdf手册-唐朝资源网

}

时钟频率

设置使用默认内部时钟HSI(Internal clock)

void SystemClock_Config_HSI(void)
{
    // 设置CPU频率, 直接选择, 不需要计算
    SYSCTRL_PLLConfig(SYSCTRL_PLL_204MHz);
    // 分频后产生 FCLK -> 这是主程序的时钟
    SYSCTRL_PLLDivConfig(SYSCTRL_PLL_Div_None);
    // 分频产生 HCLK, 如果 FCLK > 102MHz 则无论如何设置, 都会被二分频
    SYSCTRL_HCLKConfig(SYSCTRL_HCLK_Div2);
    // 分频产生 PCLK -> 这是大部分外设的时钟
    SYSCTRL_PCLKConfig(SYSCTRL_PCLK_Div2);
    QSPI_SetLatency((uint32_t)0);
}

PLL 分频选项

#define SYSCTRL_PLL_Div_None                       ((uint32_t)0x00)
#define SYSCTRL_PLL_Div2                           ((uint32_t)0x01)
#define SYSCTRL_PLL_Div4                           ((uint32_t)0x10)

设置 SysTick

void Delay_Init(void)
{
    SYSCTRL_ClocksTypeDef clocks;
    SYSCTRL_GetClocksFreq(&clocks);
    SysTick_Config(clocks.CPU_Frequency / 1000000);   ///< 1us
}

调用 SysTick_Config 将单个 SysTick 设置为 1 us。

您也可以直接使用 SYSCTRL->HCLK_1MS_VAL * 2 / 1000。该变量表示当前时钟配置下 1ms 所需的 HCLK 时钟周期。根据当前FCLK是否大于108MHz判断是否乘以2.</p

之后每1us会调用一次SysTick_Handler(void),这里设置32bit的g_current_tick递增,可以用来做延时控制。由于 32bit 数量的限制,1. 会在 2 小时后溢出,所以这里有一个延迟限制。

void SysTick_Handler(void)
{

    g_current_tick++;
}

延时功能

为了避免溢出导致的延迟错误,需要做出判断

uint32_t get_diff_tick(uint32_t cur_tick, uint32_t prior_tick)
{
    if (cur_tick < prior_tick)
    {
        // 如果当前值比前值还小, 说明发生了溢出, 用当前值加上原值取反(即原值离溢出的距离)
        return (cur_tick + (~prior_tick));
    }
    else
    {
        return (cur_tick - prior_tick);
    }
}

图片[3]-基于air105_project的库函数寄存器芯片数据手册_1.1.pdf手册-唐朝资源网

延迟函数

void Delay_us(uint32_t usec)
{
    uint32_t old_tick;
    old_tick = g_current_tick;
    while (get_diff_tick(g_current_tick, old_tick) < usec);
}
void Delay_ms(uint32_t msec)
{
    uint32_t old_tick;
    old_tick = g_current_tick;
    while (get_diff_tick(g_current_tick, old_tick) < (msec * 1000));
}

代码

代码地址:

可以使用Keil5 MDK直接打开Demos目录下的示例工程,与Air105开发板的接线请参考上一篇文章贺州AIR105(一):Keil MDK开发环境,DAP-链接编程与调试

© 版权声明
THE END
喜欢就支持一下吧
点赞280赞赏 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容