#include "../main/SystemInclude.h" /*-===================================================================================================== //TIMER1 -=====================================================================================================*/ /**------------------------------------------------------------------------ * @brief 通用周期定时器(自适应时钟周期) * @note 时钟源:APB2_CLK * @param uploadCounter: 期望的周期,单位:毫秒 范围:(1~4000) * @example: StartTimer1(10); // 启动10ms周期定时器 **/ void StartTimer1_UIE(u16 uploadCounter) { if(uploadCounter>4000)uploadCounter = 4000; if(uploadCounter<= 0)uploadCounter = 1; u32 APB2_CLK = LHL_RCC_GetPCLK2Freq(); u32 prescaler = (APB2_CLK / 16000UL) - 1; //固定分频系数 (APB1_CLK / 32000UL) - 1; u32 period =(u32)(16UL * uploadCounter);//动态ARR计数 (uint32_t)(32000UL * uploadCounter) / 1000UL; TIM_InitTypeDef TIM_InitStructure; TIM_InitStructure.Period = period; TIM_InitStructure.Prescaler = prescaler; TIM_InitStructure.ClockDivision = TIM_CKD_DIV1; TIM_InitStructure.CounterMode = TIM_COUNTERMODE_UP; TIM_InitStructure.AutoReloadPreload = ENABLE; LHL_TIM_Init(TIM1, &TIM_InitStructure); /*使能TIM1更新中断UIE */ LHL_TIM_ITConfig(TIM1, TIM_IT_UPDATE, ENABLE); NVIC_EnableIRQ(TIM1_IRQn); NVIC_SetPriority(TIM1_IRQn,1); LHL_TIM_Start(TIM1); } /**------------------------------------------------------------------------ * @brief 通用周期定时器(自适应时钟周期)修改周期 * @note 时钟源:APB2_CLK * @param uploadCounter: 期望的周期,单位:毫秒 范围:(1~4000) * @example: ResetTimer1_UIE(20); // 定时器周期改为20ms **/ void ResetTimer1_UIE( u16 uploadCounter ) { // 参数检查 if(uploadCounter>4000)uploadCounter = 4000; if(uploadCounter<= 0)uploadCounter = 1; // 计算新ARR的值 u32 period =(u32)(16UL * uploadCounter); //PSC不变,ARR计算与StartTimer1相同 TIM1->CNT = 0; //先重置计数器 再设置ARR,避免立即溢出 LHL_TIM_ClearPending(TIM1, TIM_IT_UPDATE);//当前CNT已经接近或超过ARR,这里可能产生更新事件 所以需要先清除标志 TIM1->ARR = (u16)period ; //修改ARR 如果PSC需要改变,必须停止定时器! LHL_TIM_Start(TIM1); //确保定时器启用 } /**------------------------------------------------------------------------ * @brief 通用比较定时器(无电平输出) * @note 时钟源:APB2_CLK * @param uploadCounter: 计数值(1~65535),需要换算成期望周期 计数值=65535/4000*t * @example: StartTimer1(327); //启动20ms比较定时器 327=65535/4000*20 **/ void StartTimer1_CC1(u16 uploadCounter) { TIM_InitTypeDef TIM_InitStructure; TIM_InitStructure.Period = 65535; TIM_InitStructure.Prescaler = 244; TIM_InitStructure.ClockDivision = TIM_CKD_DIV1; TIM_InitStructure.CounterMode = TIM_COUNTERMODE_UP; TIM_InitStructure.AutoReloadPreload = DISABLE; LHL_TIM_Init(TIM1, &TIM_InitStructure); TIM1->CCR1 = uploadCounter; TIM1->CNT = 0; LHL_TIM_ITConfig(TIM1, TIM_IT_CC1, ENABLE);/* 使能TIM1比较中断CC1 */ NVIC_EnableIRQ(TIM1_IRQn); NVIC_SetPriority(TIM1_IRQn, 1); LHL_TIM_Start(TIM1); /* 运行TIM1 */ } /**------------------------------------------------------------------------ * @brief 通用比较定时器(无电平输出)不重置TIM1->CNT 更新比较值 * @note 时钟源:APB2_CLK * @param uploadCounter: 计数值(1~65535),需要换算成期望周期 计数值=65535/4000*t * @example: ResetTimer1_CC1(327+TIM1->CNT); // 下个20ms进入比较中断 **/ void ResetTimer1_CC1( u16 uploadCounter ) { TIM1->CCR1 = uploadCounter; TIM1->SR = (uint16_t)~TIM_IT_CC1; LHL_TIM_ITConfig(TIM1, TIM_IT_CC1, ENABLE); } /**------------------------------------------------------------------------ * @brief 停用定时器 * @note * @param * @example **/ void StopTimer1(void) { LHL_TIM_Stop(TIM1); NVIC_DisableIRQ( TIM1_IRQn ); LHL_TIM_ClearFlag(TIM1, TIM_IT_UPDATE|TIM_IT_CC1|TIM_IT_CC2|TIM_IT_TRIGGER); LHL_TIM_ITConfig( TIM1, TIM_IT_UPDATE|TIM_IT_CC1|TIM_IT_CC2|TIM_IT_TRIGGER, DISABLE ); } /*-===================================================================================================== //TIMER2 -=====================================================================================================*/ /**------------------------------------------------------------------------ * @brief 通用定时器启动(自适应时钟周期) * @note 时钟源:APB1_CLK * @param uploadCounter: 期望的周期,单位:毫秒 范围:(1~4000) * @example: StartTimer2(10); // 启动10ms周期定时器 **/ void StartTimer2_UIE(u16 uploadCounter) { if(uploadCounter>4000)uploadCounter = 4000; if(uploadCounter<= 0)uploadCounter = 1; u32 APB1_CLK = LHL_RCC_GetPCLK1Freq(); u32 prescaler = (APB1_CLK / 16000UL) - 1; //固定分频系数 (APB1_CLK / 32000UL) - 1; u32 period =(u32)(16UL * uploadCounter);//动态ARR计数 (uint32_t)(32000UL * uploadCounter) / 1000UL; TIM_InitTypeDef TIM_InitStructure; TIM_InitStructure.Period = period; TIM_InitStructure.Prescaler = prescaler; TIM_InitStructure.ClockDivision = TIM_CKD_DIV1; TIM_InitStructure.CounterMode = TIM_COUNTERMODE_UP; TIM_InitStructure.AutoReloadPreload = ENABLE; LHL_TIM_Init(TIM2, &TIM_InitStructure); /*使能TIM1更新中断UIE */ LHL_TIM_ITConfig(TIM2, TIM_IT_UPDATE, ENABLE); NVIC_EnableIRQ(TIM2_IRQn); NVIC_SetPriority(TIM2_IRQn, 1); LHL_TIM_Start(TIM2); } /**------------------------------------------------------------------------ * @brief 通用周期定时器(自适应时钟周期)修改周期 * @note 时钟源:APB1_CLK * @param uploadCounter: 期望的周期,单位:毫秒 范围:(1~4000) * @example: ResetTimer2_UIE(20); // 定时器周期改为20ms **/ void ResetTimer2_UIE(u16 uploadCounter) { // 参数检查 if(uploadCounter>4000)uploadCounter = 4000; if(uploadCounter<= 0)uploadCounter = 1; // 计算新ARR的值 u32 period =(u32)(16UL * uploadCounter); //PSC不变,ARR计算与StartTimer1相同 TIM2->CNT = 0; //先重置计数器 再设置ARR,避免立即溢出 LHL_TIM_ClearPending(TIM2, TIM_IT_UPDATE);//当前CNT已经接近或超过ARR,这里可能产生更新事件 所以需要先清除标志 TIM2->ARR = (u16)period ; //修改ARR 如果PSC需要改变,必须停止定时器! LHL_TIM_Start(TIM2); //确保定时器启用 } /**------------------------------------------------------------------------ * @brief 停用定时器 * @note * @param * @example **/ void StopTimer2(void) { LHL_TIM_Stop(TIM2); NVIC_DisableIRQ( TIM2_IRQn ); LHL_TIM_ClearFlag(TIM2, TIM_IT_UPDATE|TIM_IT_CC1|TIM_IT_CC2|TIM_IT_TRIGGER); LHL_TIM_ITConfig( TIM2, TIM_IT_UPDATE|TIM_IT_CC1|TIM_IT_CC2|TIM_IT_TRIGGER, DISABLE ); } /**------------------------------------------------------------------------ * @brief 输出定时器 * @note 时钟源:APB2_CLK * @param uploadCounter: PWM期望的周期,单位:Hz 范围:(1~400) duty :PWM占空比 范围:(0-100) * @example: StartTimer1_PWM(10,50); // 启动10Hz(100ms)周期定时器,PWM输出占空比50% StartTimer1_PWM(400,50); //启动400Hz(2.5ms)周期定时器,PWM输出占空比50% **/ void StartTimer1_PWM(u16 freq_hz , u16 duty) { GPIO_InitTypeDef GPIO_InitStructure; TIM_InitTypeDef TIM_InitStructure; TIM_PWMInitTypeDef TIM_PWMInitStructure; u32 APB2_CLK = LHL_RCC_GetPCLK2Freq(); u16 period =10000; //固定ARR计数 u32 prescaler = (APB2_CLK /(period*freq_hz) )-1; u16 dutyValue = period*duty/100; /* 1. TIM1 通道1 GPIO复用配置 */ GPIO_InitStructure.Pin = GPIO_PIN_5; // P0.5->TIM1 CHANNEL1 GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStructure.Current = GPIO_CURRENT_16mA; GPIO_InitStructure.Pull = GPIO_NOPULL; GPIO_InitStructure.SchmittTrigger = ENABLE; GPIO_InitStructure.Alternate = GPIO0_5_AF_TIM1_CH1; LHL_GPIO_Init(pGPIO0, &GPIO_InitStructure); /* 2. TIM1 时基配置 */ TIM_InitStructure.Prescaler = prescaler; // 设置定时器时钟 TIM_InitStructure.Period = period-1; // 设置定时器周期 TIM_InitStructure.ClockDivision = TIM_CKD_DIV1; TIM_InitStructure.CounterMode = TIM_COUNTERMODE_UP; TIM_InitStructure.AutoReloadPreload = ENABLE; // 开启ARR预加载 LHL_TIM_Init(TIM1, &TIM_InitStructure); /* 3. TIM1 通道1输出PWM配置 */ TIM_PWMInitStructure.Pulse = dutyValue; // 设置占空比 TIM_PWMInitStructure.PWMMode = TIM_PWMMODE_PWM1; // PWM模式1 TIM_PWMInitStructure.PWMPolarity = TIM_PWMPOLARITY_ACTIVE_HIGH; // PULSE期间输出有效电平 TIM_PWMInitStructure.PWMPreload = ENABLE; // 开启CCR预加载 TIM_PWMInitStructure.PWMFastMode = DISABLE; LHL_TIM_PWM_Init(TIM1, &TIM_PWMInitStructure, TIM_CHANNEL_1); /* 4. 开启TIM1 的PWM输出 */ LHL_TIM_Start(TIM1); } void ResetTimer1_PWM(u16 duty) { //限幅 if(duty > 100)duty = 100; if(duty < 0)duty = 0; u16 dutyValue = 100*duty ; //10000*duty/100; //更新占空比 LHL_TIM_PWM_SetDutyCycle(TIM1, dutyValue, TIM_CHANNEL_1); } /*-===================================================================================================== //定时器中断回调 -=====================================================================================================*/ /**------------------------------------------------------------------------ * @brief 定时器回调函数注册 * @note * @param TIM_TypeDef *timer:pTIM1 pTIM2 ; timer_irq_callback_t tim_irq_callback :自定义回调函数名 * @example: Timer_register_irq_callback(pTIM1,callback1); **/ static timer_irq_callback_t tim1_irq_callback ,tim2_irq_callback; void Timer_register_irq_callback(TIM_TypeDef *timer, timer_irq_callback_t tim_irq_callback) { if(timer == TIM1) {tim1_irq_callback = tim_irq_callback; NVIC_EnableIRQ(TIM1_IRQn);} else if(timer == TIM2) {tim2_irq_callback = tim_irq_callback; NVIC_EnableIRQ(TIM2_IRQn);} } /**------------------------------------------------------------------------ * @brief 低功耗定时器1中断函数 * @note 中断类型: * TIM_IT_UPDATE * TIM_IT_CC1 * TIM_IT_CC2 * TIM_IT_TRIGGER **/ void TIM1_IRQHandler(void) { uint16_t irq_type = TIM1->SR ; //中断标志 if (irq_type & TIM_IT_CC1) { // 处理比较中断 if (tim1_irq_callback != NULL) tim1_irq_callback();// 调用用户注册的回调函数 } TIM1->SR = (uint16_t)~irq_type; //清除中断标志 /* if (LHL_TIM_GetPending(TIM1, TIM_IT_UPDATE)== SET) // 判断是否TIM1 Update中断 { LHL_TIM_ClearPending(TIM1, TIM_IT_UPDATE); // 清除中断标志 } if (LHL_TIM_GetPending(TIM1, TIM_IT_CC1) == SET) // 判断是否TIM1 CC1中断 { LHL_TIM_ClearPending(TIM1, TIM_IT_CC1); // 清除中断标志 } if (LHL_TIM_GetPending(TIM1, TIM_IT_CC2) == SET) { LHL_TIM_ClearPending(TIM1, TIM_IT_CC2); } if (LHL_TIM_GetPending(TIM1, TIM_IT_TRIGGER) == SET) { LHL_TIM_ClearPending(TIM1, TIM_IT_TRIGGER); } */ } /**------------------------------------------------------------------------ * @brief 低功耗定时器2中断函数 **/ void TIM2_IRQHandler(void) { uint16_t irq_type = TIM2->SR ; //中断标志 if (tim2_irq_callback != NULL) tim2_irq_callback();// 调用用户注册的回调函数 TIM2->SR = (uint16_t)~irq_type; //清除中断标志 }