PY32F003F18滴答定时器HAL库,用户接口函数如下:
//HAL_Delay(x)延时x毫秒,x<0xFFFFFFFF,至少需要延时一个周期
//HAL_SuspendTick();不使能"SysTick滴答定时器"中断
//HAL_ResumeTick();使能"SysTick滴答定时器"中断
//HAL_GetTickFreq();读取"SysTick滴答定时器"的中断频率
//HAL_SetTickFreq(Freq);设置"SysTick滴答定时器"的中断频率为Freq
//HAL_GetTickPrio();读取"SysTick滴答定时器"的中断优先级
//HAL_GetTick();读取"SysTick滴答定时器"的中断次数计数器uwTick
//HAL_IncTick();供SysTick_Handler()调用
//uwTickFreq=HAL_TICK_FREQ_1KHZ;//准备配置"SysTick定时器"每1ms中断一次
//HAL_InitTick(PRIORITY_LOWEST);//配置"SysTick定时器"每1ms中断一次,优先级为最低
注意:HAL库没有写微妙延时函数,这点实在无法仍受。后面,我自己写了个delay_us(uint32_t nus)。
//函数功能:配置"SysTick计数器"每1ms中断一次,优先级为最低
HAL_StatusTypeDef HAL_Init(void)
{
HAL_StatusTypeDef status = HAL_OK;
/* Configure Flash prefetch, Instruction cache */
/* Default configuration at reset is: */
/* - Prefetch disabled */
/* - Instruction cache enabled */
/* Use SysTick as time base source and configure 1ms tick (default clock after Reset is HSI) */
if (HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK)
{
status = HAL_ERROR;
}
else
{
/* Init the low level hardware */
HAL_MspInit();//用户在PY32F0xx_hal_msp.c中定义的函数
}
/* Return function status */
return status;
}
//函数功能:设置"SysTick计数器"重装载值为(SystemCoreClock * uwTickFreq/1000U -1),配置中断优先级,并使能计数和中断
//初始化成功返回0
//SystemCoreClock为系统时钟,单位为Hz
//HAL_TICK_FREQ_1KHZ=1表示周期为1ms
//全局变量uwTickFreq=HAL_TICK_FREQ_1KHZ,"SysTick计数器"中断周期为:uwTickFreq,单位为ms
//"SysTick计数器"重装载值为: (SystemCoreClock * uwTickFreq/1000U -1)
__weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
HAL_StatusTypeDef status = HAL_OK;//HAL_OK=0x00U
if (uwTickFreq != 0U)//"SysTick计数器"的中断频率为1KHz,即中断周期为1ms
{
if (HAL_SYSTICK_Config( SystemCoreClock / (1000U/uwTickFreq) ) == 0U)
{//设置"SysTick定时器"自动重装载值为SystemCoreClock / (1000U/uwTickFreq)-1
//并设置中断优先级为最低,使能"SysTick定时器"时钟源,"SysTick定时器中断"和"SysTick定时器模块"
if (TickPriority < (1UL << __NVIC_PRIO_BITS))
{//如果TickPriority<4,表示"SysTick计数器"优先级正确
HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority, 0U);
//设置"SysTick计数器"中断优先级为TickPriority,这个0无意义
uwTickPrio = TickPriority;
//记录中断优先级,后面要读取"SysTick计数器"中断优先级
}
else//"SysTick计数器"优先级不正确
{
status = HAL_ERROR;//HAL_ERROR=0x01U
}
}
else//"SysTick计数器"的中断频率为0Hz
{
status = HAL_ERROR;//HAL_ERROR=0x01U
}
}
else
{
status = HAL_ERROR;//HAL_ERROR=0x01U
}
return status;//Return function status
}
//设置"SysTick定时器"自动重装载值为TicksNumb-1,并设置中断优先级为最低,使能"SysTick定时器"时钟源,"SysTick定时器中断"和"SysTick定时器模块"
uint32_t HAL_SYSTICK_Config(uint32_t TicksNumb)
{
return SysTick_Config(TicksNumb);
//设置"SysTick定时器"自动重装载值为TicksNumb-1,并设置中断优先级为最低,使能"SysTick定时器"时钟源,"SysTick定时器中断"和"SysTick定时器模块"
}
//函数功能:设置"SysTick定时器"自动重装载值为ticks-1,并设置中断优先级为最低,使能"SysTick定时器"时钟源,"SysTick定时器中断"和"SysTick定时器模块"
__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
{
if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
{//SysTick_LOAD_RELOAD_Msk=0xFFFFFF,系统滴答定时器为24位,这里做了限定
return (1UL);//Reload value impossible
}
SysTick->LOAD = (uint32_t)(ticks - 1UL);
//设置"SysTick定时器"自动重装载值,set reload register
NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL);
//设置"SysTick定时器"中断优先级为最低
//set Priority for Systick Interrupt
SysTick->VAL = 0UL;
//设置系统滴答定时器的初始计数值为0
//Load the SysTick Counter Value
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk |
SysTick_CTRL_ENABLE_Msk;
//使能"SysTick定时器"时钟源,使能"SysTick定时器中断",使能"SysTick定时器模块"
//Enable SysTick IRQ and SysTick Timer
return (0UL);//Function successful
}
#include "delay.h"
static uint8_t fac_us=0; //us延时倍乘数
void delay_init(void);
void delay_us(uint32_t nus);
void delay_ms(uint32_t nms);
//函数功能:配置"SysTick定时器"每1ms中断一次,优先级为最低
void delay_init(void)
{
fac_us=SystemCoreClock/1000000;//不论是否使用OS,fac_us都需要使用
uwTickFreq=HAL_TICK_FREQ_1KHZ;//准备配置"SysTick定时器"每1ms中断一次
HAL_InitTick(PRIORITY_LOWEST);//配置"SysTick定时器"每1ms中断一次,优先级为最低
// HAL_Init();//配置"SysTick定时器"每1ms中断一次,优先级为最低
}
//函数功能:延时nus
//nus:要延时的us数.
//nus:0~204522252(最大值即2^32/fac_us)
void delay_us(uint32_t nus)
{
uint32_t ticks;
uint32_t told,tnow,tcnt=0;
uint32_t reload=SysTick->LOAD;//读取"SysTick定时器"自动重装载值
ticks=nus*fac_us; //需要的节拍数
told=SysTick->VAL; //读取"系统滴答定时器的计数值"
while(1)
{
tnow=SysTick->VAL;//读取"系统滴答定时器的计数值"
if(tnow!=told)
{
if(tnow<told)tcnt+=told-tnow; //这里注意一下SYSTICK是一个递减的计数器就可以了.
else tcnt+=reload-tnow+told;
told=tnow;
if(tcnt>=ticks)break; //时间超过/等于要延迟的时间,则退出.
}
}
}
//函数功能:延时nms
//nms:要延时的ms数
//nms:0~65535
void delay_ms(uint32_t nms)
{
delay_us((uint32_t)(nms*1000));//普通方式延时
}
//HAL库接口函数
//HAL_Delay(x)延时x毫秒,x<0xFFFFFFFF,至少需要延时一个周期
//HAL_SuspendTick();不使能"SysTick滴答定时器"中断
//HAL_ResumeTick();使能"SysTick滴答定时器"中断
//HAL_GetTickFreq();读取"SysTick滴答定时器"的中断频率
//HAL_SetTickFreq(Freq);设置"SysTick滴答定时器"的中断频率为Freq
//HAL_GetTickPrio();读取"SysTick滴答定时器"的中断优先级
//HAL_GetTick();读取"SysTick滴答定时器"的中断次数计数器uwTick
//HAL_IncTick();供SysTick_Handler()调用
//uwTickFreq=HAL_TICK_FREQ_1KHZ;//准备配置"SysTick定时器"每1ms中断一次
//HAL_InitTick(PRIORITY_LOWEST);//配置"SysTick定时器"每1ms中断一次,优先级为最低
我觉得直接调用,会更加清晰易懂,如下:
uwTickFreq=HAL_TICK_FREQ_1KHZ;//准备配置"SysTick定时器"每1ms中断一次
HAL_InitTick(PRIORITY_LOWEST);//配置"SysTick定时器"每1ms中断一次,优先级为最低
#include "py32f0xx_hal.h"
#include "delay.h"
int main(void)
{
delay_init();
HAL_Delay(1000);//上电后延时1秒
while (1)
{
delay_ms(500);
}
}
几个很重要的用户函数
//函数功能:供SysTick_Handler()调用
__weak void HAL_IncTick(void)
{
uwTick += uwTickFreq;
//SysTick计数器"每中断一次,中断次数计数器uwTick=uwTick+uwTickFreq
//uwTickFreq为"SysTick计数器"的中断频率
}
//函数功能:读取"SysTick计数器"的中断次数计数器uwTick
__weak uint32_t HAL_GetTick(void)
{
return uwTick;
}
//函数功能:读取"SysTick计数器"的中断优先级
uint32_t HAL_GetTickPrio(void)
{
return uwTickPrio;//将"SysTick计数器"的中断优先级返回
}
//函数功能:读取"SysTick计数器"的中断频率
uint32_t HAL_GetTickFreq(void)
{
return uwTickFreq;//读取"SysTick计数器"的中断频率
}
//函数功能:延时Delay毫秒
//Delay为延时的毫秒数值
__weak void HAL_Delay(uint32_t Delay)
{
uint32_t tickstart = HAL_GetTick();
//读取"SysTick计数器"的中断次数计数器uwTick
//使用tickstart记录"中断次数计数器的初始值"
uint32_t wait = Delay;
/* Add a freq to guarantee minimum wait */
if (wait < HAL_MAX_DELAY)
{
wait += (uint32_t)(uwTickFreq);
//计算至少需要等待的"中断次数"
//uwTickFreq为"SysTick计数器"的中断频率
}
while ((HAL_GetTick() - tickstart) < wait)
{
//HAL_GetTick()读取"SysTick计数器"的中断次数计数器uwTick
}
}
//函数功能:不使能"SysTick计数器"中断
__weak void HAL_SuspendTick(void)
{
CLEAR_BIT(SysTick->CTRL,SysTick_CTRL_TICKINT_Msk);
//不使能"SysTick计数器"中断,Disable SysTick Interrupt
}
//函数功能:使能"SysTick计数器"中断
__weak void HAL_ResumeTick(void)
{
/* Enable SysTick Interrupt */
SET_BIT(SysTick->CTRL, SysTick_CTRL_TICKINT_Msk);
//使能"SysTick计数器"中断,Enable SysTick Interrupt
}