谷动谷力

 找回密码
 立即注册
查看: 2392|回复: 0
打印 上一主题 下一主题
收起左侧

【巧秒电路设计】锂电池电压测量电路设计实现低功耗

[复制链接]
跳转到指定楼层
楼主
发表于 2021-12-25 00:40:10 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 sunsili 于 2021-12-25 00:41 编辑

        【巧秒电路设计】锂电池电压测量电路设计实现低功耗        瑞生



        
        随着物联网的发展,单片机+锂电池,这种组合越来越普遍,单片机厂商也不断推出适合物联网的单片机。
先补充一下锂电池的基本知识…
锂电池在充满电的时候,是4.2V;在用完电的时候,不是0V,而是2.7V左右,每个厂家制作的锂电池,略有差异…
鉴于锂电池材料的局限性,电压超过4.2V,会发生危险,比如燃烧;电压低于2.7V左右,会造成无法再次充电,总之…
锂电池电压过高和过低,都会造成永久损坏,所以…
我们的产品在使用锂电池的时候,需要时刻监测锂电池电压。
充电的时候,不要超过4.2V,这个要求,需要产品中加入充电管理芯片,充电管理芯片会自动在4.2V的时候切断充电。
放电的时候,也就是产品在正常使用的时候,不要让锂电池电压低于2.7V,比如,在2.7V的时候,自动强制关机。
那么,锂电池电压监测电路应该怎么设计呢?


如上图所示,应该是初学者最先想到的办法。不过,仔细分析后会发现,有大问题,我们来分析一下···
VBAT连接到锂电池正极,通过两个电阻分压,连接到单片机的ADC引脚。ADC测到的电压,就是锂电池电压的一半···
因为锂电池的电压范围大概在2.7V到4.2V之间,所以ADC引脚的电压会在1.35~2.1V之间,不会超过普通单片机的3.3V电压,看起来很合理,不过···
当产品处于关机状态时,我们以为锂电池就不耗电了,其实,通过电路可以发现,锂电池其实还在通过2个10k的电阻耗电···
随着时间的推移,该产品放着放着电就减少了,而且当电池电压减少到2.7V以下时,就可能无法充起电来了···
我在国外的一款产品上,看到了这样的一个电路,当然,已经把它使用到我的产品当中···
上面电路,很巧妙的解决了这个问题,代价是电路板上多了1个MOS管和2个电阻,CTRL引脚是单片机的一个普通引脚,在单片机断电的时候,要求是高阻态,否则也会耗电···
这里加MOS管并不是用来控制“是否要测量电池电压”,而是为了在产品关机的时候,不要让锂电池电池的电压通过两个分压电阻。
此时,还有个问题要解决···
产品在正常使用的过程中,当电池电压小于3.3V时,LDO的输出电压,就不再是3.3V了,随着电池电压的减小,LDO的输出电压也会减小,此时…
如果一直使用3.3V作为基准来测量电池电压,就会出现错误,所以…
需要使用有基准电压引脚的单片机,或者有“内部参考电压”+“内部测量通道”功能的单片机···
用基准电压引脚计算电池电压,这个大家都清楚,我重点说一下“内部参考电压”+“内部测量通道”这个功能。
简单来说,有了“内部参考电压”+“内部测量通道”之后,我们就可以直接通过内部测量通道得到精确的VDD电压,而不必使用基准电压芯片了,毕竟···
基准电压芯片也挺贵的,还得在电路板上占个地方,以及多几分钱的焊接费用···
下面,我们以STC8G系列单片机为例来说一下。

STC8G的ADC第15通道,用来测量内部参考电压源,内部参考电压为1.19V,通过测量它的值,反推出VDD值。
  1. unsigned int VDDA; // VDDA的电压值 单位毫伏
  2. unsigned int *BGV; // 内部参考电压值 单位毫伏

  3. //ADC初始化
  4. void ADC_Init(void)
  5. {
  6.   BGV = (int idata *)0xEF;
  7.   ADCCFG = 0X2F; // 设置ADC时钟 = 24000000/2/16/512 = 1465Hz 转换结果右对齐
  8. }

  9. unsigned int ADCRead(void)
  10. {
  11.   unsigned int res;

  12.   ADC_CONTR |= 0X40; // 启动AD转换
  13.   _nop_();
  14.   _nop_();
  15.   while(!(ADC_CONTR&0X20)); // 查询ADC完成标志
  16.   ADC_CONTR &= ~0X20;  // 清除完成标志
  17.   res = (ADC_RES<<8)|ADC_RESL; //读取ADC结果

  18.   return res;
  19. }

  20. void Fetch_VDDA(void)
  21. {
  22.   unsigned int res=0;
  23.   unsigned char i;

  24.   ADC_CONTR = 0X8F; // 使能ADC模块 并选择第15通道
  25.   ADCRead();
  26.   ADCRead();
  27.   for(i=0;i<8;i++)
  28.   {
  29.     res+=ADCRead();
  30.   }
  31.   res>>=3; // 读取8次 取平均值
  32.   VDDA = (unsigned int)(1023L**BGV/res); // 得出的结果单位是毫伏
  33. }
复制代码

上面代码,获得了真实的VDDA值,然后就可以计算出真实的电池电压。


+10
回复

使用道具 举报

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

本版积分规则

QQ|Archiver|手机版|深圳市光明谷科技有限公司|光明谷商城|Sunshine Silicon Corpporation ( 粤ICP备14060730号|Sitemap

GMT+8, 2024-11-15 13:35 , Processed in 0.291220 second(s), 40 queries .

Powered by Discuz! X3.2 Licensed

© 2001-2013 Comsenz Inc.

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