//*********************************************************************** 
//Copyright (c) 2024   HuaXin Micro-electronics Co.,Ltd 
//
//HS16P2811 
//ADC
//configuration introduction
//使用PA0，AIN0通道采样ADC，2V基准
//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 int ADC_Data; 

unsigned char ADC_PIN_Mode = 0;
unsigned char ADC_CLK_Mode = 0;
unsigned char ADC_VREF_Mode = 0;
 

bit ADC_Flag = 0;

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		128
/**
 * @ 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:	ADC_ANSEL_PIN()
 * @ param:	null
 * @ retval:null
 */
void ADC_ANSEL_PIN(unsigned char ansel)
{
	// TRISA = 0;
	// TRISC = 0;
	
	switch(ansel)
	{
		case ANSEL15_GND:
		case ANSEL12_qVDD:
		default: break;
		
		case ANSEL14_PA7:	TRISA |= (1<<7); PAHCON |= (1<<7); PADCON |= (1<<7); ADPCON1 |= (1<<5);	break;
		case ANSEL13_PA6:	TRISA |= (1<<6); PAHCON |= (1<<6); PADCON |= (1<<6); ADPCON1 |= (1<<4);	break;

		case ANSEL11_PA5:	TRISA |= (1<<5); PAHCON |= (1<<5); PADCON |= (1<<5); ADPCON1 |= (1<<3);	break;
		case ANSEL10_PA4:	TRISA |= (1<<4); PAHCON |= (1<<4); PADCON |= (1<<4); ADPCON1 |= (1<<2);	break;
		case ANSEL9_PC5: 	TRISC |= (1<<5); PCHCON |= (1<<5); PCDCON |= (1<<5); ADPCON1 |= (1<<1);	break;
		case ANSEL8_PC4: 	TRISC |= (1<<4); PCHCON |= (1<<4); PCDCON |= (1<<4); ADPCON1 |= (1<<0);	break;

		case ANSEL7_PC3: 	TRISC |= (1<<3); PCHCON |= (1<<3); PCDCON |= (1<<3); ADPCON |= (1<<7);	break;
		case ANSEL6_PC2: 	TRISC |= (1<<2); PCHCON |= (1<<2); PCDCON |= (1<<2); ADPCON |= (1<<6);	break;
		case ANSEL5_PC1: 	TRISC |= (1<<1); PCHCON |= (1<<1); PCDCON |= (1<<1); ADPCON |= (1<<5);	break;
		case ANSEL4_PC0: 	TRISC |= (1<<0); PCHCON |= (1<<0); PCDCON |= (1<<0); ADPCON |= (1<<4);	break;

 		case ANSEL3_PA3: 	TRISA |= (1<<3); PAHCON |= (1<<3); PADCON |= (1<<3); ADPCON |= (1<<3);	break;
 		case ANSEL2_PA2: 	TRISA |= (1<<2); PAHCON |= (1<<2); PADCON |= (1<<2); ADPCON |= (1<<2);	break;
		case ANSEL1_PA1: 	TRISA |= (1<<1); PAHCON |= (1<<1); PADCON |= (1<<1); ADPCON |= (1<<1);	break;
		case ANSEL0_PA0:	TRISA |= (1<<0); PAHCON |= (1<<0); PADCON |= (1<<0); ADPCON |= (1<<0);	break;
	}
}


unsigned char adc_last_chx;
/**
 * @ brief:	ADC_Get()
 * @ param:	adch-AIN; vrefh-基准电压；ck-采样时钟
 * @ retval:AD采样值
 */
 //0;0;2
unsigned int adc_polling(unsigned char adch, unsigned char vrefh, unsigned char adc_div)
{
	unsigned int adcDat=0;
	
	ADR = adc_div;
	
	if(adch < 8)//设置对应的通道为模拟脚
	{
		ADPCON |= (1<<adch);
	}
	else if(adch <= 14)
	{
		ADPCON1 |= (1<<(adch-8));
	}
	
	ADT = 0x1B;  //AD结果微调
	VREFH = vrefh;//设置参考电压
	
	if((adc_last_chx != adch) || (FADENB==0))//ad切换通道，或者ad没使能第一个采样数据丢掉
	{
		ADM = (0x90|adch);
		ADS = 1;
		while(!EOC){
			adcDat++;
			if(adcDat>=600)
				break;
		}
		adc_last_chx = adch;
	}
	ADM = (0x90|adch);
	ADS = 1;
	while(!EOC){
		adcDat++;
		if(adcDat>=600)
			break;
	}
	
	adcDat = ADB;
	adcDat <<= 4;
	adcDat += (ADR & 0x0f);
	
	return adcDat;
}


/**
 * @ brief:	main
 * @ param:	null
 * @ retval:null
 * @ note:Fcpu=16M2T=8M;Ft1=Fcpu4T=2M
 */
void main(void) 
{
	System_Init();
	GPIO_Init();
	CLR_RAM_EveryBank();
	
	T1_Frq_Fcpu(iT1_4_rate,iT1_val);	//64us-int
	
	adc_last_chx = 0xFF;
	
	while(1) 
	{ 
		CLRWDT();  
		//PORTA = PORTA^0xff;	
		PORTA ^= (1<<2);		
		//DelayUs(1);
		//if(ADC_Flag)
		{
			ADC_Flag = 0;
			
			//PORTA = PORTA^0x03;
			ADC_Data = adc_polling(ADC_PIN_Mode, ADC_VREF_Mode, ADC_CLK_Mode);
			//PORTA = PORTA^0x03;
			_send_data_uart(0x55);
			_send_data_uart(0xAA);
			_send_data_uart(ADC_Data/256);
			_send_data_uart(ADC_Data%256);
		}
	} 
} 

/*****************************************************    
;UART-调试函数        
;TX_Dat 发送数据寄存器         
;TX_Cnt	8位数据         
;起始位：0      
;数据位：LSB->MSB      
;结束位：1      
//***************************************************/ 
#define		TX_PIN		FPA7
#define		I_TX_DELAY	22//16M2T-delay26us
#define		I_TX_DELAY	48//16M2T-delay26us
//****************************************************    
void _send_data_uart(unsigned char Uart_Data) 
{
	unsigned char TXD_Cnt; 
	unsigned char TXD_Dat; 
	
 	CLRWDT();
	TXD_Dat = Uart_Data; 

	FGIE = 0;
//start-bit 
	TX_PIN = 0; 
	DelayUs(I_TX_DELAY+1); 
 
//8bit-dat 
	for(TXD_Cnt = 8; TXD_Cnt > 0; TXD_Cnt--) 
	{ 
		if(TXD_Dat & 0x01)	TX_PIN = 1;	
		else 				TX_PIN = 0;
		
		DelayUs(I_TX_DELAY); 		 
		TXD_Dat = TXD_Dat >> 1; 
	} 
 
//stop-bit 
	TX_PIN = 1;	 
	DelayUs(I_TX_DELAY); 
	DelayUs(I_TX_DELAY); 
	FGIE = 1;
} 
//===================================================================

/**
 * @ 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 0	//adc
	if(ADCIF)
	{
		ADCIF = 0;
		ADC_Flag = 1;
	}
	#endif
	
	if(T1IF)
	{
		T1TH = (0xffff - iT1_val) / 256;	//初值high-8位
		T1TL = (0xffff - iT1_val) % 256;	//初值low-8位
		
		PORTA ^= (1<<1);
		T1_Timer_Cnt++;
		if(T1_Timer_Cnt > 5)
		{
			T1_Timer_Cnt = 0;
			PORTA ^= (1<<3);
		}
		T1IF = 0;
	}
	//----User Code end----/
}