//*****************************************************   
//Copyright (c) 2024, 苏州华芯微电子股份有限公司
//All rights reserved                                 
//
//文件名称: HS16F1880-TC0
//摘    要: HS16F1880-TC0功能演示
//  	    TC0周期定时溢出中断演示
//
//当前版本: 1.0                                      
//作    者: 华芯微MCU组
//完成日期: 2025.08.7
//*****************************************************   
//Files include 
#include 	"hs16p1880.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  uint64_t     	unsigned long long
#define  uint32_t     	unsigned long
#define  uint16_t      	unsigned int
#define  uint8_t     	unsigned char 

//============Define  Flag=================
typedef union {
   	unsigned char byte;
   	struct
   	{
   	   	uint8_t bit0 : 1;
   	   	uint8_t bit1 : 1;
   	   	uint8_t bit2 : 1;
   	   	uint8_t bit3 : 1;
   	   	uint8_t bit4 : 1;
   	   	uint8_t bit5 : 1;
   	   	uint8_t bit6 : 1;
   	   	uint8_t bit7 : 1;
   	} bits;
}bit_flag;


#define 	SEG1_O	   	  PB0
#define 	SEG2_O	   	  PB1
#define 	SEG3_O	   	  PB2
#define 	SEG4_O	   	  PB4
#define 	SEG5_O	   	  PB5


#define 	SEG1_M   	  TRISB0
#define 	SEG2_M   	  TRISB1
#define 	SEG3_M   	  TRISB2
#define 	SEG4_M   	  TRISB4
#define 	SEG5_M   	  TRISB5

////////////////
bit_flag	dsp_dat1;
	#define	b_a1_dsp	dsp_dat1.bits.bit0
	#define	b_b1_dsp	dsp_dat1.bits.bit1
	#define	b_c1_dsp	dsp_dat1.bits.bit2
	#define	b_d1_dsp	dsp_dat1.bits.bit3
	#define	b_e1_dsp	dsp_dat1.bits.bit4
	#define	b_f1_dsp	dsp_dat1.bits.bit5
	#define	b_g1_dsp	dsp_dat1.bits.bit6
	// #define	b_18dp_dsp	dsp_dat1.bt.b7

bit_flag	dsp_dat2;
	#define	b_a2_dsp	dsp_dat2.bits.bit0
	#define	b_b2_dsp	dsp_dat2.bits.bit1
	#define	b_c2_dsp	dsp_dat2.bits.bit2
	#define	b_d2_dsp	dsp_dat2.bits.bit3
	#define	b_e2_dsp	dsp_dat2.bits.bit4
	#define	b_f2_dsp	dsp_dat2.bits.bit5
	#define	b_g2_dsp	dsp_dat2.bits.bit6
	
bit_flag	dsp_dat3;
	#define	b_a3_dsp	dsp_dat3.bits.bit0
	#define	b_b3_dsp	dsp_dat3.bits.bit1
	#define	b_c3_dsp	dsp_dat3.bits.bit2
	#define	b_d3_dsp	dsp_dat3.bits.bit3
	#define	b_e3_dsp	dsp_dat3.bits.bit4
	#define	b_f3_dsp	dsp_dat3.bits.bit5
	#define	b_g3_dsp	dsp_dat3.bits.bit6


// bit_flag	dsp_dpv;
	// #define	b_dp1	dsp_dpv.bits.bit0
	// #define	b_dp2	dsp_dpv.bits.bit1
	// #define	b_k1	dsp_dpv.bits.bit2
	// #define	b_k2	dsp_dpv.bits.bit3



//seg 输出高
#define 	SEG1		do{SEG1_M=0;SEG1_O=1;}while(0)//SEG1_O=1;
#define 	SEG2		do{SEG2_M=0;SEG2_O=1;}while(0)//SEG2_O=1;
#define 	SEG3		do{SEG3_M=0;SEG3_O=1;}while(0)//SEG3_O=1;
#define 	SEG4		do{SEG4_M=0;SEG4_O=1;}while(0)//SEG4_O=1;
#define 	SEG5		do{SEG5_M=0;SEG5_O=1;}while(0)//SEG5_O=1;

//com输出低
#define 	COM1		do{SEG1_M=0;SEG1_O=0;}while(0)
#define 	COM2		do{SEG2_M=0;SEG2_O=0;}while(0)
#define 	COM3		do{SEG3_M=0;SEG3_O=0;}while(0)
#define 	COM4		do{SEG4_M=0;SEG4_O=0;}while(0)
#define 	COM5		do{SEG5_M=0;SEG5_O=0;}while(0)
    
uint8_t led_wei;


//**所有中断统一入口，没有优先级区分，只能靠软件查询顺序排优先级***//
void interrupt myIsr(void)
{
	if(TC0IF)//检查TC0溢出中断
	{
		TC0IF=0;
		TC0L = 256-200;//TC0 无重装载功能，要改变周期需要在中断里手动改变 TC0L的值
		//理论上200us翻转一次，实际多1-2个TC0时钟，并非内部RC误差导致，内部HIRC误差在2.5%
		
		//扫描开始所有IO设置输入
		SEG1_M=1;
		SEG2_M=1;
		SEG3_M=1;
		SEG4_M=1;
		SEG5_M=1;
		
		
		if(++led_wei>=16)
			led_wei=0;
		switch(led_wei)
		{
			case  0:if(b_b1_dsp){SEG3;COM4;}break;//第一个数码管的B段，根据数码管资料点亮
			case  1:if(b_c1_dsp){SEG2;COM4;}break;//第一个数码管的C段，根据数码管资料点亮
			
			case  2:if(b_a2_dsp){SEG2;COM3;}break;//第二个数码管的A段，根据数码管资料点亮
			case  3:if(b_b2_dsp){SEG3;COM2;}break;
			case  4:if(b_c2_dsp){SEG4;COM3;}break;
			case  5:if(b_d2_dsp){SEG4;COM2;}break;
			case  6:if(b_e2_dsp){SEG5;COM2;}break;
			case  7:if(b_f2_dsp){SEG5;COM3;}break;
			case  8:if(b_g2_dsp){SEG5;COM4;}break;
			
			case  9:if(b_a3_dsp){SEG1;COM2;}break;//第三个数码管的A段，根据数码管资料点亮
			case 10:if(b_b3_dsp){SEG2;COM1;}break;
			case 11:if(b_c3_dsp){SEG1;COM3;}break;
			case 12:if(b_d3_dsp){SEG3;COM1;}break;
			case 13:if(b_e3_dsp){SEG1;COM4;}break;
			case 14:if(b_f3_dsp){SEG4;COM1;}break;
			case 15:if(b_g3_dsp){SEG5;COM1;}break;
			
			default:break;
		}
	}
	
	if(PBIF)//检查PORTB变化中断
	{
		PBIF = 0; 
		
		
	}
}

const uint8_t seg_tab[]={0x3F,0x6,0x5B,0x4F,0x66,0x6D,0x7D,0x7,0x7F,0x6F};

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

/**
  * @brief  tc0定时器初始化函数
  *
  * @note   TC0 无重装载功能，要改变周期需要在中断里手动改变 TC0L的值
  * @note   - 本示例使用Fpcu的4分频作为TC0时钟，也就是TC0时钟为1Mhz
  *           
  * @retval None
  */
void tc0_tim_init(void)
{
	TC0M = 0x60;	
					//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作为时钟;
					
	
	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= 0b000000000;//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 = 0b00000001;	//--00 0001 :PORTB输入输出配置寄存器 (0-OUT;1-IN)
	WUCON = 0b00000000;	//--00 0000	:PORTB变化中断唤醒寄存器 (1-EN;0=DIS)
	ODCON = 0b00000000;	//--00 0000 :PORTB开漏寄存器 (1-EN;0-DIS)
	PHCON = 0b11111110;	//--11 1110 :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
	//----------------------------------------------------------------------
}


//****************************************************  
//清除所有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--);    
} 