基于单片机的多路数据采集ADCWord文件下载.docx
《基于单片机的多路数据采集ADCWord文件下载.docx》由会员分享,可在线阅读,更多相关《基于单片机的多路数据采集ADCWord文件下载.docx(15页珍藏版)》请在冰豆网上搜索。
STC89C51、ADC0809、8路电压采集。
2.1系统设计方案
在电量的测量中,电压、电流和频率是最基本的三个被测量,其中电压量的测量最为经常。
而且随着电子技术的发展,更是经常需要测量高精度的电压,所以数字电压表就成为一种必不可少的测量仪器。
本次设计主要由三个模块组成:
A/D转换模块,数据处理模块及显示模块。
A/D转换主要由芯片ADC0809来完成,它负责把采集到的模拟量转换为相应的数字量在传送到数据处理模块。
数据处理则由芯片STC89C51来完成,其负责把ADC0809传送来的数字量经过一定的数据处理,产生相应的显示码送到显示模块进行显示;
此外它还控制着ADC0809芯片工作。
2.2总体设计方案
图1系统原理总框图
3硬件设计
3.1晶振电路
晶体振荡器,简称晶振,它可以等效成一个电容和一个电阻并联再串联一个电容的二端网络。
晶振有一个重要的参数,那就是负载电容值,选择与负载电容值相等的并联电容,就可以得到晶振标称的谐振频率。
图2晶振电路
3.2P0口上拉电阻
图3九排上拉电阻
本次设计中九位排阻在依次连接单片机P0口各引脚的同时并依序连接数码管各引脚(上拉电阻VCC端接单片机VCC端)。
上拉电阻既能为单片机提供部分电压能力,同时也能起到预防线路中电流过大的作用。
3.38路电压输入模块
电位器是可变电阻器的一种。
通常是由电阻体与转动或滑动系统组成,即靠一个动触点在电阻体上移动,获得部分电压输出。
电位器的作用即是调节电压(含直流电压与信号电压和电流的大小)。
图58路电压输入电路
3.4显示模块
四位数码管是一种半导体发光器件,其基本单元是发光二极管。
本次设计用的是4位共阴数码管,其内部结构如图6。
图6四位数码管内部结构图
3.5AD转换模块
本设计中AD转换采用ADC0809A芯片。
ADC0809是美国国家半导体公司生产的CMOS工艺8通道,8位逐次逼近式A/D模数转换器。
其内部有一个8通道多路开关,它可以根据地址码锁存译码后的信号,只选通8路模拟输入信号中的一个进行A/D转换。
该芯片具有以下特性:
1)8路输入通道,8位A/D转换器,即分辨率为8位;
2)具有转换起停控制端;
3)转换时间为100μs(时钟为640kHz时),130μs(时钟为500kHz时);
4)单个+5V电源供电;
5)模拟输入电压范围0~+5V,不需零点和满刻度校准;
图7ADC0809引脚图
ADC0809芯片有28条引脚,采用双列直插式封装,其芯片引脚图如图7所示。
下面说明各引脚功能。
(1)IN0~IN7:
8路模拟量输入端。
(2)D0~D7:
8位数字量输出端。
D0~D7均为三态缓冲输出形式,可以和单片机的数据线直接相连。
D0为最低位,D7为最高位。
(3)A、B、C:
3位地址输入线,A为低地址,C为高地址,用于选通8路模拟输入中的一路。
(4)ALE:
地址锁存允许信号,输入高电平有效。
对应ALE上跳沿,A、B、C地址状态送入地址锁存器中。
(5)START:
A/D转换启动脉冲输入端,输入一个正脉冲(至少100ns宽)使其启动(脉冲上升沿使0809复位,下降沿启动A/D转换)。
(6)EOC:
A/D转换结束信号输出,当A/D转换结束时,此端输出一个高电平,转换期间一直为低电平。
(7)OE:
数据输出允许信号,输入高电平有效。
当A/D转换结束时,此端输入一个高电平,才能打开输出三态门,输出数字量。
(8)CLK:
时钟脉冲输入端,要求时钟频率不高于640KHZ。
ADC0809的内部没有时钟电路,所需时钟信号由外界提供,因此有时钟信号引脚。
(9)VREF(+)、VREF(-):
基准电压。
用来与输入的模拟信号进行比较,作为逐次逼近的基准。
A/D转换后得到的数据应及时传送给单片机进行处理。
数据传送的关键问题是如何确认A/D转换的完成,因为只有确认完成后,才能进行传送。
为此可采用如下方式。
A/D转换芯片有表明转换完成的状态信号,ADC0809的EOC端。
因此可以用查询方式,查询EOC的状态,可确认转换是否完成,并接着进行数据传送。
3.6八路led灯显示
根据输入通道选择点亮对应的led灯。
3.7实物调试图
4.软件设计
4.1Proteus软件仿真
对抢答器电路图的Proteus软件仿真主要是由我完成的,在实际电路设计中,需要先通过仿真软件测试电路以及编译的程序,检查外围电路设计是否合理,软件编译是否正确,以及软件和硬件电路能否正常配合工作,能否准确的实现所设计的功能。
如果测试通过,电路仿真没有问题能完全实现功能的话就可以实际的做板子的焊接工作了。
我选择了常用的单片机仿真软件proteus7.0以及keil进行仿真。
4.1.1仿真开始
点击开始仿真便出现上图界面,此时数码管上显示的是第一个滑动变阻器上的电压,对应第一个滑动变阻器下面那个LED灯也为亮的状态。
这时为手动模式,当按一下按键,检测通道便切换为第二路,同时数码管显示和LED指示都发生相应变化,结果如图8所示。
图8仿真开始
图9手动切换输入通道
4.1.2设置自动或者手动采集方式
如图8所示,长按下进入自动采集并显示状态。
每隔3s,跳到下一个采集通道。
图10按下开关进入自动采集状态
4.2程序流程图
根据模块的划分原则,将该程序划分初始化模块,A/D转换子程序和显示子程序,这三个程序模块构成了整个系统软件的主程序。
程序主框图如图11所示。
图11程序设计流程图
A/D转换流程图,如图12所示。
图12A/D转换流程图
按键切换流程图,如图13所示。
图13按键切换流程图
总结
在本次设计多路数据采集的课设过程中,我们利用AT89C51单片机及ADC0809芯片,利用单片机的定时器/计数器定时和计数的原理输出需要的时钟信号,利用Proteus和Keil软件设计出实验电路,并且完成了电路板的焊接工作,将件和硬件结合在一起完成了课设的任务。
在本次课设中,我意识到将理论知识与实践相结合的重要性,对于单片机这样的课程,仅仅通过了解课本上的知识是远远不够的,我通过查资料和搜集有关文献,培养了自学能力,通过利用软件仿真和焊接电路,在很大程度上提高了我的动手能力。
我们在课设的过程中,遇到了很多问题,比如我在硬件电路的搭建过程中错把共阴极数码管接成了共阳极数码管,使得数码管无法正常显示,通过查看数码管的资料,我修改了显示程序,调试出正确的结果,类似的问题出现了很多,通过一一排查,终于完成了课设任务,结果表明,有付出必有收获,把握重点、攻克难关,活学活用对于牢固的掌握知识,是非常有用的。
在此次课设中,我学到了很多,也通过不断纠正自己的错误,意识到自身的不足,我对知识的掌握还没有实现深层次的理解记忆,我相信这些教训都为我以后的学习奠定了良好的基础,并且在以后的学习中我要有耐心,不能急功近利。
参考文献
[1]王思明,张金敏,苟军年.单片机原理及应用系统设计[M].北京:
人民邮电出版社,2008.
[2]冯育长,邹小兵.单片机系统设计与实例指导[M].西安:
西安电子科技大学出版社,2004.
附录A源程序
程序如下:
#include<
reg51.h>
//头文件定义
#defineucharunsignedchar//宏定义
#defineuintunsignedint
sbitP07=P0^7;
//控制数码管
//0809控制端口定义
sbitOE=P3^2;
sbitEOC=P3^1;
sbitST=P3^0;
sbitCLK=P3^3;
//时钟定义
sbitA_AD=P2^2;
sbitB_AD=P2^1;
sbitC_AD=P2^0;
sbitWei1=P2^4;
sbitWei2=P2^5;
sbitWei3=P2^6;
sbitWei4=P2^7;
sbitHc138_C=P3^4;
sbitHc138_B=P3^5;
sbitHc138_A=P3^6;
sbitMode_Key=P3^7;
sbitBeep=P2^3;
//共阴数码管段码定义0,1,2,3,4,5,6,7,8,9,V
ucharcodetable[11]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x3e};
floatAd_Value,V_Value;
ucharVOL_Vlaue[3];
ucharch_change=0xf0;
//通道选择变量0xf0-0xf7,8路选择
voiddelayms(uintxms)
{
uinti,j;
for(i=xms;
i>
0;
i--)
for(j=110;
j>
j--);
}
voidTimer_Init()
TMOD=0x11;
//T0:
16位计数T1:
16位计数
TH0=(65536-200)/256;
//定时器用于输出的时钟
TL0=(65536-200)%256;
TH1=(65536-50000)/256;
TL1=(65536-50000)%256;
EA=1;
ET0=1;
ET1=1;
TR0=1;
//TR1=1;
floatGet_0809_Ad(ucharCH)//CH:
0xf0-0xf7,对应8个通道
ST=0;
//启动AD转换
OE=0;
ST=1;
switch(CH)
{
case0xf0:
C_AD=0;
B_AD=0;
A_AD=0;
break;
case0xf1:
A_AD=1;
case0xf2:
B_AD=1;
case0xf3:
case0xf4:
C_AD=1;
case0xf5:
case0xf6:
case0xf7:
default:
}
while(EOC==0);
OE=1;
Ad_Value=P1;
//从P1口读取数据
returnAd_Value;
voiddisplay()
{
V_Value=(Get_0809_Ad(ch_change)*1.0/255.0)*500.0;
//数据处理
VOL_Vlaue[0]=V_Value/100;
VOL_Vlaue[1]=(uint)V_Value/10%10;
VOL_Vlaue[2]=(uint)V_Value%10;
Wei1=0;
P0=table[VOL_Vlaue[0]];
P07=1;
//显示小数点
delayms(5);
Wei1=1;
Wei2=0;
P0=table[VOL_Vlaue[1]];
Wei2=1;
Wei3=0;
P0=table[VOL_Vlaue[2]];
Wei3=1;
Wei4=0;
P0=table[10];
//最后一个符号‘V’
Wei4=1;
voidKey()//实现自动循环检测与手动循环检测
uintkey_press=0;
if(Mode_Key==0)
Beep=0;
delayms(100);
Beep=1;
while(Mode_Key==0)
key_press++;
delayms(10);
if(key_press>
=200)
=200)//2s
TR1=!
TR1;
else
ch_change=ch_change+1;
if(ch_change==0xf8)
ch_change=0xf0;
}
voidLed_Dis()
switch(ch_change)
Hc138_C=0;
Hc138_B=0;
Hc138_A=0;
Hc138_A=1;
Hc138_B=1;
Hc138_C=1;
voidmain()
Timer_Init();
while
(1)
Key();
display();
//显示数据
Led_Dis();
/******************************************
*定时器服务函数
******************************************/
voidtime0()interrupt1//TO中断服务,提供时钟信号
//5k时钟频率
CLK=~CLK;
uintt1_flag;
voidtime1()interrupt3
t1_flag++;
if(t1_flag==20*3)//到达3秒
t1_flag=0;
ch_change++;