| 利用ADC15通道在内部固定接的1.19V辅助固定信号源 ! 反推 其他ADCx通道的外部输入电压,ADC0 ~ ADC14
 反推 VCC,  【ADC_VREF+/ADC_AVCC/MCU_VCC】 
 采样转换二次,只需要计算一次
 ===1,假定ADC采样转换足够快 ===2,假定2次ADC转换期间,【ADC_VREF+/ADC_VCC/MCU_VCC】不变,变的误差也可以接受 ===3,应用场景,【ADC_VREF+/ADC_AVCC/MCU_VCC】 这3条重要的电源线直接接在一起 
 8H/8G/8A系列 单片机内部集成了一个10位/12位高速A/D转换器。ADC的时钟频率为系统频率2分频再经过用户设置的分频系数进行 再次分频(ADC的工作时钟频率范围为SYSclk/2/1到SYSclk/2/16)。 STC8H系列的ADC最快速度:12位ADC为800K(每秒进行80万次ADC转换),10位ADC为500K(每秒进行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的外部输入信号采样转换一次就知到转换后的值
 
 则外部通道输入电压Vx=BGV / resbg * resx;
 采样转换二次,只需要计算一次
 注意,是假定2次采样转换期间 【ADC_VREF+ = ADC_VCC = MCU_VCC】不变
 ===所以对外部采样转换一次,也要对内部ADC15接的信号源立即采样转换一次
 ==============================================================================
 
 19.7.4                 利用ADC第15通道测量外部电压或电池电压
 STC8H系列ADC的第15通道用于测量内部参考信号源,由于内部参考信号源很稳定,约为1.19V, 且不会随芯片的工作电压的改变而变化,所以可以通过测量内部1.19V参考信号源, 然后通过ADC的值便可反推出外部电压或外部电池电压。 下图为参考线路图: 
 C语言代码 
 //测试工作频率为11.0592MHz #include "stc8h.h" #include "intrins.h" #define       FOSC                 11059200UL #define       BRT                    (65536-(FOSC / 115200+2) / 4) //加2操作是为了让Keil编译器                                                                                                                 //自动实现四舍五入运算 int              *BGV;                                                                                  //内部参考信号源值存放在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() {          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);                                                 //(12位ADC算法)计算VREF管脚电压,即电池电压 //       vcc= (int)(1024L * *BGV / res);                                                 //(10位ADC算法)计算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接的信号源立即采样转换一次
 
 |