crystal 发表于 2024-1-17 14:27:04

通过MCU内部1.19V参考电压,计算ADC_VRef引脚电压,即VCC电压;选用ADC查询方式;

适用范围:STC8H系类(ADC10位与12位可选)

测试MCU型号:STC8H1K08(ADC10位)、STC8H3K48S4(ADC12位)
STC8H1K08:短路VCC与ADC_VRef;
STC8H3K48S4:短路VCC、AVcc、ADC_VRef;
方案:通过MCU内部1.19V参考电压,计算ADC_VRef引脚电压,即VCC电压;选用ADC查询方式;

初始化入口:Init_ADC()
读取VCC电压:ADC_GetVcc()


#include "ADC.h"
#include "intrins.h"
/*******************************************************************************/
uint xdata nADC_Buff;
/*******************************************************************************/
/*****************************************************/
/* 功能:ADC初始化
/*****************************************************/
void Init_ADC()
{
    P_SW2 |= 0x80;
    ADCTIM = 0x3f;                              //设置ADC内部时序
    P_SW2 &= 0x7f;

    ADCCFG = 0x2f;                              //设置ADC时钟为系统时钟/2/16
    ADC_CONTR = 0x8f;                           //使能ADC模块,并选择第15通道
}
/*****************************************************/
/* 功能:读入AD值
/*****************************************************/
uint ADC_Read()
{
    uint res;

    ADC_CONTR |= 0x40;                        //启动AD转换
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    while( !( ADC_CONTR & 0x20 ) );             //查询ADC完成标志
    ADC_CONTR &= ~0x20;                         //清完成标志
    res = ( ADC_RES << 8 ) | ADC_RESL;          //读取ADC结果

    return res;
}

/****************************************************************/
/* 功能: 排序平均滤波,获取Vcc
/* 输入:最新一个AD值
/* 返回:滤波后的值(Vcc)
/****************************************************************/
uint ADC_GetVcc()
{
    uchar i, j;
    ulong res = 0;
    uint k, Vcc = 0;
    uint *BGV;      //内部1.19V参考信号源值存放在idata中
    //idata的EFH地址存放高字节
    //idata的F0H地址存放低字节
    //电压单位为毫伏(mV)

    BGV = ( uint idata * )0xef;

    for( i = 0; i < 8; i++ )
    {
      nADC_Buff = ADC_Read();    //读取8次数据
    }

    /* 排序(从小到大排列) */
    for( j = 0; j < 8; j++ ) {
      for( i = 0; i < 8 - j; i++ ) {
            if( nADC_Buff[ i ] > nADC_Buff[ i + 1 ] ) {
                k = nADC_Buff[ i ];
                nADC_Buff[ i ] = nADC_Buff[ i + 1 ];
                nADC_Buff[ i + 1 ] = k;
            }
      }
    }
    /* 求平均 */
    res = 0;
    for( i = 3; i < 5; i++ ) {
      res += nADC_Buff[ i ];
    }

    res += 1;                                                     // 四舍五入
    res >>= 1;                                                   // 求平均

    Vcc = ( uint )( 1024L * *BGV / res );      //(10位ADC算法)计算VREF管脚电压,即VCC电压
//Vcc = (uint)(4096L * *BGV / res);            //(12位ADC算法)计算VREF管脚电压,即VCC电压

    //注意,此电压的单位为毫伏(mV)
    return Vcc;
}




Snapdragon 发表于 2024-1-20 09:29:18

{:lol:}我现在都是整个TL431放上去,价格不贵,买了好多。DIY够用好久的了。

xxkj2010 发表于 2024-1-20 09:43:18

Snapdragon 发表于 2024-1-20 09:29
我现在都是整个TL431放上去,价格不贵,买了好多。DIY够用好久的了。
包括给MCU供电?

Snapdragon 发表于 2024-1-20 11:08:41

xxkj2010 发表于 2024-1-20 09:43
包括给MCU供电?

肯定不是啊,TL431专门给VREF供电。
页: [1]
查看完整版本: 通过MCU内部1.19V参考电压,计算ADC_VRef引脚电压,即VCC电压;选用ADC查询方式;