2、HAL库利用滴答定时器systick(1ms中断)实现时间计数戳
文档说明:通过滴答定时器的1ms中断实现时间计数,标记需要的时间标志,在主函数中查询标志,避免延时函数消耗CPU
1、HAL库systick定时器说明
在CubeMx生成的代码main()函数首先执行的函数为HAL_Init();里面会进行滴答定时器初始化;
/*** @brief This function is used to initialize the HAL Library; it must be the first * instruction to be executed in the main program (before to call any other* HAL function), it performs the following:* Configure the Flash prefetch, instruction and Data caches.* Configures the SysTick to generate an interrupt each 1 millisecond,* which is clocked by the HSI (at this stage, the clock is not yet* configured and thus the system is running from the internal HSI at 16 MHz).* Set NVIC Group Priority to 4.* Calls the HAL_MspInit() callback function defined in user file * "stm32f4xx_hal_msp.c" to do the global low level hardware initialization * * @note SysTick is used as time base for the HAL_Delay() function, the application* need to ensure that the SysTick time base is always set to 1 millisecond* to have correct HAL operation.* @retval HAL status*/
HAL_StatusTypeDef HAL_Init(void)
{/* Configure Flash prefetch, Instruction cache, Data cache */
#if (INSTRUCTION_CACHE_ENABLE != 0U)__HAL_FLASH_INSTRUCTION_CACHE_ENABLE();
#endif /* INSTRUCTION_CACHE_ENABLE */#if (DATA_CACHE_ENABLE != 0U)__HAL_FLASH_DATA_CACHE_ENABLE();
#endif /* DATA_CACHE_ENABLE */#if (PREFETCH_ENABLE != 0U)__HAL_FLASH_PREFETCH_BUFFER_ENABLE();
#endif /* PREFETCH_ENABLE *//* Set Interrupt Group Priority */HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);/* Use systick as time base source and configure 1ms tick (default clock after Reset is HSI) */HAL_InitTick(TICK_INT_PRIORITY);/* Init the low level hardware */HAL_MspInit();/* Return function status */return HAL_OK;
}
此处就是在做初始化滴答定时器:
/* Use systick as time base source and configure 1ms tick (default clock after Reset is HSI) */HAL_InitTick(TICK_INT_PRIORITY);
意思就是他的中断函数会1ms调用1次,HAL_InitTick函数里面就是实现配置的
__weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{/* Configure the SysTick to have interrupt in 1ms time basis*/if (HAL_SYSTICK_Config(SystemCoreClock / (1000U / uwTickFreq)) > 0U){return HAL_ERROR;}......return HAL_OK;
}typedef enum
{HAL_TICK_FREQ_10HZ = 100U,HAL_TICK_FREQ_100HZ = 10U,HAL_TICK_FREQ_1KHZ = 1U,HAL_TICK_FREQ_DEFAULT = HAL_TICK_FREQ_1KHZ
} HAL_TickFreqTypeDef;
HAL_TickFreqTypeDef uwTickFreq = HAL_TICK_FREQ_DEFAULT; /* 1KHz */
由此可得HAL_SYSTICK_Config(系统时钟/1000U/1),所以是1KHz的中断
2、时间戳文件
Timestamp_Driver.h
#ifndef _Timestamp_Driver_H_
#define _Timestamp_Driver_H_
#include "main.h"typedef enum
{Timestamp_10ms = 0,Timestamp_50ms = 1,Timestamp_100ms = 2,Timestamp_200ms = 3,Timestamp_500ms = 4,Timestamp_1s = 5,Timestamp_2s = 6,Timestamp_10s = 7,
}Timestamp_Flag_EnumDef;typedef struct
{/******************************* bit Annotation:Timestamp_Flag_EnumDef 使用后需自行清零* 7--10s* 6--2s* 5--1s* 4--500ms* 3--200ms* 2--100ms* 1--50ms* 0--10ms* ***************************/uint8_t Flag;uint16_t msCnt;//Max 10s
}Timestamp_User_StructDef;extern void Timestamp_UserInit(Timestamp_User_StructDef *p);
extern void Timestamp_Timer(Timestamp_User_StructDef *p);
extern uint8_t Timestamp_GetStatus(Timestamp_User_StructDef *p,Timestamp_Flag_EnumDef flag);#endif
Timestamp_Driver.c
/**********************************************************************
*file:时间戳文件
*author:残梦
*date:2022.9.2
*note:注:用户禁止使用、更改
为了方便将时间进行计数划分,方便将任务按实时性划分运行,减少消耗
**********************************************************************/
#include "Timestamp_Driver.h"/****************************************
@function:时间戳初始化
@param:
@return:void
@date:2022.9.2
@note:
****************************************/
void Timestamp_UserInit(Timestamp_User_StructDef *p)
{p->msCnt = 0; p->Flag = 0;
}/****************************************
@function:时间戳计时器
@param:
@return:void
@date:2022.9.2
@note:
****************************************/
void Timestamp_Timer(Timestamp_User_StructDef *p)
{p->msCnt++;p->Flag |= ((((p->msCnt % 10) == 0)?1:0) << Timestamp_10ms);p->Flag |= ((((p->msCnt % 50) == 0)?1:0) << Timestamp_50ms);p->Flag |= ((((p->msCnt % 100) == 0)?1:0) << Timestamp_100ms);p->Flag |= ((((p->msCnt % 200) == 0)?1:0) << Timestamp_200ms);p->Flag |= ((((p->msCnt % 500) == 0)?1:0) << Timestamp_500ms);p->Flag |= ((((p->msCnt % 1000) == 0)?1:0) << Timestamp_1s);p->Flag |= ((((p->msCnt % 2000) == 0)?1:0) << Timestamp_2s);p->Flag |= ((((p->msCnt % 10000) == 0)?1:0) << Timestamp_10s);p->msCnt = (p->msCnt >= 10000)?0:p->msCnt;
}/****************************************
@function:获取时间戳x状态
@param:flag--Timestamp_Flag_EnumDef
@return:0--无效,1--有效
@date:2022.8.13
@note:
****************************************/
uint8_t Timestamp_GetStatus(Timestamp_User_StructDef *p,Timestamp_Flag_EnumDef flag)
{uint8_t temp = 0,status = 0;temp = 1 << flag;status = (p->Flag & temp)?1:0;p->Flag &= (~temp);return status;
}
说明:此文件其实就是循环计数1ms计算时间是否等于标志时间,没什么特别的
3、使用时间戳
1、添加文件Timestamp_Driver.c到工程
2、定义时间戳变量
Timestamp_User_StructDef TimestampNRT;//定义时间戳:SysTick_Handler()调用计数
3、主函数初始化时间戳
Timestamp_UserInit(&TimestampNRT);
4、滴答定时器中断服务函数中调用时间戳计数函数
void SysTick_Handler(void)
{/* USER CODE BEGIN SysTick_IRQn 0 *//* USER CODE END SysTick_IRQn 0 */HAL_IncTick();/* USER CODE BEGIN SysTick_IRQn 1 */extern Timestamp_User_StructDef TimestampNRT;//时间戳Timestamp_Timer(&TimestampNRT); //1ms计数一次/* USER CODE END SysTick_IRQn 1 */
}
5、main()函数while中查询时间标志并执行操作
if(Timestamp_GetStatus(&TimestampNRT,Timestamp_1s))//标志会查询后清除{printf("Timestamp_1s\r\n");}