/*************************** (C) COPYRIGHT 2018 Ping ****************************
 * 文件名  ：timer.c
 * 描  述  ：定时器驱动代码     
 * 版  本  ：V1.0
 * 作  者  ：XuZhongPing
 * 日  期  ：2017/02/07 
*********************************************************************************/
#include "timer.h"
#include "usart1.h"
#include "device.h"
#include "data_typedef.h"

uint32_t time_value = 0;//uip 计时器，每10ms增加1.

/*
***********************************************************************
*	函 数 名: clock_time
*	功能说明: 取得当前计时值
*	形    参: 无
*	返 回 值: 当前计时值
***********************************************************************
*/
clock_time_t clock_time(void)
{
	return time_value; /* 10ms 单位 */	 
}

/*
***********************************************************************
*	函 数 名: timer_set
*	功能说明: 设置一个定时间隔
*	形    参:	
*						t:定时变量
*						interval：定时间隔值
*	返 回 值: 无
***********************************************************************
*/
void timer_set(timer *t, clock_time_t interval)
{
  t->interval = interval;
  t->start = clock_time();
}

/*
***********************************************************************
*	函 数 名: timer_reset
*	功能说明: 对定时变量进行复位
*	形    参:	
*						t:定时变量
*	返 回 值: 无
***********************************************************************
*/
void timer_reset(timer *t)
{
  t->start += t->interval;
}

/*
***********************************************************************
*	函 数 名: timer_reset_interval
*	功能说明: 重新设置定时时间
*	形    参:	
*						t:定时变量
*	返 回 值: 无
***********************************************************************
*/
void timer_reset_interval(timer *t, clock_time_t interval)
{
  t->interval = interval;
}

/*
***********************************************************************
*	函 数 名: timer_restart
*	功能说明: 从当前时间点重新启动定时器
*	形    参:	
*						t:定时变量
*	返 回 值: 无
***********************************************************************
*/
void timer_restart(timer *t)
{
  t->start = clock_time();
}

/*
***********************************************************************
*	函 数 名: timer_expired
*	功能说明: 判断一个定时器是否达到定时时间
*	形    参:	
*						t:定时变量
*	返 回 值: 非零则已经到了定时时间，零则定时还未到
***********************************************************************
*/
int timer_expired(timer *t)
{
  return (clock_time_t)(clock_time() - t->start) >= (clock_time_t)t->interval;
}

/*
***********************************************************************
*	函 数 名: timer_remaining
*	功能说明: 判断一个定时器还剩下多少时间达到定时时间
*	形    参:	
*						t:定时变量
*	返 回 值: 返回定时器剩余时间
***********************************************************************
*/
uint32_t timer_remaining(timer *t)
{
	uint32_t res = 0;
	
	if(clock_time() < (t->start + (clock_time_t)t->interval))
	{
		res = (t->start + (clock_time_t)t->interval) - clock_time();
		return res;
	}else{
		return 0;
	}
}

//定时器定时器2用于开始一个软件定时供外部程序使用
//单位为100ms(0.1S)
/*
***********************************************************************
*	函 数 名: TIM2_Int_Init
*	功能说明: 定时器2初始化配置
*	形    参：arr：自动重装值
*						psc：时钟预分频数
*	返 回 值: 无
***********************************************************************
*/
void TIM2_Int_Init(uint16_t arr,uint16_t psc)
{
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); 					//时钟使能

	TIM_TimeBaseStructure.TIM_Period = arr; 											//设置在下一个更新事件装入活动的自动重装载寄存器周期的值	 计数到5000为500ms
	TIM_TimeBaseStructure.TIM_Prescaler = psc; 										//设置用来作为TIMx时钟频率除数的预分频值  10Khz的计数频率（即0.1ms周期）  
	TIM_TimeBaseStructure.TIM_ClockDivision = 0; 									//设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  	//TIM向上计数模式
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); 							//根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
 
	TIM_ITConfig( TIM2, TIM_IT_Update|TIM_IT_Trigger, ENABLE);		//使能定时器2更新触发中断
	TIM_Cmd(TIM2, ENABLE);  																			//使能TIMx外设
	
	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;  							//TIM3中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  		//先占优先级0级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  					//从优先级3级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 							//IRQ通道被使能
	NVIC_Init(&NVIC_InitStructure);  															//根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器				 
}

/*
***********************************************************************
*	函 数 名: TIM2_IRQHandler
*	功能说明: 定时器2中断服务子程序
*	形    参：无
*	返 回 值: 无
***********************************************************************
*/
void TIM2_IRQHandler(void)   //TIM2中断
{
	if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源 
	{
		time_value++;						//计时器增加1	
	}
	TIM_ClearITPendingBit(TIM2, TIM_IT_Update);  //清除TIMx的中断待处理位:TIM 中断源 
}

/////////////////////////////////////////////////////////////////////////////////////////////////
//定时器3部分（用于按键扫描）每10ms中断一次
/*
***********************************************************************
*	函 数 名: TIM3_Int_Init
*	功能说明: 定时器3初始化配置
*	形    参：arr：自动重装值
*						psc：时钟预分频数
*	返 回 值: 无
***********************************************************************
*/
void TIM3_Int_Init(uint16_t arr,uint16_t psc)
{
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); 					//时钟使能

	TIM_TimeBaseStructure.TIM_Period = arr; 											//设置在下一个更新事件装入活动的自动重装载寄存器周期的值
	TIM_TimeBaseStructure.TIM_Prescaler = psc; 										//设置用来作为TIMx时钟频率除数的预分频值  10Khz的计数频率（即0.1ms周期）  
	TIM_TimeBaseStructure.TIM_ClockDivision = 0; 									//设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  	//TIM向上计数模式
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); 							//根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
 
	TIM_ITConfig( TIM3, TIM_IT_Update|TIM_IT_Trigger, ENABLE);		//使能定时器2更新触发中断
	TIM_Cmd(TIM3, ENABLE);  																			//使能TIMx外设
	
	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  							//TIM3中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;  		//先占优先级0级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;  					//从优先级3级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 							//IRQ通道被使能
	NVIC_Init(&NVIC_InitStructure);  															//根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器			 
}

/*
***********************************************************************
*	函 数 名: TIM3_IRQHandler
*	功能说明: 定时器2中断服务子程序
*	形    参：无
*	返 回 值: 无
***********************************************************************
*/
void TIM3_IRQHandler(void)   //TIM3中断
{
	uint8_t keyTemp = 0;
	static uint8_t timerCut = 0;
	
	if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) 	//检查指定的TIM中断发生与否:TIM 中断源 
	{
		if(deviceInitFlag == 1)
		{
// 			OptoKeyScanning();
// 			BottleScanning();																	//调用瓶子扫描检测函数
			
			if(keyType == 0)
			{
				keyTemp = KeyScanning();				
			}else if(keyType == 1){
				keyTemp = TouchKeyScanning();
			}

			if(keyTemp != 0)
			{		
				keyValue = keyTemp;															//输出键值由外部读取后清除
			}
		}
	}
	TIM_ClearITPendingBit(TIM3, TIM_IT_Update);  				//清除TIMx的中断待处理位:TIM 中断源 
}

/////////////////////////////////////////////////////////////////////////////////////////////////
//定时器4部分（用于超声波测距）
/*
***********************************************************************
*	函 数 名: TIM4_Int_Init
*	功能说明: 定时器4初始化配置
*	形    参：arr：自动重装值
*						psc：时钟预分频数
*	返 回 值: 无
***********************************************************************
*/
void TIM4_Int_Init(u16 arr,u16 psc)
{
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); 					//时钟使能
	
	//定时器TIM4初始化
	TIM_TimeBaseStructure.TIM_Period = arr; 											//设置在下一个更新事件装入活动的自动重装载寄存器周期的值	
	TIM_TimeBaseStructure.TIM_Prescaler =psc; 										//设置用来作为TIMx时钟频率除数的预分频值
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; 			//设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  	//TIM向上计数模式
	TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); 							//根据指定的参数初始化TIMx的时间基数单位
 
	TIM_ITConfig(TIM4, TIM_IT_Update | TIM_IT_Trigger, ENABLE); 	//使能指定的TIM4中断,允许更新中断

	//中断优先级NVIC设置
	NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;  						
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; 
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; 
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 
	NVIC_Init(&NVIC_InitStructure);

	TIM_Cmd(TIM4, DISABLE);
// 	TIM_Cmd(TIM4, ENABLE);			 
}

/*
***********************************************************************
*	函 数 名: TIM4_IRQHandler
*	功能说明: 定时器4中断服务子程序
*	形    参：无
*	返 回 值: 无
***********************************************************************
*/
void TIM4_IRQHandler(void)   //TIM4中断
{
	if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET)  //检查TIM4更新中断发生与否
	{
		TIM_ClearITPendingBit(TIM4, TIM_IT_Update);  //清除TIMx更新中断标志 
	}
}

/////////////////////////////////////////////////////////////////////////////////////////////////
//定时器4部分（用于二维码读头数据接收完成标记用）
/*
***********************************************************************
*	函 数 名: TIM5_Int_Init
*	功能说明: 定时器5初始化配置
*	形    参：arr：自动重装值
*						psc：时钟预分频数
*	返 回 值: 无
***********************************************************************
*/
void TIM5_Int_Init(uint16_t arr, uint16_t psc)
{
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
	
	//定时器TIM5初始化
	TIM_TimeBaseStructure.TIM_Period = arr; 											//设置在下一个更新事件装入活动的自动重装载寄存器周期的值	
	TIM_TimeBaseStructure.TIM_Prescaler =psc; 										//设置用来作为TIMx时钟频率除数的预分频值
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; 			//设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  	//TIM向上计数模式
	TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure); 							//根据指定的参数初始化TIMx的时间基数单位
 
	TIM_ITConfig(TIM5,TIM_IT_Update,ENABLE ); 										//使能指定的TIM4中断,允许更新中断

	//中断优先级NVIC设置
	NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;  							//TIM5中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;  		//先占优先级3级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;  					//从优先级2级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 							//IRQ通道被使能
	NVIC_Init(&NVIC_InitStructure);  															//初始化NVIC寄存器

	TIM_Cmd(TIM5, DISABLE);  																			//失能TIMx外设			 
}

/*
***********************************************************************
*	函 数 名: TIM5_IRQHandler
*	功能说明: 定时器4中断服务子程序
*	形    参：无
*	返 回 值: 无
***********************************************************************
*/
void TIM5_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET)  	//检查TIM5更新中断发生与否
	{
		USART1_RX_STA |= 1<<15;														//标记接收完成
		TIM_ClearITPendingBit(TIM5, TIM_IT_Update);  			//清除TIMx更新中断标志 
		TIM_Cmd(TIM5, DISABLE);  	 												//关闭TIMx
	}
}

/******************** (C) COPYRIGHT 2018 Ping *****END OF FILE*******************/

