278 lines
6.6 KiB
C
278 lines
6.6 KiB
C
/*
|
|
******************************************************************************
|
|
*
|
|
* @file adc.c
|
|
* @brief adc module
|
|
* @ic TP3102
|
|
*
|
|
* @version 1.0
|
|
* @date 2024/03/26 15:00:40
|
|
* @author Alex Xu
|
|
*
|
|
* Copyright (c) 2013-2099,Tkplusemi Technology Co.,Ltd.
|
|
* All Rights Reserved
|
|
*
|
|
* History:
|
|
* Revision Date Author Desc
|
|
* 1.0.0 2022/08/04 Alex build this file
|
|
******************************************************************************/
|
|
/*_____ I N C L U D E S ____________________________________________________*/
|
|
|
|
#include "adc.h"
|
|
#include "system.h"
|
|
#include "sys_tim.h"
|
|
|
|
#if ADC_ENABLE
|
|
|
|
/******************************************************************************\
|
|
Macro definitions
|
|
\******************************************************************************/
|
|
|
|
/******************************************************************************\
|
|
Variables definitions
|
|
\******************************************************************************/
|
|
|
|
idata uint16_t g_VREF_Value = 0; //IREF 系统上电时采集一次。
|
|
|
|
idata uint16_t Vbat_Adc = 0;
|
|
|
|
idata uint16_t VNTC_Adc = 0;
|
|
|
|
|
|
/******************************************************************************\
|
|
Functions definitions
|
|
\******************************************************************************/
|
|
|
|
|
|
/*
|
|
*******************************************************************************
|
|
* void Adc_Init(void)
|
|
*
|
|
* Description : ADC Initialization. --- 系统初始化调用。
|
|
*
|
|
* Arguments :
|
|
|
|
* Returns :
|
|
|
|
* Notes :
|
|
*
|
|
*******************************************************************************
|
|
*/
|
|
void Adc_Init(void)
|
|
{
|
|
#if ADC_CHN_ENABLE
|
|
|
|
SFRADDR = MFP_CTL1; //Set P07 Pinmux As AD4 Function
|
|
SFRDATA &= 0x3F;
|
|
SFRDATA |= 0x80;
|
|
|
|
SFRADDR = ADCCS_CTL0; //AD0~AD4 GPIO constant 20uA current source enable.
|
|
SFRDATA = 0x10;
|
|
|
|
#endif
|
|
|
|
//g_VREF_Value = Vref_AdcValue();
|
|
//g_VREF_Value = 311;
|
|
}
|
|
|
|
#if 1
|
|
/*
|
|
*******************************************************************************
|
|
* uint16_t Vref_AdcValue(void)
|
|
*
|
|
* Description : Vref Value.获取基准参考电压ADC值。系统上电采集一次。
|
|
*
|
|
* Arguments : NONE
|
|
|
|
* Returns : Iref Value (mA)
|
|
|
|
* Notes : NONE
|
|
*
|
|
*******************************************************************************
|
|
*/
|
|
|
|
uint16_t Vref_AdcValue(void)
|
|
{
|
|
uint8_t index = 0;
|
|
uint16_t n_Vref_Data = 0;
|
|
uint16_t n_ADC_Plus = 0;
|
|
|
|
SFRADDR = ADC_CTL0;
|
|
SFRDATA = 0x8B; //0x8B -- ADC EN; Single mode; ADC CLK divided by 24=460k
|
|
|
|
for( index=0; index<8; index++ )
|
|
{
|
|
ADC_CTL1 = 0x61; //Channel set and Start conversion
|
|
|
|
while(ADC_CTL1 & 0x01); //Wait for conversion complete
|
|
|
|
n_Vref_Data = ADC_DATL;
|
|
|
|
n_Vref_Data |= (uint16_t)(ADC_DATH << 8);
|
|
|
|
n_ADC_Plus += n_Vref_Data;
|
|
|
|
n_Vref_Data = 0;
|
|
}
|
|
|
|
n_Vref_Data = (n_ADC_Plus / 8);
|
|
|
|
return n_Vref_Data;
|
|
}
|
|
|
|
|
|
/*
|
|
*******************************************************************************
|
|
* uint16_t Vbat_Value(void)
|
|
*
|
|
* Description : Vbat Value.获取电池电压。
|
|
*
|
|
* Arguments : NONE
|
|
|
|
* Returns : Vbat Value (mV)
|
|
|
|
* Notes : NONE
|
|
*
|
|
*******************************************************************************
|
|
*/
|
|
uint16_t Vbat_Value(void)
|
|
{
|
|
uint8_t index = 0;
|
|
uint16_t n_Vbat_Data = 0;
|
|
uint16_t n_ADC_Plus = 0;
|
|
|
|
SFRADDR = ADC_CTL0;
|
|
SFRDATA = 0x8B; //0x8B--ADC EN; Single mode; ADC CLK divided by 24=460k
|
|
|
|
for( index=0; index<8; index++ )
|
|
{
|
|
ADC_CTL1 = 0x51; //Channel set and Start conversion
|
|
|
|
while(ADC_CTL1 & 0x01); //Wait for conversion complete
|
|
|
|
n_Vbat_Data = ADC_DATL;
|
|
|
|
n_Vbat_Data |= (uint16_t)(ADC_DATH << 8);
|
|
|
|
n_ADC_Plus += n_Vbat_Data;
|
|
#ifdef _DEBUG_ADC
|
|
printf("Vbat:%d,plus:%d.\r\n",(uint16_t)n_Vbat_Data,(uint16_t)n_ADC_Plus);
|
|
#endif
|
|
n_Vbat_Data = 0;
|
|
}
|
|
|
|
n_Vbat_Data = ( n_ADC_Plus / 4 ); //Vbat采样值为二分压值。
|
|
#ifdef _DEBUG_ADC
|
|
printf("bat_Vbat1:%d.\r\n",(uint16_t)n_Vbat_Data);
|
|
#endif
|
|
|
|
g_VREF_Value = Vref_AdcValue(); //获取VREF
|
|
|
|
n_Vbat_Data = (uint32_t)(n_Vbat_Data) * VREF / g_VREF_Value; //Vadx = VREF*DATAadx/DATAvref
|
|
|
|
#ifdef _DEBUG_ADC
|
|
printf("bat,Vbat:%d,vref:%d.\r\n",(uint16_t)n_Vbat_Data, g_VREF_Value);
|
|
#endif
|
|
|
|
return n_Vbat_Data;
|
|
}
|
|
|
|
/*
|
|
*******************************************************************************
|
|
* uint16_t ADC_Chn_Value(ADC_CHANNELS_E adc_chn)
|
|
*
|
|
* Description : ADC_Chn_Value. ADC0 ~ ADC4。
|
|
|
|
* Arguments : NONE
|
|
|
|
* Returns : ADC Value (mV)
|
|
|
|
* Notes : NONE
|
|
*
|
|
*******************************************************************************
|
|
*/
|
|
#if ADC_CHN_ENABLE
|
|
|
|
uint16_t ADC_Chn_Value(ADC_CHANNELS_E adc_chn)
|
|
{
|
|
uint8_t index = 0;
|
|
uint16_t adc_data = 0;
|
|
uint16_t adc_plus_data = 0;
|
|
|
|
SFRADDR = ADC_CTL0;
|
|
SFRDATA = 0x8B; //0x8B--ADC EN; Single mode; ADC CLK divided by 24=460k
|
|
|
|
for(index=0; index<8; index++)
|
|
{
|
|
ADC_CTL1 = (adc_chn << 4) | 0x01; //Channel set and Start conversion
|
|
|
|
while(ADC_CTL1 & 0x01); //Wait for conversion complete
|
|
|
|
adc_data = ADC_DATL; //Read low byte first! Lock ADC Value.
|
|
|
|
adc_data |= (uint16_t)(ADC_DATH << 8);
|
|
|
|
adc_plus_data += adc_data;
|
|
#ifdef _DEBUG_ADC
|
|
printf("adc4:%d,plus:%d.\r\n",(uint16_t)adc_data,(uint16_t)adc_plus_data);
|
|
#endif
|
|
adc_data = 0;
|
|
}
|
|
|
|
adc_data = adc_plus_data / 8;
|
|
#ifdef _DEBUG_ADC
|
|
printf("adc_chn1:%d.\r\n",(uint16_t)adc_data);
|
|
#endif
|
|
g_VREF_Value = Vref_AdcValue(); //获取VREF
|
|
|
|
adc_plus_data = (uint32_t)(adc_data) * VREF / g_VREF_Value; //Vadx = VREF*DATAadx/DATAvref
|
|
|
|
#ifdef _DEBUG_ADC
|
|
printf("Adc,Vadc:%d,Vref:%d.\r\n", (uint16_t)adc_plus_data, (uint16_t)g_VREF_Value);
|
|
#endif
|
|
|
|
return adc_plus_data;
|
|
}
|
|
#endif
|
|
#else
|
|
|
|
void ADC_Value_Machine(void)
|
|
{
|
|
uint8_t i = 0;
|
|
uint8_t index = 0;
|
|
uint16_t adc_data[8] = 0;
|
|
|
|
SFRADDR = ADC_CTL0;
|
|
SFRDATA = 0x83; //0x83--ADC EN; Successive mode; ADC CLK divided by 24=460k
|
|
|
|
for(i=0; i<7; i++)
|
|
{
|
|
ADC_CTL1 = (i << 4); //Channel set
|
|
ADC_CTL1 |= 1; //Start conversion
|
|
|
|
for(index=0; index<8; index++)
|
|
{
|
|
while( !(IRQ_FLAG10 & 0x01) ); //Wait for conversion complete
|
|
IRQ_FLAG10 = 1; //Write 1 to clear
|
|
|
|
adc_data[i] = ADC_DATL; //Read low byte first!
|
|
|
|
adc_data[i] = adc_data[i] + (u16)(ADC_DATH << 8);
|
|
}
|
|
|
|
ADC_CTL1 &= 0xFE; //Stop conversion
|
|
IRQ_FLAG10 = 1; //Write 1 to clear--Clear possible flag before stop conversion!!!
|
|
}
|
|
|
|
g_VREF_Value = adc_data[6] / 8;
|
|
|
|
Vbat_Adc = (uint32_t)(adc_data[5] / 4) * VREF / g_VREF_Value; //Vadx = VREF*DATAadx/DATAvref
|
|
|
|
VNTC_Adc = (uint32_t)(adc_data[4] / 8) * VREF / g_VREF_Value; //Vadx = VREF*DATAadx/DATAvref;
|
|
|
|
}
|
|
#endif
|
|
|
|
#endif
|
|
|