320 lines
11 KiB
C
320 lines
11 KiB
C
#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; //清除中断标志
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
|