[APM32E0] APM32E030的SYSTICK驱动

[复制链接]
194|4
口天土立口 发表于 2025-9-6 15:57 | 显示全部楼层 |阅读模式
本帖最后由 口天土立口 于 2025-9-7 18:33 编辑

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

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

  1. /* 微秒系统滴答数 */
  2. volatile static uint32_t systick_per_us = 0;
  3. /* 上电系统毫秒数 */
  4. volatile uint32_t system_ms_from_poweron = 0;
  1. /*
  2. * @brief       SysTick初始化
  3. *
  4. * @param       priority: 中断优先级
  5. *
  6. * @retval      None
  7. *
  8. */
  9. void bsp_systick_init(uint8_t priority)
  10. {
  11.     systick_per_us = RCM_ReadHCLKFreq() / 1000;
  12.     SysTick_Config(systick_per_us);
  13.     NVIC_SetPriority (SysTick_IRQn, priority);
  14.     systick_per_us /= 1000;
  15. }
  1. /*
  2. * @brief       SysTick微秒延时
  3. *
  4. * @param       us: 微秒延时数
  5. *
  6. * @retval      None
  7. *
  8. */
  9. void bsp_systick_delay_us(uint32_t us)
  10. {
  11.     uint32_t tick_old = 0U, tick_new = 0U;
  12.         uint32_t tick_diff_need = 0U;
  13.         uint32_t tick_diff_current = 0U;
  14.    
  15.     // 此段代码实际多1.78us延时,根据实际情况调整
  16.     if (us > 2) {
  17.         us -= 2;
  18.     }
  19.         
  20.         tick_old = SysTick->VAL;
  21.         tick_diff_need = systick_per_us * us;
  22.         while (1)
  23.         {
  24.                 tick_new = SysTick->VAL;
  25.                 // tick为向下计数
  26.                 tick_diff_current = (tick_new <= tick_old) ?
  27.                                                 (tick_old - tick_new) : (SysTick->LOAD - tick_new + tick_old);
  28.                 if (tick_diff_current >= tick_diff_need)
  29.                         return ;
  30.         }
  31. }
  1. /*
  2. * @brief       SysTick毫秒延时
  3. *
  4. * @param       us: 毫秒延时数
  5. *
  6. * @retval      None
  7. *
  8. */
  9. void bsp_systick_delay_ms(uint32_t ms)
  10. {
  11.     while (ms--) {
  12.         // us延时有误差,999us已经非常接近1ms
  13.         bsp_systick_delay_us(999);
  14.     }
  15. }
  1. /*
  2. * @brief       获取上电系统毫秒数
  3. *
  4. * @param       None
  5. *
  6. * @retval      获取上电系统毫秒数
  7. *
  8. */
  9. uint32_t bsp_get_system_ms_from_poweron(void)
  10. {
  11.     return system_ms_from_poweron;
  12. }

  13. void SysTick_Handler(void)
  14. {
  15.     system_ms_from_poweron++;
  16. }


测试代码如下:
  1. // IO初始化
  2. void gpio_test_init(void)
  3. {
  4.     GPIO_Config_T gpioConfig;
  5.    
  6.     RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOB);   
  7.     GPIO_ConfigStructInit(&gpioConfig);
  8.     gpioConfig.pin     = GPIO_PIN_6;
  9.     gpioConfig.mode    = GPIO_MODE_OUT;
  10.     gpioConfig.outtype = GPIO_OUT_TYPE_PP;
  11.     gpioConfig.speed   = GPIO_SPEED_50MHz;
  12.     gpioConfig.pupd    = GPIO_PUPD_NO;
  13.     GPIO_Config(GPIOB, &gpioConfig);
  14. }

  15. // IO翻转
  16. void gpio_toggle(void)
  17. {
  18.     if (GPIO_ReadOutputBit(GPIOB, GPIO_PIN_6) == BIT_SET) {
  19.         GPIO_ClearBit(GPIOB, GPIO_PIN_6);
  20.     } else {
  21.         GPIO_SetBit(GPIOB, GPIO_PIN_6);
  22.     }
  23. }
  1. // 应用初始化
  2. void app_init(void)
  3. {
  4.     gpio_test_init();
  5.     bsp_systick_init(0);
  6. }

  7. // 应用任务
  8. void app_task(void)
  9. {
  10.     // 毫秒中断验证
  11. //    static uint32_t ms_last = 0;   
  12. //    while (ms_last == bsp_get_system_ms_from_poweron());
  13. //    ms_last = bsp_get_system_ms_from_poweron();
  14.    
  15.     gpio_toggle();
  16.     // 延时验证
  17. //    bsp_systick_delay_us(10);
  18.     bsp_systick_delay_ms(100);
  19. }


详细代码,请查看附件!
SysTick.zip (2.1 MB, 下载次数: 0)




霜之闪耀 发表于 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提供的要完善
您需要登录后才可以回帖 登录 | 注册

本版积分规则

16

主题

37

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部