/****************************************************************************************
 * KF8A系列单片机	KF8A100EON_DEMO	开发板演示程序
 * 标    题: 运算放大器实验
 * 项目名: 09- OP_Test
 * 开发环境：ChipON IDE
 * 版          本     ：V1.0 (2019/07/23)
 * 作 者: 上海芯旺微电子有限公司
 * 功能简述：测试运放功能，带校准
 * 硬件说明：通过与外部元件连接实现其放大等作用
 * 跳线接法：单片机供电选择为3.3V或5V
 ****************************************************************************************/
#include<KF8A100EON.h>


#define uchar unsigned char
#define uint  unsigned int
void Delay_200us()
{
	uchar i = 240;
	while(--i);
}
//;***************************************************************
//; 函  数 名：void Delay50Us()
//;功能函数：延时函数，50us
//;入口参数：无
//;返回参数：无
//;***************************************************************
void Delay50Us()
{
	char cnt ;
	cnt = 30;
	while(cnt--);
}
/*****************************************************
 * 函数名称：initFun()
 * 函数功能：运放校正使能
 * 输入：	无
 * 输出：	无
 *
 *
 ***************************************************** */
void	OP_fun()
{
	unsigned char val_AMPCALI,first_back_up,i,shift_data;
	INPS1 = 0;		//设置运放正向输入口 P2.3
	INPS0 = 1;
	AMPON =1;		//运放使能
	//延迟，给一个输出缓冲时间
	Delay50Us();
	AMPCALEN = 1;		//开启自校准
	//延迟，给一个输出缓冲时间
	Delay50Us();
	Delay50Us();
	Delay50Us();
	//读出AMPCTL中的第7位（CALID）放入AMPCALI中的最高位，用于正负失调判断，次高位置1，其它位设置为全0
	first_back_up = AMPCTL & 0x80;		//保存第一次的值，用于以后判断的标准
	val_AMPCALI = first_back_up;		//得到AMPCALI的第7位
	//bit6-bit2 采用二分法获得最佳值,方法是先把该位 置1，如果和第一次相比翻转了就把该位清0，进行下一位的判断，否则直接进行下一位的判断
	shift_data = 0B01000000;						//位置1或清0	，初始值为 bit6
	for(i = 0; i < 4; i++)							//计数，bit6-bit3 只需要循环4次
	{
		val_AMPCALI = val_AMPCALI | shift_data;		//位置1
		AMPDT = val_AMPCALI;
		//延迟，给一个输出缓冲时间
		Delay50Us();
		if(first_back_up != (AMPCTL & 0x80))		//和第一次相比，如果翻转,当前位清0，不翻转直接跳过
		{
			val_AMPCALI = val_AMPCALI ^ shift_data;	//清0
		}
		shift_data = shift_data >> 1;				//右移一位，进行下一位的置1准备
	}

	//bit2 bit1 bit0 采用累加方式确定临界值，这里只要翻转必定是临界值，校准直接完成
	for(i = 0; i < 8; i++)
	{
		//延迟，给一个输出缓冲时间
		AMPDT = val_AMPCALI;
		Delay50Us();
		Delay50Us();


		if(first_back_up != (AMPCTL & 0x80))		//和第一次相比，如果翻转,当前位清0，不翻转直接跳过
		{
			AMPCALEN = 0;								//关闭自校准使能，运放2可以进行采样，运放2已经使能，不需要重新打开
			return;
		}
		val_AMPCALI++;								//累加判断
	}
	AMPCALEN = 0;								        //关闭自校准使能，运放2可以进行采样，运放2已经使能，不需要重新打开
	return;

}



/*****************************************************
 * 函数名称：initFun()
 * 函数功能：IO口初始化
 * 输入：	无
 * 输出：	无
 *
 *
 ***************************************************** */
void initFun()
{
	OSCCTL = 0X70;
	TR0 = 0b00000100;
	TR1 = 0b00000000;
	TR2 = 0b00111100;
	TR3 = 0b00000000;

	P0LR = 0b00000000;
	P1LR = 0b00000100;
	P2LR = 0b00000000;
	P3LR = 0b00000000;

	ANSEL = 0b01111000;

}



void DelayMs (uint Num)
{
	uint	cnt;
	while(Num--)
	{
		cnt=2000;
		while(cnt--);
	}
}
//主函数
void main()
{

	initFun();
	DelayMs(50);
	OP_fun();
	while(1);
}
//中断函数0:0X04入口地址
void int_fun0() __interrupt (0)
{

}


//中断函数1:0x14入口地址
void int_fun1() __interrupt (1)
{

}
