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

584 lines
19 KiB
C
Raw Normal View History

/*
*********************************************************************************************************
*
* :
* : 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"
#define TIM_HARD TIM2
#define TIM_HARD_IRQn TIM2_IRQn
#define TIM_HARD_RCC RCC_APB1Periph_TIM2
/* 这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);
/*
*********************************************************************************************************
* : bsp_InitTimer
* : systick中断
* :
* :
*********************************************************************************************************
*/
void bsp_InitTimer(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中断周期为1mssystick中断
SystemCoreClock STM32F4XX, 168MHz
SysTick_Config() Systick定时中断.
-- SystemCoreClock / 1000 1000Hz 1ms
-- SystemCoreClock / 500 500Hz 2ms
-- SystemCoreClock / 2000 2000Hz 500us
1msCPU或者低功耗应用 10ms
*/
SysTick_Config(SystemCoreClock / 1000);
bsp_InitHardTimer(); /* 开启硬件定时中断 */
}
/*
*********************************************************************************************************
* : 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对所有定时器变量减1SysTick_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 : ID0,TMR_COUNT-1IDID冲突
* _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 : ID0,TMR_COUNT-1IDID冲突
* _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 : ID0,TMR_COUNT-1IDID冲突
* :
*********************************************************************************************************
*/
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 : ID0,TMR_COUNT-1IDID冲突
* _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;
}
/*
*********************************************************************************************************
* : SysTick_Handler
* :
* :
* :
*********************************************************************************************************
*/
void SysTick_Handler(void)
{
SysTick_ISR();
}
/*
*********************************************************************************************************
* : bsp_InitHardTimer
* : TIM2us级别硬件定时TIM4将自由运行.
* TIM4可以用TIM2 - TIM5 TIM, TIM有4个通道, APB1 =SystemCoreClock / 2
* :
* :
*********************************************************************************************************
*/
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;
APB1 TIM2, TIM3 ,TIM4, TIM5, TIM6, TIM7, TIM12, TIM13,TIM14
APB2 TIM1, TIM8 ,TIM9, TIM10, TIM11
TIM_Prescaler TIM_Period (0-65535)
----------------------------------------------------------------------- */
// 时基单元定义 此处定义1ms的
TIM_TimeBaseStructure.TIM_Period = (10u - 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_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);
}
/*
*********************************************************************************************************
* : 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;
}
}
/*
*********************************************************************************************************
* : TIMx_IRQHandler
* : TIM
*
* :
*********************************************************************************************************
*/
//void TIM2_IRQHandler(void)
//void TIM3_IRQHandler(void)
//void TIM4_IRQHandler(void)
void TIM2_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();
}
}
/***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/