电流
直播中

张辉

7年用户 1343经验值
私信 关注
[问答]

怎样通过MAX4372与STC12C5A60S2来检测输入电压及其电流

MAX4372是什么?MAX4372模块电路有何功能?
如何使用STC12C5A60S2芯片的AD转换功能?

怎样通过MAX4372与STC12C5A60S2来检测输入电压及其电流?并最终使用LCD1602显示?

回帖(1)

张洁

2021-9-27 09:59:06
  本篇文章是介绍通过高端电流检测放大器MAX4372与芯片STC12C5A60S2组合电路来检测输入电压、输出电压、输出电流,并最终使用LCD1602显示,要求做到误差小于正负0.1。
  那么下面我们先从MAX4372这个模块电路说起:
  1、MAX4372概述
  MAX4375是MAXIM公司最新推出的高端电流检测放大器,工作电压+2.7V到+28V,电源电流30uA,放大器增益分20/50/100三档,具有与电源电压无关的0V+28V共模输入范围,输出电压2V10V,满刻度准确性0.18%,输出阻抗1.5Ω,容性负载1000PF,可应用与电流保护/电流检测设备、4~20mA电流环系统、可编程电流源、智能电池/充电器等系统中。
  2、引脚排列及功能
  
  典型应用电路图
  
  3实际应用图片
  实际电路图:
  
  排版图:
  
  接下来介绍的是使用STC12C5A60S2芯片的AD转换功能,来实现输入电压、输出电压、输出电流的显示。
  1、STC12C5A60S2 AD转换功能原理知识
  先来一张引脚图:
  
  再来看下一张:
  
  整理出来的重点有如下几点:
  一、
  AD转换结束后,最终的转换结果保存到ADC转换结果寄存器ADC_RES和ADC_RESL,同时,置位ADC控制寄存器ADC_CONTR中的A/D转换结束标志位ADC_FLAG,以供程序查询或发出中断申请。
  二、
  模拟通道的选择控制由ADC控制寄存器ADC_CONTR中的CHS2~CHS0确定。
  三、
  ADC的转换速度由ADC控制寄存器中的SPEED1和SPEED0确定。
  四、
  在使用ADC之前,应先给ADC上电,也就是置位ADC控制寄存器中的ADC_POWER位。
  五、
  AUXR1辅助寄存器的ADRJ位是A/D转换结果寄存器(ADC_RES、ADC_RESL)的数据格式调整控制位。当ADRJ=0时,10位A/D转换结果的高8位存放在ADC_RES中,低2位存放在ADC_RESL的低2位中。当ADRJ=1时,10位A/D转换结果的高2位存放在ADC_RES中,低8位存放在ADC_RESL的低2位中。
  P1口模拟功能控制寄存器P1ASF
  
  ADC控制寄存器ADC_CONTR
  
  ADC_POWER:
  ADC电源控制位:
  0:关闭A/D转换器电源
  1:打开A/D转换器电源
  
  STC12C5A60S2系列单片机的A/D转换模块所使用的时钟是内部R/C振荡器所产生的系统时钟。
  ADC_FLAG:
  数模转换器转换结束标志位,当A/D转换完成后,ADC_FLAG=1,一定要软件清零。
  ADC_START:
  数模转换器(ADC)转换启动控制位,设置为1时,开始转换,转换结束后为零。
  
  设置ADC_CONTP控制寄存器后,要加4个空操作延时才可以正确读到ADC_CONTR寄存器的值。
  EA:
  CPU的中断开放标志位,EA=1,CPU开放中断,EA=0,CPU屏蔽所有的中断申请。
  EADC:
  A/D转换中断允许位。
  EADC=1,允许A/D转换中断;
  EADC=0,禁止A/D转换中断。
  PADCH,PADC:
  A/D转换中断优先级控制位。
  当PADCH=0且PADC=0时,A/D转换中断为最低优先级中断(优先级0)
  当PADCH=0且PADC=1时,A/D转换中断为较低优先级中断(优先级1)
  当PADCH=1且PADC=1时,A/D转换中断为较高优先级中断(优先级2)
  当PADCH=1且PADC=1时,A/D转换中断为最高优先级中断(优先级3)
  2、STC12C5A60S2 AD转换、LCD显示核心代码
  #include “reg51.h”
  #include “intrins.h”
  #include “1602.h”
  #include “ADC.H”
  #include “Display.h”
  /*****************主函数*****************/
  unsigned char set;
  void main()
  {
  unsigned int a;
  double VIN,VOUT,VOI; //输入、输出电压、电流存放变量
  unsigned int UIN,UOUT,UOI; //定义ADC结果读回存放变量
  LcdInit(); //LCD初始化
  InitADC(); //ADC初始化
  set = 32; //设置默认关断电流阀值
  while(1)
  {
  UIN = GetADCResult(0); //读取输入电压
  UOUT = GetADCResult(1); //读取输出电压
  UOI = filter(2); //读取输出电流值,并采用中位值滤波
  VIN = (float)UIN*5/1024*4; //计算输入电压
  VIN *=10000;
  if(VIN》160000)
  VIN += 1000;
  if(VIN》10000)
  VIN += 1000;
  VOUT = (float)UOUT*5/1024*3; //计算输出电压
  VOUT *=10000;
  VOI = (float)UOI*5/1024; //计算输出电流
  VOI /= 0.128;
  VOI *= 10000;
  if(VOI》30000)
  VOI += 2000;
  if(VOI》14500)
  VOI += 1000;
  if(VOI》6000)
  VOI += 200;
  if(VOI》100)
  VOI += 2000;
  /********显示结果*************/
  V_IN(VIN);
  V_OUT(VOUT);
  V_OI(VOI);
  SET(set);
  }
  }
  下面为ADC.c代码
  //++++++++++++++++++++++++++++++++++++++++++++++
  //+以下代码中ADC及串口配置部分引用了STC的代码+
  //++++++++++++++++++++++++++++++++++++++++++++++
  #include “reg52.h”
  #include “intrins.h”
  /******ADC功能寄存器*********/
  sfr ADC_CONTR = 0xBC; //ADC控制寄存器 //BC 地址
  sfr ADC_RES = 0xBD; //ADC高8位结果 //转换结果
  sfr ADC_RESL = 0xBE; //ADC低2位结果 //转换结果
  sfr P1ASF = 0x9D; //P1口第2功能控制寄存器 模拟功能配置寄存器
  #define ADC_POWER 0x80 //ADC电源控制位
  #define ADC_FLAG 0x10 //ADC完成标志
  #define ADC_START 0x08 //ADC起始控制位
  #define ADC_SPEEDLL 0x00 //540个时钟
  #define ADC_SPEEDL 0x20 //360个时钟
  #define ADC_SPEEDH 0x40 //180个时钟
  #define ADC_SPEEDHH 0x60 //90个时钟
  #define N 21 //ADC中值滤波次数,必须为基数
  /*----------------------------
  软件延时
  ----------------------------*/
  void Delay(unsigned int n)
  {
  unsigned int x;
  while (n--)
  {
  x = 5000;
  while (x--);
  }
  }
  /*----------------------------
  初始化ADC
  ----------------------------*/
  void InitADC()
  {
  P1ASF = 0x07; //设置P1口为AD口 0000 0111 //P1ASF 模拟功能配置寄存器
  ADC_RES = 0; //清除结果寄存器(高位)
  ADC_RESL= 0; //清除结果寄存器(低位)
  ADC_CONTR = ADC_POWER | ADC_SPEEDLL;
  Delay(2); //ADC上电并延时
  //yan:ADC_POWER=1;
  //yan:ADC_FLAG=1;
  }
  /*----------------------------
  读取ADC结果
  ----------------------------*/
  unsigned int GetADCResult(unsigned char ch)
  {
  unsigned int rew;
  ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ch | ADC_START;
  _nop_(); //等待4个NOP
  _nop_();
  _nop_();
  _nop_();
  while (!(ADC_CONTR & ADC_FLAG)); //等待ADC转换完成
  ADC_CONTR &= ~ADC_FLAG; //Close ADC
  rew=ADC_RES*4+ADC_RESL; //组合成10位
  _nop_();
  _nop_();
  //return ADC_RES; //返回ADC结果
  return rew;
  }
  unsigned int filter(unsigned char dat) //中位值滤波
  {
  unsigned int value_buf[N];
  unsigned int count,i,j,temp;
  for(count=0;count《N;count++)
  {
  InitADC(); //初始化ADC
  value_buf[count] = GetADCResult(dat);//读ADC数值
  Delay(1);
  }
  for (j=0;j《N-1;j++)
  {
  for (i=0;i《N-j;i++)
  {
  if ( value_buf[i]》value_buf[i+1] )
  {
  temp = value_buf[i];
  value_buf[i] = value_buf[i+1];
  value_buf[i+1] = temp;
  }
  }
  }
  return value_buf[(N-1)/2];
  }
  void timer_init(void)//定时器初始化
  {
  TMOD=0x01;/设置工作方式1
  TH0=(65536-50000)/256;///赋值
  TL0=(65536-50000)%256;
  EA=1;ET0=1;//开总中断;开定时器中断
  TR0=1;启动计数器
  }
举报

更多回帖

发帖
×
20
完善资料,
赚取积分