口天土立口 发表于 2025-9-6 15:57

APM32E030的SYSTICK驱动

本帖最后由 口天土立口 于 2025-9-7 18:33 编辑

每个Cortex-M处理器内部均为SysTick计时器,为24bit倒计时计数器。
可用于计时和延时。

本次代码基于开发板:APM32E030R Micro-EVB

/* 微秒系统滴答数 */
volatile static uint32_t systick_per_us = 0;
/* 上电系统毫秒数 */
volatile uint32_t system_ms_from_poweron = 0;/*
* @brief       SysTick初始化
*
* @param       priority: 中断优先级
*
* @retval      None
*
*/
void bsp_systick_init(uint8_t priority)
{
    systick_per_us = RCM_ReadHCLKFreq() / 1000;
    SysTick_Config(systick_per_us);
    NVIC_SetPriority (SysTick_IRQn, priority);
    systick_per_us /= 1000;
}/*
* @brief       SysTick微秒延时
*
* @param       us: 微秒延时数
*
* @retval      None
*
*/
void bsp_systick_delay_us(uint32_t us)
{
    uint32_t tick_old = 0U, tick_new = 0U;
      uint32_t tick_diff_need = 0U;
      uint32_t tick_diff_current = 0U;
   
    // 此段代码实际多1.78us延时,根据实际情况调整
    if (us > 2) {
      us -= 2;
    }
      
      tick_old = SysTick->VAL;
      tick_diff_need = systick_per_us * us;
      while (1)
      {
                tick_new = SysTick->VAL;
                // tick为向下计数
                tick_diff_current = (tick_new <= tick_old) ?
                                                (tick_old - tick_new) : (SysTick->LOAD - tick_new + tick_old);
                if (tick_diff_current >= tick_diff_need)
                        return ;
      }
}/*
* @brief       SysTick毫秒延时
*
* @param       us: 毫秒延时数
*
* @retval      None
*
*/
void bsp_systick_delay_ms(uint32_t ms)
{
    while (ms--) {
      // us延时有误差,999us已经非常接近1ms
      bsp_systick_delay_us(999);
    }
}/*
* @brief       获取上电系统毫秒数
*
* @param       None
*
* @retval      获取上电系统毫秒数
*
*/
uint32_t bsp_get_system_ms_from_poweron(void)
{
    return system_ms_from_poweron;
}

void SysTick_Handler(void)
{
    system_ms_from_poweron++;
}

测试代码如下:
// IO初始化
void gpio_test_init(void)
{
    GPIO_Config_T gpioConfig;
   
    RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOB);   
    GPIO_ConfigStructInit(&gpioConfig);
    gpioConfig.pin   = GPIO_PIN_6;
    gpioConfig.mode    = GPIO_MODE_OUT;
    gpioConfig.outtype = GPIO_OUT_TYPE_PP;
    gpioConfig.speed   = GPIO_SPEED_50MHz;
    gpioConfig.pupd    = GPIO_PUPD_NO;
    GPIO_Config(GPIOB, &gpioConfig);
}

// IO翻转
void gpio_toggle(void)
{
    if (GPIO_ReadOutputBit(GPIOB, GPIO_PIN_6) == BIT_SET) {
      GPIO_ClearBit(GPIOB, GPIO_PIN_6);
    } else {
      GPIO_SetBit(GPIOB, GPIO_PIN_6);
    }
}// 应用初始化
void app_init(void)
{
    gpio_test_init();
    bsp_systick_init(0);
}

// 应用任务
void app_task(void)
{
    // 毫秒中断验证
//    static uint32_t ms_last = 0;   
//    while (ms_last == bsp_get_system_ms_from_poweron());
//    ms_last = bsp_get_system_ms_from_poweron();
   
    gpio_toggle();
    // 延时验证
//    bsp_systick_delay_us(10);
    bsp_systick_delay_ms(100);
}

详细代码,请查看附件!





霜之闪耀 发表于 2025-9-7 19:07

systick的设计是时基,看ARM的设计应用,其主要是给RTOS使用。
楼主的驱动 多多少少失去了其价值吧

作业天敌在此 发表于 2025-9-8 16:51

我注意到代码中有一个注释提到微秒延时实际多1.78us延时,这个误差是如何计算出来的?能否分享更多的背景信息?

口天土立口 发表于 2025-9-8 09:01

霜之闪耀 发表于 2025-9-7 19:07
systick的设计是时基,看ARM的设计应用,其主要是给RTOS使用。
楼主的驱动 多多少少失去了其价值吧 ...

不用只局限于人家给的思路

分形梦想家 发表于 2025-9-10 19:32

楼主这个驱动实现添加优先级配置,比ARM提供的要完善

破晓战神 发表于 2025-9-12 10:02

我注意到代码中提到了微秒延时实际上有1.78us的误差,这个误差在实际应用中是否会影响性能

口天土立口 发表于 2025-9-12 17:10

破晓战神 发表于 2025-9-12 10:02
我注意到代码中提到了微秒延时实际上有1.78us的误差,这个误差在实际应用中是否会影响性能
...

代码执行没法避免误差,实际应该考虑到就问题不大

天体书记 发表于 2025-9-12 20:10

还真没有注意过这个细小的误差。
话说要怎么测量出来啊

口天土立口 发表于 2025-9-13 09:51

天体书记 发表于 2025-9-12 20:10
还真没有注意过这个细小的误差。
话说要怎么测量出来啊

翻转IO,用示波器或逻辑分析仪测量IO的电平时长

ShadowDance 发表于 2025-9-14 21:57

我去查看了一下极海SDK,里面对于systick的封装还是相当不错的。而且还添加了分频系数的API

神话编织者 发表于 2025-10-5 10:25

官方的库函数里面有提供systick的函数调用
页: [1]
查看完整版本: APM32E030的SYSTICK驱动