电流
登录
直播中
张辉
7年用户
1343经验值
私信
关注
[问答]
怎样通过MAX4372与STC12C5A60S2来检测输入电压及其电流
开启该帖子的消息推送
MAX4372
输入电压
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;启动计数器
}
本篇文章是介绍通过高端电流检测放大器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;启动计数器
}
举报
更多回帖
rotate(-90deg);
回复
相关问答
MAX4372
输入电压
kile
怎样
添加
stc12c5a60s2
的头文件?使得可以编程
stc12c5a60s2
2014-03-28
6212
基于
STC12C5A60S2
的智能循迹小车该
怎样
去设计呢
2021-12-20
2245
STC12C
2052AD与
STC12C5A60S2
的区别?
2015-05-31
6428
为什么
STC
-isp
检测
不到我的单片机(
STC12C5A60S2
)
2015-06-02
23048
谁用过
STC12C5A60S2
的?
2014-07-05
4552
stc12c5a60s2
与
STC89C
51在延时上面的区别?
2013-07-29
21132
请问如何用
stc12c5a60s2
中的pwm定时?
2023-11-09
245
求教!
stc12c5a60s2
采集
电压
测功率因数的问题
2017-08-11
2663
STC12C5A60S2
免掉电自动下载
2019-04-08
1472
STC12C5A60S2
和
STC89C
54RD+一样的程序吗/原有的
STC12C5A6S2
程序可以...
2013-02-24
6615
发帖
登录/注册
20万+
工程师都在用,
免费
PCB检查工具
无需安装、支持浏览器和手机在线查看、实时共享
查看
点击登录
登录更多精彩功能!
首页
论坛版块
小组
免费开发板试用
ebook
直播
搜索
登录
×
20
完善资料,
赚取积分