/***********************************************************************
 * Copyright (c)  2017 - 2022, Unicmicro Co.,Ltd .
 * All rights reserved.
 * Filename    : atimer.c
 * Description : atimer source file
 * Author(s)   : Hackett
 * version     : V1.0
 * Modify date : 2022-07-10
 ***********************************************************************/
#include "atimer.h"
#include "gpio.h"

void (*atimer_pfunc)(void) = NULL;

/************************************************************************
 * Function   : ATIMER_IRQHandler
 * Description: ATIM中断处理函数
 * Input : none
 * Output: none
 * Return: none
 ************************************************************************/
void ATIMER_IRQHandler(void)
{
	if(atimer_pfunc != NULL)
	{
		(*atimer_pfunc)();
	}
	REG_ATIM_SR = 0x1FFF;//清除中断标志
}


/************************************************************************
 * Function   	: atimer_get_status
 * Description	: 获取相应的状态
 * Input : uint8_t object: 状态标志
 * Output: none
 * Return: 相应的状态
 ************************************************************************/
uint8_t atimer_get_status(uint8_t object)
{
	uint8_t temp = 0;
	switch(object)
	{
		case ATIM_STATUS_UIF:
				temp = (REG_ATIM_SR & (uint32_t)0x01)>>0;
				break;
		
		case ATIM_STATUS_CC1IF:
				temp = (REG_ATIM_SR & (uint32_t)0x02)>>1;
				break;		
		
		case ATIM_STATUS_CC2IF:
				temp = (REG_ATIM_SR & (uint32_t)0x04)>>2;
				break;		
		
		case ATIM_STATUS_CC3IF:
				temp = (REG_ATIM_SR & (uint32_t)0x08)>>3;
				break;		
		
		case ATIM_STATUS_CC4IF:
				temp = (REG_ATIM_SR & (uint32_t)0x10)>>4;			
				break;		
		
		case ATIM_STATUS_COMIF:
				temp = (REG_ATIM_SR & (uint32_t)0x20)>>5;	
				break;		
		
		case ATIM_STATUS_TIF:
				temp = (REG_ATIM_SR & (uint32_t)0x40)>>6;				
				break;
		
		case ATIM_STATUS_BIF:
				temp = (REG_ATIM_SR & (uint32_t)0x80)>>7;
				break;		
		
		case ATIM_STATUS_CC1OF:
				temp = (REG_ATIM_SR & (uint32_t)0x200)>>9;
				break;

		case ATIM_STATUS_CC2OF:
				temp = (REG_ATIM_SR & (uint32_t)0x400)>>10;
				break;

		case ATIM_STATUS_CC3OF:
				temp = (REG_ATIM_SR & (uint32_t)0x800)>>11;
				break;

		case ATIM_STATUS_CC4OF:
				temp = (REG_ATIM_SR & (uint32_t)0x1000)>>12;
				break;		
		
		default:
				temp = 0;
				break;
	}
	
	return temp;
}

/************************************************************************
 * Function   : atimer_module_enable
 * Description: 使能时钟并复位定时器0模块
 * Input : none
 * Output: none
 * Return: none
 ************************************************************************/
void atimer_module_enable(void)
{
	REG_SCU_PERICLKEN |= (1<<27);//atimer模块时钟使能
	REG_SCU_PERIRESET |= (1<<27);//atimer控制器模块复位使能
}

/************************************************************************
 * function   : atimer_dmac_enable
 * Description: dma使能
 * input : uint8_t length 	: DMA Burst长度
 *		   uint8_t base_addr: DMA基地址
 * Output: none
 * return: none
 ************************************************************************/
void atimer_dmac_enable(uint8_t length, uint8_t base_addr)
{
	REG_ATIM_DCR |= ((length - 1)<<8);//DMA Burst长度为1~18
	REG_ATIM_DCR |= (base_addr<<0);//DMA基地址			
}

/************************************************************************
 * Function   : atimer_irq
 * Description: atimer中断控制
 * Input : uint8_t dier		 ：ATIM DMA和中断使能寄存器
 *		   IRQn_Type nvic_com：ATIM_IRQn			全局中断
 *							   ATIM_BRK_IRQn		刹车事件
 *							   ATIM_UP_IRQn			更新事件
 *							   ATIM_TRIGCOM_IRQn	触发/COM事件
 *							   ATIM_CC_IRQn			通道比较/捕捉
 *		   uint8_t newstate	 ：ATIM使能/失能
 *		   void (*pfunc)()	 ：回调函数
 * Output: none
 * Return: none
 ************************************************************************/
void atimer_irq(uint8_t dier, IRQn_Type nvic_com, uint8_t newstate, void (*pfunc)())
{	
	if(newstate == ATIM_ENABLE)
	{
		atimer_pfunc = pfunc;
	
		if(dier == (ATIM_CC1OF | ATIM_CC2OF | ATIM_CC3OF | ATIM_CC4OF))
		{
			REG_ATIM_DIER &= ~(1<<dier);//允许中断
		}
		else 
		{
			REG_ATIM_DIER |= (1<<dier);	//允许中断
		}			
		
#ifdef	NVIC_COM
		REG_SCU_CTRLPROTECT = 0xA5A55A5A;//启动寄存器SYSCTL的写使能
		REG_SCU_CTRL1 |= (1<<13);	//ATIM中断响应选择，CPU分别响应

		NVIC_ClearPendingIRQ(nvic_com);
		NVIC_EnableIRQ(nvic_com);		//开启四个通道的比较/捕捉中断
#else
		NVIC_ClearPendingIRQ(nvic_com);
		NVIC_EnableIRQ(nvic_com);		//开启中断
#endif
	
	}
	else
	{
		atimer_pfunc = NULL;
		
		if(dier == (ATIM_CC1OF | ATIM_CC2OF | ATIM_CC3OF | ATIM_CC4OF))
		{
			REG_ATIM_DIER |= (1<<dier);	//禁止中断
		}
		else 
		{
			REG_ATIM_DIER &= ~(1<<dier);//禁止中断
		}
		
#ifdef	NVIC_COM
		REG_SCU_CTRLPROTECT = 0xA5A55A5A;//启动寄存器SYSCTL的写使能
		REG_SCU_CTRL1 |= (1<<13);	//ATIM中断响应选择，CPU分别响应

		NVIC_ClearPendingIRQ(nvic_com);
		NVIC_DisableIRQ(nvic_com);	//关闭四个通道的比较/捕捉中断
#else
		NVIC_ClearPendingIRQ(nvic_com);
		NVIC_DisableIRQ(nvic_com);	//关闭中断
#endif		

	}
	
}

/************************************************************************
 * Function   : atimer_counter
 * Description: atimer计时器使能/失能
 * Input : uint8_t newstate: ATIM使能/失能
 * Output: none
 * Return: none
 ************************************************************************/
void atimer_counter(uint8_t newstate)
{
	if(newstate == ATIM_ENABLE)
	{
		REG_ATIM_CR1 |= (1<<0);		//计数器使能		
	}
	else
	{
		REG_ATIM_CR1 &= ~(1<<0);	//计数器失能
	}
}

/************************************************************************
 * function   : atimer_init
 * Description: 定时器0初始化
 * input : uint16_t arr:自动重载值
 *		   uint16_t psc:分频系数   
 * Output: none
 * return: none
 ************************************************************************/
void atimer_init(uint16_t arr, uint16_t psc)
{
	REG_ATIM_CR1 &= ~(1<<4);		//向上计数
	REG_ATIM_CR1 |= (1<<7);			//预装载使能	
	
	
	REG_ATIM_ARR = arr - 1;			//计数溢出时的自动重载值
	REG_ATIM_PSC = psc - 1;			//计数器时钟（CK_CNT）预分频值;fCK_CNT=fCK_PSC/(PSC[15:0]+1)
	
	REG_ATIM_RCR = 0;				//重复计数功能测试

	REG_ATIM_CR1 |= (1<<2);			//仅计数器上溢出或下溢出会产生update中断或DMA请求
	REG_ATIM_CR1 &= ~(1<<1);		//使能update事件	

	REG_ATIM_EGR |= (1<<0);			//软件置位UG时会重新初始化计数器并更新shadow寄存器，预分频计数器被清零。
}




/************************************************************************
 * function   : atimer_pwm_init
 * Description: 定时器0初始化PWM模式
 * input : uint16_t arr		：自动重载值
 *		   uint16_t psc		：分频系数
 *		   uint8_t mode		：输出比较模式
 *		   uint8_t channel	：ATIM通道
 * Output: none
 * return: none
 ************************************************************************/
void atimer_pwm_init(uint16_t arr, uint16_t psc, uint8_t mode, uint8_t channel)
{
	if((mode == ATIM_DEADTIME) || (mode == ATIM_BRAKE))		//死区配置或刹车功能
	{	
		if(mode == ATIM_BRAKE)								//刹车功能
		{
			REG_SCU_CTRLPROTECT = 0xA5A55A5A;				//启动寄存器SYSCTL的写使能
			REG_SCU_CTRL1 &= ~(1<<12);						//刹车时 OCx和 OCxn为 OCxp和 OCxnp				
			
			gpio_init(GPIOG, PIN2, 13);						//PD3 ATIM_BKIN	刹车信号输入				
			
			REG_ATIM_BDTR |= (1<<11);						//运行状态下的输出关闭状态选择: 输出通道不使能时，OC和OCN不驱动GPIO
			REG_ATIM_BDTR &= ~(1<<10);						//DLE状态下的输出关闭状态选择: 输出通道不使能时，OC和OCN不驱动GPIO
			
			REG_ATIM_BDTR &= ~(1<<13);						//刹车极性: 刹车输入为低电平有效
					
			REG_ATIM_CCER &= ~(1<<((channel * 4) + 1));		//OCx为OC1REF反转	在刹车功能中，需要配合TIM_CR2中的OISx和OISxN
			REG_ATIM_CCER &= ~(1<<((channel * 4) + 3));		//OCxN为OC1REF
			
			REG_ATIM_CR2 &= ~(1<<12);						//定义OC3的输出IDLE状态: 当MOE=0时，经过dead time后，OC1N=1，对于OC1~3N，
															//						还需要（CCxP||CCxNP）=1来时OCxN=1
			REG_ATIM_CR2 &= ~(1<<13);						//定义OC3N的输出IDLE状态: 当MOE=0时（如果使能了互补输出，需经过dead time后），OC1=1，对于OC1~3，
															//						还需要（CCxP||CCxNP）来时OCx=1
						
			REG_ATIM_BDTR |= (1<<14);						//：MOE可以软件置位，或者由update事件自动置位
			REG_ATIM_BDTR |= (1<<12);						//允许刹车输入				
		}
			

		REG_ATIM_BDTR |= (0x10<<0);//死区时间4us	
		REG_ATIM_CCER |= (1<<((channel * 4) + 2));			//捕捉/比较通道x的互补输出使能
				
	}
	else if(mode == ATIM_EXTERNALEVENTS)					//外部事件清除OCxREF
	{				
		if((channel == ATIM_CHANNEL1 ) || (channel == ATIM_CHANNEL2))
		{
			REG_ATIM_CCMR1 |= (1<<((channel * 8) + 7));		//输出比较x清零使能:检测到ETRF高电平时，自动清零OC1REF						
		}
		else if((channel == ATIM_CHANNEL3 ) || (channel == ATIM_CHANNEL4))
		{			
			channel = channel - 2;
			REG_ATIM_CCMR2 |= (1<<((channel * 8) + 7));		//输出比较x清零使能:检测到ETRF高电平时，自动清零OC1REF				
			channel = channel + 2;
		}		
	}
	else if(mode == ATIM_6STEPPWM)							//6-step PWM输出
	{	
		REG_ATIM_CR2 |= (1<<2);								//更新预装载的捕获/比较控制位可通过将COMG置1或者TRGI信号来更新
		REG_ATIM_CR2 |= (1<<0);								//CCxE, CCxNE, OCxM寄存器使能preload
	}
	
	REG_ATIM_ARR = arr - 1;									//计数溢出时的自动重载值
	REG_ATIM_PSC = psc - 1;									//计数器时钟（CK_CNT）预分频值;fCK_CNT=fCK_PSC/(PSC[15:0]+1)	
			
	REG_ATIM_CR1 &= ~(1<<4);								//向上计数	
	
	if((channel == ATIM_CHANNEL1 ) || (channel == ATIM_CHANNEL2))
	{
		REG_ATIM_CCMR1 &= ~(3<<(channel * 8));				//CCx通道配置为输出			
		REG_ATIM_CCMR1 = ((REG_ATIM_CCMR1&(~(7<<(4+8*channel)))) | ATIM_PWM1(channel));//PWM模式1:在向上计数时，OC1REF在CNT<CCRx时置高						
		
		if(mode != ATIM_BRAKE)
		{
			REG_ATIM_CCER &= ~(1<<((channel * 4) + 1));		//比较通道x的输出极性,OCx为OC1REF			
		}
		REG_ATIM_CCER |= (1<<(channel * 4));				//比较通道x的输出使能		
	}
	else if((channel == ATIM_CHANNEL3 ) || (channel == ATIM_CHANNEL4))
	{			
		channel = channel - 2;
		REG_ATIM_CCMR2 &= ~(3<<(channel * 8));				//CCx通道配置为输出			
		REG_ATIM_CCMR2 = ((REG_ATIM_CCMR2&(~(7<<(4+8*channel)))) | ATIM_PWM1(channel));//PWM模式1:在向上计数时，OC1REF在CNT<CCRx时置高				

		channel = channel + 2;
		if(mode != ATIM_BRAKE)
		{
			REG_ATIM_CCER &= ~(1<<((channel * 4) + 1));		//比较通道x的输出极性,OCx为OC1REF			
		}
		REG_ATIM_CCER |= (1<<(channel * 4));				//比较通道x的输出使能		
	}
	
	REG_ATIM_BDTR |= (1<<15);								//使能OC和OCN输出（仍需各个通道的CCxE和CCxNE状态来决定是否输出）
	
	REG_ATIM_CR1 |= (1<<7);									//预装载使能	
	REG_ATIM_CR1 |= (1<<2);									//仅计数器上溢出或下溢出会产生update中断或DMA请求
	
	REG_ATIM_CR1 &= ~(1<<1);								//使能update事件	
	
	REG_ATIM_EGR |= (1<<0);									//软件置位UG时会重新初始化计数器并更新shadow寄存器，预分频计数器被清零。
	
}

/************************************************************************
 * function   : atimer_singlepulse_init
 * Description: 定时器0单脉冲模式初始化
 * input : uint16_t arr			：自动重载值
 *		   uint16_t psc			：分频系数
 *		   uint8_t channel		：输出ATIM通道
 *		   uint8_t input_channel：输入ATIM通道
 * Output: none
 * return: none
 ************************************************************************/
void atimer_singlepulse_init(uint16_t arr, uint16_t psc, uint8_t channel, uint8_t input_channel)
{

	REG_ATIM_ARR = arr - 1;								//计数溢出时的自动重载值
	REG_ATIM_PSC = psc - 1;								//计数器时钟（CK_CNT）预分频值;fCK_CNT=fCK_PSC/(PSC[15:0]+1)	
			
	REG_ATIM_CR1 &= ~(1<<4);							//向上计数		
	
	//输入触发配置		
	REG_ATIM_CCMR1 |= (1<<(input_channel * 8));			//CC2通道配置为输入，IC2映射到TI1	
	
	REG_ATIM_CCER &= ~(1<<((input_channel * 4) + 3));	//CCx通道配置为输入时，与CCxNP配合，{CCxNP,CCxP}选择ICx的极性
	REG_ATIM_CCER |= (1<<((input_channel * 4) + 1));	//捕获通道2的极性,OC2为OC1REF反转
	
	REG_ATIM_SMCR |= (6<<4);							//触发选择：用于选择同步计数器的触发源,滤波后TI2（TI2FP2）
	REG_ATIM_SMCR |= (6<<0);							//从机模式选择：触发模式；TRGI上升沿触发计数器开始计数（不会复位计数器）
	
	REG_ATIM_CCER |= (1<<(input_channel * 4));			//捕获通道2的输入使能

	//输出配置
	if((channel == ATIM_CHANNEL1 ) || (channel == ATIM_CHANNEL2))
	{		
		REG_ATIM_CCMR1 &= ~(3<<(channel * 8));			//CCx通道配置为输出			
		REG_ATIM_CCMR1 = ((REG_ATIM_CCMR1&(~(7<<(4+8*channel)))) | ATIM_PWM2(channel));//PWM模式2:在向上计数时，OC1REF在CNT<CCRx时置低
		
		REG_ATIM_CCER |= (1<<(channel * 4));			//比较通道x的输出使能
	}
	else if((channel == ATIM_CHANNEL3 ) || (channel == ATIM_CHANNEL4))
	{			
		channel = channel - 2;
		REG_ATIM_CCMR2 &= ~(3<<(channel * 8));			//CCx通道配置为输出			
		REG_ATIM_CCMR2 = ((REG_ATIM_CCMR2&(~(7<<(4+8*channel)))) | ATIM_PWM2(channel));//PWM模式2:在向上计数时，OC1REF在CNT<CCRx时置低
		
		channel = channel + 2;
		REG_ATIM_CCER |= (1<<(channel * 4));			//比较通道x的输出使能
	}	
	REG_ATIM_CR1 |= (1<<3);								//单脉冲输出模式:Update Event发生时计数器停止（自动清零CEN）	
	
	REG_ATIM_BDTR |= (1<<15);							//使能OC和OCN输出（仍需各个通道的CCxE和CCxNE状态来决定是否输出）
	REG_ATIM_CR1 |= (1<<7);								//预装载使能	
	REG_ATIM_CR1 |= (1<<2);								//仅计数器上溢出或下溢出会产生update中断或DMA请求	
	REG_ATIM_CR1 &= ~(1<<1);							//使能update事件	
	
	REG_ATIM_EGR |= (1<<0);								//软件置位UG时会重新初始化计数器并更新shadow寄存器，预分频计数器被清零。
			
}

/************************************************************************
 * Function   : atimer_inputcapture_init
 * Description: 定时器0输入捕获模式初始化
 * Input : uint16_t arr		：自动重载值
 *		   uint16_t psc		：分频系数
 *		   uint8_t mode		：输入捕获模式
 *		   uint8_t channel	：ATIM通道
 * Output: none
 * Return: none
 ************************************************************************/
void atimer_inputcapture_init(uint16_t arr, uint16_t psc, uint8_t mode, uint8_t channel)
{

	REG_ATIM_ARR = arr - 1;									//计数溢出时的自动重载值
	REG_ATIM_PSC = psc - 1;									//计数器时钟（CK_CNT）预分频值;fCK_CNT=fCK_PSC/(PSC[15:0]+1)	
								
	REG_ATIM_CR1 &= ~(1<<4);								//向上计数	
						
	if(mode == ATIM_PWMINPUT)								//pwm输入捕获功能
	{					
		REG_ATIM_CCMR1 |= (2<<8);							//CC2通道配置为输入，IC2映射到TI1
		REG_ATIM_CCMR1 |= (1<<0);							//CC1通道配置为输入，IC1映射到TI1
							
		REG_ATIM_CCER |= (1<<5);							//非取反模式–捕捉在IC2的上升沿进行
		REG_ATIM_CCER &= ~(1<<1);							//取反模式–捕捉在IC1的下降沿进行
					
		REG_ATIM_CCMR1 &= ~(15<<4);							//输入捕捉2滤波,此寄存器定义TI2的采样频率和滤波长度
		REG_ATIM_CCMR1 &= ~(15<<12);						//输入捕捉1滤波,此寄存器定义TI1的采样频率和滤波长度
								
		REG_ATIM_CCMR1 &= ~(3<<2);							//输入捕捉2预分频 :无分频
		REG_ATIM_CCMR1 &= ~(3<<10);							//输入捕捉1预分频 :无分频	
							
		REG_ATIM_SMCR |= (5<<4);							//触发选择：用于选择同步计数器的触发源,滤波后TI1（TI1FP1）
							
		REG_ATIM_SMCR |= (4<<0);							//从机模式选择: 复位模式；TRGI上升沿初始化计数器，并触发寄存器update
		
		REG_ATIM_CCER |= (1<<4);							//CC2通道使能捕捉功能
		REG_ATIM_CCER |= (1<<0);							//CC1通道使能捕捉功能
			
	}			
	else//普通输入捕获功能
	{
		if((channel == ATIM_CHANNEL1 ) || (channel == ATIM_CHANNEL2))
		{		
			REG_ATIM_CCMR1 |= (1<<(channel * 8));			//捕捉x通道选择,CCx通道配置为输入，ICx映射到TI1		

			REG_ATIM_CCER &= ~(1<<((channel * 4) + 3));		//CCx通道配置为输入时，与CCxNP配合，{CCxNP,CCxP}选择ICx的极性
			REG_ATIM_CCER |= (1<<((channel * 4) + 1));		//捕获通道x的极性,OCx为OC1REF反转	

			REG_ATIM_CCMR1 &= ~(15<<((channel * 8) + 4));	//输入捕捉x滤波,此寄存器定义TIx的采样频率和滤波长度
			REG_ATIM_CCMR1 &= ~(3<<((channel * 8) + 2));	//输入捕捉x预分频 :无分频
		}
		else if((channel == ATIM_CHANNEL3 ) || (channel == ATIM_CHANNEL4))
		{			
			channel = channel - 2;
			REG_ATIM_CCMR2 |= (1<<(channel * 8));			//捕捉x通道选择,CCx通道配置为输入，ICx映射到TI1		

			channel = channel + 2;
			REG_ATIM_CCER &= ~(1<<((channel * 4) + 3));		//CCx通道配置为输入时，与CCxNP配合，{CCxNP,CCxP}选择ICx的极性
			REG_ATIM_CCER |= (1<<((channel * 4) + 1));		//捕获通道x的极性,OCx为OC1REF反转	

			channel = channel - 2;
			REG_ATIM_CCMR2 &= ~(15<<((channel * 8) + 4));	//输入捕捉x滤波,此寄存器定义TIx的采样频率和滤波长度
			REG_ATIM_CCMR2 &= ~(3<<((channel * 8) + 2));	//输入捕捉x预分频 :无分频
			channel = channel + 2;
		}		
		
		REG_ATIM_CCER |= (1<<(channel * 4));				//CCx通道配置为输入时,使能捕捉功能
			
	}
	
	REG_ATIM_EGR |= (1<<0);									//软件置位UG时会重新初始化计数器并更新shadow寄存器，预分频计数器被清零。

}

/************************************************************************
 * Function   : atimer_xorinput_init
 * Description: 定时器0输入异或模式初始化
 * Input : uint16_t arr		：自动重载值
 *		   uint16_t psc		：分频系数
 * Output: none
 * Return: none
 ************************************************************************/
void atimer_xorinput_init(uint16_t arr, uint16_t psc)
{
		
	REG_ATIM_ARR = arr - 1;			//计数溢出时的自动重载值
	REG_ATIM_PSC = psc - 1;			//计数器时钟（CK_CNT）预分频值;fCK_CNT=fCK_PSC/(PSC[15:0]+1)	
			
	REG_ATIM_CR1 &= ~(1<<4);		//向上计数	

	REG_ATIM_CCMR1 |= (2<<8);		//CC2通道配置为输入，IC2映射到TI1
	REG_ATIM_CCMR1 |= (1<<0);		//CC1通道配置为输入，IC1映射到TI1
	REG_ATIM_CCMR2 |= (1<<0);		//CC3通道配置为输入，IC3映射到TI1

	REG_ATIM_SMCR |= (4<<4);		//触发选择：用于选择同步计数器的触发源,TI1边沿检测（TI1F_ED）
	REG_ATIM_SMCR |= (4<<0);		//从机模式选择: 复位模式；TRGI上升沿初始化计数器，并触发寄存器update	

	REG_ATIM_CR2 |= (1<<7);			//T1输入来自CH1、CH2、CH3引脚异或组合

	REG_ATIM_CCMR1 &= ~(15<<12);	//输入捕捉1滤波,此寄存器定义TI1的采样频率和滤波长度	
	REG_ATIM_CCMR1 &= ~(3<<10);		//输入捕捉1预分频 :无分频	
	
	REG_ATIM_CCER |= (1<<0);		//CC1通道使能捕捉功能

	REG_ATIM_EGR |= (1<<0);			//软件置位UG时会重新初始化计数器并更新shadow寄存器，预分频计数器被清零。

}

/************************************************************************
 * Function   : atimer_slave_init
 * Description: 定时器0单脉冲模式初始化
 * Input : uint16_t arr		：自动重载值
 *		   uint16_t psc		：分频系数
 *		   uint8_t mode 	：从机模式
 *		   uint8_t channel 	：ATIM通道
 * Output: none
 * Return: none
 ************************************************************************/
void atimer_slave_init(uint16_t arr, uint16_t psc, uint8_t mode, uint8_t channel)
{
	
	REG_ATIM_ARR = arr - 1;							//计数溢出时的自动重载值
	REG_ATIM_PSC = psc - 1;							//计数器时钟（CK_CNT）预分频值;fCK_CNT=fCK_PSC/(PSC[15:0]+1)	
			
	REG_ATIM_CR1 &= ~(1<<4);						//向上计数		
	
	
	if(mode == ATIM_EXTERNALCLOCK)					//外部事件触发的外部时钟计数模式
	{
		REG_ATIM_SMCR &= ~(1<<15);					//外部触发信号极性配置:高电平或上升沿有效
		REG_ATIM_SMCR &= ~(3<<12);					//外部触发信号预分频寄存器；配置为无分频
													//注：外部触发信号ETRP的频率最多只能是TIM工作时钟的1/4！！！！
		REG_ATIM_SMCR &= ~(15<<8);					//外部触发信号滤波时钟和长度选择：无滤波
		REG_ATIM_SMCR |= (1<<14);					//使能外部时钟模式2，计数器时钟为ETRF有效沿	
	}	
	

	if((channel == ATIM_CHANNEL1 ) || (channel == ATIM_CHANNEL2))
	{		
		REG_ATIM_CCMR1 |= (1<<(channel * 8));		//捕捉/比较x通道选择,CCx通道配置为输入，ICx映射到TI1
	}
	else if((channel == ATIM_CHANNEL3 ) || (channel == ATIM_CHANNEL4))
	{			
		channel = channel - 2;
		REG_ATIM_CCMR2 |= (1<<(channel * 8));		//捕捉/比较x通道选择,CCx通道配置为输入，ICx映射到TI1	
		channel = channel + 2;
	}		
		
	REG_ATIM_CCER	&= ~(1<<((channel * 4) + 1));	//捕捉x输出极性,CCx通道配置为输入时，与CCxNP配合，{CCxNP,CCxP}选择ICx的极性
	REG_ATIM_CCER	&= ~(1<<((channel * 4) + 3));	//非取反模式–捕捉在ICx的上升沿进行	

	REG_ATIM_SMCR |= (5<<4);						//触发选择，用于选择同步计数器的触发源:滤波后TI1（TI1FP1）
	
	REG_ATIM_SMCR |= ((mode)<<0);					//复位模式；TRGI上升沿初始化计数器，并触发寄存器update
													//闸门模式；TRGI为高电平时，计数时钟使能，TRGI为低电平时，计数时钟停止
													//触发模式；TRGI上升沿触发计数器开始计数（不会复位计数器）
													//外部时钟模式1；TRGI上升沿直接驱动计数器
	
	REG_ATIM_CCER |= (1<<(channel * 4));			//使能CCx捕捉功能	
		
	REG_ATIM_EGR |= (1<<0);							//软件置位UG时会重新初始化计数器并更新shadow寄存器，预分频计数器被清零。
		
}

/************************************************************************
 * Function   : atimer_encoder_init
 * Description: 
 * Input : uint16_t arr		：自动重载值
 *		   uint16_t psc		：分频系数
 *		   uint8_t mode		：编码器模式（从机模式）
 * Output: none
 * Return: none
 ************************************************************************/
void atimer_encoder_init(uint16_t arr, uint16_t psc, uint8_t mode)
{
	
	REG_ATIM_ARR = arr - 1;			//计数溢出时的自动重载值
	REG_ATIM_PSC = psc - 1;			//计数器时钟（CK_CNT）预分频值;fCK_CNT=fCK_PSC/(PSC[15:0]+1)	
			
	REG_ATIM_CR1 &= ~(1<<4);		//向上计数	

	REG_ATIM_CCMR1 |= (1<<8);		//CC2通道配置为输入，IC2映射到TI2
	REG_ATIM_CCMR1 |= (1<<0);		//CC1通道配置为输入，IC1映射到TI1

	REG_ATIM_CCMR1 &= ~(15<<12);	//输入捕捉2滤波:无滤波，使用fDTS采样
	REG_ATIM_CCMR1 &= ~(15<<4);		//输入捕捉1滤波:无滤波，使用fDTS采样

	REG_ATIM_CCER &= ~(1<<7);
	REG_ATIM_CCER &= ~(1<<5);		//非取反模式–捕捉在IC2的上升沿进行
	REG_ATIM_CCER &= ~(1<<3);
	REG_ATIM_CCER &= ~(1<<1);		//非取反模式–捕捉在IC1的上升沿进行
	
	REG_ATIM_SMCR |= (mode<<0);		//从机模式选择: Encoder模式1；计数器使用TI2FP1边沿，根据TI1FP2电平高低来计数(注意此处的高低电平，即一个周期计数两次)
												  //Encoder模式2；计数器使用TI1FP2边沿，根据TI2FP1电平高低来计数
												  //Encoder模式3；计数器同时使用TI1FP1和TI2FP2边沿，根据其他输入信号电平来计数
	
	REG_ATIM_CCER |= (1<<4);		//CC2通道使能捕捉功能
	REG_ATIM_CCER |= (1<<0);		//CC1通道使能捕捉功能

	REG_ATIM_DIER |= (1<<16);		//选择禁用CC1OF中断
	REG_ATIM_DIER |= (1<<17);		//选择禁用CC2OF中断
	REG_ATIM_DIER |= (1<<18);		//选择禁用CC3OF中断
	REG_ATIM_DIER |= (1<<19);		//选择禁用CC4OF中断
	
	REG_ATIM_EGR |= (1<<0);			//软件置位UG时会重新初始化计数器并更新shadow寄存器，预分频计数器被清零。
}

/************************************************************************
 * Function   : atimer2sram_init
 * Description: 定时器0的DMA模式初始化
 * Input : uint16_t arr		：自动重载值
 *		   uint16_t psc		：分频系数
 *		   uint8_t channel	：ATIM通道
 * Output: none
 * Return: none
 ************************************************************************/	
void atimer_atimer2sram_init(uint16_t arr, uint16_t psc, uint8_t channel)
{	

	REG_ATIM_ARR = arr - 1;			//计数溢出时的自动重载值
	REG_ATIM_PSC = psc - 1;			//计数器时钟（CK_CNT）预分频值;fCK_CNT=fCK_PSC/(PSC[15:0]+1)	
			
	REG_ATIM_CR1 &= ~(1<<4);		//向上计数	
	
		if((channel == ATIM_CHANNEL1 ) || (channel == ATIM_CHANNEL2))
		{		
			REG_ATIM_CCMR1 |= (1<<(channel * 8));			//捕捉x通道选择,CCx通道配置为输入，ICx映射到TI1		

			REG_ATIM_CCER &= ~(1<<((channel * 4) + 3));		//CCx通道配置为输入时，与CCxNP配合，{CCxNP,CCxP}选择ICx的极性
			REG_ATIM_CCER |= (1<<((channel * 4) + 1));		//捕获通道x的极性,OCx为OC1REF反转	

			REG_ATIM_CCMR1 &= ~(15<<((channel * 8) + 4));	//输入捕捉x滤波,此寄存器定义TIx的采样频率和滤波长度
			REG_ATIM_CCMR1 &= ~(3<<((channel * 8) + 2));	//输入捕捉x预分频 :无分频
		}
		else if((channel == ATIM_CHANNEL3 ) || (channel == ATIM_CHANNEL4))
		{			
			channel = channel - 2;
			REG_ATIM_CCMR2 |= (1<<(channel * 8));			//捕捉x通道选择,CCx通道配置为输入，ICx映射到TI1		

			channel = channel + 2;
			REG_ATIM_CCER &= ~(1<<((channel * 4) + 3));		//CCx通道配置为输入时，与CCxNP配合，{CCxNP,CCxP}选择ICx的极性
			REG_ATIM_CCER |= (1<<((channel * 4) + 1));		//捕获通道x的极性,OCx为OC1REF反转	

			channel = channel - 2;
			REG_ATIM_CCMR2 &= ~(15<<((channel * 8) + 4));	//输入捕捉x滤波,此寄存器定义TIx的采样频率和滤波长度
			REG_ATIM_CCMR2 &= ~(3<<((channel * 8) + 2));	//输入捕捉x预分频 :无分频
			channel = channel + 2;
		}		
			
	REG_ATIM_CCER |= (1<<(channel * 4));					//CCx通道配置为输入时,使能捕捉功能
				
	/*捕捉模式下，向CCRx中写入值，开启DMA传输，读取SRAM中的值是否与CCRx的值匹配*/
	if(channel == ATIM_CHANNEL1)
	{
		atimer_dmac_enable(1, TIM_CCR1);	//DMA Burst长度,长度=1;DMA基地址为TIM_CCR1
		REG_ATIM_DIER |= (1<<9);		//允许CC1 DMA请求		
	}
	else if(channel == ATIM_CHANNEL2)
	{
		atimer_dmac_enable(1, TIM_CCR2);	//DMA Burst长度,长度=1;DMA基地址为TIM_CCR2	
		REG_ATIM_DIER |= (1<<10);		//允许CC2 DMA请求		
	}
	else if(channel == ATIM_CHANNEL3)
	{
		atimer_dmac_enable(1, TIM_CCR3);	//DMA Burst长度,长度=1;DMA基地址为TIM_CCR3
		REG_ATIM_DIER |= (1<<11);		//允许CC3 DMA请求			
	}
	else if(channel == ATIM_CHANNEL4)
	{
		atimer_dmac_enable(1, TIM_CCR4);	//DMA Burst长度,长度=1;DMA基地址为TIM_CCR4
		REG_ATIM_DIER |= (1<<12);		//允许CC4 DMA请求		
	}	
	REG_ATIM_CR2 &= ~(1<<3);			//发生CCx事件时产生CCxDMA请求

	
	REG_ATIM_EGR |= (1<<0);				//软件置位UG时会重新初始化计数器并更新shadow寄存器，预分频计数器被清零。
	REG_ATIM_CR1 |= (1<<0);				//计数器使能

}	

/************************************************************************
 * Function   : sram2atimer_init
 * Description: 定时器0的DMA模式初始化
 * Input : uint16_t arr		：自动重载值
 *		   uint16_t psc		：分频系数
 *		   uint8_t channel	：ATIM通道
 * Output: none
 * Return: none
 ************************************************************************/	
void atimer_sram2atimer_init(uint16_t arr, uint16_t psc, uint8_t channel)
{

	REG_ATIM_ARR = arr - 1;							//计数溢出时的自动重载值
	REG_ATIM_PSC = psc - 1;							//计数器时钟（CK_CNT）预分频值;fCK_CNT=fCK_PSC/(PSC[15:0]+1)	
			
	REG_ATIM_CR1 &= ~(1<<4);						//向上计数


	if((channel == ATIM_CHANNEL1 ) || (channel == ATIM_CHANNEL2))
	{
		REG_ATIM_CCMR1 &= ~(3<<(channel * 8));		//CCx通道配置为输出			
		REG_ATIM_CCMR1 = ((REG_ATIM_CCMR1&(~(7<<(4+8*channel)))) | ATIM_PWM1(channel));//PWM模式1:在向上计数时，OC1REF在CNT<CCRx时置高						
		
		REG_ATIM_CCER &= ~(1<<((channel * 4) + 1));	//比较通道x的输出极性,OCx为OC1REF	
		REG_ATIM_CCER |= (1<<(channel * 4));		//比较通道x的输出使能		
	}
	else if((channel == ATIM_CHANNEL3 ) || (channel == ATIM_CHANNEL4))
	{			
		channel = channel - 2;
		REG_ATIM_CCMR2 &= ~(3<<(channel * 8));		//CCx通道配置为输出			
		REG_ATIM_CCMR2 = ((REG_ATIM_CCMR2&(~(7<<(4+8*channel)))) | ATIM_PWM1(channel));//PWM模式1:在向上计数时，OC1REF在CNT<CCRx时置高				

		channel = channel + 2;
		REG_ATIM_CCER &= ~(1<<((channel * 4) + 1));	//比较通道x的输出极性,OCx为OC1REF	
		REG_ATIM_CCER |= (1<<(channel * 4));		//比较通道x的输出使能		
	}
	
	REG_ATIM_BDTR |= (1<<15);						//使能OC和OCN输出（仍需各个通道的CCxE和CCxNE状态来决定是否输出）
	
	REG_ATIM_CR1 |= (1<<7);							//预装载使能		
	REG_ATIM_CR1 &= ~(1<<1);						//使能update事件	
	
	
	/*比较模式下，向SRAM中写入值，开启DMA传输，查看PWM值有无变化*/
	if(channel == ATIM_CHANNEL1)
	{
		atimer_dmac_enable(1, TIM_CCR1);				//DMA Burst长度,长度=1;DMA基地址为TIM_CCR1
		REG_ATIM_DIER |= (1<<9);					//允许CC1 DMA请求		
	}
	else if(channel == ATIM_CHANNEL2)
	{
		atimer_dmac_enable(1, TIM_CCR2);				//DMA Burst长度,长度=1;DMA基地址为TIM_CCR2	
		REG_ATIM_DIER |= (1<<10);					//允许CC2 DMA请求		
	}
	else if(channel == ATIM_CHANNEL3)
	{
		atimer_dmac_enable(1, TIM_CCR3);				//DMA Burst长度,长度=1;DMA基地址为TIM_CCR3
		REG_ATIM_DIER |= (1<<11);					//允许CC3 DMA请求			
	}
	else if(channel == ATIM_CHANNEL4)
	{
		atimer_dmac_enable(1, TIM_CCR4);				//DMA Burst长度,长度=1;DMA基地址为TIM_CCR4
		REG_ATIM_DIER |= (1<<12);					//允许CC4 DMA请求		
	}	
	REG_ATIM_CR2 &= ~(1<<3);						//发生CCx事件时产生CCxDMA请求
	

	REG_ATIM_EGR |= (1<<0);							//软件置位UG时会重新初始化计数器并更新shadow寄存器，预分频计数器被清零。
	REG_ATIM_CR1 |= (1<<0);							//计数器使能
	
}

/************************************************************************
 * Function   : atimer_set_compare
 * Description: 设置通道x的输出比较值
 * Input : uint8_t channel 			：ATIM通道
 *		   uint16_t compare_value	：比较值
 * Output: none
 * Return: none
 ************************************************************************/	
void atimer_set_compare(uint8_t channel, uint16_t compare_value)
{
	if(channel == ATIM_CHANNEL1)
	{
		REG_ATIM_CCR1 = compare_value;		
	}
	else if(channel == ATIM_CHANNEL2)
	{
		REG_ATIM_CCR2 = compare_value;	
	}
	else if(channel == ATIM_CHANNEL3)
	{
		REG_ATIM_CCR3 = compare_value;
	}
	else if(channel == ATIM_CHANNEL4)
	{
		REG_ATIM_CCR4 = compare_value;	
	}
}

/************************************************************************
 * Function   : atimer_get_capture
 * Description: 读取通道x的输入捕获值
 * Input : uint8_t channel：ATIM通道
 * Output: none
 * Return: 捕获值
 ************************************************************************/	
uint16_t atimer_get_capture(uint8_t channel)
{
	if(channel == ATIM_CHANNEL1)
	{
		return REG_ATIM_CCR1;		
	}
	else if(channel == ATIM_CHANNEL2)
	{
		return REG_ATIM_CCR2;	
	}
	else if(channel == ATIM_CHANNEL3)
	{
		return REG_ATIM_CCR3;
	}
	else if(channel == ATIM_CHANNEL4)
	{
		return REG_ATIM_CCR4;	
	}
	
	return 0;
}

/************************************************************************
 * Function   : atimer_get_cnt
 * Description: 读取定时器计数值
 * Input : none
 * Output: none
 * Return: 定时器计数值
 ************************************************************************/	
uint16_t atimer_get_cnt(void)
{
	return REG_ATIM_CNT;
}




