Files
CHJ/user/MCU/lhl_lptimer.c
2026-03-20 21:19:53 +08:00

196 lines
6.6 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "../main/SystemInclude.h"
/**------------------------------------------------------------------------
* @brief LPTimer 基础初始化(内部调用)
* @note 配置为定时器/计数器模式,时钟源由 LPTIM_CLK_ENABLE_LSE 宏决定,
* 预分频系数固定为 DIV2LSI 或 LSE 频率除以2禁用自由运行模式。
* @param lptimer: LPTIM1 或 LPTIM2
* @example 内部使用,不直接调用
**/
static void LPTIM_Init(LPTIM_TypeDef *lptimer)
{
LPTIM_InitTypeDef LPTIM_InitStructure; /* 1. 初始化LPTimer Base */
LPTIM_InitStructure.Mode = LPTIM_MODE_TIMER_COUNTER; // 定时器模式
#if LPTIM_CLK_ENABLE_LSE
LHL_RCC_LSEConfig(ENABLE);
LPTIM_InitStructure.Clock = LPTIM_CLOCKSOURCE_LSE; // LPTIM时钟源LSE
#else
LHL_RCC_LSEConfig(DISABLE);
LPTIM_InitStructure.Clock = LPTIM_CLOCKSOURCE_LSI; // LPTIM时钟源LSI
#endif
LPTIM_InitStructure.Prescaler = LPTIM_PRESCALER_DIV2; // 预分频系数2 变成 16384 为1s
LPTIM_InitStructure.FreeRunning = DISABLE; // 禁用自由运行模式
LHL_LPTIM_Init(lptimer, &LPTIM_InitStructure);
}
/*==================================================================================*/
/*LPTimer1==========================================================================*/
/*==================================================================================*/
/**------------------------------------------------------------------------
* @brief 启动 LPTIM1产生周期性中断
* @note 时钟频率为 32768Hz预分频 DIV2 后实际时钟为 16384Hz。
* 周期计算:计数值 uploadCounter = (16384/1000) * t(ms) = 16.384 * t
* 例如 t=125msuploadCounter≈2048。
* @param uploadCounter: 自动重装载值(范围 1~65535对应定时周期
* @example StartLPTimer1(2048); // 启动 125ms 周期定时器
**/
void StartLPTimer1(u16 uploadCounter)//125ms 250ms ......
{
/* 1. 初始化LPTimer Base */
LHL_LPTIM_DeInit(LPTIM1);
LPTIM_Init(LPTIM1);
/* 2. 开启LPTimer中断 */
LHL_LPTIM_ITConfig(LPTIM1, ENABLE);
NVIC_EnableIRQ(LPTIM1_IRQn);
/* 3. 启动LPTimer1 */
LHL_LPTIM_Start(LPTIM1, uploadCounter);
}
/**------------------------------------------------------------------------
* @brief 重置 LPTIM1 周期(运行时修改)
* @note 先停用定时器,更新比较值 CMR再重新使能计数器从 0 重新开始。
* @param uploadCounter: 新的重装载值 计算方式16.384 * t
* @example ResetLPTimer1(4096); // 将周期改为 250ms
**/
void ResetLPTimer1(u16 uploadCounter)
{
LPTIM1->CSR &= ~LPTIM_CSR_TEN_Msk;// 1. 禁用定时器
LPTIM1->CSR |= LPTIM_CSR_TCF_Msk; // 2. 清除比较中断标志
LPTIM1->CMR = uploadCounter; // 3. 设置新的比较值
LPTIM1->CSR |= LPTIM_CSR_TEN_Msk; // 4. 重新使能 → 计数器从 0 开始
}
/**------------------------------------------------------------------------
* @brief 停止 LPTIM1
* @note 禁用定时器并使能位 TEN 清零,清除比较中断标志。
* @param 无
* @example StopLPTimer1();
**/
void StopLPTimer1(void)
{
LPTIM1->CSR &= ~LPTIM_CSR_TEN_Msk;// 1. 禁用定时器
LPTIM1->CSR |= LPTIM_CSR_TCF_Msk; // 2. 清除比较中断标志
}
/*==================================================================================*/
/*LPTimer2==========================================================================*/
/*==================================================================================*/
/**------------------------------------------------------------------------
* @brief 启动 LPTIM2产生周期性中断
* @note 同 LPTIM1时钟频率 32768Hz预分频 DIV2周期计算相同。
* @param uploadCounter: 自动重装载值
* @example StartLPTimer2(2048); // 启动 125ms 周期定时器
**/
void StartLPTimer2(u16 uploadCounter)//125ms 250ms ......
{
/* 1. 初始化LPTimer Base */
LHL_LPTIM_DeInit(LPTIM2);
LPTIM_Init(LPTIM2);
/* 2. 开启LPTimer中断 */
LHL_LPTIM_ITConfig(LPTIM2, ENABLE);
NVIC_EnableIRQ(LPTIM2_IRQn);
/* 3. 启动LPTimer1和2 */
LHL_LPTIM_Start(LPTIM2, uploadCounter);
}
/**------------------------------------------------------------------------
* @brief 重置 LPTIM2 周期(运行时修改)
* @param uploadCounter: 新的重装载值 计算方式16.384 * t
* @example ResetLPTimer2(4096);
**/
void ResetLPTimer2(u16 uploadCounter)
{
LPTIM2->CSR &= ~LPTIM_CSR_TEN_Msk;// 1. 禁用定时器
LPTIM2->CSR |= LPTIM_CSR_TCF_Msk; // 2. 清除比较中断标志
LPTIM2->CMR = uploadCounter; // 3. 设置新的比较值
LPTIM2->CSR |= LPTIM_CSR_TEN_Msk; // 4. 重新使能 → 计数器从 0 开始
}
/**------------------------------------------------------------------------
* @brief 停止 LPTIM2
* @example StopLPTimer2();
**/
void StopLPTimer2(void)
{
LPTIM2->CSR &= ~LPTIM_CSR_TEN_Msk;// 1. 禁用定时器
LPTIM2->CSR |= LPTIM_CSR_TCF_Msk; // 2. 清除比较中断标志
}
/*==================================================================================*/
/*低功耗定时器回调函数====================================================================*/
/*==================================================================================*/
/**------------------------------------------------------------------------
* @brief 注册 LPTIM1/LPTIM2 中断回调函数
* @param lptimer: LPTIM1 或 LPTIM2
* @param lptim_irq_callback: 用户回调函数指针(无参数无返回值)
* @note 每个定时器只能注册一个回调函数(若需多源,可自行扩展)。
* 注册时会自动清除中断标志并开启 NVIC 中断。
* @example lptimer_register_irq_callback(LPTIM1, my_callback);
**/
static lptimer_irq_callback_t lptim1_irq_callback,lptim2_irq_callback ;
void lptimer_register_irq_callback(LPTIM_TypeDef *lptimer ,lptimer_irq_callback_t lptim_irq_callback)
{
if(lptimer == LPTIM1)
{
lptim1_irq_callback = lptim_irq_callback;//赋值回调函数
LHL_LPTIM_ClearPending(LPTIM1);// 清除中断标志
NVIC_EnableIRQ(LPTIM1_IRQn);//开启中断
}
else if(lptimer == LPTIM2)
{
lptim2_irq_callback = lptim_irq_callback;
LHL_LPTIM_ClearPending(LPTIM2);// 清除中断标志
NVIC_EnableIRQ(LPTIM2_IRQn);
}
}
/**------------------------------------------------------------------------
* @brief LPTIM1 中断服务函数
* @note 调用已注册的回调函数(若存在),然后清除中断标志。
* @param 无
**/
void LPTIM1_IRQHandler(void)
{
// 如果有中断发生且注册了回调函数
if (lptim1_irq_callback != NULL) lptim1_irq_callback();// 调用用户注册的回调函数
LHL_LPTIM_ClearPending(LPTIM1); // 清除中断标志
}
/**------------------------------------------------------------------------
* @brief LPTIM2 中断服务函数
* @note 调用已注册的回调函数(若存在),然后清除中断标志。
* @param 无
**/
void LPTIM2_IRQHandler(void)
{
// 如果有中断发生且注册了回调函数
if (lptim2_irq_callback != NULL) lptim2_irq_callback();// 调用用户注册的回调函数
LHL_LPTIM_ClearPending(LPTIM2); // 清除中断标志
}