//*****************************************************   
//Copyright (c) 2025, 苏州华芯微电子股份有限公司
//All rights reserved                                 
//
//文件名称: HS16F1886-TC0 16bit
//摘    要: HS16F1886-TC0功能演示
//  	    TC0周期定时溢出中断演示
//
//当前版本: 1.0                                      
//作    者: 华芯微MCU组
//完成日期: 2025.08.22
//*****************************************************   
//Files include 
#include 	"hs16p1886.h" 
#include 	"main.h"		


//***********************宏定义*****************************
#define  unchar     unsigned char 
#define  unint      unsigned int
#define  unlong     unsigned long

#define  u8     	unsigned char 
#define  u16      	unsigned int
#define  u32     	unsigned long


//*****************************************************   
#define		timer0_8bit_mode		0
#define		timer0_16bit_mode		1
#define		timer0_mode			timer0_16bit_mode




//**所有中断统一入口，没有优先级区分，只能靠软件查询顺序排优先级***//
void interrupt myIsr(void)
{
	if(TC0IF)//检查TC0溢出中断
	{		
		TC0IF=0;
	#if(timer0_mode == timer0_8bit_mode)
		TC0L = 128;//TC0 无重装载功能，要改变周期需要在中断里手动改变 TC0L的值
		//理论上128us翻转一次，实际多1-2个TC0时钟，并非内部RC误差导致，内部HIRC误差在2.5%
	#else
		TC0H = (65536-500)/256;
		TC0L = (65536-500)%256;
	#endif
		PB1 = ~PB1;//PB1翻转
	}
	
	if(PBIF)//检查PORTB变化中断
	{
		PBIF = 0; 		 
	}
}


void main(void) 
{
	sys_gpio_init(); //系统寄存器和GPIO配置
	clr_all_ram();   //清所有ram
	
	WDT_Init();		//看门狗初始化
	tc0_tim_init();	//tc0初始化
	
	GIE = 1;		//开总中断
	while(1)
	{
		CLRWDT;	//清看门狗
	}
}

/**
  * @brief  tc0定时器初始化函数
  *
  * @note   TC0 无重装载功能，要改变周期需要在中断里手动改变 TC0L的值
  * @note   - 本示例使用Fpcu的4分频作为TC0时钟，也就是TC0时钟为1Mhz
  *           
  * @retval None
  */
void tc0_tim_init(void)
{
	TC0M = 0;
#if(timer0_mode == timer0_8bit_mode)
	
	//TC0M = 0x60|(1<<3);	//Fosc
	TC0M = 0x60;	//default Fcpu with + [TC0S[2:0]]
		//Bit7：TC0TR:TC0 启动控制位。
		
		//Bit6~Bit4：TC0S[2:0]:TC0 分频选择位
			//TC0S[2:0]		Fcpu作为时钟(TCCKS=0)		Fosc作为时钟(TCCKS=1)
			// 000				Fcpu/256					Fosc/128
			// 001				Fcpu/128                	Fosc/64
			// 010				Fcpu/64                 	Fosc/32
			// 011				Fcpu/32                 	Fosc/16
			// 100				Fcpu/16                 	Fosc/8
			// 101				Fcpu/8                  	Fosc/4
			// 110				Fcpu/4                  	Fosc/2
			// 111				Fcpu/2						Fosc/1
		//Bit3：TCCKS:TC0 时钟信号控制位 0:Fcpu作为时钟; 1:Fosc作为时钟;
		//Bit2: TC0S16：TC0 溢出位选择； 0-8bit timer ；1-16bit timer
		
#else
	TC0M |=(1<<3);	//Fosc(16MHz)
	TC0M |=(4<<4);	//Fosc/8
	TC0M |=(1<<2);	//16bit-timer
#endif	
	
	TC0IF = 0;		//TC0 overflow flag
	TC0IE = 1;  	//TC0 overflow enable bit(1=EN,0=DIS)	
	
	TC0TR = 1;		//TC0 启动TC0
}



//*********************************************************************** 
/****WDT overflow reset，have no wakeup funtions****；
	则看门狗复位时间仅由烧录配置：288ms；512ms；766ms；1024ms；
*/
void WDT_Init(void)
{
	CLRWDT;
	 
//;option attentions 
	OPTION= 0b00000000; //-000 0000
			//;Bit7：INT1EDG：外部中断1触发方式选择位（PB1）;0-falling edge, 1-rising edge
			//;Bit6：INTEDG：外部中断触发方式选择位（PB0）	;0-falling edge, 1-rising edge
		
	
//;PCON 
	PCON  = 0b10100000;	//100- ----	
			//;Bit7：WDTE: WDT（看门狗定时器）使能位	;0-DIS, 1-EN
		
			//;Bit5：LVREN: 低电压复位使能位			;0-DIS, 1-EN			
}
 
//****GPIO configuration****//
void sys_gpio_init(void)
{
	OPTION= 0b00000000;//0000 0000	
			//;Bit7：INT1EDG：外部中断1触发方式选择位（PB1）;0-falling edge, 1-rising edge
			//;Bit6：INTEDG：外部中断触发方式选择位（PB0）	;0-falling edge, 1-rising edge
		
	
	PCON  = 0b10100000;	//101- ----		
			//;Bit7：WDTE: WDT（看门狗定时器）使能位	;0-DIS, 1-EN
		
			//;Bit5：LVREN: 低电压复位使能位			;0-DIS, 1-EN
	
	//PORTB //----------------------------------------------------------------------
	PORTB = 0b00000000;	//0000 0000 :PORTB数据寄存器
	TRISB = 0b00000000;	//--00 0000 :PORTB输入输出配置寄存器 (0-OUT;1-IN)
	WUCON = 0b00000000;	//--00 0000	:PORTB变化中断唤醒寄存器 (1-EN;0=DIS)
	ODCON = 0b00000000;	//--00 0000 :PORTB开漏寄存器 (1-EN;0-DIS)
	PHCON = 0b11111111;	//--11 1111 :PORTB上拉寄存器 (1-DIS;0-EN)
	
	PDCON = 0b11111111;	//0000 ---- :bit7:4 PORTB3:0下拉寄存器;1-DIS;0-EN
	PDCON1= 0b11111111;	//---- --11 :bit1:0 PORTB5:4下拉寄存器;1-DIS;0-EN
	
	//PB0~2 配置大驱动----------------------------------------------------------
	PBIC0 = 0b00000000;	//--00 0000 :1-PB口低电平驱动增强；0-低电平驱动默认
	DRVC0 = 0b00000000;	//---- -111	:PB0 端口大驱动选择
	DRVC1 = 0b00000000;	//---- -111	:PB1 端口大驱动选择
	DRVC2 = 0b00000000;	//---- -111	:PB2 端口大驱动选择
	
	//外振 模式控制寄存器
	XTCON = 0x00;		//--00 0000	:
				// bit5: XTSEN1：外振软件增强使能位 1（与上位机配置共同控制） 0-en;1-dis
				// bit4: XTSEN0：外振软件增强使能位 0（与上位机配置共同控制） 0-en;1-dis
				// bit3: XTEN：外振软件使能位（与上位机配置共同控制）		 0-en;1-dis
				// bit2: XT_TC0S：TC0 低速时钟选择		0-内部低速时钟；1-外部32.768K 
				// bit1: XT_LRCS：低速模式系统时钟选择	0-dis ; 1-EN
				// bit0: XT_MONE：外振监测使能
}


//****************************************************  
//清除所有ram 
//C中嵌入ASM，指令操作特殊寄存器前面需要加下划线“_”;
//****************************************************    
void clr_all_ram(void)
{
	STATUS &= 0x1F;
#asm  
	MOVLW	0X3F
	MOVWF	040H
	MOVLW	0X7F
	MOVWF	_FSR
	
BANK0_RAM_CLR_LOOP:	
	CLRF	_INDF
	DECF	_FSR,F
	DECFSZ	040H,F
	GOTO	BANK0_RAM_CLR_LOOP
#endasm
}

/*-------------------------------------------------
 *  函数名：DelayMs
 *	功能：  软件延时函数
 *  输入：  延时时间 单位 MS 存在一定的误差 8M2分频情况下，未开优化
 *  输出：  无
 --------------------------------------------------*/	
void DelayMs(unsigned char delayMs)
{
	unsigned int delay_us;
	while(delayMs--)
	{
		delay_us=285;
		while(delay_us--);
	}
}


//****delay function****// 
//;Fcpu=1MHz;DelayUs = 11+7x     
void DelayUs(unsigned char delayUs)
{
	while(delayUs--);    
} 