专注电子技术学习与研究
当前位置:单片机教程网 >> MCU设计实例 >> 浏览文章

基于TLC1549的单片机数字电压表程序

作者:jcde225   来源:本站原创   点击数:  更新时间:2009年09月21日   【字体:

        本文介绍了一种以51单片机为主控器的数字电压表。该数字电压表采用1602液晶作为显示部分。采用TLC1549模数转换器将检测到的模拟电压值转换为10位二进制数据送往单片机处理。采用STC89C52单片机将接收到的二进制数据进行运算处理后在液晶显示器显示被测电压值。由运放LM339和与非门74LS00构成输入电压接反报警功能,超过测量量程提示功能。

    该系统实现了0-50V直流电压的测量,测量精度为0.05V。采用10位串行A/D (TLC1549)进行模数转换,比采用常用的8位并行A/D(ADC0809等)硬件电路更为简单,测量精度更高。1602液晶显示器比数码管显示更为直观,丰富的信息。

    该系统只设计了测量显示功能,由于为单片机留有丰富的I/O,所以可以方便的扩展其他功能。

(本文系51hei单片机网会员jcde225原创。由于本人菜鸟一只,不足之处还请各位大虾指点。例如显示的电压值最低位常在0,4,9之间跳动。调了很久都没解决这个问题。)
 

#include <reg52.h>    //52系列头文件
#define Disdata P1    //液晶数据端口
#define uchar unsigned char    //无符号字符8位
#define uint unsigned int //无符号整数8位
uint data dis[4]={0x00,0x00,0x00,0x00};//4个数据单元和一个
uchar code table[]="VOLTAGE:+  .   V"; //定义初始上电液晶默认显示状态
uchar code table1[]="designed by :";
uchar code table3[]="      Li Xiaojun";
uchar code table2[]="SCOPE:  0-50.00V";
uchar code table4[]="  not reversed! ";
sbit lcden=P3^2;//定义液晶使能端
sbit lcdrs=P3^0;//定义液晶RS端
sbit rw=P3^1;//定义液晶RW端
sbit ALE=P2^3;//定义锁存地址控制位
sbit cs_ad=P3^5;//片选段,低电平有效
sbit dout=P3^4;//数据输出端
sbit clk=P3^3;  //转换结束标志位
sbit speak=P3^7;//蜂鸣器
sbit bijiao=P3^6;//接反检测信号
data int result;//测量变量暂存地址
void jiefan();//接反子函数
uchar num,num1,num2,num3,num4,num5;
uchar shii,gei;

//********延时函数************
void delay(uint z)
{
   uint x,y;
    for(x=z;x>0;x--)
    for(y=110;y>0;y--);
}
  
//*************
void write_com(uchar com)          //液晶写命令函数
{
  lcdrs=0;
  P1=com;
  delay(5);
  lcden=1;
  delay(5);
  lcden=0;
 }
 void write_data(uchar date)       //液晶写数据函数
 {
   lcdrs=1;
   P1=date;
   delay(5);
   lcden=1;
   delay(5);
   lcden=0;
 }
void write_sg(uchar add,uchar date)       //写整数位和小数位函数
{
  uchar shi,ge;
  shi=date/10;       //分解出一个2位数的十位
  ge=date%10;
  write_com(0x80+add);       //设置显示位置
  write_data(0x30+shi);        //送去液晶显示十位
  write_data(0x30+ge);        //送去液晶显示个位
}

void init()                                       
{
 rw=0;                                                  
 lcden=0;
 shii=0;
 gei=0;
 write_com(0x38);     //初始化1602液晶
 write_com(0x0c);
 write_com(0x06);
 write_com(0x01);
 write_com(0x80);     //设置显示初始坐标

 for(num2=0;num2<13;num2++)
  {
    write_data(table1[num2]);
 delay(5);
  }
 write_com(0x80+40);    
   for(num3;num3<16;num3++)
   {
     write_data(table3[num3]);
     delay(5);
 }
 delay(3000);
 
 }

 //*******************************
void scan1()
{
 write_com(0x80);              //设置显示初始坐标
  for(num=0;num<16;num++)
  {
    write_data(table[num]);
 delay(5);
  }
  write_sg(9,shii);                                       
  write_sg(12,gei);
 write_com(0x80+40);    
   for(num1;num1<16;num1++)
   {
     write_data(table2[num1]);
     delay(5);
 }
     write_sg(9,shii);
     write_sg(12,gei);
 }
  
//****TLC1549转换处理子函数********

void test()

{
   
     data  uchar i;
  
     cs_ad=1; //禁止i/o clock
     cs_ad=0; //开启控制电路,使能data out和i/o clock
     result=0; //清转换变量
     for(i=0;i<10;i++) //采集10次 ,即10bit
       {
    clk=0;
       result*=2;
       if(dout) result++;
       clk=1;
    }
     delay(590);
     cs_ad=1; ;;;; //data out 返回到高阻状态而终止序列
//****数据转换处理**********
     result=result*10;     //结果值扩大10倍
     dis[2]=result/205;    //计算整数位
  dis[3]=result%205;     //余数暂存
  dis[3]=dis[3]*10;          //计算小数第一位
  dis[1]=dis[3]/205;                                  
  dis[3]=dis[3]%205;                  
  dis[3]=dis[3]*10;     //计算小数第二位
  dis[0]=dis[3]/205;
  shii=dis[2];
  gei=dis[1]*10+dis[0];
     write_sg(9,shii);
     write_sg(12,gei);
 
}
//*****接反子函数*********
void jiefan()
 {
   if(bijiao==0)
     {
   delay(100);
    if(bijiao==0)
     {
  speak=0;
  }
    else
     speak=1;
 
  }
    else
 {
    speak=1;

 }
 }
//*******主函数*****
void main()
{
init();
scan1();
while(1)
{
test();
jiefan();
}
}
 

关闭窗口

相关文章