#include "include.h"

void System_Int(void)
{
	Ram_Int();  	///RAM清零  
	
	Gpio_Int(); 	//IO初始化		
		
	////以下两种ADC-OFFSET方式二选一
	
	//方式1：使用内部GND通道，进行校准ADC-OFFSET
	Adc_Offset1();	

	//方式2：使用AN0通道，进行校准ADC-OFFSET，AN0通道需外接下拉电阻到GND
//	Adc_Offset2();
	
	////若需要串口打印，则取消注释
	Uart_Int(); 	///UART初始化 用于发送采集值

	////若需要采集OPOUT，则取消注释
//	OP_Int();  		///  OP使能	
}

void Gpio_Int(void)
{
	////数字/模拟模式：   1：数字    0：模拟
	ANSELA = 0x00;
	ANSELB = 0x00;
	ANSELC = 0x00;
	
	////输入/输出模式：   1：输出    0：输入
	TRISA = 0x00;
	TRISB = 0x00;
	TRISC = 0x00;
	
	////IO数据寄存器：   1：高电平    0：低电平
	PORTA = 0x00;
	PORTB = 0x00;
	PORTC = 0x00;
	
	////输入上拉控制：   1：使能上拉   0：关闭上拉
	WPUA = 0x00;
	WPUB = 0x00;
	WPUC = 0x00;
	
	////输入下拉控制：   1：使能下拉   0：关闭下拉
	WPDA = 0x00;
	WPDB = 0x00;
	WPDC = 0x00;
	
	////GPIO唤醒控制：   1：使能唤醒   0：关闭唤醒
	IOCA = 0x00;
	IOCB = 0x00;
	IOCC = 0x00;	
}

void Adc_Ch_Choose_Int(unsigned char Adc_Ch)
{
	switch(Adc_Ch)
	{
		case ADC_CH_AN0:
			ANSELA0 = 0;
			TRISA0 = 0;
		break;	
		case ADC_CH_AN1:
			ANSELA1 = 0;
			TRISA1 = 0;
		break;
		case ADC_CH_AN2:
			ANSELA2 = 0;
			TRISA2 = 0;
		break;
		case ADC_CH_AN3:
			ANSELA3 = 0;
			TRISA3 = 0;
		break;
		case ADC_CH_AN4:
			ANSELA4 = 0;
			TRISA4 = 0;
		break;
		case ADC_CH_AN5:
			ANSELA5 = 0;
			TRISA5 = 0;
		break;
		case ADC_CH_AN6:
			ANSELA6 = 0;
			TRISA6 = 0;
		break;
		case ADC_CH_1_4VDD:
			asm("nop");
			asm("nop");
		break;
		case ADC_CH_AN8:
			ANSELB0 = 0;
			TRISB0 = 0;
		break;
		case ADC_CH_AN9:
			ANSELB1 = 0;
			TRISB1 = 0;
		break;
		case ADC_CH_AN10:
			ANSELB2 = 0;
			TRISB2 = 0;
		break;
		case ADC_CH_AN11:
			ANSELB3 = 0;
			TRISB3 = 0;
		break;
		case ADC_CH_AN12:
			ANSELB4 = 0;
			TRISB4 = 0;
		break;
		case ADC_CH_AN13:
			ANSELB5 = 0;
			TRISB5 = 0;
		break;
		case ADC_CH_AN14:
			ANSELB6 = 0;
			TRISB6 = 0;
		break;
		case ADC_CH_AN15:
			ANSELC0 = 0;
			TRISC0 = 0;
		break;
		case ADC_CH_AN16:
			ANSELC1 = 0;
			TRISC1 = 0;
		break;
		case ADC_CH_AN17:
			ANSELC2 = 0;
			TRISC2 = 0;
		break;
		case ADC_CH_AN18:
			ANSELC3 = 0;
			TRISC3 = 0;
		break;
		case ADC_CH_AN19:
			ANSELC4 = 0;
			TRISC4 = 0;
		break;
		case ADC_CH_AN20:
			ANSELC5 = 0;
			TRISC5 = 0;
		break;
		case ADC_CH_AN21:
			ANSELC6 = 0;
			TRISC6 = 0;
		break;
		case ADC_CH_AN22:
			ANSELC7 = 0;
			TRISC7 = 0;
		break;
		case ADC_CH_OPO:
			asm("nop");
			asm("nop");
		break;
		case ADC_CH_GND:
			asm("nop");
			asm("nop");
		break;
		default:
		break;
	}	
}
void Get_ADC_Int(unsigned char Adc_Ch,unsigned char Adc_Vref,unsigned Adc_Fre)
{
	//ADC通道选择 0 - 24
	ADCON0  = 0x00;
	ADCON0 |= Adc_Ch << 2;
	Adc_Ch_Choose_Int(Adc_Ch);
	
	ADCON1  = 0x00;
	ADCON1 |= ((Adc_Fre << 4) | (Adc_Vref << 1));
	
	ADEN    = 1;
	Delay_Us(100);
	
}
unsigned short Get_Adc_Value()
{
	unsigned char i;
	unsigned short result,Data_Max,Data_Min,Data_Sum;
	
	result   = 0;
	Data_Max = 0;
	Data_Min = 4096;
	Data_Sum = 0;
	
	ADON = 1;
	while(ADON);
	asm("nop");

	ADON = 1;
	while(ADON);
	asm("nop");
	
	for(i = 0;i <= 5;i ++)
	{
		ADON   =  1;
		while(ADON);
		result = ADRESH;
		result = result << 8;
		result = result | ADRESL;
		result = result >> 4;
		
		if(result > Data_Max)
		{
			Data_Max = result;
		}
		if(result < Data_Min)
		{
			Data_Min = result;
		}
		Data_Sum += result;
		Data_Sum = Data_Sum;
	}
	
	return((Data_Sum - Data_Max - Data_Min) >> 2);
}

void Ram_Int(void)
{
	IRP = 0;
	FSR = 0x60;
	do{
		INDF = 0;
		FSR++;
	}while(FSR != 0x80);//BANK0 60H~7FH 地址清0
      
	FSR = 0xD0;
	do{
		INDF = 0;
		FSR++;
	}while(FSR != 0xF0);//BANK1 D0H~EFH 地址清0
	
	IRP = 1;
	FSR = 0x10;
	do{
		INDF = 0;
		FSR++;
	}while(FSR != 0x70);//BANK2 110H~16FH 地址清0
      
	FSR = 0x90;
	do{
		INDF = 0;
		FSR++;
	}while(FSR != 0xF0);//BANK3 190H~1EFH 地址清0

	IRP = 0;
}

void Delay_Us(unsigned int t)
{
 	while(--t);
}

void Uart_Int(void)
{
	ANSELC0   = 1;
	TRISC0    = 1;

	UART_MAP  = 0x22;   //TX PC0  RX PB5
	
	S1CON     = 0;
	
	BRTL      = 0xE6;
	BRTH      = 0xFF;  ///9600波特率   8M 2T  CPU 4M	
	S1CON2    = 0x20;
	
	TXIF = 0;
	UARTEN = 1;
}

void OP_Int(void)
{
	//OP+ 及 OPOUT 端口需配置模式输入模式
	ANSELC6 = 0;
	TRISC6 = 0;
	
	ANSELC4 = 0;
	TRISC4 = 0;
	
	OPASW2 = 0;		//若使用放大1倍，需配置 OPASW2 = 0 和 OPASW1 = 1
	OPASW1 = 1;		//若使用放大5倍、10倍、20倍需配置OPASW2 = 1;OPASW1 = 1;
	
	OPCMPSW = 1;	///OP模式
	OPOUTEN = 1;	///OP输出使能  PC4
	
	OPAOFM = 0;		//OP正常工作模式
	OPARSP = 0;    	

	///内部放大倍数  bit0-1  00  1倍   01  5倍  10  10倍  11 20倍
	///注意放大倍数以及电源电压
	OPA0C |= 0x00;
	
	OPCMP2EN = 1;	//使能OP
}

/*****************************ADC-OFFSET***************************************/	
////方式1：使用内部GND通道，校准完成后ADC-OFFSET补偿5个值（10LSB，每个值2LSB/STEP）
void Adc_Offset1(void)
{
	ADC_TIM_FLAG = 1;
	ADCON0 = 0x60;			//内部GND通道
	ADCON1 = 0x44;			//内部参考电压2.0V，ADC时钟源16分频
	ADCJMD= 0x20;
	ADEN = 1;
	Delay_Us(200);

	Gui_AdcValue = Get_Adc_Value();		
	if(Gui_AdcValue == 0)
	{		
		ADC_NEGATIVE_FLAG = 1;	//负偏
	}
	else
	{
		ADC_POSITIVE_FLAG = 1;	//正偏
	}

	while(ADC_TIM_FLAG)
	{
		if(ADC_NEGATIVE_FLAG == 1)	//负偏
		{
			ADCJMD = ADCJMD + 1;
			number++;	
			Gui_AdcValue = Get_Adc_Value();	
			if(Gui_AdcValue != 0)
			{									
				ADCJMD = ADCJMD - 1;	
				ADC_NEGATIVE_FLAG= 0;
				ADC_TIM_FLAG  = 0;				
			}
			if((ADCJMD == 0x3F)||(number == 31))
			{
				ADC_NEGATIVE_FLAG= 0;
				ADC_TIM_FLAG  = 0;
			}
		}
					
		if(ADC_POSITIVE_FLAG == 1)	//正偏
		{
			ADCJMD = ADCJMD - 1;
			number++;	
			Gui_AdcValue = Get_Adc_Value();	
			if((Gui_AdcValue == 0)||(ADCJMD == 0x00)||(number == 32))
			{						
				ADC_POSITIVE_FLAG = 0;
				ADC_TIM_FLAG  = 0;								
			}

		}
	}
	if(ADCJMD <= 58)
	{
		ADCJMD = ADCJMD + 5;
	}
	else
	{
		ADCJMD = 0x3F;
	}
}
//
////方式2：使用AN0通道，进行校准ADC-OFFSET
void Adc_Offset2(void)
{
	ADC_TIM_FLAG = 1;
	ADCON0 = 0x00;			//外部AN0通道
	ADCON1 = 0x44;			//内部参考电压2.0V，ADC时钟源16分频
	ADCJMD= 0x20;
	ADEN = 1;
	Delay_Us(200);

	Gui_AdcValue = Get_Adc_Value();		
	if(Gui_AdcValue == 0)
	{		
		ADC_NEGATIVE_FLAG = 1;	//负偏
	}
	else
	{
		ADC_POSITIVE_FLAG = 1;	//正偏
	}

	while(ADC_TIM_FLAG)
	{
		if(ADC_NEGATIVE_FLAG == 1)	//负偏
		{
			ADCJMD = ADCJMD + 1;
			number++;	
			Gui_AdcValue = Get_Adc_Value();	
			if(Gui_AdcValue != 0)
			{									
				ADCJMD = ADCJMD - 1;	
				ADC_NEGATIVE_FLAG = 0;
				ADC_TIM_FLAG  = 0;				
			}
			if((ADCJMD == 0x3F)||(number == 31))
			{
				ADC_NEGATIVE_FLAG = 0;
				ADC_TIM_FLAG  = 0;
			}
		}
					
		if(ADC_POSITIVE_FLAG == 1)	//正偏
		{
			ADCJMD = ADCJMD - 1;
			number++;	
			Gui_AdcValue = Get_Adc_Value();	
			if((Gui_AdcValue == 0)||(ADCJMD == 0x00)||(number == 32))
			{						
				ADC_POSITIVE_FLAG = 0;
				ADC_TIM_FLAG  = 0;								
			}
		}

	}
}