SmartCar-V1/Code/bsp/src/bsp_timer.c

769 lines
27 KiB
C
Raw 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.

/*
*********************************************************************************************************
*
* 模块名称 : 定时器模块
* 文件名称 : bsp_timer.c
* 版 本 : V1.2
* 说 明 : 配置systick定时器作为系统滴答定时器。缺省定时周期为1ms。
*
* 实现了多个软件定时器供主程序使用(精度1ms) 可以通过修改 TMR_COUNT 增减定时器个数
* 实现了ms级别延迟函数精度1ms 和us级延迟函数
* 实现了系统运行时间函数1ms单位
*
* 修改记录 :
* 版本号 日期 作者 说明
* V1.0 2013-02-01 armfly 正式发布
* V1.1 2013-06-21 armfly 增加us级延迟函数 bsp_DelayUS
* V1.2 2014-09-07 armfly 增加TIM4 硬件定时中断实现us级别定时.20us - 16秒
*
* Copyright (C), 2014-2015, 安富莱电子 www.armfly.com
*
*********************************************************************************************************
*/
//#include "bsp.h"
#include "bsp_timer.h"
#include "stm32f10x_tim.h"
#include "public_diy.h"
#include "bsp_core.h"
// /* 外部时钟源定时器 */
// #define TIM_EXTERN_INPUT TIM2
// #define TIM_EXTERN_INPUT_IRQn TIM2_IRQn
// #define TIM_EXTERN_INPUT_RCC RCC_APB1Periph_TIM2
/* 硬件定时器 */
#define TIM_HARD TIM3
#define TIM_HARD_IRQn TIM3_IRQn
#define TIM_HARD_RCC RCC_APB1Periph_TIM3
/* PWM输出比较 定时器 */
#define TIM_PWM TIM4
#define TIM_PWM_IRQn TIM4_IRQn
#define TIM_PWM_RCC RCC_APB1Periph_TIM4
#define TIM_PWM_CH1_PORT GPIOB
#define TIM_PWM_CH1_PIN GPIO_Pin_6
// /* 测试 TIM2_ETR 是否使用重映射功能 */
// #define USE_REMAP_PA15_ENABLE
/* 这2个全局变量转用于 bsp_DelayMS() 函数 */
static volatile uint32_t s_uiDelayCount = 0;
static volatile uint8_t s_ucTimeOutFlag = 0;
/* 定于软件定时器结构体变量 */
static SOFT_TMR s_tTmr[TMR_COUNT];
/*
全局运行时间单位1ms
最长可以表示 24.85天,如果你的产品连续运行时间超过这个数,则必须考虑溢出问题
*/
__IO int32_t g_iRunTime = 0;
static void bsp_SoftTimerDec(SOFT_TMR *_tmr);
/* 保存 TIM定时中断到后执行的回调函数指针 */
static void (*s_TIM_CallBack1)(void);
static void (*s_TIM_CallBack2)(void);
static void (*s_TIM_CallBack3)(void);
static void (*s_TIM_CallBack4)(void);
/*
*********************************************************************************************************
* 函 数 名: SysTick_ISR
* 功能说明: SysTick中断服务程序每隔1ms进入1次
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
extern void bsp_RunPer1ms(void);
extern void bsp_RunPer10ms(void);
void SysTick_ISR(void)
{
// static uint8_t s_count = 0;
uint8_t i;
/* 每隔1ms进来1次 (仅用于 bsp_DelayMS */
if (s_uiDelayCount > 0)
{
if (--s_uiDelayCount == 0)
{
s_ucTimeOutFlag = 1;
}
}
/* 每隔1ms对软件定时器的计数器进行减一操作 */
for (i = 0; i < TMR_COUNT; i++)
{
bsp_SoftTimerDec(&s_tTmr[i]);
}
/* 全局运行时间每1ms增1 */
// g_iRunTime++;
// if (g_iRunTime == 0x7FFFFFFF) /* 这个变量是 int32_t 类型,最大数为 0x7FFFFFFF */
// {
// g_iRunTime = 0;
// }
// bsp_RunPer1ms(); /* 每隔1ms调用一次此函数此函数在 bsp.c */
// if (++s_count >= 10)
// {
// s_count = 0;
// bsp_RunPer10ms(); /* 每隔10ms调用一次此函数此函数在 bsp.c */
// }
}
/*
*********************************************************************************************************
* 函 数 名: bsp_SoftTimerDec
* 功能说明: 每隔1ms对所有定时器变量减1。必须被SysTick_ISR周期性调用。
* 形 参: _tmr : 定时器变量指针
* 返 回 值: 无
*********************************************************************************************************
*/
static void bsp_SoftTimerDec(SOFT_TMR *_tmr)
{
if (_tmr->Count > 0)
{
/* 如果定时器变量减到1则设置定时器到达标志 */
if (--_tmr->Count == 0)
{
_tmr->Flag = 1;
/* 如果是自动模式,则自动重装计数器 */
if(_tmr->Mode == TMR_AUTO_MODE)
{
_tmr->Count = _tmr->PreLoad;
}
}
}
}
/*
*********************************************************************************************************
* 函 数 名: bsp_DelayMS
* 功能说明: ms级延迟延迟精度为正负1ms
* 形 参: n : 延迟长度单位1 ms。 n 应大于2
* 返 回 值: 无
*********************************************************************************************************
*/
void bsp_DelayMS(uint32_t n)
{
if (n == 0)
{
return;
}
else if (n == 1)
{
n = 2;
}
DISABLE_INT(); /* 关中断 */
s_uiDelayCount = n;
s_ucTimeOutFlag = 0;
ENABLE_INT(); /* 开中断 */
while (1)
{
// bsp_Idle(); /* CPU空闲执行的操作 见 bsp.c 和 bsp.h 文件 */
/*
等待延迟时间到
注意:编译器认为 s_ucTimeOutFlag = 0所以可能优化错误因此 s_ucTimeOutFlag 变量必须申明为 volatile
*/
if (s_ucTimeOutFlag == 1)
{
break;
}
}
}
/*
*********************************************************************************************************
* 函 数 名: bsp_DelayUS
* 功能说明: us级延迟。 必须在systick定时器启动后才能调用此函数。
* 形 参: n : 延迟长度单位1 us
* 返 回 值: 无
*********************************************************************************************************
*/
void bsp_DelayUS(uint32_t n)
{
uint32_t ticks;
uint32_t told;
uint32_t tnow;
uint32_t tcnt = 0;
uint32_t reload;
reload = SysTick->LOAD;
ticks = n * (SystemCoreClock / 1000000); /* 需要的节拍数 */
tcnt = 0;
told = SysTick->VAL; /* 刚进入时的计数器值 */
while (1)
{
tnow = SysTick->VAL;
if (tnow != told)
{
/* SYSTICK是一个递减的计数器 */
if (tnow < told)
{
tcnt += told - tnow;
}
/* 重新装载递减 */
else
{
tcnt += reload - tnow + told;
}
told = tnow;
/* 时间超过/等于要延迟的时间,则退出 */
if (tcnt >= ticks)
{
break;
}
}
}
}
/*
*********************************************************************************************************
* 函 数 名: bsp_StartTimer
* 功能说明: 启动一个定时器,并设置定时周期。
* 形 参: _id : 定时器ID值域【0,TMR_COUNT-1】。用户必须自行维护定时器ID以避免定时器ID冲突。
* _period : 定时周期单位1ms
* 返 回 值: 无
*********************************************************************************************************
*/
void bsp_StartTimer(uint8_t _id, uint32_t _period)
{
if (_id >= TMR_COUNT)
{
/* 打印出错的源代码文件名、函数名称 */
BSP_Printf("Error: file %s, function %s()\r\n", __FILE__, __FUNCTION__);
while(1); /* 参数异常,死机等待看门狗复位 */
}
DISABLE_INT(); /* 关中断 */
s_tTmr[_id].Count = _period; /* 实时计数器初值 */
s_tTmr[_id].PreLoad = _period; /* 计数器自动重装值,仅自动模式起作用 */
s_tTmr[_id].Flag = 0; /* 定时时间到标志 */
s_tTmr[_id].Mode = TMR_ONCE_MODE; /* 1次性工作模式 */
ENABLE_INT(); /* 开中断 */
}
/*
*********************************************************************************************************
* 函 数 名: bsp_StartAutoTimer
* 功能说明: 启动一个自动定时器,并设置定时周期。
* 形 参: _id : 定时器ID值域【0,TMR_COUNT-1】。用户必须自行维护定时器ID以避免定时器ID冲突。
* _period : 定时周期单位10ms
* 返 回 值: 无
*********************************************************************************************************
*/
void bsp_StartAutoTimer(uint8_t _id, uint32_t _period)
{
if (_id >= TMR_COUNT)
{
/* 打印出错的源代码文件名、函数名称 */
BSP_Printf("Error: file %s, function %s()\r\n", __FILE__, __FUNCTION__);
while(1); /* 参数异常,死机等待看门狗复位 */
}
DISABLE_INT(); /* 关中断 */
s_tTmr[_id].Count = _period; /* 实时计数器初值 */
s_tTmr[_id].PreLoad = _period; /* 计数器自动重装值,仅自动模式起作用 */
s_tTmr[_id].Flag = 0; /* 定时时间到标志 */
s_tTmr[_id].Mode = TMR_AUTO_MODE; /* 自动工作模式 */
ENABLE_INT(); /* 开中断 */
}
/*
*********************************************************************************************************
* 函 数 名: bsp_StopTimer
* 功能说明: 停止一个定时器
* 形 参: _id : 定时器ID值域【0,TMR_COUNT-1】。用户必须自行维护定时器ID以避免定时器ID冲突。
* 返 回 值: 无
*********************************************************************************************************
*/
void bsp_StopTimer(uint8_t _id)
{
if (_id >= TMR_COUNT)
{
/* 打印出错的源代码文件名、函数名称 */
BSP_Printf("Error: file %s, function %s()\r\n", __FILE__, __FUNCTION__);
while(1); /* 参数异常,死机等待看门狗复位 */
}
DISABLE_INT(); /* 关中断 */
s_tTmr[_id].Count = 0; /* 实时计数器初值 */
s_tTmr[_id].Flag = 0; /* 定时时间到标志 */
s_tTmr[_id].Mode = TMR_ONCE_MODE; /* 自动工作模式 */
ENABLE_INT(); /* 开中断 */
}
/*
*********************************************************************************************************
* 函 数 名: bsp_CheckTimer
* 功能说明: 检测定时器是否超时
* 形 参: _id : 定时器ID值域【0,TMR_COUNT-1】。用户必须自行维护定时器ID以避免定时器ID冲突。
* _period : 定时周期单位1ms
* 返 回 值: 返回 0 表示定时未到, 1表示定时到
*********************************************************************************************************
*/
uint8_t bsp_CheckTimer(uint8_t _id)
{
if (_id >= TMR_COUNT)
{
return 0;
}
if (s_tTmr[_id].Flag == 1)
{
s_tTmr[_id].Flag = 0;
return 1;
}
else
{
return 0;
}
}
/*
*********************************************************************************************************
* 函 数 名: bsp_GetRunTime
* 功能说明: 获取CPU运行时间单位1ms。最长可以表示 24.85天,如果你的产品连续运行时间超过这个数,则必须考虑溢出问题
* 形 参: 无
* 返 回 值: CPU运行时间单位1ms
*********************************************************************************************************
*/
int32_t bsp_GetRunTime(void)
{
int32_t runtime;
DISABLE_INT(); /* 关中断 */
runtime = g_iRunTime; /* 这个变量在Systick中断中被改写因此需要关中断进行保护 */
ENABLE_INT(); /* 开中断 */
return runtime;
}
/*************************************************************************************
* @brief 配置 TIM2用于us级别硬件定时。自由运行永不停止.
*
* @warning
* @note
*************************************************************************************/
void bsp_InitHardTimer(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure; /* 中断结构体在 misc.h 中定义 */
/* 1. 使能TIM时钟 */
RCC_APB1PeriphClockCmd(TIM_HARD_RCC, ENABLE);
/* 2. 使用内部时钟 */
TIM_InternalClockConfig(TIM_HARD);
/* 3. 配置时基单元 */
/*-----------------------------------------------------------------------
system_stm32f10x.c 文件中 void SetSysClock(void) 函数对时钟的配置如下:
HCLK = SYSCLK / 1 (AHBPeriph)
PCLK2 = HCLK / 1 (APB2Periph)
PCLK1 = HCLK / 2 (APB1Periph)
因为APB1 prescaler != 1, 所以 APB1上的TIMxCLK = PCLK1 x 2 = SystemCoreClock;
因为APB2 prescaler = 1, 所以 APB2上的TIMxCLK = PCLK2 = SystemCoreClock;
注意TIM_Prescaler 和 TIM_Period 不要溢出(0-65535)
----------------------------------------------------------------------- */
// 时基单元定义 此处定义1ms的
TIM_TimeBaseStructure.TIM_Period = (10 - 1); // 周期 ARR自动重装器的值
TIM_TimeBaseStructure.TIM_Prescaler = (SystemCoreClock / 10000) - 1 ; // PSC预分频器的值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // 计数器模式
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; // 重复计数器的值,高级定时器才有
TIM_TimeBaseInit(TIM_HARD, &TIM_TimeBaseStructure);
/* 4. 开启更新中断到NVIC的通路 */
TIM_ClearITPendingBit(TIM_HARD, TIM_IT_Update);
// 在开启更新中断之前,先把这个更新中断清掉,防止一开始就触发了更新中断
TIM_ITConfig(TIM_HARD, TIM_IT_Update, ENABLE);
// 启用影子寄存器
TIM_ARRPreloadConfig(TIM_HARD, ENABLE);
/* 5. 配置TIM定时中断 (Update) */
NVIC_InitStructure.NVIC_IRQChannel = TIM_HARD_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 4; /* 比串口优先级低 */
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* 6. TIMx enable counter */
TIM_Cmd(TIM_HARD, ENABLE);
}
void bsp_pwm_init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
GPIO_InitTypeDef GPIO_InitStructure;
// NVIC_InitTypeDef NVIC_InitStructure; /* 中断结构体在 misc.h 中定义 */
TIM_OCInitTypeDef TIM_OCInitStructure;
/* 1. 使能TIM时钟 */
RCC_APB1PeriphClockCmd(TIM_PWM_RCC, ENABLE);
/* 2. 使用内部时钟 */
TIM_InternalClockConfig(TIM_PWM);
/* 3. 初始化GPIO */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = TIM_PWM_CH1_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(TIM_PWM_CH1_PORT, &GPIO_InitStructure);
/* 3. 配置时基单元 */
/*-----------------------------------------------------------------------
system_stm32f10x.c 文件中 void SetSysClock(void) 函数对时钟的配置如下:
HCLK = SYSCLK / 1 (AHBPeriph)
PCLK2 = HCLK / 1 (APB2Periph)
PCLK1 = HCLK / 2 (APB1Periph)
因为APB1 prescaler != 1, 所以 APB1上的TIMxCLK = PCLK1 x 2 = SystemCoreClock;
因为APB2 prescaler = 1, 所以 APB2上的TIMxCLK = PCLK2 = SystemCoreClock;
注意TIM_Prescaler 和 TIM_Period 不要溢出(0-65535)
----------------------------------------------------------------------- */
// 时基单元定义 此处定义1ms的
TIM_TimeBaseStructure.TIM_Period = (10 - 1); // 周期 ARR自动重装器的值
TIM_TimeBaseStructure.TIM_Prescaler = (36 - 1); // PSC预分频器的值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // 计数器模式
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; // 重复计数器的值,高级定时器才有
TIM_TimeBaseInit(TIM_PWM, &TIM_TimeBaseStructure);
TIM_OCStructInit(&TIM_OCInitStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM_PWM, &TIM_OCInitStructure);
// /* 4. 开启更新中断到NVIC的通路 */
// TIM_ClearITPendingBit(TIM_PWM, TIM_IT_Update);
// // 在开启更新中断之前,先把这个更新中断清掉,防止一开始就触发了更新中断
// TIM_ITConfig(TIM_PWM, TIM_IT_Update, ENABLE);
// 启用影子寄存器
TIM_ARRPreloadConfig(TIM_PWM, ENABLE);
// /* 5. 配置TIM定时中断 (Update) */
// NVIC_InitStructure.NVIC_IRQChannel = TIM_HARD_IRQn;
// NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 4; /* 比串口优先级低 */
// NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
// NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
// NVIC_Init(&NVIC_InitStructure);
/* 6. TIMx enable counter */
TIM_Cmd(TIM_PWM, ENABLE);
}
void bsp_change_pwm(uint8_t ucData)
{
TIM_SetCompare1(TIM_PWM, ucData);
}
/*************************************************************************************
* @brief 呼吸灯测试例程
*
* @warning
* @note
*************************************************************************************/
void bsp_pwm_test_loop(void)
{
int8_t tmp_i = 0;
for(tmp_i = 0; tmp_i <= 10; ++tmp_i)
{
bsp_change_pwm(tmp_i);
bsp_DelayMS(50);
}
for(tmp_i = 10; tmp_i >= 0; tmp_i--)
{
bsp_change_pwm(tmp_i);
bsp_DelayMS(50);
}
}
/*************************************************************************************
* @brief 初始化外部时钟
* 此处使用TIM2_ETR 外部时钟模式2 假设外部时钟频率为 100kHz
* TIM2_ETR 使用 PA0引脚
*
* @warning
* @note
*************************************************************************************/
//void bsp_InitExternInputTimer(void)
//{
// /* 采用PA0 作为外部ETR时钟信号 */
// GPIO_InitTypeDef GPIO_InitStructure;
// TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
// NVIC_InitTypeDef NVIC_InitStructure;
// /* 1. 使能TIM时钟 */
// RCC_APB1PeriphClockCmd(TIM_EXTERN_INPUT_RCC, ENABLE);
// /* 2. 使用外部时钟 ETR */
// TIM_ETRClockMode2Config(TIM_EXTERN_INPUT, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_Inverted, 0x00);
// /* 3. 初始化GPIO */
//#ifdef USE_REMAP_PA15_ENABLE
// RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能 PA 端口时钟
// RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //使能 PA 端口时钟
// GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2, ENABLE);
// GPIO_PinRemapConfig(GPIO_Remap_SWJ_NoJTRST, ENABLE);
// GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15; // ETR-->PA.0 端口配置
// GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入
// GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO 口速度为 50MHz
//#else
// GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化 GPIOA.0
// RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能 PA 端口时钟
// GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; // ETR-->PA.0 端口配置
// GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入
// GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO 口速度为 50MHz
// GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化 GPIOA.0
//#endif
// /* 4. 定义时基单元 */
// // 此处以外部时钟为100KHz为例
// TIM_TimeBaseStructure.TIM_Period = (100u - 1); // 周期 ARR自动重装器的值
// TIM_TimeBaseStructure.TIM_Prescaler = (1000u - 1) ; // PSC预分频器的值
// TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
// TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // 计数器模式
// TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; // 重复计数器的值,高级定时器才有
// TIM_TimeBaseInit(TIM_EXTERN_INPUT, &TIM_TimeBaseStructure);
// /* 5. 开启更新中断到NVIC的通路 */
// TIM_ITConfig(TIM_EXTERN_INPUT, TIM_IT_Update, ENABLE);
// // 在开启更新中断之前,先把这个更新中断清掉,防止一开始就触发了更新中断
// TIM_ITConfig(TIM_EXTERN_INPUT, TIM_IT_Update, ENABLE);
// // 启用影子寄存器
// TIM_ARRPreloadConfig(TIM_EXTERN_INPUT, ENABLE);
// /* 6. 配置TIM定时中断 (Update) */
// NVIC_InitStructure.NVIC_IRQChannel = TIM_EXTERN_INPUT_IRQn;
// NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 5; /* 比串口优先级低 */
// NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
// NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
// NVIC_Init(&NVIC_InitStructure);
// /* 7. TIMx enable counter */
// TIM_Cmd(TIM_EXTERN_INPUT, ENABLE);
//}
/*
*********************************************************************************************************
* 函 数 名: bsp_StartHardTimer
* 功能说明: 使用TIM2-5做单次定时器使用, 定时时间到后执行回调函数。可以同时启动4个定时器互不干扰。
* 定时精度正负10us (主要耗费在调用本函数的执行时间,函数内部进行了补偿减小误差)
* TIM2和TIM5 是32位定时器。定时范围很大
* TIM3和TIM4 是16位定时器。
* 形 参: _CC : 捕获通道几123, 4
* _uiTimeOut : 超时时间, 单位 1us. 对于16位定时器最大 65.5ms; 对于32位定时器最大 4294秒
* _pCallBack : 定时时间到后,被执行的函数
* 返 回 值: 无
*********************************************************************************************************
*/
void bsp_StartHardTimer(uint8_t _CC, uint32_t _uiTimeOut, void * _pCallBack)
{
uint32_t cnt_now;
uint32_t cnt_tar;
/*
执行下面这个语句,时长 = 18us (通过逻辑分析仪测量IO翻转)
bsp_StartTimer2(3, 500, (void *)test1);
*/
if (_uiTimeOut < 5)
{
;
}
else
{
_uiTimeOut -= 5;
}
cnt_now = TIM_GetCounter(TIM_HARD); /* 读取当前的计数器值 */
cnt_tar = cnt_now + _uiTimeOut; /* 计算捕获的计数器值 */
if (_CC == 1)
{
s_TIM_CallBack1 = (void (*)(void))_pCallBack;
TIM_SetCompare1(TIM_HARD, cnt_tar); /* 设置捕获比较计数器CC1 */
TIM_ClearITPendingBit(TIM_HARD, TIM_IT_CC1);
TIM_ITConfig(TIM_HARD, TIM_IT_CC1, ENABLE); /* 使能CC1中断 */
}
else if (_CC == 2)
{
s_TIM_CallBack2 = (void (*)(void))_pCallBack;
TIM_SetCompare2(TIM_HARD, cnt_tar); /* 设置捕获比较计数器CC2 */
TIM_ClearITPendingBit(TIM_HARD, TIM_IT_CC2);
TIM_ITConfig(TIM_HARD, TIM_IT_CC2, ENABLE); /* 使能CC2中断 */
}
else if (_CC == 3)
{
s_TIM_CallBack3 = (void (*)(void))_pCallBack;
TIM_SetCompare3(TIM_HARD, cnt_tar); /* 设置捕获比较计数器CC3 */
TIM_ClearITPendingBit(TIM_HARD, TIM_IT_CC3);
TIM_ITConfig(TIM_HARD, TIM_IT_CC3, ENABLE); /* 使能CC3中断 */
}
else if (_CC == 4)
{
s_TIM_CallBack4 = (void (*)(void))_pCallBack;
TIM_SetCompare4(TIM_HARD, cnt_tar); /* 设置捕获比较计数器CC4 */
TIM_ClearITPendingBit(TIM_HARD, TIM_IT_CC4);
TIM_ITConfig(TIM_HARD, TIM_IT_CC4, ENABLE); /* 使能CC4中断 */
}
else
{
return;
}
}
/*
*********************************************************************************************************
* 函 数 名: bsp_InitTimer
* 功能说明: 配置systick中断并初始化软件定时器变量
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void bsp_timer_init(void)
{
uint8_t i;
/* 清零所有的软件定时器 */
for (i = 0; i < TMR_COUNT; i++)
{
s_tTmr[i].Count = 0;
s_tTmr[i].PreLoad = 0;
s_tTmr[i].Flag = 0;
s_tTmr[i].Mode = TMR_ONCE_MODE; /* 缺省是1次性工作模式 */
}
/*
配置systic中断周期为1ms并启动systick中断。
SystemCoreClock 是固件中定义的系统内核时钟对于STM32F4XX,一般为 168MHz
SysTick_Config() 函数的形参表示内核时钟多少个周期后触发一次Systick定时中断.
-- SystemCoreClock / 1000 表示定时频率为 1000Hz 也就是定时周期为 1ms
-- SystemCoreClock / 500 表示定时频率为 500Hz 也就是定时周期为 2ms
-- SystemCoreClock / 2000 表示定时频率为 2000Hz 也就是定时周期为 500us
对于常规的应用我们一般取定时周期1ms。对于低速CPU或者低功耗应用可以设置定时周期为 10ms
*/
SysTick_Config(SystemCoreClock / 1000);
/* 开启硬件定时中断 */
// bsp_InitHardTimer();
// /* 初始化外部输入定时器 */
// bsp_InitExternInputTimer();
// /* 初始化 pwm 输出比较 */
// bsp_pwm_init();
}
/*************************************************************************************
* @brief TIM2 中断服务程序
*
* @warning
* @note
*************************************************************************************/
void TIM2_IRQHandler(void)
{
// if(RESET != TIM_GetITStatus(TIM_EXTERN_INPUT, TIM_IT_Update))
// {
// TIM_ClearITPendingBit(TIM_EXTERN_INPUT, TIM_IT_Update);
// /* add your code here. */
// // bsp_LedToggle(LED1);
// }
}
/*************************************************************************************
* @brief TIM3 中断服务程序
*
* @warning
* @note
*************************************************************************************/
void TIM3_IRQHandler(void)
{
if(RESET != TIM_GetITStatus(TIM_HARD, TIM_IT_Update))
{
TIM_ClearITPendingBit(TIM_HARD, TIM_IT_Update);
/* add your code here. */
// bsp_LedToggle(LED2);
}
if (TIM_GetITStatus(TIM_HARD, TIM_IT_CC1))
{
TIM_ClearITPendingBit(TIM_HARD, TIM_IT_CC1);
TIM_ITConfig(TIM_HARD, TIM_IT_CC1, DISABLE); /* 禁能CC1中断 */
/* 先关闭中断,再执行回调函数。因为回调函数可能需要重启定时器 */
s_TIM_CallBack1();
}
if (TIM_GetITStatus(TIM_HARD, TIM_IT_CC2))
{
TIM_ClearITPendingBit(TIM_HARD, TIM_IT_CC2);
TIM_ITConfig(TIM_HARD, TIM_IT_CC2, DISABLE); /* 禁能CC2中断 */
/* 先关闭中断,再执行回调函数。因为回调函数可能需要重启定时器 */
s_TIM_CallBack2();
}
if (TIM_GetITStatus(TIM_HARD, TIM_IT_CC3))
{
TIM_ClearITPendingBit(TIM_HARD, TIM_IT_CC3);
TIM_ITConfig(TIM_HARD, TIM_IT_CC3, DISABLE); /* 禁能CC3中断 */
/* 先关闭中断,再执行回调函数。因为回调函数可能需要重启定时器 */
s_TIM_CallBack3();
}
if (TIM_GetITStatus(TIM_HARD, TIM_IT_CC4))
{
TIM_ClearITPendingBit(TIM_HARD, TIM_IT_CC4);
TIM_ITConfig(TIM_HARD, TIM_IT_CC4, DISABLE); /* 禁能CC4中断 */
/* 先关闭中断,再执行回调函数。因为回调函数可能需要重启定时器 */
s_TIM_CallBack4();
}
}
/*
*********************************************************************************************************
* 函 数 名: SysTick_Handler
* 功能说明: 系统嘀嗒定时器中断服务程序。启动文件中引用了该函数。
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void SysTick_Handler(void)
{
SysTick_ISR();
}
/***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/