找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1987|回复: 13
打印 上一主题 下一主题
收起左侧

单片机ADC检测电压怎样校准(电压标定)

[复制链接]
跳转到指定楼层
楼主
ID:169142 发表于 2022-2-16 21:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
请问下,各位老大,单片机用ADC去检测电压,由于精度问题,怎样做电压校准。比如,检测一个锂电池的电压满电是12V电量4个LED,11.75V点亮3个LED,11.35V点亮2个LED,10.65V点亮1个LED,9.6V判断为低电压自动关断。检测精度为+/-0.01V。怎样去校准这几个电压点,以51单片机为例。
谢谢!!!
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:72649 发表于 2022-2-16 23:46 来自手机 | 只看该作者
加常数修正
回复

使用道具 举报

板凳
ID:857072 发表于 2022-2-17 02:38 来自手机 | 只看该作者
就我知道的stc8的有内部基准电压,测到的AD值换算成电压时要根据基准电压校正。测量12v电压还要做分压,电阻的精度低了影响也很大。
回复

使用道具 举报

地板
ID:960157 发表于 2022-2-17 07:12 | 只看该作者
MC1403电压基准,软件加修正。
回复

使用道具 举报

5#
ID:65956 发表于 2022-2-17 08:18 | 只看该作者
以STC单片机10位ADC来说,可以采用读内部基准源来计算采集电压值,这样就可实现精准电压采集。如果达不到要求,就得加外部其准源,对于你这个简单电路,加个基准源显示没必要
回复

使用道具 举报

6#
ID:807651 发表于 2022-2-17 09:08 | 只看该作者
求多次ad 取平均值
回复

使用道具 举报

7#
ID:401564 发表于 2022-2-17 13:52 | 只看该作者
STC8G或者STC8A系列有内部稳定的参考电压(精度1%),可以用来作为基准电压,用于测量锂电池
STC15系列不行,STC15系列的内部参考电压不是固定的
对于锂电池通过电压来大概显示电量,一定要有一个完整的放电曲线数据,用来进行电量处理,因为锂电压放电时电压会下降,不能用简单的电压比例来计算电量
回复

使用道具 举报

8#
ID:169142 发表于 2022-2-17 19:01 | 只看该作者

C语言怎么做常数修正?
回复

使用道具 举报

9#
ID:169142 发表于 2022-2-17 19:03 | 只看该作者
wskufo 发表于 2022-2-17 07:12
MC1403电压基准,软件加修正。

软件怎么做修正啊??
回复

使用道具 举报

10#
ID:169142 发表于 2022-2-17 19:04 | 只看该作者
aking991 发表于 2022-2-17 08:18
以STC单片机10位ADC来说,可以采用读内部基准源来计算采集电压值,这样就可实现精准电压采集。如果达不到要 ...

这个内部基准源是怎么读取的???
回复

使用道具 举报

11#
ID:169142 发表于 2022-2-17 19:05 | 只看该作者
wd1988 发表于 2022-2-17 09:08
求多次ad 取平均值

这个好像也达不到要求
回复

使用道具 举报

12#
ID:857072 发表于 2022-2-17 23:33 来自手机 | 只看该作者
#ifndef __NTC_TY_H #define __NTC_TY_H  //#include <STC8HX.h>  #include "ADC.h"  #ifndef  BIAO_PIANYI         //阻值表偏移量 #define  BIAO_PIANYI                  10 #endif   float ntcty_read_temp(ADC_Name ntcn,uint8 wei,uint16 cankao);  //获取ntc温度 uint16 ntcty_read(ADC_Name ntcn,uint8 wei); //ntc转换取均值一次 float ntcty_gongdian(uint8 ADW);//功能:根据内部参考电压计算ADC外部参考电压, float ntcty_ADCdian(ADC_Name ntcn);//根据内部参考电压计算ADC电压  //ntc_ty //数据放大1000倍方便整数计算 extern code uint16 ntc_ty[]; //------------------------------------------------------------------------------------------------------------------- //  @brief      ntc转换取均值一次 //  @param      ntcn            选择ntc通道 //  @param      wei      读ADC次数 //  @return     void //  Sample usage:               ntc_convert(ntc_P10, 10); //------------------------------------------------------------------------------------------------------------------- uint16 ntcty_read(ADC_Name ntcn,uint8 wei) {         uint8 y,i,u;     uint16 shuzu[10];         uint16 yaogan_max,yaogan_min,yaogan_sum;         y=wei;     adc_init(ntcn, ADC_SYSclk_DIV_2, ADC_12BIT);         if (ntcn > 15)ntcn = ntcn - 8;         for(i=0;i<y;i++)         {                 shuzu[i] = adc_read(ntcn);         }         for(u=0;u<2;u++)//抛弃最大值和最小值         {         yaogan_min = shuzu[0];                 yaogan_max = shuzu[0];                 for(i=0;i<y;i++)                 {                                                  if(yaogan_max < shuzu[i])                         {                            yaogan_max=shuzu[i];                         }                         if(yaogan_min >= shuzu[i])                         {                                 yaogan_min = shuzu[i];                         }                 }                                  for(i=0;i<y;i++)                 {                                                  if(yaogan_max==shuzu[i])                         {                            shuzu[i] =shuzu[y-1] ;                            break;                         }                    }                 for(i=0;i<y;i++)                 {                         if(yaogan_min==shuzu[i] )                         {                            shuzu[i] =shuzu[y-2] ;                            break;                                                      }                    }                 y=y-2;         }     yaogan_sum=0;         for(i=0;i<y;i++)         {            yaogan_sum=yaogan_sum+shuzu[i];//计算剩余AD值的和         }         yaogan_sum = yaogan_sum/y;//计算AD平均值         return yaogan_sum;//返回计算的AD平均值 }    //*******************************************************************/ //功能:读ADC电压值 //形参:无 //返回:电压值 //详解:根据内部参考电压计算ADC电压, //*******************************************************************/ float ntcty_ADCdian(ADC_Name ntcn)//根据内部参考电压计算ADC电压, {         uint16 adjg,adck;         adjg = ntcty_read(ntcn,6);         adck = ntcty_read(ADC_REF,6);     return 1.19/adck*adjg; }   //*******************************************************************/ //功能:读供电电压(ADC外部参考电压) //形参:ADW:ADC的实际最高位数。12,10,8 //返回:电压值 //详解:根据内部参考电压计算ADC外部参考电压, //*******************************************************************/ float ntcty_gongdian(uint8 ADW)//功能:根据内部参考电压计算ADC外部参考电压, {         uint16 adjg; //        ntc_init(ADC_REF, ntc_SYSclk_DIV_2);         adjg = ntcty_read(ADC_REF,6);         switch (ADW) {         case 12:    return 4095*1.19/adjg;     break;         case 10:    return 2047*1.19/adjg;     break;         default:    return 255*1.19/adjg;     break;   }         } //======================================================================== // 描述: ntc从电阻分度表格里查找最靠近的位置. // 参数: 电阻值*1000. // 返回: 分度表格里最靠近的位置. //======================================================================== uint8 ntcty_find_r(uint16 data) {     uint8  start_index, mid = 0, end_index;     uint16  dat;          start_index = 0;     end_index = 50;            // 2. 开始二分法查找     while (start_index < end_index)     {         mid = (end_index + start_index) >> 1;         dat = ntc_ty[mid];                  if (data < dat)         {             start_index = mid + 1;         }         else if (data > dat)         {             if (mid)             {                 end_index = mid;             }             else             {                 break;             }         }         else         {             return (mid);         }     }          return (mid); }  //======================================================================== // 描述: 根据查表结果计算温度. // 参数: 电阻值*1000. // 返回: 温度. //======================================================================== float ntcty_get_value(uint16 data) {   uint8 index;   float temp;   data = (data > ntc_ty[0]) ? ntc_ty[0] : data;   data = (data < ntc_ty[50]) ? ntc_ty[50] : data;      index = ntcty_find_r(data);    if(ntc_ty[index]>data)   {     temp = index + (float)(ntc_ty[index]-data)/(ntc_ty[index]-ntc_ty[index+1]);//线性插值          return temp+BIAO_PIANYI-1;//偏移   }   else if(ntc_ty[index]<data)   {     temp =  index-(float)(data-ntc_ty[index])/(ntc_ty[index-1]-ntc_ty[index]);//线性插值     return temp+BIAO_PIANYI+1;//偏移   }   else   {     return index+BIAO_PIANYI;   } }  //======================================================================== // 描述: 获取ntc温度. // 参数: None. // 返回: 温度. //======================================================================== float ntcty_read_temp(ADC_Name ntcn,uint8 wei,uint16 cankao) {     float V,V0;         V0=ntcty_ADCdian(ntcn);//读ADC电压值     V=ntcty_gongdian(wei); //读供电电压     V=V/(V0-V)*cankao;     V = ntcty_get_value(V*1000);//电阻值放大1000倍查找温度     V = (int)(10.0 * V + 0.5) / 10.0;//保留一位小数     return V*1.0; }  #endif
回复

使用道具 举报

13#
ID:857072 发表于 2022-2-17 23:35 来自手机 | 只看该作者
给你看这个stc8的ntc库测温我用到了内部基准电压校正AD电压。的
回复

使用道具 举报

14#
ID:382454 发表于 2022-2-23 12:04 | 只看该作者
要精准测量,MCU板的基准电源要用低温漂的作为参考电源,至于怎么修正,进行多次AD后,比如128次,再做平均值,即除于128,在这一段代码里有一个基准参照电源,比如参照电源是4V,在代码里就是4000   你可以用福录克万用表测量对比一下,如果太低可以把参照源改成4010,计算出来不行再进行微调。
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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