PY32F003F18滴答定时器

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
}
相关推荐
yutian06063 小时前
Keil MDK下载程序后MCU自动重启设置
单片机·嵌入式硬件·keil
析木不会编程6 小时前
【小白51单片机专用教程】protues仿真独立按键控制LED
单片机·嵌入式硬件·51单片机
枯无穷肉10 小时前
stm32制作CAN适配器4--WinUsb的使用
stm32·单片机·嵌入式硬件
不过四级不改名67710 小时前
基于HAL库的stm32的can收发实验
stm32·单片机·嵌入式硬件
嵌入式大圣10 小时前
单片机UDP数据透传
单片机·嵌入式硬件·udp
云山工作室11 小时前
基于单片机的视力保护及身姿矫正器设计(论文+源码)
stm32·单片机·嵌入式硬件·毕业设计·毕设
嵌入式-老费11 小时前
基于海思soc的智能产品开发(mcu读保护的设置)
单片机·嵌入式硬件
liyinuo201713 小时前
嵌入式(单片机方向)面试题总结
嵌入式硬件·设计模式·面试·设计规范
艺术家天选13 小时前
STM32点亮LED灯
stm32·单片机·嵌入式硬件
小猪写代码14 小时前
STM32 水质水位检测项目 (调试模块)和(延时模块)
stm32·单片机·嵌入式硬件