单片机论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 201|回复: 0
收起左侧

基于51单片机和Proteus仿真的自动换挡电压表

[复制链接]
futao 发表于 2019-5-9 17:29 | 显示全部楼层 |阅读模式
#include <AT89X52.H>

#define LEDDATA P0
#define v20_on {s3=0;s2=0;s1=1;} //宏定义不同量程,不同的开关状态
#define v2_on {s3=0;s2=1;s1=0;}
#define v02_on {s3=1;s2=0;s1=0;}
unsigned char code dispcode[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00};
unsigned char dispbuf[8]={0,0,0,0,0,0,0,0};
unsigned char getdata;
unsigned long temp;
unsigned char i,k,l,m;
unsigned char code  mytable0[]=" Welcome to use  ";
unsigned char code  mytable1[]="Auto Voltmeter!";
unsigned char code line0[]="  Voltmeter   ";    //初始化显示
unsigned char code line1[]=" Value:     V ";
//引脚定义
sbit lcdrs=P2^0;
sbit lcden=P2^1;                                                       
sbit s3=P3^7;  
sbit s2=P3^6;
sbit s1=P3^5;
sbit OE=P3^0;
sbit EOC=P3^1;
sbit ST=P3^2;

void delay(unsigned int z)      //延时子函数  z*1ms
{
        unsigned int x,y;
        for(x=z;x>0;x--)
                for(y=110;y>0;y--);
}
void write_com(unsigned char c)   //写命令子函数
{
        lcdrs=0;                //低电平选择为 写指令
        lcden=0;               
        LEDDATA=c;                   //把指令写入P0口
        delay(5);               //参考时序图
        lcden=1;                //开使能
        delay(5);               //读取指令
        lcden=0;                //关闭使能         
}

void write_data(unsigned char d)  //写数据子函数
{
        lcdrs=1;             //高电平选择为 写数据
        LEDDATA=d;                //把数据写入P0口
        delay(5);            //参考时序图
        lcden=1;             //开使能
        delay(5);            //读取数据
        lcden=0;                 //关闭使能
}
void initialize()      //LCD初始化函数
{   
    unsigned char num;
        lcden=0;
        write_com(0x38);   //设置16x2显示,5x7点阵显示,8位数据接口
        write_com(0x0c);   //00001DCB,D(开关显示),C(是否显示光标),B(光标闪烁,光标不显示)
        write_com(0x06);   //000001N0,N(地址指针+-1)
        write_com(0x01);      //清屏指令  每次显示下一屏内容时,必须清屏            
        write_com(0x80+0x10);           //第一行,顶格显示                           
        for(num=0;num<17;num++)        
        {
                write_data(mytable0[num]);
                delay(10);
        }
        write_com(0x80+0x50);           //第二行,从第一格开始显示
        for(num=0;num<15;num++)      
        {
                write_data(mytable1[num]);
                delay(10);
        }
                for(num=0;num<16;num++)
        {
                write_com(0x1c);   //0001(S/C)(R/L)**;  S/C:高电平移动字符,低电平移动光标;  R/L:高电平左移,低电平右移
                delay(300);
        }
           delay(1000);
                     
        write_com(0x01);      //清屏指令  每次显示下一屏内容时,必须清屏
        write_com(0x80);                                   
        for(num=0;num<14;num++)     
        {
                write_data(line0[num]);
                delay(10);
        }

        write_com(0x80+0x40);         
        for(num=0;num<15;num++)        
        {
                write_data(line1[num]);
                delay(10);
        }        
}
void value(unsigned char add,unsigned char dat)   
{       
         write_com(0x80+0x47+add);
         if(l==3&&add==2||l!=3&&add==1)
           {
              write_data(0x2e);
           }
         else
           {
              write_data(0x30+dat);
           }       
}
main()
{
   initialize();
   while(1)
_20v:
     {
       v20_on;                  
       ST=0;                  
       ST=1;
       ST=0;   
          while(EOC==0);
          OE=1;
                  getdata=P1;
          OE=0;
                   if(getdata<21)            
           {
             goto _2v;
           }
                  l=3;
              temp=getdata;      
          temp=(temp*1000/51)/2;
                  goto disp;

_2v:                          
         v2_on;
          ST=0;
          ST=1;
          ST=0;   
          while(EOC==0);
           OE=1;
           getdata=P1;
           OE=0;
           if(getdata<21)
           {
             goto _02v;
           }
           else if(getdata>204)
           {
             goto _20v;
           }
           l=2;
           temp=getdata;
           temp=(temp*1000/51)/2;
           goto disp;

_02v:                     
          v02_on;
          ST=0;
          ST=1;
          ST=0;   
          while(EOC==0);
           OE=1;
           getdata=P1;
           OE=0;
          if(getdata>204)
           {
             goto _2v;
           }
           l=1;
           temp=getdata;
           temp=(temp*1000/51)/2;
                   m=temp%10;
                   if(m>5){temp=temp/10+1;}
                   else{temp=temp/10;}
                   goto disp;

disp:          for(i=0;i<=3;i++)         
             {
               dispbuf[i]=temp%10;
               temp=temp/10;  
             }
                  if(l==3)
                    {
                           for(i=4;i>=3;i--)       
                           dispbuf[i]=dispbuf[i-1];
                    }
                  else
                   {
                          dispbuf[4]=dispbuf[3];
                   }
              for(k=0;k<5;k++)            
           {
                      value(k,dispbuf[4-k]);
               }
                 if(l==2){goto _2v;}
                 else if(l==1){goto _02v;}
          }
}

电压表.png

基于51单片机和Proteus仿真的自动换挡电压表.zip

69.9 KB, 下载次数: 6, 下载积分: 黑币 -5

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|单片机论坛 |51黑电子论坛单片机 联系QQ:125739409;技术交流QQ群582644647

Powered by 单片机教程网

快速回复 返回顶部 返回列表