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);
}
详细代码,请查看附件!
systick的设计是时基,看ARM的设计应用,其主要是给RTOS使用。
楼主的驱动 多多少少失去了其价值吧 我注意到代码中有一个注释提到微秒延时实际多1.78us延时,这个误差是如何计算出来的?能否分享更多的背景信息?
霜之闪耀 发表于 2025-9-7 19:07
systick的设计是时基,看ARM的设计应用,其主要是给RTOS使用。
楼主的驱动 多多少少失去了其价值吧 ...
不用只局限于人家给的思路 楼主这个驱动实现添加优先级配置,比ARM提供的要完善 我注意到代码中提到了微秒延时实际上有1.78us的误差,这个误差在实际应用中是否会影响性能
破晓战神 发表于 2025-9-12 10:02
我注意到代码中提到了微秒延时实际上有1.78us的误差,这个误差在实际应用中是否会影响性能
...
代码执行没法避免误差,实际应该考虑到就问题不大 还真没有注意过这个细小的误差。
话说要怎么测量出来啊
天体书记 发表于 2025-9-12 20:10
还真没有注意过这个细小的误差。
话说要怎么测量出来啊
翻转IO,用示波器或逻辑分析仪测量IO的电平时长 我去查看了一下极海SDK,里面对于systick的封装还是相当不错的。而且还添加了分频系数的API 官方的库函数里面有提供systick的函数调用
页:
[1]