
直流电压表的设计
一、实验目的
1 理解双积分A/D转换器7109及数字电压表的工作原理。
2 掌握直流电压表的界面设计和软件设计。
3.测量数据的误差分析。
二、实验任务和内容
1 设计一个直流电压表,设计要求为
(1)测量量程分为200mV、400mV、800mV、2V、4V、8V;
(2)测量分辩率为12bit;
(3)测量对象可选择为可调电位器的输出或外部电压
2 设计完成后,用电压表不同量程进行测量,求相对误差。
三、实验器材
1 计算机(具有运行windows2000和图形化控件的能力) 1台
2 SJ-8002B电子测量实验箱 1台
3 Q9连接线 1根
4 4 1/2数字万用表 1台
四、实验原理
1、直流电压表原理
直流电压表的测量原理是,被测模拟直流电压经输入放大后,经A/D转换器为数字量,通过计算机的EPP接口传到计算机进行数据处理,将测量结果显示在计算机屏幕上。本实验使用“SJ8002B电子测量实验箱”的双积分A/D转换器7109完成直流电压的数字化转换,采样 PC机的虚拟仪器软件平台(LabVIEW)完成界面设计和软件设计,实现直流电压的数字化测量。测量原理如图1所示
图1 直流电压测量原理框图
42 A/D7109的接口工作原理
本实验双积分A/D转换器ICL7109实验电路图。
图2 双积分式A/D转换器7109测量电压原理图
ICL 7109 是双积分式12 位A/D转换器,转换时间由外部时钟周期决定,为10140/58个时钟周期。其主要引脚定义如下:
① B1~B12:12bit的数据输出端
②OR:溢出判别,输出高电平表示过量程;反之,数据有效。
③POL:极性判别,输出高电平表示测量值为正值;反之,负值。
④MODE:方式选择, 当输入低电平信号时,转换器处于直接输出工作方式。此时可在片选和字节使能的控制下直接读取数据;当输入高电平时,转换器将在信号信号握手方式的每一转换周期的结尾输出数据(本实验选用直接输出工作方式)。
⑤REF:外部参考电压输入(本实验用其典型值:2048V)。
⑥INL,INH:输入电压端口(有效范围是参考电压的2倍)。
⑦OO,OI:外部时钟输入(本实验用其典型值:3579MHz)。
⑧RUN/HOLD_:运行/保持输入, 当输入高电平时,每经8192时钟脉冲完成一次转换;当输入低电平时,完成正在进行的转换,并停在自动调零阶段
⑨STATUS:状态输出,输出高电平,表明芯片处于积分和反向积分阶段;输出为低电平,表明反向积分结束,数据被锁存,模拟部分处于自动返回零态阶段。
⑩CE/LOAD_:片选,当其为低电平时,数据正常输出;当其为高电平时,所有数据输出端(B1~B12、POL、OR)均处于高阻状态。
⑾LBEN_:低字节使能,输入低电平时,数据线输出低位字节B1~B8。
⑿HBEN_:高字节使能,输入低电平时,数据线输出高位字节B9~B12及POL、OR的状态值。
A/D7109转换时序:ICL7109直接接口方式的定时图如图3所示。
图3 7109转换时序
7109的A/D转换关系为:
(1)
式中, —— A/D转换器输入电压;
—— A/D转换结果的12bit数字量;
—— A/D转换器外部参考输入电压,调节为=2048V;
由式(1)可知,若=2048V ,则即为以mv单位表示了,即
43 输入通道电路
外部待测直流电压信号从实验箱的DCin的Q9接线端输入如图3。另外,实验箱上提供了通过电位器调节的-4096V-+4096V的直流电压。由于实验中双积分式A/D转换器7109的输入电压范围为:-4096V-+4096V,为了较好的适应A/D转换器的输入范围,不同大小的待测模拟电压信号需经过不同的增益进行信号放大。增益的选择由计算机发出信号控制模拟开关选择。
图4 实验连接图
44 实验原理图
实验箱提供直流电压测量电路原理图如图4所示
图5 直流电压测量电路原理图
五、设计指导 在实验设计之前应认真思考设计任务要求,仔细阅读实验原理。
51功能与前面板设计
虚拟直流数字电压表主要完成对电位器或外部直流电压的测量与显示。因此,在虚拟仪器界面上需有测量对象的选择功能。为了适应不同大小的待测模拟电压信号,还应有测量量程选择功能,量程设置10档: 40mV、80mV、200mV、400mV、800mV、2V、4V、8V(对应增益:×100 、× 50、× 20、×10、×5、×2、×1、×05),量程缺省值设为8V。界面上设置有超量程指示灯,当测量溢出时,超量程指示灯点亮。测量结果同时进行表盘和数字显示,并通过实验箱上的七段LED显示出来。此外,界面上还需设置测量的启动和退出测量功能。
图5为前面板设计的参考。
图6 虚拟直流数字电压表面板
前面板控件说明如表1:
表1 前面板控件
控件类别
序号
名称
控件在控件模板中的位置
注释
指示类
(1)
电压显示表盘
All controls>Numeric>Meter
设置电压表的显示量程属性,对不同测量量程进行显示控制
(2)
超量程指示灯
LEDS>Round LED
溢出时点亮
(3)
电压数字显示框
Num Indis>Numeric Indicator
设置显示量程属性,对不同显示位数进行控制
测量选择类
(4)
量程选择旋钮
Num Ctrls>Dial
用于选择测量量程
(5)
测试对象选择开关
AllControls>Classic Controls>Classic Boolean>HorizontalSwitch
选择测试对象
程序控制类
(6)
退出
Buttons>OK Button
控制程序退出
(7)
测量
Buttons>Push Button
控制程序开始
52程序设计指导
SJ8002B电子测量实验箱通过EPP接口和计算机主机相连,通过EPP接口 *** 作实验箱的双积分A/D转换器7109的 *** 作步骤依次是,EPP接口的初始化、EPP接口的读数检查、 启动A/D7109转换、读取转换数据、数据的显示处理。本程序设计的主要实现已经做成底层fp函数(用Labwindows/CVI实现),在程序设计时可直接调用实验箱提供的驱动函数动态链接库(即cvidlldll函数),驱动函数原型及常数和变量在cvidllprj中。
1.程序流程图
整个程序采取顺序结构,整个设计思路流程图如下:
图7 直流电压表程序流程图
//按照我的电路图我这是四位有负温度显示你可以看一下。有什么问题可以问我?
/
created: 2010/07/27
created: 27:7:2010 10:27
filename: D:\Keil Debug\ds18b20c
file path: D:\Keil Debug
file base: ds18b20
file ext: c
author: Honguo ZHU
purpose:
//DS18B20的读写程序,数据脚P27
//温度传感器18B20汇编程序,采用器件默认的12位转化
//最大转化时间750微秒,显示温度-55到+125度,显示精度
//为01度,显示采用4位LED共阳显示测温值
//P0口为段码输入,P34~P37为位选
/
#include "reg51h"
#include "intrinsh" //_nop_();延时函数用
#define Disdata P0 //段码输出口
#define discan P3 //扫描口
#define uchar unsigned char
#define uint unsigned int
#define READROM_18b20_CM 0x33
#define MATCHROM_18b20_CM 0x55
#define SKIPROM_18b20_CM 0xCC
#define SEARCHROM_18b20_CM 0xF0
#define ALARMSEARCH_18b20_CM 0xEC
#define CONVERTT_CM 0x44
#define RSCRATCHPAD_CM 0xBE
#define WSCRATCHPAD_CM 0x4E
#define CSCRATCHPAD_CM 0x48
#define RECALLE2_CM 0xB8
#define RPOWERSUNNLY_CM 0xB4
sbit DQ=P2^7; //温度输入口
sbit DIN=P0^7; //LED小数点控制
//
//
//温度小数部分用查表法//
uchar code ditab[16]=
{0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,0x05,0x06,0x06,0x07,0x08,0x08,0x09,0x09};
//
uchar code dis_7[12]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0xbf};
//共阳LED段码表 "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "不亮" "-"
uchar code scan_con[4]={0x8f,0x4f,0x2f,0x1f}; //列扫描控制字
uchar data temp_data[2]={0x00,0x00}; //读出温度暂放
uchar data display[5]={0x00,0x00,0x00,0x00,0x00}; //显示单元数据,共4个数据和一个运算暂用
//
//
//
/11us延时函数/
//
void delay(uint t)
{
for (;t>0;t--);
}
//
/显示函数/
scan()
{
char k;
for(k=0;k<4;k++) //4位LED扫描控制
{
Disdata = 0xff; //
discan=scan_con[k]; //位选
Disdata=dis_7[display[k]]; //数据显示
if (k==1)
{
DIN=0;
} //小数点显示
delay(300);
}
}
//
//
/DS18B20复位函数/
ow_reset(void)
{
char presence=1;
while(presence)
{
while(presence)
{
DQ=1;_nop_();_nop_(); //从高拉倒低
DQ=0;
delay(50); //550 us
DQ=1;
delay(6); //66 us
presence=DQ; //presence=0 复位成功,继续下一步
}
delay(45); //延时500 us
presence=~DQ;
}
DQ=1; //拉高电平
}
//
//
/DS18B20写命令函数/
//向1-WIRE 总线上写1个字节
void write_byte(uchar val)
{
uchar i;
for(i=8;i>0;i--)
{
DQ=1;_nop_();_nop_(); //从高拉倒低
DQ=0;_nop_();_nop_();_nop_();_nop_(); //5 us
DQ=val&0x01; //最低位移出
delay(6); //66 us
val=val/2; //右移1位
}
DQ=1;
delay(1);
}
//
/DS18B20读1字节函数/
//从总线上取1个字节
uchar read_byte(void)
{
uchar i;
uchar value=0;
for(i=8;i>0;i--)
{
DQ=1;_nop_();_nop_();
value>>=1;
DQ=0;_nop_();_nop_();_nop_();_nop_(); //4 us
DQ=1;_nop_();_nop_();_nop_();_nop_(); //4 us
if(DQ)
{value|=0x80;}
delay(6); //66 us
}
DQ=1;
return(value);
}
//
/读出温度函数/
//
uint read_temp()
{
uint temp;
// ow_reset(); //总线复位
// delay(200);
// write_byte(SKIPROM_18b20_CM); //发命令
// write_byte(CONVERTT_CM); //发转换命令
ow_reset();
delay(1);
write_byte(SKIPROM_18b20_CM); //发命令
write_byte(RSCRATCHPAD_CM);
temp_data[0]=read_byte(); //读温度值的第字节
temp_data[1]=read_byte(); //读温度值的高字节
temp=temp_data[1];
temp<<=8;
temp=temp|temp_data[0]; // 两字节合成一个整型变量。
return temp; //返回温度值
}
//
/温度数据处理函数/
//二进制高字节的低半字节和低字节的高半字节组成一字节,这个
//字节的二进制转换为十进制后,就是温度值的百、十、个位值,而剩
//下的低字节的低半字节转化成十进制后,就是温度值的小数部分
//
work_temp(uint tem)
{
uchar n=0;
if(tem>6348) // 温度值正负判断
{
tem=65536-tem;
n=1;
} // 负温度求补码,标志位置1
display[4]=tem&0x0f; // 取小数部分的值
display[0]=ditab[display[4]]; // 存入小数部分显示值
display[4]=tem>>4; // 取中间八位,即整数部分的值
display[3]=display[4]/100; // 取百位数据暂存
display[1]=display[4]%100; // 取后两位数据暂存
display[2]=display[1]/10; // 取十位数据暂存
display[1]=display[1]%10;
/符号位显示判断/
if(!display[3])
{
display[3]=0; //最高位为0时不显示
if(!display[2])
{
display[2]=0; //次高位为0时不显示
}
}
if(n)
{
display[3]=0x0b;
} //负温度时最高位显示"-"
}
//
//
/主函数/
main()
{
uint h;
Disdata=0xff; //初始化端口
discan=0xff;
for(h=0;h<4;h++) //开机显示"0000"
{display[h]=0;}
ow_reset(); //开机先转换一次
write_byte(SKIPROM_18b20_CM); //Skip ROM
write_byte(CONVERTT_CM); //发转换命令
for(h=0;h<100;h++) //开机显示"0000"
{scan();}
while(1)
{
work_temp(read_temp()); //处理温度数据
scan(); //显示温度值
}
}
//
//结束//
#include <reg52H>
extern GetTemp(); //声明引用外部函数
extern unsigned int idata Temperature; // 声明引用外部变量
void delay(unsigned int i);
//else IO
sbit LS138A=P2^2; //管脚定义
sbit LS138B=P2^3;
sbit LS138C=P2^4;
//此表为 LED 的字模, 共阴数码管 0-9 -
unsigned char code Disp_Tab[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40};
unsigned long LedOut[5],LedNumVal;
void system_Ini()
{
TMOD|= 0x11;
TH1 = 0xD8; //10
TL1 = 0xF0;
IE = 0x8A;
TR1 = 1;
}
main()
{ unsigned char i;
system_Ini();
while(1)
{
GetTemp();
/以下将读18b20的数据送到LED数码管显示/
LedNumVal=Temperature; //把实际温度送到LedNumVal变量中
LedOut[0]=Disp_Tab[LedNumVal%10000/1000];
LedOut[1]=Disp_Tab[LedNumVal%1000/100];
LedOut[2]=Disp_Tab[LedNumVal%100/10]; //十位
LedOut[3]=Disp_Tab[LedNumVal%10]; //个位
for(i=0; i<4; i++)
{
P0 = LedOut[i] ;
switch(i)
{ //138译码
case 0:LS138A=0; LS138B=0; LS138C=0; break;
case 1:LS138A=1; LS138B=0; LS138C=0; break;
case 2:LS138A=0; LS138B=1; LS138C=0; break;
case 3:LS138A=1; LS138B=1; LS138C=0; break;
}
delay(100);
}
P0 = 0;
}
}
//延时程序
void delay(unsigned int i)
{
char j;
for(i; i > 0; i--)
for(j = 200; j > 0; j--);
}
/此部分为18B20的驱动程序/
#include <reg52H>
#include <intrinsh>
sbit D18B20=P3^7;
#define NOP() _nop_() / 定义空指令 /
#define _Nop() _nop_() /定义空指令/
void TempDelay (unsigned char idata us);
void Init18b20 (void);
void WriteByte (unsigned char idata wr); //单字节写入
void read_bytes (unsigned char idata j);
unsigned char CRC (unsigned char j);
void GemTemp (void);
void Config18b20 (void);
void ReadID (void);
void TemperatuerResult(void);
bit flag;
unsigned int idata Temperature;
unsigned char idata temp_buff[9]; //存储读取的字节,read scratchpad为9字节,read rom ID为8字节
unsigned char idata id_buff[8];
unsigned char idata p,TIM;
unsigned char idata crc_data;
unsigned char code CrcTable [256]={
0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65,
157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220,
35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98,
190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255,
70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102, 229, 187, 89, 7,
219, 133, 103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 196, 154,
101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36,
248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185,
140, 210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113, 147, 205,
17, 79, 173, 243, 112, 46, 204, 146, 211, 141, 111, 49, 178, 236, 14, 80,
175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82, 176, 238,
50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115,
202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139,
87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22,
233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168,
116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53};
//
/
Function:延时处理
parameter:
Return:
Modify:
/
void TempDelay (unsigned char idata us)
{
while(us--);
}
/
Function:18B20初始化
parameter:
Return:
Modify:
/
void Init18b20 (void)
{
D18B20=1;
_nop_();
D18B20=0;
TempDelay(80); //delay 530 uS//80
_nop_();
D18B20=1;
TempDelay(14); //delay 100 uS//14
_nop_();
_nop_();
_nop_();
if(D18B20==0)
flag = 1; //detect 1820 success!
else
flag = 0; //detect 1820 fail!
TempDelay(20); //20
_nop_();
_nop_();
D18B20 = 1;
}
/
Function:向18B20写入一个字节
parameter:
Return:
Modify:
/
void WriteByte (unsigned char idata wr) //单字节写入
{
unsigned char idata i;
for (i=0;i<8;i++)
{
D18B20 = 0;
_nop_();
D18B20=wr&0x01;
TempDelay(3); //delay 45 uS //5
_nop_();
_nop_();
D18B20=1;
wr >>= 1;
}
}
/
Function:读18B20的一个字节
parameter:
Return:
Modify:
/
unsigned char ReadByte (void) //读取单字节
{
unsigned char idata i,u=0;
for(i=0;i<8;i++)
{
D18B20 = 0;
u >>= 1;
D18B20 = 1;
if(D18B20==1)
u |= 0x80;
TempDelay (2);
_nop_();
}
return(u);
}
/
Function:读18B20
parameter:
Return:
Modify:
/
void read_bytes (unsigned char idata j)
{
unsigned char idata i;
for(i=0;i<j;i++)
{
p = ReadByte();
p++;
}
}
/
Function:CRC校验
parameter:
Return:
Modify:
/
unsigned char CRC (unsigned char j)
{
unsigned char idata i,crc_data=0;
for(i=0;i<j;i++) //查表校验
crc_data = CrcTable[crc_data^temp_buff[i]];
return (crc_data);
}
/
Function:读取温度
parameter:
Return:
Modify:
/
void GemTemp (void)
{
read_bytes (9);
if (CRC(9)==0) //校验正确
{
Temperature = temp_buff[1]0x100 + temp_buff[0];
// Temperature = 0625;
Temperature /= 16;
TempDelay(1);
}
}
/
Function:内部配置
parameter:
Return:
Modify:
/
void Config18b20 (void) //重新配置报警限定值和分辨率
{
Init18b20();
WriteByte(0xcc); //skip rom
WriteByte(0x4e); //write scratchpad
WriteByte(0x19); //上限
WriteByte(0x1a); //下限
WriteByte(0x7f); //set 11 bit (0125)
Init18b20();
WriteByte(0xcc); //skip rom
WriteByte(0x48); //保存设定值
Init18b20();
WriteByte(0xcc); //skip rom
WriteByte(0xb8); //回调设定值
}
/
Function:读18B20ID
parameter:
Return:
Modify:
/
void ReadID (void)//读取器件 id
{
Init18b20();
WriteByte(0x33); //read rom
read_bytes(8);
}
/
Function:18B20ID全处理
parameter:
Return:
Modify:
/
void TemperatuerResult(void)
{
p = id_buff;
ReadID();
Config18b20();
Init18b20 ();
WriteByte(0xcc); //skip rom
WriteByte(0x44); //Temperature convert
Init18b20 ();
WriteByte(0xcc); //skip rom
WriteByte(0xbe); //read Temperature
p = temp_buff;
GemTemp();
}
void GetTemp()
{
if(TIM==100) //每隔 1000ms 读取温度
{ TIM=0;
TemperatuerResult();
}
}
/
[ t1 (10ms)中断] 中断
/
void T1zd(void) interrupt 3
{
TH1 = 0xD8; //10
TL1 = 0xF0;
TIM++;
}
以上就是关于用8051单片机和A/D7109,LED显示屏设计温度监测系统全部的内容,包括:用8051单片机和A/D7109,LED显示屏设计温度监测系统、18b20和51单片机实现温度显示,求程序、急求关于51单片机开发板实现对led的温控和光控的方法和程序等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)