//*********************************************************************** 
//Copyright (c) 2024   HuaXin Micro-electronics Co.,Ltd 
//
//HS16P2811 
//T1
//configuration introduction
//芯片T1定时器周期溢出功能，时钟源选外部时钟源（PA7-分频后）；同步模式下分频有效
//designer:华芯微MCU组
//updata：20241105
//***********************************************************************  
//RAM: 176*8bytes
//ROM: 2K
//STACK: 8-level
//*********************************************************************** 
#include 	"main.h"		

  
//--------------------------------------------------------------------------------------------------
/*
	     ╔══════╗　 ╔══════╗
	VDD  ╬1 ●   ╚═══╝    16╬   GND
	PA7  ╬2              15╬   PA0
	PA6  ╬3              14╬   PA1
	PA5  ╬4              13╬   PA2
	PA4  ╬5              12╬   PA3
	PC5  ╬6              11╬   PC0
	PC4  ╬7              10╬   PC1
	PC3  ╬8              9 ╬   PC2
         ╚═════════════════╝
*/
//--------------------------------------------------------------------------------------------------

unsigned char T1_Timer_Cnt = 0;

//--------------------------------------------------------------------------------------------------
//Timer1-define
#define  iT1_1_rate		0
#define  iT1_2_rate		1
#define  iT1_4_rate		2
#define  iT1_8_rate		3

#define  iT1_val		200
/**
 * @ brief:	T1_Frq_Fcpu 初始化函数
 * @ note: T1时钟源选Fcpu;异步无效
 * @ param:	1-分频系数【0~3】; 2-初值【<65536】
 * @ retval:null
 */
void T1_Frq_Fcpu(unsigned char rate,unsigned int timer_val)
{
	T1TH = (0xffff - timer_val) / 256;	//初值high-8位
	T1TL = (0xffff - timer_val) % 256;	//初值low-8位
	
	T1CON = 0b00000000;	//--00 000 //bit1=0-Fcpu;bit2=0-同步；
	T1CON|=(rate<<4);	//分配系数	
		//bit5~4:T1CK<1:0> T1分频选择
			//00 = 1分频		01 = 2分频
			//10 = 4分频		11 = 8分频
		//bit3:T1CKS1 T1外部时钟源选择(T1CKS0=1时有效)
			//0 = 外部时钟PA7	1 = 内部低速RC
		//bit2:T1SYNC T1外部时钟源与内部时钟同步控制(T1CKS0=1时有效)
			//0 = 同步-√		1 = 异步
		//bit1:T1CKS0 
			//0 = 内部Fcpu-√	1 = 外部时钟源
		//bit0:T1REN 
			//0 = T1关闭		1 = T1使能
	
	T1IF = 0;	//Timer1 溢出标志位
	T1IE = 1;	//Timer1 中断使能位
	PEIE = 1;	//外设 中断总使能
	T1REN = 1;	//Timer1 启动位
	GIE = 1;	//总中断
}

/**
 * @ brief:	T1_ExCLK_PA7_asyn 初始化函数
 * @ note: T1时钟源选 外部时钟源（PA7）；异步模式下分频无效；
 * @ param:	1-初值【<65536】
 * @ retval:null
 */
void T1_ExCLK_PA7_asyn(unsigned int timer_val)
{
	TRISA |= 0b10000000;	//(0-OUT;1-IN) 	
	PAHCON &= 0b01111111;	//--11 1111 :1-DIS;0-EN 
	
	T1TH = (0xffff - timer_val) / 256;	//初值high-8位
	T1TL = (0xffff - timer_val) % 256;	//初值low-8位
	
	T1CON = 0b00000000;	//--00 0000
	T1CON|=(1<<1);	//bit1=1-外部时钟源
	T1CON|=(1<<2);	//bit2=1-异步模式
		//bit5~4:T1CK<1:0> T1分频选择
			//00 = 1分频		01 = 2分频
			//10 = 4分频		11 = 8分频
		//bit3:T1CKS1 T1外部时钟源选择(T1CKS0=1时有效)
			//0 = 外部时钟PA7-√	1 = 内部低速RC
		//bit2:T1SYNC T1外部时钟源与内部时钟同步控制(T1CKS0=1时有效)
			//0 = 同步			1 = 异步-√
		//bit1:T1CKS0 
			//0 = 内部Fcpu		1 = 外部时钟源-√
		//bit0:T1REN 
			//0 = T1关闭		1 = T1使能
	
	T1IF = 0;
	T1IE = 1;
	PEIE = 1;
	T1REN = 1;
	GIE = 1;
}
/**
 * @ brief:	T1_ExCLK_PA7_syn 初始化函数
 * @ note: T1时钟源选 外部时钟源（PA7-分频后）；同步模式下分频有效
 * @ param:	1-分频系数【0~3】; 2-初值【<65536】
 * @ retval:null
 */
void T1_ExCLK_PA7_syn(unsigned char rate,unsigned int timer_val)
{
	TRISA |= 0b10000000;	//(0-OUT;1-IN) 	
	PAHCON &= 0b01111111;	//--11 1111 :1-DIS;0-EN 
	
	T1TH = (0xffff - timer_val) / 256;	//初值high-8位
	T1TL = (0xffff - timer_val) % 256;	//初值low-8位
	
	T1CON = 0b00000000;	//--00 0000
	T1CON|=(1<<1);		//bit1=1-外部时钟源;
	T1CON|=(rate<<4);	//分配系数	
		//bit5~4:T1CK<1:0> T1分频选择
			//00 = 1分频		01 = 2分频
			//10 = 4分频		11 = 8分频
		//bit3:T1CKS1 T1外部时钟源选择(T1CKS0=1时有效)
			//0 = 外部时钟PA7-√	1 = 内部低速RC
		//bit2:T1SYNC T1外部时钟源与内部时钟同步控制(T1CKS0=1时有效)
			//0 = 同步-√		1 = 异步
		//bit1:T1CKS0 
			//0 = 内部Fcpu		1 = 外部时钟源-√
		//bit0:T1REN 
			//0 = T1关闭		1 = T1使能
	
	T1IF = 0;
	T1IE = 1;
	PEIE = 1;
	T1REN = 1;
	GIE = 1;
}

/**
 * @ brief:	T1_ExCLK_ILRC_asyn 初始化函数
 * @ note: T1时钟源选 外部时钟源（ILRC）；异步模式下分频无效；
 * @ param:	1-初值【<65536】
 * @ retval:null
 */
void T1_ExCLK_ILRC_asyn(unsigned int timer_val)
{
	T1TH = (0xffff - timer_val) / 256;	//初值high-8位
	T1TL = (0xffff - timer_val) % 256;	//初值low-8位
	
	T1CON = 0b00000000;	//--00 0000
	T1CON|=(1<<1);	//bit1=1-外部时钟源
	T1CON|=(1<<2);	//bit2=1-异步模式
	T1CON|=(1<<3);	//bit3=1-内部低速RC
		//bit5~4:T1CK<1:0> T1分频选择
			//00 = 1分频		01 = 2分频
			//10 = 4分频		11 = 8分频
		//bit3:T1CKS1 T1外部时钟源选择(T1CKS0=1时有效)
			//0 = 外部时钟PA7	1 = 内部低速RC-√
		//bit2:T1SYNC T1外部时钟源与内部时钟同步控制(T1CKS0=1时有效)
			//0 = 同步			1 = 异步-√
		//bit1:T1CKS0 
			//0 = 内部Fcpu		1 = 外部时钟源-√
		//bit0:T1REN 
			//0 = T1关闭		1 = T1使能
	
	T1IF = 0;
	T1IE = 1;
	PEIE = 1;
	T1REN = 1;
	GIE = 1;
}
/**
 * @ brief:	T1_ExCLK_ILRC_syn 初始化函数
 * @ note: T1时钟源选 外部时钟源（ILRC分频后）；同步模式下分频有效
 * @ param:	1-分频系数【0~3】; 2-初值【<65536】
 * @ retval:null
 */
void T1_ExCLK_ILRC_syn(unsigned char rate,unsigned int timer_val)
{
	T1TH = (0xffff - timer_val) / 256;	//初值high-8位
	T1TL = (0xffff - timer_val) % 256;	//初值low-8位
	
	T1CON = 0b00000000;	//--00 0000	
	T1CON|=(1<<1);	//bit1=1-外部时钟源
	T1CON|=(1<<3);	//bit3=1-内部低速RC
	T1CON|=(rate<<4);	//分配系数	
		//bit5~4:T1CK<1:0> T1分频选择
			//00 = 1分频		01 = 2分频
			//10 = 4分频		11 = 8分频
		//bit3:T1CKS1 T1外部时钟源选择(T1CKS0=1时有效)
			//0 = 外部时钟PA7	1 = 内部低速RC-√
		//bit2:T1SYNC T1外部时钟源与内部时钟同步控制(T1CKS0=1时有效)
			//0 = 同步-√		1 = 异步
		//bit1:T1CKS0 
			//0 = 内部Fcpu		1 = 外部时钟源-√
		//bit0:T1REN 
			//0 = T1关闭		1 = T1使能
	
	T1IF = 0;
	T1IE = 1;
	PEIE = 1;
	T1REN = 1;
	GIE = 1;
}
/**
 * @ brief:	T1_SLEEP_ILRC 初始化函数
 * @ note: T1时钟源选 外部时钟源（ILRC分频后）；同步模式;
 * @ param:	1-分频系数【0~3】; 2-初值【<65536】
 * @ retval:null
 */
void T1_SLEEP_ILRC_syn(unsigned char rate, unsigned int timer_val)
{
//T1-set	
	T1TH = (0xffff - timer_val) / 256;	//初值high-8位
	T1TL = (0xffff - timer_val) % 256;	//初值low-8位
	
	T1CON = 0b00000000;	//--00 0000
	T1CON|= (1<<1);		//bit1=1-外部时钟源
	T1CON|= (1<<3);		//bit3=1-ILRC
	T1CON|=(rate<<4);	//分配系数	
		//bit5~4:T1CK<1:0> T1分频选择
			//00 = 1分频		01 = 2分频
			//10 = 4分频		11 = 8分频
		//bit3:T1CKS1 T1外部时钟源选择(T1CKS0=1时有效)
			//0 = 外部时钟PA7	1 = 内部低速RC-√
		//bit2:T1SYNC T1外部时钟源与内部时钟同步控制(T1CKS0=1时有效)
			//0 = 同步-√		1 = 异步
		//bit1:T1CKS0 
			//0 = 内部Fcpu		1 = 外部时钟源-√
		//bit0:T1REN 
			//0 = T1关闭		1 = T1使能
	
//goto sleep set
	CLRWDT();
	FWDTE=0; 
	
	T1IF = 0;
	//T1IE = 1;
	//PEIE = 1;
	//T1REN = 1;
	//GIE = 1;
	OSCM = 0x00;	//-00- 0-00
		//bit6:WAKEMODE-唤醒后系统时钟选择:	
			//0=选择内部低速	1=选择高速RC
		//bit5:GREENEN-绿色模式使能位:	
			//0=普通模式;		1=绿色模式
		//bit3:SLCON-内外低速控制:	
			//0=开启内外低速时钟;1=关闭内外低速时钟(同事SLEEP需使能)
		//bit1:STPHX-内部高速振荡器控制位;	
			//0=运行;			1=停止,内部低速RC仍然运行
		//bit0:CLKMD-系统时钟模式控制位;	
			//0=普通模式,高速时钟为系统时钟;1=低速模式,低速时钟作为系统时钟
	OSCM|=(1<<6);	//WAKEMODE-bit6=1=选择高速RC
	OSCM|=(1<<0);	//CLKMD-bit0=1=低速模式
	OSCM|=(1<<1);	//STPHX-bit1=1=停止,内部低速RC仍然运行
	T1REN = 1;
	_NOP();
	SLEEP(); 
	
	while(T1IF == 0);
	T1IF = 0;
	T1REN = 0;
	
	CLRWDT();
	FWDTE=1; 
}
/**
 * @ brief:	T1_GREEN_ILRC 初始化函数
 * @ note: T1时钟源选 外部时钟源（ILRC）；异步模式-分频无效
 * @ param:	1-初值【<65536】
 * @ retval:null
 */
void T1_GREEN_ILRC_asyn(unsigned int timer_val)
{
//T1-set	
	T1TH = (0xffff - timer_val) / 256;	//初值high-8位
	T1TL = (0xffff - timer_val) % 256;	//初值low-8位
	
	T1CON = 0b00000000;	//--00 0000
	T1CON|= (1<<1);		//bit1=1-外部时钟源
	T1CON|= (1<<2);		//异步
	T1CON|= (1<<3);		//bit3=1-ILRC
		//bit5~4:T1CK<1:0> T1分频选择
			//00 = 1分频		01 = 2分频
			//10 = 4分频		11 = 8分频
		//bit3:T1CKS1 T1外部时钟源选择(T1CKS0=1时有效)
			//0 = 外部时钟PA7	1 = 内部低速RC-√
		//bit2:T1SYNC T1外部时钟源与内部时钟同步控制(T1CKS0=1时有效)
			//0 = 同步			1 = 异步-√
		//bit1:T1CKS0 
			//0 = 内部Fcpu		1 = 外部时钟源-√
		//bit0:T1REN 
			//0 = T1关闭		1 = T1使能
	
//goto sleep set
	CLRWDT();
	FWDTE=0; 
	
	T1IF = 0;
	//T1IE = 1;
	//PEIE = 1;
	//T1REN = 1;
	//GIE = 1;
	OSCM = 0x00;	//-00- 0-00
		//bit6:WAKEMODE-唤醒后系统时钟选择:	
			//0=选择内部低速	1=选择高速RC
		//bit5:GREENEN-绿色模式使能位:	
			//0=普通模式;		1=绿色模式
		//bit3:SLCON-内外低速控制:	
			//0=开启内外低速时钟;1=关闭内外低速时钟(同事SLEEP需使能)
		//bit1:STPHX-内部高速振荡器控制位;	
			//0=运行;			1=停止,内部低速RC仍然运行
		//bit0:CLKMD-系统时钟模式控制位;	
			//0=普通模式,高速时钟为系统时钟;1=低速模式,低速时钟作为系统时钟
	OSCM|=(1<<6);	//WAKEMODE-bit6=1=选择高速RC
	OSCM|=(1<<5);	//GREENEN-bit5=1=绿色模式
	OSCM|=(1<<0);	//CLKMD-bit0=1=低速模式
	OSCM|=(1<<1);	//STPHX-bit1=1=停止,内部低速RC仍然运行
	T1REN = 1;
	_NOP();
	SLEEP(); 
	
	while(T1IF == 0);
	T1IF = 0;	
	T1REN = 0;
	
	CLRWDT();
	FWDTE=1; 
}
/**
 * @ brief:	main
 * @ param:	null
 * @ retval:null
 */

unsigned char T1_mode = 0;

void main(void) 
{
	System_Init();
	GPIO_Init();
	CLR_RAM_EveryBank();
	
	T1_mode = 2;
	switch(T1_mode)	//T1_Init();
	{
		case 0: T1_Frq_Fcpu(iT1_1_rate,iT1_val);		break;	//2分频；初值200
		
		case 1: T1_ExCLK_PA7_asyn(iT1_val);				break;
		case 2: T1_ExCLK_PA7_syn(iT1_4_rate,iT1_val);	break;
		
		case 3: T1_ExCLK_ILRC_asyn(iT1_val);			break;
		case 4: T1_ExCLK_ILRC_syn(iT1_1_rate,iT1_val);	break;
		
		default: break;
	}
	
	while(1) 
	{ 
		CLRWDT();  
		PORTA = PORTA^0x01;	
		//PORTC = PORTC^0xff;	
		//DelayUs(1);
		
		switch(T1_mode)	//T1_Init();
		{			
			case 5: T1_SLEEP_ILRC_syn(iT1_1_rate,iT1_val);	PORTA ^= (1<<1);	break;
			case 6: T1_GREEN_ILRC_asyn(iT1_val);			PORTA ^= (1<<2);	break;
			default: break;
		}
	} 
} 


/**
 * @ brief:	GPIO Init
 * @ param:	null
 * @ retval:null
 */
void GPIO_Init(void) 
{
//;PORTA
	PORTA = 0b00000000;		//0000 0000	//端口输出赋值
	TRISA = 0b00000000;		//0000 0000	:0-OUT;1-IN 	//输入输出配置
	PAODCON = 0b00000000;	//0000 0000 :1-EN;0-DIS 	//开漏配置
	PAHCON = 0b11111111;	//1111 1111 :1-DIS;0-EN 	//内部上拉配置
	PADCON = 0b11111111;	//1111 1111 :1-DIS;0-EN 	//内部下拉配置
	WUACON = 0b00000000;	//0000 0000	:1-EN;0=DIS 	//端口唤醒配置
		
//;PORTC
	PORTC = 0b00000000;		//--00 0000	//端口输出赋值
	TRISC = 0b00000000;		//--00 0000	:0-OUT;1-IN 	//输入输出配置
	PCDCON = 0b11111111;	//--11 1111 :1-DIS;0-EN		//内部下拉配置
	PCHCON = 0b11111111;	//--11 1111 :1-DIS;0-EN 	//内部上拉配置
} 


/**
 * @ brief:	System_Init
 * @ param:	null
 * @ retval:null
 */ 
void System_Init(void)
{
	OPTION = 0b000000000;	 //-0-- ----
			//bit6:INTEDG：外部中断触发方式选择位（PC1）	;0-falling edge, 1-rising edge
			
	INTCON = 0b00000000;	//00-0 0-00
			//bit7:GIE 全局中断使能位
			//bit6:PEIE 外设总中断使能位
			//bit4:INTIE 外部中断使能位(PC1)
			//bit3:PAIE PORTA输入变化中断使能位
			//bit1:INTIF 外部中断标志位
			//bit0:PAIF PORTA输入变化中断标志位			
	
	PCON  = 0b10110000;		//1-1- ----	
			//Bit7：WDTE: WDT（看门狗定时器）使能位	;0-DIS, 1-EN
			//Bit5：LVREN: 低电压复位使能位			;0-DIS, 1-EN
				
	PIE1 = 0B00000000;		//-0-- ---0 
			//Bit6:ADCIE ADC中断使能位
			//Bit0:T1IE 定时器T1中断使能位 
			
	PIR1 = 0B00000000;		//-0-- ---0 
			//Bit6:ADCIE ADC转换完成标志位
			//Bit0:T1IE 定时器T1溢出标志位 
			
	PIE2 = 0B00000000;	//---- -0-0
			//Bit1:T3IE 定时器T3中断使能位
			//Bit2:T4IE 定时器T4中断使能位
			//Bit5:C1IE 比较器C1中断使能位
			
	PIR2 = 0B00000000;	//---- -0-0
			//Bit1:T3IE 定时器T3溢出标志位,软件清0
			//Bit2:T4IE 定时器T4溢出标志位,软件清0
			//Bit5:C1IE 比较器C1输出变化时被置位,软件清0
}


/**
 * @ brief:	CLR_RAM_EveryBank
 * @ note
 *  @对用户寄存器进行清0操作 
 *  @分BANK区清楚 
 *  @嵌入汇编操作 
 *  @IRP:FSR7:	间接寻址寻址空间（充分理解 间接寻址操作原理）
 *  @	0 0		BANK0
 *  @	0 1		BANK1
 *  @	1 0		BANK2
 *  @	1 1		BANK3
 * @ param:	null
 * @ retval:null
 */     
void CLR_RAM_EveryBank(void)
{
	#asm   
		MOVLW	0x5F  //个数
		MOVWF	0x20  //个数存放地址 
		MOVLW 	0x7F  //REG从后往前 清理 
		MOVWF	_FSR,F 
	CLR_RAM_LOOP:   
		CALL	CLR_RAM_Demo
		
		DECF	_FSR,F   
		DECFSZ	0X20,F   
		GOTO	CLR_RAM_LOOP
		
		CALL	CLR_RAM_Demo
		RETURN
		
	CLR_RAM_Demo:	
	//	0 1		BANK1
		//BCF	_STATUS,7	//IRP
		BSF		_FSR,7		//01:BANK1
		CLRF	_INDF  
		
	//	0 0		BANK0
		//BCF	_STATUS,7	//IRP
		BCF		_FSR,7		//00:BANK0
		CLRF	_INDF		
		RETURN
	#endasm	
}   

/**
 * @ brief:	Delay
 * @ note
 *  @ Fcpu=1MHz;DelayUs = 11+7x
 *  @ 不同时钟Fcpu，注意时间差异
 * @ param:	null
 * @ retval:null
 */
//****delay function****// 
void DelayUs(unsigned char delayUs)
{
	while(delayUs--);
}

//==============================================
//1.>中断函数
//;Bank0~3：进中断-编译系统会自动切换,用户不需要手动切换; 
//==============================================
void interrupt myIsr(void)    
{
	//----User Code ----/
	if(T1IF)
	{
		T1TH = (0xffff - iT1_val) / 256;	//初值high-8位
		T1TL = (0xffff - iT1_val) % 256;	//初值low-8位
		
		PORTC ^= (1<<0);
		T1_Timer_Cnt++;
		if(T1_Timer_Cnt > 5)
		{
			T1_Timer_Cnt = 0;
			PORTC ^= (1<<1);
		}
		T1IF = 0;
	}
} 
