大明狐 发表于 2025-5-12 18:04:40

梁工 发表于 2025-5-12 15:47
ADC结果是12位的,并且ADC结果也是对的,就是电压不对,很奇怪的。

“地板”楼的代码里,本该用12位的4096反推的算式被注释掉了,用的10位的1024反推的,所以结果正好变成了四分之一
3.288变成了0.822

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

topofhill 发表于 2025-5-12 18:18:09

我手边有8h4k64tl   刚跑了你的程序依然是
接收←ADC15=1482,AVREF=0.822V
                  
接收←ADC15=1481,AVREF=0.823V

但跑例程他们的结果不一样。

8h4k64tlhex模式输出0337
8h8k64u   hex模式输出0000

例程是这个
#include "reg51.h"
#include "intrins.h"

#define FOSC            11059200UL
#define BRT             (65536 - FOSC / 115200 / 4)

sfr   AUXR      =   0x8e;

sfr   ADC_CONTR   =   0xbc;
sfr   ADC_RES   =   0xbd;
sfr   ADC_RESL    =   0xbe;
sfr   ADCCFG      =   0xde;

sfr   P_SW2   =   0xba;
#define ADCTIM(*(unsigned char volatile xdata *)0xfea8)

sfr   P0M1    =   0x93;
sfr   P0M0    =   0x94;
sfr   P1M1    =   0x91;
sfr   P1M0    =   0x92;
sfr   P2M1    =   0x95;
sfr   P2M0    =   0x96;
sfr   P3M1    =   0xb1;
sfr   P3M0    =   0xb2;
sfr   P4M1    =   0xb3;
sfr   P4M0    =   0xb4;
sfr   P5M1    =   0xc9;
sfr   P5M0    =   0xca;

int *BGV;                                       //内部1.19V参考信号源值存放在idata中
                                                //idata的EFH地址存放高字节
                                                //idata的F0H地址存放低字节
                                                //电压单位为毫伏(mV)
bit busy;

void UartIsr() interrupt 4
{
    if (TI)
    {
      TI = 0;
      busy = 0;
    }
    if (RI)
    {
      RI = 0;
    }
}

void UartInit()
{
    SCON = 0x50;
    TMOD = 0x00;
    TL1 = BRT;
    TH1 = BRT >> 8;
    TR1 = 1;
    AUXR = 0x40;
    busy = 0;
}

void UartSend(char dat)
{
    while (busy);
    busy = 1;
    SBUF = dat;
}

void ADCInit()
{
    P_SW2 |= 0x80;
    ADCTIM = 0x3f;                              //设置ADC内部时序
    P_SW2 &= 0x7f;

    ADCCFG = 0x2f;                              //设置ADC时钟为系统时钟/2/16
    ADC_CONTR = 0x8f;                           //使能ADC模块,并选择第15通道
}

int ADCRead()
{
    int res;

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

    return res;
}

void main()
{
    int res;
    int vcc;
    int i;

    P0M0 = 0x00;
    P0M1 = 0x00;
    P1M0 = 0x00;
    P1M1 = 0x00;
    P2M0 = 0x00;
    P2M1 = 0x00;
    P3M0 = 0x00;
    P3M1 = 0x00;
    P4M0 = 0x00;
    P4M1 = 0x00;
    P5M0 = 0x00;
    P5M1 = 0x00;

    BGV = (int idata *)0xef;
    ADCInit();                                  //ADC初始化
    UartInit();                                 //串口初始化

    ES = 1;
    EA = 1;

//ADCRead();
//ADCRead();                                  //前两个数据建议丢弃

   

    while (1){
          res = 0;
    for (i=0; i<8; i++)
    {
      res += ADCRead();                     //读取8次数据
    }
    res >>= 3;                                  //取平均值

    vcc = (int)(1024L * *BGV / res);            //(10位ADC算法)计算VREF管脚电压,即电池电压
//vcc = (int)(4096L * *BGV / res);            //(12位ADC算法)计算VREF管脚电压,即电池电压
                                                //注意,此电压的单位为毫伏(mV)
    UartSend(vcc >> 8);                         //输出电压值到串口
    UartSend(vcc);
       
       
        };
}

vb2002 发表于 2025-5-16 17:40:18

这个我刚刚弄好的. 读出外部电压.
//        u16ADC_Read( u8 no )
//        {
//        static u16 new_value;
//        adc_val = new_value;
////                u16 adcval;                                                                //adc数值保存变量
//                ADC_CONTR &= 0xf0;                                                //清空通道
//                ADC_CONTR = (ADC_CONTR & 0xF0) | 0x40 | no;
////                ADC_CONTR |= no;                                                //选择通道
//                ADC_CONTR |=0x40;                                         //ADC_START = 1; //开启ADC转化
//                _nop_();                                                                //空操作指令
//                _nop_();                       
//                while((ADC_CONTR & 0x20) == 0);   //等待ADC结束
//                ADC_CONTR &= ~ 0x20;                //ADC_FLAG = 0;               
//                adc_val = (ADC_RES << 8)+ ADC_RESL;        //计算adc的数值
//
//        if((new_value - adc_val > 500)||(adc_val - new_value > 500)) return adc_val;//跳变大于0.3V放弃本次采样值
//        else return new_value;
//        }
adc_dianya = (int)(4096L * 1194 / res);       
页: 1 [2]
查看完整版本: 8H8K64U-TSSOP20, ADC15通道内部固定接1.19V信号源,反推VCC电池电压