GD32F4 利用查询Systick实现毫秒、微秒级延时

本文介绍了如何利用ARM内核自带的Systick定时器进行延时,考虑了系统误差并提供了系数调整方法。给出了us级和ms级延时的代码示例,以及使用Keil测试代码运行时间和示波器校准系数的建议。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Systick是ARM内核自带的系统滴答定时器,利用查询Systick的方法实现延时,可以节省定时器资源,同时不会影响到Systick的运行。

注意:由于不同单片机制造的差异,存在误差概念中的“恒值系统误差,需要自己利用示波器,更改ticks的系数值。

例如在main.c中利用GPIO延时1us翻转制造方波,不断修正系数,作者手上的MCU修正系数为7/20,系数一般是在1/2以下。

另外,手边没有示波器的友友,可以直接用keil测试代码运行时间,这里就不展开说了。

 

如何修改修正系数?

如果实际延时时间长,就增大这个系数,反之减少。直到能正确延时1us,此时1ms的延时也会随之正常。

ticks=_nus*fac_us-fac_us*系数

以下为毫秒、微秒级延时的实现代码,注释十分清晰,不再赘述。

delay.c

#include "delay.h"

/**
* @brief 提供us级的延时
* @param _nus 延时的时间,单位us
* @return 无
*/
void delay_us(uint32_t _nus)
{	
	
	uint8_t  fac_us=0;
    uint32_t ticks;
    uint32_t t_old,t_now,t_cnt=0;
    uint32_t reload=SysTick->LOAD;//获取重装载值(只查询,不影响)
	
	fac_us=SystemCoreClock/1000000;		
    ticks=_nus*fac_us-fac_us*7/20;
    t_old=SysTick->VAL;//获取当前值作为旧值(只查询,不影响)
	
    while(1)
    {
		/*systick为向下递减,未减到0导致重装载的情况下,新值小于旧值*/
        t_now=SysTick->VAL;//获取当前值作为新值(只查询,不影响)
		
		if(t_now<t_old)
		{
			t_cnt+=t_old-t_now;//未发生重装载,cnt记录减少的值
		}
		else
		{
			t_cnt+=t_old+(reload-t_now);//重装载后,旧值已递减完毕,cnt需在再加上重装载值与新值的差值
		}
		
		if(t_cnt>=ticks)
		{
			break;//当计数cnt大于等于用户需要的ticks,即认为延时完毕,跳出循环
		}
		
		t_old=t_now;//获取当前值作为旧值,以供下一次循环做判断(只查询,不影响)
    };
}

/**
* @brief 提供ms级的延时
* @param _nms 延时的时间,单位ms
* @return 无
*/
void delay_ms(uint16_t nms)
{
	uint32_t i;
	for(i=0;i<nms;i++) 
	{
		delay_us(1000);
	}
}

 

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值