您现在正在浏览:首页 > 职教文章 > 职教论文 > 自动换量程电压表的设计

自动换量程电压表的设计

日期: 2010/12/22 浏览: 2 来源: 学海网收集整理 作者: 佚名

广州周立功单片机发展有限公司 Tel: (020) 8730976 38730977 Fax: 38730925 http://www.zlgmcu.com

- 1 -

量程自动转换电压表



一 概述



在智能仪器中 常常用到自动量程转换技术 这使得仪器在很短的时间内自动选取最合适的量程 实

现高精度的测量 自动量程的实现一般通过控制输入信号的衰减 放大倍数实现 就电压表来说 其输入

测量电压会大于其 AD 转换器的输入范围 所以它的量程切换基本上是信号衰减倍数切换的过程



二 自动量程基本控制流程































自动量程转换由初设量程开始 逐级比较 直至选出最合适提量程为止 自动量程转换的操作流程如

上图所示 继电器或其它控制开关从闭合转变为断开 或从断开转变为闭合有一个短暂的过程 所以在每

次改变量程之后要延时一定的时间 然后再进行正式的测量和判断 为了避免在两种量程的交叉点上可能

出现的跳动 还应考虑低量程的超量程比较值和高量程的欠量程比较值之间有一定的重叠范围



三 简单的电压量程控制

自动量程开始

测量程序

欠量程?

超量程?

结束

最低量程?

最高量程?

N

N

降量程处理

升量程处理

Y

Y N

N

Y

过载报警显示

Y

广州周立功单片机发展有限公司 Tel: (020) 8730976 38730977 Fax: 38730925 http://www.zlgmcu.com

- 2 -





如上图 通过电阻网络实现电压衰减 测量的输入阻抗约为 R R1 R2 R3 R4 S1至S4 单独合上时

Vout 的大小分别为

S1 单独合上 Vout=Vin*1

S2 单独合上 Vout=Vin*(R2+R3+R4)/(R1+R2+R3+R4)

S3 单独合上 Vout=Vin*(R3+R4)/(R1+R2+R3+R4)

S4 单独合上 Vout=Vin*(R4)/(R1+R2+R3+R4)

选择 R1>R2>R3>R4 由式中可以看出 Vout 在一定范围时 电阻网络衰减程度越大 其可输入电压 Vin

范越大 只要把 R1 R2 R3 R4 的参数选好 然后由 S1 S2 S3 S4 选择测量电压输出端 即完成量程

选择 例如 表头 DVM 输入电压为 0 5 伏 设 DVM 输入阻抗无穷大 要求测量电压量程有 5V 50V 100V

250V 档 输入电阻 1M 则有

R4 5 1000000 250 20000 20K

R3 5 1000000 100 R4 50K 20K 30K

R2 5 1000000 50 R4 R3 100K 20K 30K 50K

R1 1000000 R4 R3 R2 1000K 20K 30K 50K 900K

自动量程控制描述

RANGE 为当前量程变量 VT 为测量电压变量 S1 S4 为量程档 S1 S4 开关对应的量程档 N2 N4

为量对应量程档的欠量程值

RANGE S4 /*预选 250 伏档进行电压测量*/

LOOP: VT Vout /*进行电压测量*/

SWITCH RANGE /*根据当前量程进行调整*/

{

CASE S4: IF(VT
IF(VT>5V)OUTTEST; /*最高量程时 Vout>5V,超负载*/

BREAK;

CASE S3: IF(VT
IF(VT>5V)RANGE++; /*超本档量程 量程升一档*/

BREAK;

CASE S2: IF(VT
广州周立功单片机发展有限公司 Tel: (020) 8730976 38730977 Fax: 38730925 http://www.zlgmcu.com

- 3 -

IF(VT>5V)RANGE++;

BREAK;

CASE S1: IF(VT>5V)RANGE++;

}

GOTO LOOP;

开关的选择 采用继电器切换 优点是导通阻抗小 开路阻抗大 但其动作速度慢 也容易老化



四 自动量程电压表原理图



由于断电器存在着体积大 动作速度慢 驱动电流大等缺点 通常用运算放大技术来实现自动量程切

换机制 先把输入电压进行衰减 不管输入测量电压多大 都是通过同一阻抗网络进行分压 最终结果是

大电压时分得的电压较大 反之则较小 然后通过运算放大电路将此电压信号放大 选择不同的放大倍数

使输出电压在 DVM 的测量范围内 从实现不同量程的电压测量



广州周立功单片机发展有限公司 Tel: (020) 8730976 38730977 Fax: 38730925 http://www.zlgmcu.com

- 4 -



说明

电压量程部分 先把输入电压进行衰减 1 20 然后通过运算放大进行信号的主大 只在改变放大

电路的放大倍数 即可实现量程的切换 运算放大器是用电压负反馈比例放大 由 MC14051 模拟开关进行

Rf 的选择 从而实现放大倍数的控制 图中 S1 S3 为调节电位器 因为模拟开关存在导通电阻 要用电

位器进行调节利得到理想放大倍数

DVM 测量部分 基于 P87LPC76X 的 - ADC 实现 AD 转换 应用了 8 位 - AD 算法 进行测量

时对测量数据进行去极值平均滤波处理 电压测量范围在 0 VCC 之间 精度受 76X 内部比较器失调电压

I O 口失调电压 MCU 电源电压和采样周期大小影响

显示部分 采用 8 段共阳数码管 4 个 用于电压值显示 6 个状态发光二极管指示当前量程和测量状

态等 用 74HC164 静态驱动 只占用 MCU 的两个 I O 口 数码管阳极的输入电压由 LM317 稳压 2V 输出得

到 固可省去限流电阻



五 软件部分



1 量程的整定

MC1405 1选通0 放大倍数

0 通道 1.2 倍 MC14051 存在一定的导通电阻

1通道 2 倍

2 通道 5 倍

3 通道 20 倍

测量电压输入衰减 1 20 设 Vin 为要测量的电压 Vt 为衷减后的电压 Vout 为放大后的电压 Vout

最大输出为 5V 则最压量程范围为

Vin=(5/N)*20 (N 为放大倍数)



MC1405 1选通0 最大量程范围

0 通道 83V

1通道 50V

2 通道 20V

3 通道 5V





























广州周立功单片机发展有限公司 Tel: (020) 8730976 38730977 Fax: 38730925 http://www.zlgmcu.com

- 5 -

2 软件流程

















































3 程序清单

/* 文件名 DVM.C

自动量程直流电压测量

采用模块化编程 主模块主要负责调度和接口

各模块对应于相应硬件或相应功能

*/

#include



#define uchar unsigned char

#define uint unsigned int



/*DVM.C 模块的全局变量*/

uchar range; /*定义量程控制变量 即运放放大倍数参数*/



/*DVM_DISP.C 模块的函数和变量声明*/

extern void DISP_Fill(uchar c); /*全部填充函数*/

extern bit DISP_Coding(); /*显示缓冲区译*/

extern void DISP_Send(); /*发送显示缓冲区的数据*/

extern uchar disp_ram[5]; /*显示缓冲区*/

开始

显示器自检

AD 控制通道自检

置量程初值

AD 转换 测量

转换并显示

自动量程判断

超载报警提示

若不是最低量程则

隆一级量程

是最高量程 升量程一级

欠量程 超量程 N

Y

广州周立功单片机发展有限公司 Tel: (020) 8730976 38730977 Fax: 38730925 http://www.zlgmcu.com

- 6 -

extern uchar bdata disp_staled; /*状态发光二极管使用的寄存器*/

extern bit L1; /*对应于各状态发光二极管*/

extern bit L2;

extern bit L3;

extern bit L4;

extern bit L5;

extern bit L6;



/*DVM_ADC.C 模块的函数和变量声明*/

extern bit ADC_HChk(); /*AD 通道自检 AD 控制输出通道 */

extern uchar ADC_AdcN();/*AD 转换 进行 10 次 AD 转换 返回去极值平均滤波值 */

extern bit ADC_ORange();/*检测是否超量程*/



/*

函数 短延时 MAIN_DelayS(uchar i)

功能 延时 i*310us

*/

void MAIN_DelayS(uchar i)

{

uchar j;

for(;i>0;i--)

for(j=0;j<100;j++);

}



/*

函数 长软件延时 MAIN_DelayL(uchar i)

功能 进行延时 i*20.3ms

*/

void MAIN_DelayL(uchar i)

{

uchar l;

uint j;

for(l=0;l
for(j=0;j<4000;j++);

}



/*

函数 切换量程

描述 量程有 0 4 共五档 输入量程 i 应在 0 4 之间

硬件操作对应于 P0.1 P0.2 P0.3

*/

APPL_Range()

{

range=range&0x07; /*rage 不能大于 7,否则会破坏其它 I O*/

广州周立功单片机发展有限公司 Tel: (020) 8730976 38730977 Fax: 38730925 http://www.zlgmcu.com

- 7 -

if(range>4)range=0;/*量程选择错误 复位为 0 档*/

P0=P0&0xf8; /*将其值放入 P0.1 P0.2 P0.3*/

P0=P0|range;

L1=1; L2=1; L3=1; L4=1;

switch(range) /*指示当前量程*/

{

case 3: L4=0;

break;

case 2: L4=0;L3=0;

break;

case 1: L4=0;L3=0;L2=0;

break;

case 0: L4=0;L3=0;L2=0;L1=0;

break;

}

}



/*

函数 APPL_Dcv()

描述 电压测量 对测量量实行自动量程切换

*/

void APPL_Dcv()

{

uchar ad; float muli; /*ad 为 AD 转换结果 muli 为运算所要倍数*/

bit range_ok; /*量程合适标志 为 1 时表示量程合适*/



disp_staled=0xff; /*状态灯全灭*/

/*选择最高量程 83V 为默认量程*/

range=0;

muli=16.33;

range_ok=0;



/*测量电压*/

while(1)

{

float vin;uint bak;

if(range_ok==0)APPL_Range(); /*量程末合适 输出量程控制信号*/

L6=0; /*状态灯 L6 亮 表示当前是测电压*/

range_ok=1;

ad=ADC_AdcN(); /*进行 AD 转换*/



/* Vin=((ad/255)*VCC/N)*20 ;ad 为 AD 转换值 N 为运放电路放大倍数 */

/* 设 muli=(Vcc/5)*(20/N) 则 Vin=(ad/51)*muli */

vin=(float)ad/51; /*运算显示数据 1/255 *5 =1/51 */

广州周立功单片机发展有限公司 Tel: (020) 8730976 38730977 Fax: 38730925 http://www.zlgmcu.com

- 8 -

vin=vin*muli;

if(vin>10)

{

disp_ram[1]=vin/10;

bak=vin;

disp_ram[2]=bak%10;

bak=vin*10;

disp_ram[3]=bak%10;

DISP_Coding();

disp_ram[2]&=0x7f; /*置小数点位*/

disp_ram[0]=0xff;

}

else

{

bak=vin;

disp_ram[1]=bak%10;

bak=vin*10;

disp_ram[2]=bak%10;

bak=vin*100;

disp_ram[3]=bak%10;

DISP_Coding();

disp_ram[1]&=0x7f; /*置小数点位*/

disp_ram[0]=0xff;

}

DISP_Send(); /*显示输出*/



/*判断超量程*/

if(ad==0&&ADC_ORange()==1)

{

range_ok=0;

if(range>0)range--; /*超量程 未到 100V 档 升量程*/

else

{ /*若超过 100V,显示溢出*/

disp_staled=0xff;

disp_ram[0]=0xa3; /*显示'out-',表示溢出*/

disp_ram[1]=0xe3;

disp_ram[2]=0x87;

disp_ram[3]=0xbf;

DISP_Send();

}

}

/*判断是否可降低量程*/

else

{

广州周立功单片机发展有限公司 Tel: (020) 8730976 38730977 Fax: 38730925 http://www.zlgmcu.com

- 9 -

switch(range)

{

case 0: if(ad<0x85){range++;range_ok=0;} /*小于 50 伏?*/

else muli=16.33;

break;

case 1:if(ad<0x55){range++;range_ok=0;} /*小于 20 伏?*/

else muli=9.8;

break;

case 2:if(ad<0x35){range++;range_ok=0;} /*小于 5 伏?*/

else muli=3.92;

break;

case 3:muli=0.98;

break;

}

}

}

}



/*

函数 显示器自检 DISP_Chk()

功能 LED1-4 显示 0 2 4 6 8 ' '且状态灯依次点亮

*/

void DISP_Chk()

{

uchar i;

disp_staled=0xff; /*状态灯全灭*/

for(i=0;i<10;i+=2)

{

disp_staled=disp_staled<<1;/*右移时后面是用 0 来填充 实现依次点亮*/

DISP_Fill(i);

DISP_Coding(); /*字模转换*/

DISP_Send(); /*发送显示,发送前先把 disp_staled 装入 disp_ram[4]*/

MAIN_DelayL(20);

}

disp_staled=disp_staled<<1;

DISP_Fill(0x7f); /*显示' '*/

DISP_Send();

MAIN_DelayL(20);

}



/*

系统自检 APPL_Chk()

描述 对 AD 控制通道进行测试 若有错误则显示出错号 并延时

*/

广州周立功单片机发展有限公司 Tel: (020) 8730976 38730977 Fax: 38730925 http://www.zlgmcu.com

- 10 -

APPL_Chk()

{

if(ADC_HChk()==0) /*进行 AD 通道的检测*/

{

disp_staled=0xff;

disp_ram[0]=0x86; /*显示 Err1*/

disp_ram[1]=0xaf;

disp_ram[2]=0xaf;

disp_ram[3]=0xf9;

DISP_Send(); /*发送显示*/

MAIN_DelayL(200); /*延时 4 秒*/

}

}



/*

主函数 void main()

功能 负责进程的调度

*/

void main()

{

DISP_Chk(); /*显示器自检*/

APPL_Chk(); /*系统自检:AD 控制通道*/

APPL_Dcv(); /*进入电压测量部分*/

}



/* 文件名 DVM_DISP.C

此功能模块对应于系统的显示硬件模块

公有成员

变量 显示缓冲区 5 字节 disp_ram LED1 LED4 STA_LED

对应于状态灯的一字节可位寻址变量 实际定义了几个对应位变量

disp_staled 和 L1 L2 L3 L4 L5 L6

全部填充函数 DISP_Fill();

显示缓冲区译码 DISP_Coding();

发送显示缓冲区的数据 DISP_Send();

注 把显示分为译码及发送有很大的灵活性 可以显示不在译码范围内的符号



私有成员

常量为 显示译码的字模 disp_TAB

对应于接口的 CLK DAT

向串口发送一字节数据 DISP_SendByte();

*/



#include



广州周立功单片机发展有限公司 Tel: (020) 8730976 38730977 Fax: 38730925 http://www.zlgmcu.com

- 11 -

#define uchar unsigned char



/*私有变量的定义*/

sbit CLK=P1^6; /*164 的控制线*/

sbit DAT=P1^7;



/*公有变量的定义*/

uchar disp_ram[5];

uchar bdata disp_staled;



sbit L1=disp_staled^0; /*对应于状态显示发光二极管*/

sbit L2=disp_staled^1;

sbit L3=disp_staled^2;

sbit L4=disp_staled^3;

sbit L5=disp_staled^4;

sbit L6=disp_staled^5;



/*

函数 向串口发送一字节数据 DISP_SendByte()

功能 先发送字节的高位 CLK 下降沿有效

*/

static void DISP_SendByte(uchar c)

{

uchar i;

CLK=1;

for(i=0;i<8;i++)

{

if((c&0x80)==0)DAT=0; /*取最高位*/

else DAT=1;

CLK=0;

CLK=0;

CLK=1;

c=c<<1; /*数据左移*/

}

}



/*

函数 填充显示缓冲区 DISP_Fill(uchar c)

功能 用 c 来填充显示缓冲区 4 字节 不会影响 disp_staled

*/

void DISP_Fill(uchar c)

{

uchar i;

for(i=0;i<4;i++) /*填充 5 字节数据*/

广州周立功单片机发展有限公司 Tel: (020) 8730976 38730977 Fax: 38730925 http://www.zlgmcu.com

- 12 -

{

disp_ram[i]=c;

}

}



/*

函数 显示缓冲区译码 bit DISP_Coding()

功能 将显示缓冲区的进行译码 0-3 若其中有超出译码范围不对它译码并在返回时

返回 0 否则返回 1

译码成功对 disp_ram 数据已译码

*/

bit DISP_Coding()

{

/*共阳数据码管字模 A-F,P,U,N,-,*/

uchar code disp_TAB[20]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,

0x88,0x83,0xc6,0xa1,0x86,0x8e,

0x8c,0xc1,0xc8,0xbf};

bit ret;

uchar i,bak;

ret=1;

for(i=0;i<4;i++)

{

bak=disp_ram[i]; /*取得 disp_ram 的数据*/

if(bak>19)ret=0; /*若数据超出译码范围 置 ret=0*/

disp_ram[i]=disp_TAB[bak];

}

return(ret);

}



/*

函数 发送显示缓冲区的数据 DISP_Send()

功能 先把 disp_staled 装入 disp_ram[4] 将显示缓冲区的数据发送至 164 进行显示

在发送之前要对显示缓冲区 disp_ram 进行填值或译码等操作

*/

void DISP_Send()

{

uchar i;

disp_ram[4]=disp_staled;

for(i=0;i<5;i++)

{

DISP_SendByte(disp_ram[4-i]);

}

}



广州周立功单片机发展有限公司 Tel: (020) 8730976 38730977 Fax: 38730925 http://www.zlgmcu.com

- 13 -

/* 文件名 DVM_ADC.C

此功能模块对应于系统的 - ADC 硬件模块

公有成员

AD 通道自检 ADC_HChk()

进行 10 次 AD 转换 返回去极值平均滤波值:ADC_AdcN()

检测是否超量程:ADC_ORange()



私有成员

常量为 AD 输入通道 adc_CIN1A

AD 比较通道 adc_CMPREF

AD 控制通道 adc_CON

8 位 - AD ADC_Adc()

*/

#include

#define uchar unsigned char

#define uint unsigned int



extern void MAIN_DelayS(uchar i); /*调用主程序的短延时函数*/

extern uchar ADC_Adc(); /*调用汇编子程序 实现 - AD*/



sbit adc_CIN1A=P0^4; /* - AD 端口定义*/

sbit adc_CMPREF=P0^5;

sbit adc_CON=P0^3;



/*

函数 AD 控制通道检测 ADC_HChk()

功能 对 AD 控制通道进行测试 测试通过返回 1 否则返回 0

注意 使用此函数条件 adc_CON 为准双向口 0 口数据输入有效 即开机时调用此函数

*/

bit ADC_HChk()

{

P0M1=P0M1|0x30; /*设置 adc_CIN1A,adc_CMPREF 端为输入*/

P0M2=P0M2&0xcf;

adc_CON=1; /*输出 1 测试*/

MAIN_DelayS(5);

if(adc_CMPREF==0)return(0);

adc_CON=0; /*输出 0 测试*/

MAIN_DelayS(5);

if(adc_CMPREF==1)return(0);

return(1);

}







广州周立功单片机发展有限公司 Tel: (020) 8730976 38730977 Fax: 38730925 http://www.zlgmcu.com

- 14 -

/*

函数 ADC_AdcN()

功能 进行 10 次 AD 转换 返回去极值平均滤波值

注意 使用此函数后 adc_CMPREF adc_CIN1A 为高阻输入

adc_CON 为强上拉输出

*/

uchar ADC_AdcN()

{

uchar i,max,min,bak;

uint result;

result=ADC_Adc(); /*ADC_Adc()会设置 AD 占用的口线*/

max=min=result;

for(i=0;i<9;i++) /*进行 9 次转换 再加上前面 1 次 共10 次*/

{

bak=ADC_Adc(); /*ADC_Adc()内使用了 A 及 CY*/

result=result+bak;

if(bak>max)max=bak; /*找出最大值及最小值*/

if(bak
}

CMP1=0; /*关比较器*/

bak=(result-max-min)/8; /*去极值平均滤波*/

return(bak);

}



/*

函数 ADC_ORange()

功能 超量程判断 若超量程时返回 1 ,否则返回 0 在 AD 值为 0 时调用此函数即可

判断是否超量程 因为超量程时 AD 值为 0

*/

bit ADC_ORange()

{

PT0AD=0x20; /*adc_CIN1A 数据输入有效*/

P0M1=P0M1|0x10; /*设 adc_CIN1A 为输入方式*/

P0M2=P0M2&0xef;

if(adc_CIN1A==1)return(1);/*若为高电平 超量程 返回 1 */

return(0);

}



;文件名 ADC_AD.ASM

;用于软件 - AD

;本模块是向 DVM_ADC.C 提供 uchar ADC_Adc()函数 uchar ADC_Adc()是 - ADC 的操作部分 此处采用

;8 位 - 转换后直接把值返回



NAME ADCASM

广州周立功单片机发展有限公司 Tel: (020) 8730976 38730977 Fax: 38730925 http://www.zlgmcu.com

- 15 -



PR_ADCA SEGMENT CODE

DT_ADCA SEGMENT DATA OVERLAYABLE

PUBLIC ADC_Adc



;特殊功能寄存器定义

PT0AD DATA 0F6H

P0M1 DATA 84H ;P0 方式寄存器 1

P0M2 DATA 85H ;P0 方式寄存器 2

P1M1 DATA 91H ;P1 方式寄存器 1

P1M2 DATA 92H ;P1 方式寄存器 2

CMP1 DATA 0ACH ;比较器 1 控制寄存器

CMP2 DATA 0ADH ;比较器 2 控制寄存器



AD_CON BIT P0.3 ;定义 AD 控制端



;变量定义段

RSEG DT_ADCA

ADCA_BYTE:

Cont1: DS 1

Cont2: DS 1

bak: DS 1



;程序段

;**************************************************************

; - AD 转换程序

;占用 Cont1,Cont2,bak 结果于 R7 中

;**************************************************************

RSEG PR_ADCA

ADC_Adc:

ANL P0M1,#0F7H

ORL P0M2,#08H ;AD_CON 设为上拉



MOV PT0AD,#30H ;禁止 CMPREF CIN1A 数字输入

ANL P0M2,#0CFH ;设为仅为输入

ORL P0M1,#30H



MOV CMP1,#20H ;比较器 1 的 CIN1A 为输入端 比较器使能

AD_START:

MOV Cont1,#2 ;循环次数

MOV Cont2,#0 ;总计数值 256

AD_TEST:

MOV R7,#0 ;TON 计数值 256 开始转换

AD_LOOP:

广州周立功单片机发展有限公司 Tel: (020) 8730976 38730977 Fax: 38730925 http://www.zlgmcu.com

- 16 -

MOV A,CMP1

JB ACC.1,AD_HIGH

CLR AD_CON ;输出负脉冲

DEC R7

SJMP AD_COUNT

AD_HIGH:

SETB AD_CON ;输出正脉冲

NOP

NOP

NOP ;平衡时间

AD_COUNT:

LCALL DELAY10us

DJNZ Cont2,AD_LOOP ;未完成 256 次循环 继续

DJNZ Cont1,AD_TEST

RET ;返回值 R7 即是 AD 值

;---------------------------------------------------------

DELAY10us:

MOV bak,#5

DJNZ bak,$

RET

;*********************************************************



END






自动换量程电压表的设计.pdf

返回顶部