简单的数字直流电压表电路及程序
设计简单的数字直流电压表。(量程0V-2V、测量速度大于或等于2次/秒±0.05V有超限报警,数字管显示。
3.5.1模块1:系统设计
(1)分析任务要求,写出系统整体设计思路
从试题的要求分析来看,主要内容是ADC用定时器定期读取转换电路的控制ADC转换器数据,将ADC转换器的数据计算为相应的电压值,最后显示在数字管上。
整体设计理念:硬件采用单片机P7段码输出数码管,P2口输出数字管的位控信号。P1的三个I/O管脚连接ADC通过查询定时器,转换器的接口T0中断标志是否有效启动ADC读取转换器的工作ADC转换器的转换结果。然后,根据ADC转换器的参考电压将ADC转换器的转换结果计算为相应的电压值,并显示在数字管上。
(2)选择单片机型号和所需外围设备型号,设计单片机硬件电路原理图
采用MCS51系列单片机At89S作为主控制器,为主控制器,包括数字管驱动,AD转换器TLC549、基准电压TL431等。
由于单片机驱动能力有限,数码管驱动采用两个四联阴极数码管显示。HC244作为数字管的驱动。HC2447段码输出线串联100欧姆电阻起限流作用。
AD精密基准电源转换器的参考电压TL431提供标准参考电压Vref 为2.5伏,Vref-为0伏。由于0V-2V内测误差控制在±0.05V因此,所以8 位A/D转换器可以满足要求。AD转换器TLC549以8位开关电容逐渐逼近A/D基于转换器的转换器结构CMOS A/D转换器。它们通过三态数据输出和模拟输入与微处理器或外围设备串行。TLC549只使用输入/输出时钟(I/O CLOCK)以及芯片选择 (CS)数据控制输入。TLC549的IO CLOCK最高输入频率可达1.1MHz。
TLC549提供了电影中的系统时钟,它通常工作在4MHz不需要外部元件。片内系统时钟使内部设备的操作独立于串行输入/输出的时间顺序,并允许TLC548和TLC549就像许多软件和硬件要求的一样 I/O CLOCK高速数据传输可以与内部系统时钟一起实现TLC549是每秒4000次转换的转换速度。TLC549 引脚排列如图3-17所示。
如图3-17 TLC549 引脚排列
TLC549 的工作时序如图3-18所示。
图3-18 TLC549 工作顺序
转换周期需要36个系统时钟周期(最大限度为 17μs),它开始于CS变成低电平后I/O CLOCK第八个下降边适用于存储器中存在地址的通道。
在CS最高有效位 变成低电平后(A7)自动放置DATA OUT总线上。其余7 位置(A6-A0)在前7个I/O CLOCK下降沿时钟同步输出。
TLC549的工作原理
TLC549是一个完善的单芯片数据采集系统。每个设备包括内部系统时钟、采样和维护,8位A/D该设备有两个控制输入:转换器、数据寄存器和控制逻辑电路。I/OCLOCK和芯片选择(CS)。这些控制输入和和和TTL与微处理器或小容易与微处理器或小型计算机串行通信。设备可在17岁μs或在更短的时间内完成转换。TLC549每25μs重复完整的输入-转换-输出(input-conversion-output)周期。
时钟和内部系统I/OCLOCK独立使用,不需要任何特定的速度或两者之间的相位关系。这种独立性简化了设备的硬件和软件控制任务。由于种独立性和系统时钟的内部生成,控制硬件和软件只需要使用I/O时钟读取以前的转换结果和启动转换。内部系统时钟以这种方式驱动转换电路,以控制硬件和软件不涉及任务。
当CS为高电平时,DATAOUT处于高阻状态I/OCLOCK(I/O禁止时钟)。正常控制时序为:
1.CS被拉到低电平CS前次转换结果的最高有效位变成低电平时(MSB)开始出现在DATAOUT端。
2.前4个I/OCLOCK第二、第三、第四和第五个最高有效位的输出周期下降。I/OCLOCK在第四个高电平到低电平跳转后,电影中的采样和保持电路开始模拟输入采样。采样操作主要包括内部电容器充电到模拟输入电压的电平。
3.然后三个I/OCLOCK周期加至I/OCLOCK端,在这些时钟周期的下降沿,第6、第7和第8个转换位被移出。
4.最后(8)时钟周期增加I/OCLOCK。此时钟周期高电平至低电平的跳变使片内采样和保持电路开始保持功能。保持功能在接着四个内部系统时钟周期内继续进行,在此之后保持功能结束且在下面32个系统时钟周期内完成转换,总共为36个周期。在第8个I/OCLOCK周期之后,CS必须变成高电平,否则,I/OCLOCK维护和转换功能的完成必须保持至少36个低电平系统时钟周期。在多个转换周期内CS保持低电平。在多个转换周期内使用CS保持低电平时一定要特别注意防止I/OCLOCK在线噪声闪变。I/OCLOCK闪变发生在微处理器/控制器和设备之间I/O时序将失去同步。此外,如果CS要变成高电平,必须保持高电平直到转换结束。CS从高电平到低电平的有效跳变会导致复位,使正在进行的转换失败。
在36个系统时钟周期发生之前,新的转换可以通过完成步骤1到4启动,正在进行的转换可以暂停。该操作产生了以前的转换结果,而不是正在进行的转换结果。
(3)分析软件任务要求,写程序设计思路,分配单片机内部资源,画程序流程图
该软件的任务包括定时器的定时功能AD转换器TLC549控制和数据读取,数字管动态扫描。程序设计理念,通过查询定时器中断标志来启动AD转换器TLC读取549的工作AD转换器的数据之后,再对数据进行计算换算为对应的电压值。
需要分配的单片机存储资源包括AD转换器数据的临存变量(re_data)、定时器溢出次数的计数变量(T_cnt)、数据转换系数(xishu)以及电压值(volt)等。
主程序的流程图如图3-19所示。主程序应循环完成以下任务:中断标志的查询AD读取转换器数据,转换电压值,动态扫描显示数字管。
图3-19数字电压表主程序流程图
(4)设计系统软件调试方案、硬件调试方案硬件联合调试方案
软件调试方案:伟福软件中的文件\在新文件中,新建C语言源程序文件,编写相应的程序。在“文件\在新项目菜单中,新项目并将C项目文件中包含语言源程序文件。
在 “项目\菜单中将编译C编译源文件,检查语法错误和逻辑错误。编译成功后,以 *.hex”和“*.bin 后缀目标文件。
硬件调试方案:在设计平台上,单片机P1.0接TLC549的CLK管脚,P1.1接TLC549的DOUT管脚,P1.2接TLC549的CS管脚。
将程序文件编译成目标文件后,将下载线安装在实验平台上,运行MCU下载程序flash 数据文件,点击编程按钮,将程序文件下载到单片机Flash中。
然后,重新启动单片机,检查编写的程序是否符合问题要求,试题内容是否全面完整。
3.6.2 模块2 程序设计
//晶振:11.0592MHz,定时器T0每50ms每0次中断一次.1秒读ADC一次
/* AD使用 转换器TLC549
p1.0-Clock
p1.1-Data out
p1.2-CS
*/
#include "reg51.h"
#include "intrins.h"
#include "math.h"
sbit ad_clk=P1^0;
sbit ad_dout=P1^1;
sbit ad_cs=P1^2;
unsigned char data re_data;
unsigned int data T_cnt;
double volt,xishu;
char code led_seg_code[10]={0x3f,0x06,0x05b,0x04f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
//led_seg_code代表0-9的7段码[0-9]
//---------------
void delay(unsigned int i)//延时
{ while(--i); }
//---------------
void led_show(double f)
{ unsigned char i,s;
unsigned int k,*j;
if (f<2)
{ k=f;//取整数 部分
i=k;
P0=led_seg_code[i] | 0x80;
P2=0xfb;
delay(50);
i=f*10;
i=i%10;
P0=led_seg_code[i];
P2=0xfd;
delay(50);
i=f*100; //取小数后1位
i=i%10;
P0=led_seg_code[i];
P2=0xfe;
delay(50);
else //超限报警,显示“---”
{ P0=0x40;
P2=0xfb;
delay(50);
//---------
P2=0xfd;
delay(50);
//-----------
P2=0xfe;
delay(50);
}
}
//----读取ADC转换器TLC549的数据----
unsigned char receive_data()
{unsigned char i,d;
d=0;
ad_cs=1; // /CS置高,片选无效
ad_clk=0;
ad_cs=0;
_nop_();
for(i<0;i<8;i++)
{ ad_clk=1;
d=d<<1;
if (ad_dout)
{ d++;}
ad_clk=0;
}
ad_cs=1;
for(i=0;i<10;i++) // 适当延时超过17us
_nop_();
return d;
}
//-------------
main()
{T_cnt=0;
TMOD=0x01; //定时器设置T0
TH0=0x4c; //50000us=(65536-0x4c00)*12/11.0592
TL0=00;
EA=0;
TR0=1;
re_data=0x00;
volt=0;
xishu=2.5/255.0;
//-----------------------------
while(1)
{ if(TF0==1)
{ TF0=0;
TH0=0x4c; //50000us=(65536-0x4c00)*12/11.0592
TL0=0x0;
if (T_cnt<2) //T0为50毫秒溢出一次,每100ms读取一次AD转换器数据
{T_cnt++;}
else
{ T_cnt=0;//计时到100ms了
re_data=receive_data();
//转换为电压值
volt=re_data;
volt=volt*xishu;
}
}
led_show(volt);
}
}