HAL与LL库查询方式实现精确微秒或毫秒延时,可以用于IO口模拟I2C、SPI通信等。通过HAL实现初始化5us初始化,后面在延时函数中可以再设置延时值。
1. 定时器实现1us延时
中断Enable不打钩
复制必要库文件,.c/.h单独一个文件,设置好。
生成代码如下:
/* TIM3 init function */
void MX_TIM3_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
htim3.Instance = TIM3;
htim3.Init.Prescaler = 72-1;
htim3.Init.CounterMode = TIM_COUNTERMODE_DOWN;
htim3.Init.Period = 5-1;
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim3) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
}
2. 手动复制stm32f1xx_ll_tim.h文件到工程下
3. 实际的延时函数
//delay_us.c
#include "stm32f1xx_ll_tim.h"
void delay_us(uint16_t us)
{
//设置更新请求源,只有计数器溢出/下溢才产生更新中断
LL_TIM_SetUpdateSource(TIM3, LL_TIM_UPDATESOURCE_COUNTER); //URS=1,默认0
//设置定时时间
LL_TIM_SetAutoReload(TIM3, us);
/* Force update generation */ //产生一个更新事件,需要下面清FLAG(如果设URS=1,则不需要)
LL_TIM_GenerateEvent_UPDATE(TIM3);
/* Clear the update interrupt flag*/ //清除更新,
// LL_TIM_ClearFlag_UPDATE(TIM3);
/* Enable counter */
LL_TIM_EnableCounter(TIM3);
while(LL_TIM_IsActiveFlag_UPDATE(TIM3) == 0);
LL_TIM_ClearFlag_UPDATE(TIM3);
LL_TIM_DisableCounter(TIM3);
}
//计时开始,us:定时时间,单位微妙
void delay_us_Start(uint16_t us)
{
//设置定时时间
LL_TIM_SetAutoReload(TIM3, us);
/* Force update generation */ //产生一个更新事件
LL_TIM_GenerateEvent_UPDATE(TIM3);
/* Clear the update interrupt flag*/ //清除更新
LL_TIM_ClearFlag_UPDATE(TIM3);
/* Enable counter */
LL_TIM_EnableCounter(TIM3);
}
//查询延时时间是否已到
//return 0:时间未到,1:时间已到
uint8_t delay_us_IsEnd(void)
{
if(LL_TIM_IsActiveFlag_UPDATE(TIM3) == 0)
{
return 0;
}
else
{
LL_TIM_ClearFlag_UPDATE(TIM3);
LL_TIM_DisableCounter(TIM3);
return 1;
}
}
//结束定时器计数
void delay_us_Stop(void)
{
LL_TIM_DisableCounter(TIM3);
/* Clear the update interrupt flag*/ //清除更新
LL_TIM_ClearFlag_UPDATE(TIM3);
}