摘 要
本设计利用STC15F2K60S2单片机的A/D转换功能设计一个直流数字电压表,由A/D转换、数据处理及显示控制等组成,测量0-5V范围内的输入电压值,并由4位共阴8段数码管扫描显示,最大分辨率0.01V,误差在0.05V范围内。
关键词:数字电压表;STC15F2K60S2;共阴数码管
目 录
一、数字电压表简介 5
二、数字电压表设计方案论证及选择 5
1.主控芯片 5
2.显示部分 5
三、电路设计原理 6
四、主要元器件的介绍 6
1.STC15F2K60S2单片机介绍 6
2.TL431芯片介绍 7
3.四位共阴数码管简介 8
4.74HC595芯片介绍 8
5.数模转换功能的介绍 8
五、部分电路介绍 10
1.电源模块 10
2.TL431基准电压模块 10
3.数码管显示模块 11
六、系统软件设计 11
七、设计总原理图 13
一、数字电压表简介
数字电压表出现在50年代初,60年代末发起来的电压测量仪表,简称DVM。它采用的是数字化测量技术,把连续的模拟量,也就是连续的电压值转变为不连续的数字量,加以数字处理然后再通过显示器件显示。采用单片机的数字电压表由于测量精度高、速度快,读数时也非常方便,抗干扰能力强,可扩展性强等优点已被广泛的应用于电子及电工的测量、工业自动化仪表、自动测试系统等智能化测量领域,显示出强大的生命力。
数字电压表最初是伺服步进电子管比较式,其优点是准确度比较高,但是采样速度慢,重量达几十公斤,体积大。继之出现了斜波式电压表,它的速度方面稍有提高,但是准确度低,稳定性差,再后来出现了比较式仪表改进逐次渐近式结构,它不仅保持了比较式准确度高的优点,而且速度也有了很大的提高,但它有一缺点是抗干扰能力差,很容易受到外界各种因素的影响。随后,在斜波式的基础上双引伸出阶梯波式,它的唯一的进步是成本降低了,可是准确宽,速以及抗干扰能力都未能提高。目前实现电压数字化测量的方法仍然模-数(A/D)转换的方法。
二、数字电压表设计方案论证及选择
主要设计方框图如下:
图1 设计方框图
1.主控芯片
方案1:选用专用转化芯片INC7107实现电压的测量和实现,用四位数码管显示出最后的转换电压结果。缺点是转换的精度低,内部电压转换和控制部分不可控制。优点是价格低廉。
方案2:选用单片机STC15F2K60S2及内部集成的A/D转换功能实现电压的转换和控制,用四位数码管显示出最后的转换电压结果。缺点是价格稍贵。优点是转换精度高,且转换的过程和控制、显示部分可以控制。
基于课程设计的要求和实验室能提供的芯片,本设计选用方案2。
2.显示部分
方案1:选用四个单体的共阴数码管。优点是价格比较便宜。缺点是焊接时比较麻烦,容易出错。
方案2:选用一个四联的共阴极数码管。优点是便于控制,价格低廉,焊接简单。
因而本设计选用方案2显示数据。
三、电路设计原理
本设计使用STC15F2K60S2的P1.3做ADC采集外部电压通道,使用外部TL431基准计算外部电压。模拟电压经过档位切换到不同的分压电路筛减后,经隔离干扰送到A/D转换器进行A/D转换。然后送到单片机中进行数据处理。处理后的数据送到四位共联数码管中显示。本设计包括电源模块,按键模块,1.27V 掉电检测模块,TL431基准电压模块,和数码管显示模块实现外部电压采集。原理框图如下:
图2 电路原理框图
四、主要元器件的介绍
1.STC15F2K60S2单片机介绍
图3 单片机模型图
STC15F2K60S2单片机由STC宏晶科技公司生产的,采用STC第八代 技术,不需要外部晶振和外部复位的单片机,可省掉外部EEPROM,利用IAP技术—ISP/IAP,在线编程,无需编程器/仿真器,2K字节SRAM,双串口,两个独立串口,高速10位A/D转换器,8个输入通道 ,1个时钟/机器周期8051,高速,高可靠,超低功耗,超低价。STC15F2K60S2有PDIP、PQFP/TQFP及PLCC等三种封装形式,以适应不同产品的需求。
其主要特性如下:
1.增强型8051CPU,1T型,即每个机器周期只有1个系统时钟。
2.ISP/IAP功能,即在系统可编程/在应用可编程。
3.低功耗设计:低速模式、空闲模式、掉电模式。
4.8-62KB Flash 程序存储器。
5.6个定时器:两个16位可重装载初始值的定时器T0/T1,T2定时器,3路CCP可再实现3个定时器。
6.2个全双工异步串行口。
7.8通道高速10位ADC,速度可达30万次/秒。
8.高速SPI串行口通信接口。
9.多路可编程时钟输出。
10.最多42个I/O口。
2.TL431芯片介绍
图四 TL431芯片
TL431是一个有良好的热稳定性能的三端可调分流基准电压源。它的输出电压用两个电阻就可以任意地设置到从Vref(2.5V)到36V范围内的任何值。该器件的典型动态阻抗为0.2Ω,在很多应用中可以用它代替齐纳二极管,例如,数字电压表,运放电路、可调压电源,开关电源等等。
其主要特性如下:
1.可编程输出电压为36V
2.电压参考误差:±0.4% ,典型值@25℃(TL431B)
3.低动态输出阻抗,典型0.22Ω
4.负载电流能力1.0mA to 100mA
5.等效全范围温度系数50 ppm/℃典型
6.温度补偿操作全额定工作温度范围
7.低输出噪声电压
3.四位共阴数码管简介
图五 数码管封装图
数码管有两种:一种共阴极、另一种为共阳极,本次课程设计用的是共阴极。共阴数码管的公共端高电平,数码管0-9的C51编程为:
uchar code table[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef}
4.74HC595芯片介绍
图六 74HC595引脚图
74HC595具有8位移位寄存器和一个存储器,三态输出功能。 移位寄存器和存储器有相互独立的时钟。数据在SH_cp(移位寄存器时钟输入)的上升沿输入到移位寄存器中,在ST_cp(存储器时钟输入)的上升沿输入到存储寄存器中去。如果两个时钟连在一起,则移位寄存器总是比存储寄存器早一个脉冲。移位寄存器有一个串行移位输入(Ds),和一个串行输出(Q7’),和一个异步的低电平复位,存储寄存器有一个并行8位的,具备三态的总线输出,当使能OE时(为低电平),存储寄存器的数据输出到总线。将串行输入的8位数字,转变为并行输出的8位数字
5.数模转换功能的介绍
在本设计中,模数(A/D)转换模块是一个重要的模块,它关系到最后数电压表电压值的精确度,STC15F2K60S2芯片内模数转换器具有以下特点。
• 10 位 精度
• 8 路复用的单端输入通道
• 7 路差分输入通道
• 可选的左对齐ADC读数
• 0 - VCC 的 ADC输入电压范围
• 可选的2.5V ADC参考电压
• 连续转换或单次转换模式
• 通过自动触发中断源启动ADC转换
• ADC 转换结束中断
STC15F2K60S2有一个10位的逐次逼近型ADC。ADC与一个8通道的模拟多路复用器连接,能对来自端口 A 的 8 路单端输入电压进行采样。单端电压输入以 0V (GND) 为基准。器件还支持 16 路差分电压输入组合。两路差分输入 (ADC1、 ADC0 与 ADC3、 ADC2)有可编程增益级,在 A/D 转换前给差分输入电压提供 0dB(1x)、20dB(10x) 或 46dB(200x)的放大级。七路差分模拟输入通道共享一个通用负端(ADC1),而其他任何 ADC 输入可做为正输入端。如果使用 1x 或 10x 增益,可得到 8 位分辨率。如果使用 200x 增益,可得到 7 位分辨率。
该设计采用的是外部参考电压AREF,ADC0转换通道,连续自由转换功能。ADC 通过逐次逼近的方法将输入的模拟电压转换成一个 10 位的数字量。最小值代表GND,最大值代表AREF引脚上的电压再减去1 LSB,ADC转换结果为10位,存放于ADC数据寄存器ADCH及ADCL中。默认情况下转换结果为右对齐,但可通过设置 ADMUX 寄存器的 ADLAR 变为左对齐,该设计采用左对齐。
转换结束后 (ADIF 为高 ),转换结果被存入 ADC 结果寄存器 (ADCL, ADCH)。单次转换的结果如下:
式中,VIN 为被选中引脚的输入电压,VREF 为参考电压。
五、部分电路介绍
1.电源模块
图6 电路模块原理图
电源模块为主控制芯片提供5V电压。
2.TL431基准电压模块
图7 基准电压模块原理图
使用外部TL431基准计算外部电压,该模块提供是稳定的2.5V的基准电压。
3.数码管显示模块
图8 数码管模块原理图
数码管显示模块对测得的电压进行显示。通过74HC595控制四位共阴极数码管段选,通过另一个74HC595控制位选。
六、系统软件设计
本设计是硬件电路和软件编程相结合的设计方案,选择合适的编程语言是一个重要的环节。在单片机的应用系统程序设计时,常用的是汇编语言和C语言。汇编语言的特点是占用内存单元少,执行效率高。执行速度快。但它依赖于计算机硬件,程序可读性和可移植性比较差。而C语言虽然执行效率没有汇编语言高,但语言简洁,使用方便,灵活,运算丰富,表达化类型多样化,数据结构类型丰富,具有结构化的控制语句,程序设计自由度大,有很好的可重用性,可移植性等特点。
由于现在单片机的发展已经达到了很高的水平,内部的各种资源相当的丰富,CPU的处理速度非常的快。用C语言来控制单片机无疑是一个理想的选择。所以在本设计中采用C语言编写软件程序。
程序的总体流程如下图:
七、设计总原理图
图 5
九、源程序
#define DIS_DOT 0x20
#define DIS_BLACK 0x10
#define DIS_ 0x11
#define P1n_pure_input(bitn)P1M1 |= (bitn), P1M0 &= ~(bitn)
#define Cal_MODE 1 //每次测量连续读16次ADC 再平均计算. 分辨率0.01V
#define Timer0_Reload (65536UL -(MAIN_Fosc / 1000))
u8 code t_display[]={ 0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
0x00,0x40,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e,
0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x46};
u8 code T_COM[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //位码
sbit P_HC595_SER = P4^0; //pin 14 SER data input
sbit P_HC595_RCLK = P5^4; //pin 12 RCLk store (latch) clock
sbit P_HC595_SRCLK = P4^3; //pin 11 SRCLK Shift data clock
u8 LED8[8]; //显示缓冲
u8 display_index; //显示位索引
bit B_1ms; //1ms标志
u16 msecond;
u16 Bandgap;
u16 Get_ADC10bitResult(u8 channel); //channel = 0~7
void main(void)
{
u8 i;
u16 j;
P0M1 = 0;P0M0 = 0;//设置为准双向口P1M1 = 0;P1M0 = 0;//设置为准双向口P2M1 = 0;P2M0 = 0;//设置为准双向口P3M1 = 0;P3M0 = 0;//设置为准双向口P4M1 = 0;P4M0 = 0;//设置为准双向口P5M1 = 0;P5M0 = 0;//设置为准双向口P6M1 = 0;P6M0 = 0;//设置为准双向口P7M1 = 0;P7M0 = 0;//设置为准双向口display_index = 0;P1ASF = (1<<2) + (1<<3);//P1.2 P1.3做ADCP1M1 |= (0xc0);P1M0 &= ~(0xc0);//P1.2 P1.3设置成高阻ADC_CONTR = 0xE0;//90T, ADC power onTimer0_1T();Timer0_AsTimer();Timer0_16bitAutoReload();Timer0_Load(Timer0_Reload);Timer0_InterruptEnable();Timer0_Run();EA = 1;//打开总中断for(i=0; i<8; i++)LED8[i] = 0x10;//上电消隐
while(1)
{
if(B_1ms) //1ms到
{
B_1ms = 0;
if(++msecond >= 300) //300ms到
{
msecond = 0;
#if (Cal_MODE == 1)
Get_ADC10bitResult(2);
for(j=0, i=0; i<16; i++)
{
j += Get_ADC10bitResult(2);
}
Bandgap = j >> 4; //16次平均
Get_ADC10bitResult(4);
for(j=0, i=0; i<16; i++)
{
j += Get_ADC10bitResult(4); //读外部电压ADC
}
j = j >> 4; //16次平均
j = (u16)((u32)j * 250 / Bandgap); //计算外部电压, TL431电压为2.50V, 测电压分辨率0.01V
#endif
LED8[5] = j / 100 + DIS_DOT; //显示外部电压值
LED8[6] = (j % 100) / 10;
LED8[7] = j % 10;
}}}
}
u16 Get_ADC10bitResult(u8 channel) //channel = 0~7
{
ADC_RES = 0;
ADC_RESL = 0;
ADC_CONTR = (ADC_CONTR & 0xe0) | 0x08 | channel; //start the ADCNOP(4);
while((ADC_CONTR & 0x10) == 0) ; //wait for ADC finish
ADC_CONTR &= ~0x10; //清除ADC结束标志
return (((u16)ADC_RES << 2) | (ADC_RESL & 3));
}
void Send_595(u8 dat)
{
u8 i;
for(i=0; i<8; i++)
{
dat <<= 1;
P_HC595_SER = CY;
P_HC595_SRCLK = 1;
P_HC595_SRCLK = 0;
}
}
void DisplayScan(void)
{
Send_595(~T_COM[display_index]); //输出位码
Send_595(t_display[LED8[display_index]]); //输出段码
P_HC595_RCLK = 1;P_HC595_RCLK = 0;//锁存输出数据if(++display_index >= 8)display_index = 0;//8位结束回0
}
void timer0 (void) interrupt TIMER0_VECTOR
{
DisplayScan(); //1ms扫描显示一位
B_1ms = 1; //1ms标志
}
如果觉得《直流数字电压表设计》对你有帮助,请点赞、收藏,并留下你的观点哦!