华大HC32F460 Systick滴答定时器代码详解

声明:以下都是自己学习的一些心得。

一、Systick滴答定时器基础知识

由官方提供的用户手册可知,Systick滴答定时器的时钟源来自内部低速振荡器(LRC时钟),频率为32.768KHz。

二、代码实现

打开相关寄存器的宏,在文件hc32f4xx_conf.h

#define LL_CLK_ENABLE                               (DDL_ON)
#define LL_EFM_ENABLE                               (DDL_ON)
#define LL_GPIO_ENABLE                              (DDL_ON)
#define LL_INTERRUPTS_ENABLE                        (DDL_ON)
#define LL_PWC_ENABLE                               (DDL_ON)
#define LL_FCG_ENABLE                               (DDL_ON)

main.c头文件中,定义相关寄存器写保护的宏。

/* unlock/lock peripheral */
#define EXAMPLE_PERIPH_WE               (LL_PERIPH_GPIO | LL_PERIPH_EFM | LL_PERIPH_FCG | \
                                         LL_PERIPH_PWC_CLK_RMU | LL_PERIPH_SRAM)
#define EXAMPLE_PERIPH_WP               (LL_PERIPH_EFM | LL_PERIPH_FCG | LL_PERIPH_SRAM)

解释上面的宏内容:

LL_PERIPH_EFM 是嵌入式FLASH寄存器的写保护,FLASH是用来存储程序的。

LL_PERIPH_FCG 是控制器,控制相关寄存器(自己用到的)的使能。

LL_PERIPH_PWC_CLK_RMU 是 PWC、CLK、RMU寄存器的写保护,如何实现呢?根据以下代码:

__STATIC_INLINE void PWC_REG_Unlock(uint16_t u16Module)
{
    SET_REG16_BIT(CM_PWC->FPRC, u16Module);
}

也就是通过对PWC(电源控制)中FPRC(功能保护控制寄存器)操作最低两位b0、b1实现,这两位保护对象有很多,具体看用户手册 参考表5-9。

LL_PERIPH_SRAM 是静态存储器写保护,用来存储变量的。

定时器触发中断函数和主函数

void SysTick_Handler(void)
{
    SysTick_IncTick();
}

/**
 * @brief  Main function of SysTick.
 * @param  None
 * @retval int32_t return value, if needed
 */
int32_t main(void)
{
    /* Peripheral registers write unprotected */
    LL_PERIPH_WE(EXAMPLE_PERIPH_WE);
    /* Configure BSP */
    BSP_LED_Init();
    /* SysTick configuration */
    (void)SysTick_Init(1000U);
    /* Peripheral registers write protected */
    LL_PERIPH_WP(EXAMPLE_PERIPH_WP);

    for (;;) {
        BSP_LED_Toggle(LED_RED);
        SysTick_Delay(500U);
        BSP_LED_Toggle(LED_BLUE);
        SysTick_Delay(500U);
    }
}

先看主函数中,先关闭所需寄存器的写保护,LL_PERIPH_WE(EXAMPLE_PERIPH_WE);

再初始化LED灯,BSP_LED_Init();通过for循环实现IO口初始化。

void BSP_LED_Init(void)
{
    uint8_t i;
    stc_gpio_init_t stcGpioInit;

    /* configuration structure initialization */
    (void)GPIO_StructInit(&stcGpioInit);
    stcGpioInit.u16PinDir = PIN_DIR_OUT;
    /* Initialize LED pin */
    for (i = 0U; i < BSP_LED_NUM; i++) {  //BSP_LEN_NUM = 4UL
        (void)GPIO_Init(BSP_LED_PORT_PIN[i].port, BSP_LED_PORT_PIN[i].pin, &stcGpioInit);
    }
}

初始化系统滴答定时器,(void)SysTick_Init(1000U); 注意这里的1000U是频率。

这里1000U的作用是 设置定时器的步长为 1。返回值为i32Ret ,当i32Ret为LL_OK的时候,即定时器通过SysTick_Config(HCLK_VALUE / u32Freq)开启,就会触发定时器中断。

__WEAKDEF int32_t SysTick_Init(uint32_t u32Freq)
{
    int32_t i32Ret = LL_ERR;

    if ((0UL != u32Freq) && (u32Freq <= 1000UL)) {
        m_u32TickStep = 1000UL / u32Freq;
        /* Configure the SysTick interrupt */
        if (0UL == SysTick_Config(HCLK_VALUE / u32Freq)) {
            i32Ret = LL_OK;
        }
    }

    return i32Ret;
}
__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
{
  if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) 
  {
    return (1UL);                                                   /* Reload value impossible */
  }

  SysTick->LOAD  = (uint32_t)(ticks - 1UL);                         /* set reload register */
  NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
  SysTick->VAL   = 0UL;                                             /* Load the SysTick Counter Value */
  SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |
                   SysTick_CTRL_TICKINT_Msk   |
                   SysTick_CTRL_ENABLE_Msk;                         /* Enable SysTick IRQ and SysTick Timer */
  return (0UL);                                                     /* Function successful */
}

SysTick_LOAD_RELOAD_Msk 重装置最大为0xFFFFFFUL

SysTick->VAL 清空当前计数值寄存器VAL

SysTick->CTRL 为使能标志位, 这里使能了SysTick_CTRL_CLKSOURCE_Msk和SysTick_CTRL_TICKINT_Msk 。

最后LL_PERIPH_WP(EXAMPLE_PERIPH_WP)来重新开启写保护。

main函数里面的for循环就不多详细解读,具体在GPIO口代码解读里有。

接下来我们分析一下 滴答定时器触发中断函数

void SysTick_Handler(void)
{
    SysTick_IncTick();
}

SysTick_Handler()函数不需要定义,当发生中断的时候就会自动跳到这里面,因为在启动文件startup_hc32f460.s中就使用汇编声明了,不懂没关系,知道有这回事就行了。

                DCD     PendSV_Handler            ; PendSV Handler
                DCD     SysTick_Handler           ; SysTick Handler

SysTick_IncTick()是一个计数函数。

__WEAKDEF void SysTick_IncTick(void)
{
    m_u32TickCount += m_u32TickStep;
}

而这个m_u32TickCount初始为0,m_u32TickStep在主函数中通过函数(void)SysTick_Init(1000U) 设置为步长为1。

这样例程就提供了一个 使用Systick系统滴答定时器完成ms的定时,具体使用:

SysTick_Delay(500U); //500ms定时

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值