/******************************************************************************
;  *   	@型号				  : MC32P8141
;  *   	@创建日期             : 2021.08.04
;  *   	@公司/作者			  : SINOMCU-FAE
;  *   	@晟矽微技术支持       : 2048615934
;  *   	@晟矽微官网           : http://www.sinomcu.com/
;  *   	@版权                 : 2021 SINOMCU公司版权所有.
;  *----------------------摘要描述---------------------------------
;  *   	   	   	             ADC
                     AN0(P17)：电压不同对应P00-P03输出
                     AN1(P16)：电压不同对应P10-P13输出
    使能 ADC 模块后需延迟 500ms 以上，切换参考电压需延迟 200us 以上，
   	   	   	   	   	   待电路稳定后才能启动 AD 转换；
        切换输入通道后，受外部输入影响，前两次转换的结果会有误差，建议舍弃；
   	AD校准后不要关闭AD校准位OSADJEN，此位不影响休眠功耗，ADEN影响休眠功耗
    	如果关闭AD校准位OSADJEN，需要重新再次校准
******************************************************************************/

#include "user.h"

/************************************************
;  *    @Function Name       : delay
;  *    @Description         :  
;  *    @IN_Parameter        :
;  *    @Return parameter    :
;  ***********************************************/
void delay(uint16_t num)
{
    for(cnt=0;cnt<num;cnt++)
    {
        Nop();
   	   	Nop();
   	   	Nop();
   	   	Nop();
   	   	Nop();
   	   	Nop();
   	   	Nop();
   	   	Nop();
   	   	Nop();
   	   	Nop();
    }
}
/************************************************
;  *    @Function Name       : CLR_RAM
;  *    @Description         :  
;  *    @IN_Parameter        :
;  *    @Return parameter    :
;  ***********************************************/
void CLR_RAM(void)
{
__asm
    movai 0x7F 
    movra FSR0
    clrr INDF0
    DJZR FSR0 
    goto $-2 
    clrr INDF0
__endasm;
}
/************************************************
;  *    @Function Name       : IO_Config
;  *    @Description         : io口初始化
;  *    @IN_Parameter      	 : 
;  *    @Return parameter    :
;  ***********************************************/
void IO_Init(void)
{
    IOP0 = 0x00; //io口数据位
    OEP0 = 0xff; //io口方向 1:out  0:in
    PUP0 = 0x00; //io口上拉电阻   1:enable  0:disable
    PDP0 = 0x00; //io口下拉电阻   1:enable  0:disable

    IOP1 = 0x00; //io口数据位
    OEP1 = 0x3f; //io口方向 1:out  0:in     P17、P16 in
    PUP1 = 0x00; //io口上拉电阻   1:enable  0:disable
    PDP1 = 0x00; //io口下拉电阻   1:enable  0:disable

    P0ADCR = 0x00; //端口数模控制   1:模拟  0:数字
    P1ADCR = 0xC0; //端口数模控制   1:模拟  0:数字  P17、16模拟
}
/************************************************
;  *    @Function Name       : ADC_Init
;  *    @Description         : ADC初始化
;  *    @IN_Parameter      	 : 
;  *    @Return parameter    :
;  ***********************************************/
void ADC_Init(void)
{
    ADCR0 = 0xf0; //使能ADC、256分频
    ADCR1 = 0x30; //12位数据H8L4、内部2V、15ADCLK
   	delay(65000);
   	delay(65000);
   	delay(65000);  //开启AD后延时500ms以上
}
/************************************************
;  *    @Function Name       : ADC_Zero_ADJ
;  *    @Description         : ADC零点校准
;  *    @IN_Parameter      	 : 
;  *    @Return parameter    : 0 校准成功  1校准失败
;  ***********************************************/
uint8_t ADC_Zero_ADJ(void)
{
    //零点校准
    ADCR0 = 0xff;   //使能ADC、256分频、GND通道
    ADCR1 = 0x30;   //12位数据H8L4、内部2V、15ADCLK
    OSADJCR = 0x80; //使能零点校准、负向修调
   	delay(65000);
   	delay(65000);
   	delay(65000);  //开启AD后延时500ms以上
    ADEOC = 0;
    while (!ADEOC);
    if ((ADRH == 0) && ((ADRL & 0x0F) == 0)) //结果是否为0
    {
        OSADJTD = 1; //正向修调
        OSADJCR |= 0x0F;
        ADEOC = 0;
        while (!ADEOC);
        if ((ADRH == 0) && ((ADRL & 0x0F) == 0)) //结果是否为0
        {
            //OSADJEN = 0; //关闭校准
            ADEN = 0;
            return PASS;
        }
        else
        {
            while (1)
            {
                if (OSADJCR & 0x0f)
                {
                    OSADJCR--;
                    ADEOC = 0;
                    while (!ADEOC);
                    if ((ADRH == 0) && ((ADRL & 0x0F) == 0)) //结果是否为0
                    {
                        //OSADJEN = 0; //关闭校准
                        ADEN = 0;
                        return PASS;
                    }
                }
                else
                {
                    //OSADJEN = 0; //关闭校准
                    ADEN = 0;
                    return FAIL;
                }
            }
        }
    }
    else
    {
        while (1)
        {
            if ((OSADJCR & 0x0f) == 0x0f)
            {
                //OSADJEN = 0; //关闭校准
                ADEN = 0;
                return FAIL;
            }
            else
            {
                OSADJCR++;
                ADEOC = 0;
                while (!ADEOC);
                if ((ADRH == 0) && ((ADRL & 0x0F) == 0)) //结果是否为0
                {
                    //OSADJEN = 0; //关闭校准
                    ADEN = 0;
                    return PASS;
                }
            }
        }
    }
}
/************************************************
;  *    @Function Name       : ADC_Get_Value_Average
;  *    @Description         : 连续转换
;  *    @IN_Parameter      	 : 通道
;  *    @Return parameter    : 返回ADC的值
   	   	  函数占用内存较大（180+字节），
;  ***********************************************/
uint ADC_Get_Value_Average(u8 CHX)
{
    temp_value = 0;
    channel = 0;
    tmpbuff = 0;
    ADCMAX = 0;
    ADCMIN = 0xffff;
    ADCR0 = (ADCR0 & 0xf0) | CHX; // ADC 使能  AD转换通道开启  通道  CHX
   	delay(80); 	   	//切换通道延时200uS以上
    for (channel = 0; channel < 20; channel++)
    {
        ADEOC = 0;
        while (!ADEOC); //等待转换完成
        temp_value = ADRH;
        temp_value = temp_value << 4 | (ADRL & 0x0f);
        if (channel < 2)
            continue; //丢弃前两次采样的
        if (temp_value > ADCMAX)
            ADCMAX = temp_value; //最大
        if (temp_value < ADCMIN)
            ADCMIN = temp_value; //最小
        tmpbuff += temp_value;
    }
    tmpbuff -= ADCMAX;           //去掉一个最大
    tmpbuff -= ADCMIN;           //去掉一个最小
    temp_value = (tmpbuff >> 4); //除以16，取平均值
    return temp_value;
}
/************************************************
;  *    @Function Name       : Sys_Init
;  *    @Description         : 系统初始化
;  *    @IN_Parameter      	 : 
;  *    @Return parameter    :
;  ***********************************************/
void Sys_Init(void)
{
    GIE = 0;
    CLR_RAM();
    IO_Init();
    while (ADC_Zero_ADJ()); //demo演示,校准失败一直校准
    ADC_Init();
    GIE = 1;
}
void main(void)
{
    Sys_Init();
    while (1)
    {
        temp_value1 = ADC_Get_Value_Average(0);
        if (temp_value1 > 2048 + 1024) //>1.5V
        {
            P00D = 1;
            P01D = 0;
            P02D = 0;
            P03D = 0;
        }
        else if (temp_value1 > 2048) //>1V
        {
            P00D = 0;
            P01D = 1;
            P02D = 0;
            P03D = 0;
        }
        else if (temp_value1 > 1024) //>0.5V
        {
            P00D = 0;
            P01D = 0;
            P02D = 1;
            P03D = 0;
        }
        else //<0.5V
        {
            P00D = 0;
            P01D = 0;
            P02D = 0;
            P03D = 1;
        }
        temp_value1 = ADC_Get_Value_Average(1);
        if (temp_value1 > 2048 + 1024) //>1.5V
        {
            P10D = 1;
            P11D = 0;
            P12D = 0;
            P13D = 0;
        }
        else if (temp_value1 > 2048) //>1V
        {
            P10D = 0;
            P11D = 1;
            P12D = 0;
            P13D = 0;
        }
        else if (temp_value1 > 1024) //>0.5V
        {
            P10D = 0;
            P11D = 0;
            P12D = 1;
            P13D = 0;
        }
        else //<0.5V
        {
            P10D = 0;
            P11D = 0;
            P12D = 0;
            P13D = 1;
        }
    }
}

void int_isr(void) __interrupt
{
__asm 
    movra _abuf
    swapar _PFLAG
    movra _statusbuf
__endasm;



__asm 
    swapar _statusbuf
    movra _PFLAG
    swapr _abuf
    swapar _abuf
__endasm;
}
