在实际测试中,不管是研发还是维修,我们经常需要测量设备的电压电流,根据这个情况,我做了一个电压电流表。

单片机:由于手头上STC89C52RC很多,而且这也是大多数人比较常用的,所以我用了89C52RC做处理器。
ADC采样:这个单片机没有内置ADC,我采用XPT2046做ADC采集,XPT2046不仅精度高(12位ADC),
                而且有四个通道,还很便宜,非常适合ADC采样。
基准电压:由于随着输入电压与负载的波动,会使得XPT2046的电压不是标准的5V,虽然XPT2046内置了
                基准电压,但是太小了,会导致这个表的量程不够,所以我采用了TL431产生一个基准电压。
采样电阻:电流采样使用一个0.1欧姆1%精度,2512封装的贴片电阻,如果有1A电流,则产生0.1W的功耗,
                取样电阻不会发烫,但是此时电阻只有0.1V的电压理论ADC采集是没问题,但是如果流过0.1A,
                那只有0.01V的电压,ADC采样就不合适,所以需要放大。电压采样采用两个0603的电阻并联,
                由于接了跟随器,所以这两个电阻可以取大一些降低功耗(虽然问题不大)。
放大电路:采用LM358,一路做电流采样的放大,本项目是放大10倍,另一路做电压采样跟随器。
                 LM358存在零点漂移,所以在设置放大倍数的适合可能需要进行微调。
显示:使用了OLED,测试0.96寸的,实际可以使用0.91寸即可。
电路原理图(json格式的):如下:
image.png
PCB文件(json格式的):
image.png
制作出来的实物图如下:
image.png
校正方法:接入负载,输出一个足够大的电流,1A最好,然后测试取样电阻的电压,应该是0.1V,然后可以微调LM358的电阻使得OLED的显示正确,也可以在代码微调,代码里面有微调系数。附加功能:加了三个按键,可以额外开发更多功能。代码留有很多开发的余地,并且可以自己编程序显示电阻和功率。

单片机源程序如下:
#include "oled.h"
  • #include "bmp.h"
  • #include "xpt2046.h"
  • typedef unsigned int u16;
  • #define  v_verf 3.6  //基准电压最大值
  • #define  v_aver 2 //分压比例
  • #define  v_correction 1
  • #define  i_correction 0.95
  • void delay(unsigned int i)
  • {
  •         while(i--);
  • }
  • void v_datapros()
  • {
  •         u16 v_value;
  •         u16 v;
  •         
  •     delay(50000);
  •         v_value= Read_AD_Data(0xD4);
  •         delay(50000);
  •         
  •     v=(float)v_value*v_verf/4095*1000*2; //4944
  •         
  •         OLED_ShowChar(8,2,v/1000+0x30,16);
  •         OLED_ShowChar(16,2,'.',16);
  •         OLED_ShowChar(24,2,v%1000/100+0x30,16);
  •         OLED_ShowChar(32,2,v%100/10+0x30,16);
  •         OLED_ShowChar(40,2,v%10+0x30,16);
  •         
  • }        
  • void i_datapros()
  • {
  •         u16 i_value;
  •         u16 i;
  •         delay(50000);
  •         i_value= Read_AD_Data(0x94);
  •     delay(50000);
  •         
  • //        OLED_ShowChar(8,6,i_value/1000+0x30,16);
  • //        OLED_ShowChar(16,6,i_value%1000/100+0x30,16);
  • //        OLED_ShowChar(24,6,i_value%100/10+0x30,16);
  • //        OLED_ShowChar(32,6,i_value%10+0x30,16);
  •         
  •         i=(float)i_value*v_verf/4095*1000*i_correction;     //ma
  •         
  •     OLED_ShowChar(8,6,i/1000+0x30,16);
  •         OLED_ShowChar(16,6,i%1000/100+0x30,16);
  •         OLED_ShowChar(24,6,i%100/10+0x30,16);
  •         OLED_ShowChar(32,6,i%10+0x30,16);
  •         
  • }
  • void main(void)
  • {
  •         OLED_Init(); //OLED初始化
  •         OLED_Clear();
  • //        OLED_DrawBMP(0,0,128,1,BMP1);
  •     delay(50000);        
  •         while(1)
  •         {
  •                 v_datapros();
  •                 i_datapros();
  •         }
  • }
  • 复制代码