STM32的延时函数,配合系统滴答定时

#include "delay_cfg.h"
///////////////////////////////////////////////////////////////////////////////
//////函	   数: void Delay_us(UINT32_T us)
//////功	   能: 微妙的延时函数
//////输入参数: 延时时间
//////输出参数: 无
//////说	   明: 
//////////////////////////////////////////////////////////////////////////////
void Delay_us( UINT32_T us )
{
	DelayN_us( us );
}

///////////////////////////////////////////////////////////////////////////////
//////函	   数: void Delay_ms(UINT32_T ms)
//////功	   能: 毫秒的延时函数
//////输入参数: 延时时间
//////输出参数: 无
//////说	   明: 
//////////////////////////////////////////////////////////////////////////////
void Delay_ms( UINT32_T ms )
{
	if (ms!=0)
	{
		//---等待延时到达
		SysTickTask_WaitDecTick ( ms );
	}
}

///////////////////////////////////////////////////////////////////////////////
//////函	   数: void Delay_s(UINT32_T ms)
//////功	   能: 秒延时
//////输入参数: 延时时间
//////输出参数: 无
//////说	   明: 
//////////////////////////////////////////////////////////////////////////////
void Delay_s( UINT32_T s )
{
	if( s != 0 )
	{
		while( s-- )
		{
			Delay_ms1000 );
		}
	}
}

///////////////////////////////////////////////////////////////////////////////
//////函	   数: void DelayN_us(UINT32_T us)
//////功	   能: 查询的方式,使用系统滴答定时器的作为延时计算
//////输入参数: 微妙的延时时间
//////输出参数: 无
//////说	   明: 
//////////////////////////////////////////////////////////////////////////////
void DelayN_us( UINT32_T us )
{
	if( us != 0 )
	{

		//---系统中断关闭
		CLI();
		if (us>6)
		{
			//---等待时间的到达
			SysTickTask_WaitTimer( us );
		}
		else if (us>1)
		{
			//---软件NOP延时
			
            Delay_nop((us-1)*us+1)*( SYS_CLOCK_MHZ - 1 ) );
}//---系统中断打开SEI();}}/////////////////////////////////////////////////////////////////////////////////////函    数: void DelayN_ms(UINT32_T ms)//////功    能: 查询的方式,使用系统滴答定时器的作为延时计算//////输入参数: 毫秒的延时时间//////输出参数: //////说    明: //////////////////////////////////////////////////////////////////////////////void DelayN_ms( UINT32_T ms ){if( ms != 0 ){while( ms-- ){DelayN_us1000 );WDT_RESET();}}}/////////////////////////////////////////////////////////////////////////////////////函    数: void DelayN_s(UINT32_T s)//////功    能: 查询的方式,使用系统滴答定时器的作为延时计算//////输入参数: 秒的延时时间//////输出参数: //////说    明: //////////////////////////////////////////////////////////////////////////////void DelayN_s( UINT32_T s ){if( s != 0 ){while( s-- ){DelayN_ms1000 );}}}/////////////////////////////////////////////////////////////////////////////////////函    数: void Delay_nop(UINT32_T nop)//////功    能: 系统时钟的延时//////输入参数: 系统时钟延时的个数//////输出参数: 无//////说    明: //////////////////////////////////////////////////////////////////////////////void Delay_nop( UINT32_T nop ){if( nop != 0 ){while( nop-- ){__asm"NOP" );}}}/////////////////////////////////////////////////////////////////////////////////////函    数: void Delay_1us(UINT32_T us)//////功    能: 使用nop延时函数,进行1us的整数倍的延时时间的计算//////输入参数: us延时的个数//////输出参数: 无//////说    明: //////////////////////////////////////////////////////////////////////////////void Delay_1us( UINT32_T us ){UINT32_T i = 0;if( us != 0 ){for( i = 0; i < us; i++ ){Delay_nop( SYS_CLOCK_MHZ - 1 ) );}}}
#ifndef DELAY_CFG_H
#define DELAY_CFG_H
//////////////////////////////////////////////////////////////////////////////////////
//---使用包含的头文件
#include "complier_lib.h"
#ifdef USE_MCU_STM32
	#include "systick_task.h"
#endif
//---函数定义
void Delay_us( UINT32_T us );
void Delay_ms( UINT32_T ms );
void Delay_s( UINT32_T s );
void DelayN_us( UINT32_T us );
void DelayN_ms( UINT32_T ms );
void DelayN_s( UINT32_T s );
void Delay_nop( UINT32_T nop );
void Delay_1us( UINT32_T us );
//////////////////////////////////////////////////////////////////////////////////////
#endif /*DELAY_CFG_H */
#ifndef DELAY_CFG_H
#define DELAY_CFG_H
//////////////////////////////////////////////////////////////////////////////////////
//---使用包含的头文件
#include "complier_lib.h"
#ifdef USE_MCU_STM32
	#include "systick_task.h"
#endif
//---函数定义
void Delay_us( UINT32_T us );
void Delay_ms( UINT32_T ms );
void Delay_s( UINT32_T s );
void DelayN_us( UINT32_T us );
void DelayN_ms( UINT32_T ms );
void DelayN_s( UINT32_T s );
void Delay_nop( UINT32_T nop );
void Delay_1us( UINT32_T us );
//////////////////////////////////////////////////////////////////////////////////////
#endif /*DELAY_CFG_H */
#ifndef SYSTICK_CFG_H
#define SYSTICK_CFG_H
//////////////////////////////////////////////////////////////////////////////////////
//---使用包含的头文件
#include "complier_lib.h"
//---变量定义
//---结构体声明
typedef struct _SysTick_HandlerType			SysTick_HandlerType;
//---结构体指针的声明
typedef struct _SysTick_HandlerType			*pSysTick_HandlerType;
//---定义滴答的计数计数方式
typedef enum
{
	SysTick_1MS_FREQ		= 1000U,
	SysTick_10MS_FREQ		= 100U,
	SysTick_100MS_FREQ		= 10U,
	SysTick_FREQ			= SysTick_1MS_FREQ,
} SysTickFreqType;
//---滴答定时器的结构体
struct _SysTick_HandlerType
{
	VLTUINT32_T				msgTickInc;																					//---定时器递加计数器
	VLTUINT32_T				msgTickDec;																					//---定时器递减计数器
	VLTUINT32_T				msgTickOverFlow;																			//---定时计数器溢出
	VLTUINT32_T				msgFuncTickTaskInc;																			//---任务计数器
	VLTUINT32_T				msgFunTickTaskMaxInc;																		//---任务计数上限
	void					(*msgHalTickTask)(void);																	//---hal库的计数方式
	void					(*msgFuncTickTask)(void);																	//---注册任务函数
	UINT8_T					(*msgTask)( SysTick_HandlerType *SysTickHandlerType, UINT8_T msg );							//---任务处理函数
};
 
 
//---命令消息体
#define SysTick_MSG_Init			0
#define SysTick_MSG_DeInit			1
#define SysTick_MSG_IRQTick			2
 
//---函数定义
UINT8_T SysTick_Init( UINT32_T tickInc, void*pHalTickInc )( void ) );
UINT8_T SysTick_DeInit( void );
UINT8_T SysTick_TickTask( UINT32_T tickFreq, void*pLEDTickInc )( void ) );
UINT8_T SysTick_WaitDecTick( UINT32_T waitDecTick );
UINT32_T SysTick_GetTick( void );
UINT8_T SysTick_IRQTick( void );
UINT8_T SysTick_WaitTimer( UINT32_T usTimer );
//////////////////////////////////////////////////////////////////////////////////////
#endif /* SYSTICK_CFG_H */
#include "systick_cfg.h"
 
//---变量定义
SysTick_HandlerType		g_SysTick;
pSysTick_HandlerType	pSysTick = &g_SysTick;
 
extern HAL_TickFreqTypeDef uwTickFreq;
 
 
///////////////////////////////////////////////////////////////////////////////
//////函		数: 
//////功		能: 
//////输入参数: 
//////输出参数: 
//////说		明: 
//////////////////////////////////////////////////////////////////////////////
UINT8_T SysTick_Suspend(void)
{
#ifdef USE_MCU_STM32
	//---不使能系统滴答定时器的中断
	SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk;
#endif 
	return OK_0;
}
 
///////////////////////////////////////////////////////////////////////////////
//////函		数: 
//////功		能: 
//////输入参数: 
//////输出参数: 
//////说		明: 
//////////////////////////////////////////////////////////////////////////////
UINT8_T SysTick_Resume(void)
{
#ifdef USE_MCU_STM32
	//---使能系统滴答定时器的中断
	SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk;
#endif 
	return OK_0;
}
 
///////////////////////////////////////////////////////////////////////////////
//////函		数: 
//////功		能: 
//////输入参数: 
//////输出参数: 
//////说		明: 最好1ms的滴答定时器
//////////////////////////////////////////////////////////////////////////////
UINT8_T SysTick_Init(UINT32_T tickInc, void(*pHalTickInc)(void))
{
#ifdef USE_MCU_STM32
	//---产生1ms的时间滴答器---该初始化函数没有注册中断
	LL_InitTick(SystemCoreClock, tickInc);
	//---设置中断抢占分组
	NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
	//---配置滴答定时器中断---设置为最低优先级
	NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0));
	//---使能滴答定时的中断---默认是1ms
	SysTick_Resume();
	//---hal定时计数器
	if ((pHalTickInc!=NULL)&&(pSysTick!=NULL))
	{
		uwTickFreq = HAL_TICK_FREQ_DEFAULT;
		pSysTick->msgHalTickTask = pHalTickInc;
	}
	else
	{
		return ERROR_1;
	}
#endif
	return OK_0;
}
 
///////////////////////////////////////////////////////////////////////////////
//////函		数: 
//////功		能: 
//////输入参数: 
//////输出参数: 
//////说		明: 
//////////////////////////////////////////////////////////////////////////////
UINT8_T SysTick_DeInit(void)
{
#ifdef USE_MCU_STM32
	SysTick_Suspend();
#endif
	return OK_0;
}
 
///////////////////////////////////////////////////////////////////////////////
//////函		数: 
//////功		能: 
//////输入参数: 
//////输出参数: 
//////说		明: 
//////////////////////////////////////////////////////////////////////////////
UINT8_T SysTick_TickTask(UINT32_T tickFreq, void(*pLEDTickInc)(void))
{
	if ((pLEDTickInc!=NULL)&&(pSysTick!=NULL))
	{
		//---注册任务函数
		pSysTick->msgFuncTickTask = pLEDTickInc;
		//---清零任务计数函数
		pSysTick->msgFuncTickTaskInc = 0;
		//---设置任务函数的最大计数上限
		pSysTick->msgFunTickTaskMaxInc = tickFreq;
	}
	return OK_0;
}
 
///////////////////////////////////////////////////////////////////////////////
//////函		数: 
//////功		能: 
//////输入参数: 
//////输出参数: 
//////说		明: 
//////////////////////////////////////////////////////////////////////////////
UINT8_T SysTick_WaitDecTick(UINT32_T waitDecTick)
{
	if (pSysTick!=NULL)
	{
		//---计时函数
		pSysTick->msgTickDec = waitDecTick;
		//---等待时间到达
		while (pSysTick->msgTickDec != 0)
		{
			WDT_RESET();
		}
		return OK_0;
	}
	return ERROR_1;
}
 
///////////////////////////////////////////////////////////////////////////////
//////函		数: 
//////功		能: 
//////输入参数: 
//////输出参数: 
//////说		明: 
//////////////////////////////////////////////////////////////////////////////
UINT32_T SysTick_GetTick(void)
{
	if (pSysTick!=NULL)
	{
		return pSysTick->msgTickInc;
	}
	return 0;
}
 
///////////////////////////////////////////////////////////////////////////////
//////函		数: 
//////功		能: 
//////输入参数: 
//////输出参数: 
//////说		明: 
//////////////////////////////////////////////////////////////////////////////
UINT8_T SysTick_IRQTick(void)
{
	if (pSysTick!=NULL)
	{
		//---递加计数
		pSysTick->msgTickInc++;
		pSysTick->msgFuncTickTaskInc++;
		//---判断是否溢出
		if (pSysTick->msgTickInc==0)
		{
			pSysTick->msgTickOverFlow++;
		}
		//---注册hal延时函数
		if (pSysTick->msgHalTickTask!=NULL)
		{
			pSysTick->msgHalTickTask();
		}
		//---判断任务函数
		if ((pSysTick->msgFunTickTaskMaxInc!=0)&&(pSysTick->msgFunTickTaskMaxInc==pSysTick->msgFuncTickTaskInc)&&(pSysTick->msgFuncTickTask!=NULL))
		{
			pSysTick->msgFuncTickTaskInc = 0;
			pSysTick->msgFuncTickTask();
		}
		//---递减计数
		if (pSysTick->msgTickDec!=0)
		{
			pSysTick->msgTickDec--;
		}
		return OK_0;
	}
	return ERROR_1;
}
 
///////////////////////////////////////////////////////////////////////////////
//////函		数: 
//////功		能: 
//////输入参数: 
//////输出参数: 
//////说		明: 
//////////////////////////////////////////////////////////////////////////////
UINT8_T SysTick_WaitTimer(UINT32_T usTimer)
{
#ifdef USE_MCU_STM32
	UINT32_T load = SysTick->LOAD;	
	UINT32_T ctrl = SysTick->CTRL;
	//---关闭定时器,时钟选择为系统时钟,不进行8分频
	SysTick->CTRL = 0x00000004;
	//---计算装载值
    SysTick->LOAD = usTimer*(SYS_CLOCK_MHZ - 1);
//---清零计数器
SysTick->VAL = 0x00;//---使能计数器计数SysTick->CTRL |= 0x01;//---等待计数到0while (!(SysTick->CTRL & 0x00010000)){WDT_RESET();}//---关闭定时器,时钟选择为系统时钟,不进行8分频SysTick->CTRL = 0x00000004;//---恢复装载值SysTick->LOAD = load;//---清零计数器SysTick->VAL = 0x00;//---恢复计数器配置SysTick->CTRL = ctrl;#endifreturn OK_0;}

### STM32F103C8T6 使用标准库实现延时功能 #### 微秒级延时函数 (Delay_us) 通过配置 `SysTick` 定时器来实现精确的微秒级延时。以下是基于标准库的方式实现的代码: ```c #include "stm32f1xx.h" void Delay_us(uint32_t xus) { SysTick->LOAD = 72 * xus; // 设置自动重载值,假设系统时钟为72MHz SysTick->VAL = 0x00; // 清空当前计值 SysTick->CTRL = 0x00000005; // 配置SysTick控制寄存器:使用内部时钟源并启动定时器 while (!(SysTick->CTRL & 0x00010000)); // 等待直到计完成 SysTick->CTRL = 0x00000004; // 关闭定时器 } ``` 上述代码实现了基于 `SysTick` 的微秒级延时功能[^1]。 --- #### 毫秒延时函数 (Delay_ms) 毫秒延时可以通过调用多次微秒级延时函数来实现: ```c void Delay_ms(uint32_t xms) { uint32_t i; for (i = 0; i < xms; i++) { Delay_us(1000); // 调用一次微秒级延时函数延时1000微秒即1毫秒 } } ``` 此部分代码展示了如何利用已有的微秒级延时函数构建更长时间的延迟效果。 --- #### 秒级延时函数 (Delay_s) 对于更大的时间单位(如秒),可以继续扩展逻辑: ```c void Delay_s(uint32_t xs) { uint32_t i; for (i = 0; i < xs; i++) { Delay_ms(1000); // 调用一次毫秒延时函数延时1000毫秒1秒 } } ``` 该函数进一步封装了毫秒延时函数,用于提供更高精度的时间管理能力。 --- #### 解决延时异常问题 如果在更换芯片型号后发现延时出现了偏差(例如延长至原来的十倍),可能是因为未正确初始化系统时钟频率。解决方案是在程序初始化阶段调用 `SystemInit()` 函数以重新校正时钟设置[^4]。 --- ### 总结 以上提供了三种不同级别的延时函数实现方案,并解决了因硬件差异可能导致的延时误差问题。这些方法均适用于 STM32F103C8T6 平台下的标准库开发环境。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值