首先先看一下STC32G系列单片机内部的ADC功能
STC32G系列的单片机有15条ADC测量通道,同时ADC_VRef+为外部电压参考电源,所以利用ADC测量电源电压有两种方案。第一是先利用稳压电源将ADC_VRef+的电压稳定在特定值,然后电源线可直接接到ADC的前14个通道,然后利用公式就可以得到电源电压。第二种方法就是利用ADC第15条通道,ADC_VRef+直接接到电源电压,通过内部参考电源1.19V,用公式计算可得电源电压。接下来我们会着重介绍第二种方法。
我们接下来看一下库函数:
#include "STC32G_ADC.h"
//========================================================================
// 函数: u8 ADC_Inilize(ADC_InitTypeDef *ADCx)
// 描述: ADC初始化程序.
// 参数: ADCx: 结构参数,请参考adc.h里的定义.
// 返回: none.
// 版本: V1.0, 2012-10-22
//========================================================================
u8 ADC_Inilize(ADC_InitTypeDef *ADCx)
{
ADCCFG = (ADCCFG & ~ADC_SPEED_2X16T) | ADCx->ADC_Speed; //设置ADC工作时钟频率
ADC_Justify(ADCx->ADC_AdjResult); //AD转换结果对齐方式
if(ADCx->ADC_SMPduty > 31) return FAIL; //错误
if(ADCx->ADC_CsSetup > 1) return FAIL; //错误
if(ADCx->ADC_CsHold > 3) return FAIL; //错误
ADCTIM = (ADCx->ADC_CsSetup << 7) | (ADCx->ADC_CsHold << 5) | ADCx->ADC_SMPduty ; //设置 ADC 内部时序,ADC采样时间建议设最大值
return SUCCESS;
}
//========================================================================
// 函数: void ADC_PowerControl(u8 pwr)
// 描述: ADC电源控制程序.
// 参数: pwr: 电源控制,ENABLE或DISABLE.
// 返回: none.
// 版本: V1.0, 2012-10-22
//========================================================================
void ADC_PowerControl(u8 pwr)
{
if(pwr == ENABLE) ADC_POWER = 1;
else ADC_POWER = 0;
}
//========================================================================
// 函数: u16 Get_ADCResult(u8 channel)
// 描述: 查询法读一次ADC转换结果.
// 参数: channel: 选择要转换的ADC通道.
// 返回: ADC转换结果.
// 版本: V1.0, 2012-10-22
//========================================================================
u16 Get_ADCResult(u8 channel) //channel = 0~15
{
u16 adc;
u8 i;
if(channel > ADC_CH15) return 4096; //错误,返回4096,调用的程序判断
ADC_RES = 0;
ADC_RESL = 0;
ADC_CONTR = (ADC_CONTR & 0xf0) | channel; //设置ADC转换通道
ADC_START = 1;//启动ADC转换
NOP(10); //对ADC_CONTR操作后要4T之后才能访问
for(i=0; i<250; i++) //超时返回,正常i等于10以内就可以转换完成
{
if(ADC_FLAG)
{
ADC_FLAG = 0; //清除ADC转换结束标志
if(RESFMT) //转换结果右对齐。
{
adc = ((u16)ADC_RES << 8) | ADC_RESL;
}
else //转换结果左对齐。
{
adc = (u16)ADC_RES;
adc = (adc << 4) | ((ADC_RESL >> 4) & 0x0f);
}
return adc;
}
}
return 4096; //错误,返回4096,调用的程序判断
}
首先利用ADC_Inilize()函数进行初始化,ADC_PowerControl()使能ADC,Get_ADCResult()可得到1~15通道的ADC换算值。
void Power_init(void)
{
ADC_InitTypeDef ADC15;
ADC15.ADC_SMPduty=15;
ADC15.ADC_Speed=ADC_SPEED_2X16T;
ADC15.ADC_AdjResult=ADC_LEFT_JUSTIFIED;
ADC_Inilize(&ADC15);
ADC_PowerControl(ENABLE);
}
void Get_power(void)
{
u16 res;
u16 vcc;
u8 i;
res=0;
for(i=0;i<8;i++)res+=Get_ADCResult(ADC_CH15);
res>>=3;
vcc=(u16)(4096L*BGV/res);
POWER_PRECENT=(vcc-2700)/15;
}
这里有一点需要注意的是,我们在初始化后需要先获取内部参考电压BGV
在得到15通道的测量值后利用公式就可得到电压值。