找回密码
 立即注册
查看: 2056|回复: 19

利用ADC15在内部固定接的1.19V的辅助固定信号源,反推其他通道的输入电压

[复制链接]

该用户从未签到

550

主题

9235

回帖

1万

积分

管理员

积分
13946
发表于 2023-8-13 10:22:01 | 显示全部楼层 |阅读模式
利用ADC15固定在内部接的1.19V辅助固定信号源
反推 ADC_VREF+/ADC_AVCC/MCU_VCC,
反推 其他ADCx通道的外部输入电压,ADC0 ~ ADC14
采样转换二次,只需要计算一次
===1,假定ADC采样转换足够快
===2,假定2次ADC转换期间,ADC_VREF+/ADC_VCC/MCU_VCC不变,变的误差也可以接受
===3,应用场景,ADC_VREF+/ADC_AVCC/MCU_VCC 这3条重要的电源线直接接在一起

STC8H系列单片机内部集成了一个10位/12位高速A/D转换器。ADC的时钟频率为系统频率2分频再经过用户设置的分频系数进行
再次分频(ADC的工作时钟频率范围为SYSclk/2/1到SYSclk/2/16)。
STC8H系列的ADC最快速度:12ADC800K每秒进行80万次ADC转换10ADC500K每秒进行50万次ADC转换
ADC转换结果的数据格式有两种:左对齐和右对齐。可方便用户程序进行读取和引用。

注意:ADC的第15通道是专门测量内部1.19V参考信号源的通道,参考信号源值出厂时校准为1.19V,由于制造误差以及测量误差,
导致实际的内部参考信号源相比1.19V,大约有±1%的误差。如果用户需要知道每一颗芯片的准确内部参考信号源值,可外接精准
参考信号源,然后利用ADC的第15通道进行测量标定。ADC_VRef+脚外接参考电源时,可利用ADC的第15通道可以反推ADC_VRef+
外接参考电源的电压;如将ADC_VREF+短接到MCU-VCC,就可以反推MCU-VCC的电压。
如果芯片有ADC的外部参考电源管脚ADC_VRef+,则一定不能浮空,必须接外部参考电源或者直接连到VCC
=====================================================================
使用ADC的第15通道固定接的1.19V辅助信号源,反推外部通道输入电压,假设


当前已获取了内部参考信号源电压为BGV,从CHIP中读取,或STC-ISP烧录时指定将重要参数烧录入程序Flash
内部参考信号源的ADC15测量值为resbg,对ADC15/1.19V采样转换一次就知到转换后的值
外部通道输入电压的ADCx测量值为resx,  
对ADCx的外部输入信号采样转换一次就知到转换后的值

则外部通道输入电压VxBGV / resbg * resx
采样转换二次,只需要计算一次
注意,是假定2次采样转换期间 【ADC_VREF+ = ADC_VCC = MCU_VCC】不变
===所以对外部采样转换一次,也要对内部ADC15接的信号源立即采样转换一次
==============================================================================

19.7.4                 利用ADC第15通道测量外部电压或电池电压
STC8H系列ADC的第15通道用于测量内部参考信号源,由于内部参考信号源很稳定,约为1.19V,
且不会随芯片的工作电压的改变而变化,所以可以通过测量内部1.19V参考信号源,
然后通过ADC的值便可反推出外部电压或外部电池电压。
下图为参考线路图:
利用ADC15在内部固定接的1.19V的辅助固定信号源,反推其他通道的输入电压-1.png

C语言代码

//测试工作频率为11.0592MHz
#include "stc8h.h"
#include "intrins.h"
#define       FOSC                 11059200UL
#define       BRT                    (65536-(FOSC / 115200+2) / 4)
//2操作是为了让Keil编译器
                                                                                                                //自动实现四舍五入运算
int              *BGV;                                                                                  //内部参考信号源值存放在idata
//idataEFH地址存放高字节
//idataF0H地址存放低字节
//电压单位为毫伏(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()
{
         ADCTIM= 0x3f;                                                                          //设置ADC内部时序
         ADCCFG= 0x2f;                                                                         //设置ADC时钟为系统时钟/2/16
         ADC_CONTR= 0x8f;                                                                  //使能ADC模块,并选择第15通道
}
int     ADCRead()
{
         intres;
         ADC_CONTR|= 0x40;                                                                //启动AD转换
         _nop_();
         _nop_();
         while(!(ADC_CONTR & 0x20));                                                //查询ADC完成标志
         ADC_CONTR&= ~0x20;                                                            //清完成标志
         res= (ADC_RES << 8) | ADC_RESL;                                        //读取ADC结果
         returnres;
}
void main()
{
         intres;
         intvcc;
         inti;
         P_SW2|= 0x80;                                                                            //使能访问XFR
         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();                                                                                  //前两个数据建议丢弃
         res= 0;
         for(i=0; i<8; i++)
         {
                  res += ADCRead();                                                             //读取8次数据
         }
         res>>= 3;                                                                                      //取平均值
         vcc= (int)(4096L * *BGV / res);                                                 //(12ADC算法)计算VREF管脚电压,即电池电压
//       vcc= (int)(1024L * *BGV / res);                                                 //(10ADC算法)计算VREF管脚电压,即电池电压
//注意,此电压的单位为毫伏(mV)
         UartSend(vcc>> 8);                                                                     //输出电压值到串口
         UartSend(vcc);
         while(1);
}

上面的方法是使用ADC的第15通道反推外部 MCU_VCC电压 / 电池电压 的, 电池直接给MCU_VCC供电。

在ADC测量范围内,ADC的外部测量电压与ADC的测量值是成正比例的,
所以也可以使用ADC的第15通道反推外部通道输入电压,

假设
当前已获取了内部参考信号源电压为BGV,
内部参考信号源的ADC测量值为resbg,
外部通道输入电压的ADC测量值为resx,

则外部通道输入电压Vx=BGV / resbg * resx
注意,是假定2次采样转换期间 【ADC_VREF+ = ADC_VCC = MCU_VCC】不变
===所以对外部采样转换一次,也要对内部ADC15接的信号源立即采样转换一次
回复 送花

使用道具 举报

该用户从未签到

550

主题

9235

回帖

1万

积分

管理员

积分
13946
 楼主| 发表于 2023-8-13 14:34:31 | 显示全部楼层
内部参考信号源电压为BGV,从CHIP中读取,或STC-ISP烧录时指定将重要参数烧录入程序Flash
1.png +

2.png

3.png

4.png

5.png



6.png

7.png
注意,是假定2次采样转换期间 【ADC_VREF+ = ADC_VCC = MCU_VCC】不变
===所以对外部采样转换一次,也要对内部ADC15接的信号源立即采样转换一次
回复 支持 反对 送花

使用道具 举报

该用户从未签到

1

主题

13

回帖

93

积分

注册会员

积分
93
发表于 2023-10-1 16:43:12 | 显示全部楼层
请问 使用这个1.19v内部参考电压的话  如果要测试别的电压 是不是就直接接到VREF管脚??还有就是测量的范围是多少?最大多少v?
回复 支持 反对 送花

使用道具 举报

该用户从未签到

550

主题

9235

回帖

1万

积分

管理员

积分
13946
 楼主| 发表于 2023-10-1 17:43:10 | 显示全部楼层
截图202310011742185218.jpg

ADC_VREF = MCU_VCC, 测量范围是 0 ~ [ADC_VREF = MCU_VCC]

截图202310011745179048.jpg

注意,是假定2次采样转换期间 【ADC_VREF+ = ADC_VCC = MCU_VCC】不变
===所以对外部采样转换一次,也要对内部ADC15接的信号源立即采样转换一次


回复 支持 反对 送花

使用道具 举报

该用户从未签到

1

主题

13

回帖

93

积分

注册会员

积分
93
发表于 2023-10-2 08:54:16 | 显示全部楼层
神农鼎 发表于 2023-10-1 17:43
ADC_VREF = MCU_VCC, 测量范围是 0 ~ MCU_VCC

好的谢谢
回复 支持 反对 送花

使用道具 举报

该用户从未签到

0

主题

1

回帖

22

积分

新手上路

积分
22
发表于 2023-10-28 12:16:47 | 显示全部楼层
您好 我想请问一下STC8H3K64S2这款芯片手册上注明的ADC通道是12个,
那用来反推VCC时也是采用15通道吗,我这边将通道改成12或是15,
读取的ADC值都为0,不知道该如何获取VCC电压,还请指点一二,谢谢
回复 支持 反对 送花

使用道具 举报

该用户从未签到

550

主题

9235

回帖

1万

积分

管理员

积分
13946
 楼主| 发表于 2023-10-28 13:01:14 | 显示全部楼层
反推VCC实际是反推 ADC_Vref+, 当 ADC_Vref+ = ADC_AVCC = MCU_VCC
就可以从一个已知到输入的通道,反推  【ADC_Vref+ = ADC_AVCC = MCU_VCC】


注意,是假定2次采样转换期间 【ADC_VREF+ = ADC_VCC = MCU_VCC】不变
===所以对外部采样转换一次,也要对内部ADC15接的信号源立即采样转换一次
回复 支持 反对 送花

使用道具 举报

该用户从未签到

14

主题

33

回帖

202

积分

中级会员

积分
202
发表于 2023-11-1 13:40:51 | 显示全部楼层
有没有汇编的参考代码?
回复 支持 反对 送花

使用道具 举报

该用户从未签到

550

主题

9235

回帖

1万

积分

管理员

积分
13946
 楼主| 发表于 2023-11-1 16:13:59 | 显示全部楼层
你在 STC8H的实验箱中看下


注意,是假定2次采样转换期间 【ADC_VREF+ = ADC_VCC = MCU_VCC】不变
===所以对外部采样转换一次,也要对内部ADC15接的信号源立即采样转换一次

回复 支持 反对 送花

使用道具 举报

  • TA的每日心情
    开心
    10 小时前
  • 签到天数: 109 天

    [LV.6]常住居民II

    9

    主题

    90

    回帖

    534

    积分

    高级会员

    积分
    534
    发表于 2023-11-1 21:33:45 | 显示全部楼层
    这个说一百遍都没自己操作一遍有用,假设:
    内部15通道读取的值为 1190,而读到的信号源值存放在idata中又是1.19V,
    可以知道ADC转换后的每个数表示(1.19V/1190)0.001V,
    这个时候假设ADC2通道读到的值是4000,那么这个通道的电压就是0.001*4000=4V,
    其他通道一样计算
    回复 支持 反对 送花

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

    GMT+8, 2024-4-29 18:42 , Processed in 0.076990 second(s), 68 queries .

    Powered by Discuz! X3.5

    © 2001-2024 Discuz! Team.

    快速回复 返回顶部 返回列表