微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > PCB设计问答 > PCB设计学习讨论 > proteus仿真,LCD无显示

proteus仿真,LCD无显示

时间:10-02 整理:3721RD 点击:


电子万年历,LCD屏无显示,是什么情况
判忙删掉了,PO口上拉电阻也加上了,还是没有
           #include <reg51.h>
#include <intrins.h>
#include <string.h>
#define uint unsigned int
#define uchar unsigned char
sbit IO= P1^0;             //DS1302数据线
sbit SCLK = P1^1;         //DS130时钟线
sbit RST = P1^2;         //DS1302复位线
sbit RS = P2^0;                 //LCD数据/命令选择端
sbit RW = P2^1;                 //LCD读/写控制
sbit EN = P2^2;                  //LCD使能端
sbit K1=P3^4;                //选择
sbit K2=P3^5;                //加
sbit K3=P3^6;                //减
sbit K4=P3^7;            //确定
uchar tCount=0;
uchar MonthsDays[]={0,31,0,31,30,31,30,31,31,30,31,30,31};
uchar *WEEK[]={"SUN","MON","TUS","WEN","THU","FRI","SAT"};
uchar LCD_DSY_BUFFER1[]={"DATE 00-00-00   "};  //显示格式
uchar LCD_DSY_BUFFER2[]={"TIME 00:00:00   "};
uchar DateTime[7];         //所读取的日期时间
char Adjust_Index=-1;  //当前调节的时间对象:,,分,是,日,月,年(1,2,3,4,6)
uchar Change_Flag[]= "-MHDM-Y";         //(分,时,日,月,年)(不调节秒与周)
/*---------延时程序------------------*/
void DelayMS(uint ms)
{
        uchar i;
        while(ms--){for(i=0;i<120;i++);}
}
//-----------向DS1302写入一字节------------------//
void Write_A_Byte_TO_DS1302(uchar x)
{        uchar i;
        for(i=0;i<8;i++){
                 IO=x&0x01;         //每一位与1与存入IO中
                SCLK=1;SCLK=0;        //一个高脉冲将数据送入液晶控制器
                x>>=1;              //  右移
        }
}
//-----------从DS1302读取一字节------------------//
uchar Get_A_Byte_FROM_DS1302()
{        uchar i,b=0x00;
        for(i=0;i<8;i++){
                 b |= _crol_((uchar)IO,i);
                SCLK=1;SCLK=0;                  //每一个高脉冲读取一位数据
        }
        return b/16*10+b%16; //返回BCD码
}
//-----------从DS1302指定位置读数据------------------//
uchar Read_Data(uchar addr)
{
        uchar dat;
        RST = 0;SCLK=0;RST=1;           //RST高电平时读/写
           Write_A_Byte_TO_DS1302(addr);         //先写入地址
        dat = Get_A_Byte_FROM_DS1302();
           SCLK=1;RST=0;
        return dat;
}
//---------向DS1302某地址写入数据--------------------//
void Write_DS1302(uchar addr,uchar dat)
{        SCLK=0;RST=1;
        Write_A_Byte_TO_DS1302(addr);
        Write_A_Byte_TO_DS1302(dat);
        SCLK=0;RST=0;                 //高脉冲写入数据
}
//--------------设置时间----------------//
void SET_DS1302()
{        uchar i;
        //写控制字,取消写保护
        Write_DS1302(0x8E,0x00);
        //分时日月年依次写入
        for(i=1;i<7;i++)
        {  //分的起始地址10000010(0x82),后面依次是时,日,月,周,年,写入地址每次递增2
                Write_DS1302(0x80+2*i,(DateTime/10<<4)|(DateTime%10));
        }  
        Write_DS1302(0x8E,0x80); //加保护
}
//----------读取当前日期时间------------//
void GetTime()
{uchar i;
        for(i=0;i<7;i++){        DateTime=Read_Data(0X81+2*i);}
}
//-----------读LCD状态------------------//
uchar Read_LCD_State()
{        uchar state;
        RS=0;RW=1;EN=1;         //输出:D0~D7=状态字
        DelayMS(1);
        state=P0;                  //从P0口读LCD状态
        EN = 0;DelayMS(1);
        return state;
}       
//-----------向LCD写数据------------------//
void Write_LCD_Data(uchar dat)
{
        LCD_Busy_Wait();
        RS=1;EN=0;RW=0;                 //写数据,EN为高脉冲,
        P0=dat;EN=1;DelayMS(1);EN=0;       
}
//-------------写LCD指令-------------------//
void Write_LCD_Command(uchar cmd)
{
        LCD_Busy_Wait();
        RS=0;EN=0;        RW=0; //写指令,EN高脉冲,输出:D0~D7=数据
        P0=cmd;EN=1;DelayMS(1);EN=0;       
}
//-------------LCD初始化-------------------//
void Init_LCD()
{
        Write_LCD_Command(0x38);  //设置16*2显示,5*7点阵,8位数据接口
        DelayMS(1);       
        Write_LCD_Command(0x01);  //显示清零,数据指针清零
        DelayMS(1);       
        Write_LCD_Command(0x06);  //写一个字符后地址指针自动加1
        DelayMS(1);       
        Write_LCD_Command(0x0c);   //设置开显示,不显示光标
        DelayMS(1);       
}
//------------------------------------------
//设置液晶显示位置
//------------------------------------------
void Set_LCD_POS(uchar p){
        Write_LCD_Command(p|0x80);//相当于在0x80基础上加入位置量       
}
//----在LCD上显示字符串---------//
void Display_LCD_String(uchar p,uchar *s)
{                uchar i;
        Set_LCD_POS(p);
        for(i=0;i<16;i++)
        {
                Write_LCD_Data(s);  //在固定位置显示时间日期
                DelayMS(1);
        }
}
//---------日期与时间值转换为数字字符----------------//
void Format_DateTime(uchar d,uchar *a)
{
        a[0]=d/10+'0';
        a[1]=d%10+'0';
}
//判断是否为闰年
uchar isLeapYear(uint y)
{        return (y%4==0&&y%100!=0)||(y%400==0);}
//求自2000.1.1开始的任何一天是星期几
//函数没有通过,求出总天数后再求星期几
//因为求总天数可能会超出uint的范围
void RefreshWeekDay()
{        uint i,d,w=5;         //已知1999.12.31是周五
        for(i=2000;i<2000+DateTime[6];i++)
        {
                d=isLeapYear(i)?366:365;
                w=(w+d)%7;
        }
        d=0;
        for(i=1;i<DateTime[4];i++)
        {        d+=MonthsDays;        }
        d+=DateTime[3];
        //保存星期,0~6表示星期日,星期一,二,...,六,为了与DS1302的星期格式匹配,返回值需要加1
        DateTime[5]=(w+d)%7+1;
}
//*****年月日时分++/--********//
void DateTime_Adjust(char x)
{                switch(Adjust_Index)
        {
                case 6:          //年00-99
                        if(x==1&&DateTime[6]<99) DateTime[6]++;
                        if(x==-1&&DateTime[6]>0) DateTime[6]--;
                        //获取2月天数
                        MonthsDays[2]=isLeapYear(2000+DateTime[6])?29:28;
                        //如果年份变化后当前月份的天数大于上限则设为上限
                        if(DateTime[3]>MonthsDays[DateTime[4]])
                        {        DateTime[3]=MonthsDays[DateTime[4]];}
                        RefreshWeekDay();  //刷新星期
                        break;
                case 4:         //月01-12
                        if(x==1&&DateTime[4]<12) DateTime[4]++;
                        if(x==-1&&DateTime[4]>1) DateTime[4]--;
                        MonthsDays[2]=isLeapYear(2000+DateTime[6])?29:28;
                        if(DateTime[3]>MonthsDays[DateTime[4]])
                        {        DateTime[3]=MonthsDays[DateTime[4]];}
                        RefreshWeekDay();
                        break;
                case 3:          //日00-28、29、30、31,调节之前首先根据年份得出该年中断二月 天数
                        MonthsDays[2]=isLeapYear(2000+DateTime[6])?29:28;
                        //根据当前月份决定调节日期的上限
                        if(x==1&&DateTime[3]<MonthsDays[DateTime[4]]) DateTime[3]++;
                        if(x==-1&&DateTime[3]>0) DateTime[3]--;
                        RefreshWeekDay();
                        break;
                case 2:           //时
                        if(x==1&&DateTime[2]<23) DateTime[2]++;
                        if(x==-1&&DateTime[2]>0) DateTime[2]--;
                        break;
                case 1:                //分
                        if(x==1&&DateTime[1]<59) DateTime[1]++;
                        if(x==-1&&DateTime[1]>0) DateTime[1]--;
                        break;
        }
}
//---定时器0每秒刷新LCD显示----//
void T0_INT() interrupt 1
{
        TH0=-50000/256;
        TL0=-50000%256;
        if(++tCount !=2)        return;
        tCount=0;
        //按指定格式生成待显示的日期时间串
        Format_DateTime(DateTime[6],LCD_DSY_BUFFER1+5);
        Format_DateTime(DateTime[4],LCD_DSY_BUFFER1+8);
        Format_DateTime(DateTime[3],LCD_DSY_BUFFER1+11);
        //星期
        strcpy(LCD_DSY_BUFFER1+13,WEEK[DateTime[5]-1]);
        //时分秒
        Format_DateTime(DateTime[2],LCD_DSY_BUFFER2+5);
        Format_DateTime(DateTime[1],LCD_DSY_BUFFER2+8);
        Format_DateTime(DateTime[0],LCD_DSY_BUFFER2+11);
        //显示年月日,星期,时分秒
        Display_LCD_String(0x00,LCD_DSY_BUFFER1);
        Display_LCD_String(0x40,LCD_DSY_BUFFER2);
}
//----------键盘中断(INT0)-------------//
void EX_INT0() interrupt 0
{       
        if(K1==0)          //选择调整对象(Y M D H M)
        {
                DelayMS(10);
                if(K1==0){                         
                //while(K1==0);
                if(Adjust_Index==-1||Adjust_Index==1)
                {
                        Adjust_Index=7;
                }
                Adjust_Index--;
                if(Adjust_Index==5) Adjust_Index=4;
                LCD_DSY_BUFFER2[13]='[';
        LCD_DSY_BUFFER2[14]=Change_Flag[Adjust_Index]; //显示调节对象
                LCD_DSY_BUFFER2[15]=']';
                }
        }
        else if(K2==0)                          //加
        {        //while(K2==0);
                DelayMS(10);
                if(K2==0)
                 DateTime_Adjust(1);
        }
        else if(K3==0)                         //减
        {
                        DelayMS(10);//while(K3==0);
                if(K3==0)
                        DateTime_Adjust(-1);
        }
        else if(K4==0)                           //确定
        {
                //while(K4==0);
                DelayMS(10);
                if(K4==0){
                SET_DS1302();                         //将调整后的时间写入DS1302
                LCD_DSY_BUFFER2[13]=' ';
                LCD_DSY_BUFFER2[14]=' ';
                LCD_DSY_BUFFER2[15]=' ';
                Adjust_Index=-1;
                }
        }
}
void main()
{        Init_LCD();                //液晶初始化
        IE=0x83;           //允许INT0,T0中断,EA=1,,ET0=1,EX0=1
        IP=0x01;           //设置外部中断0为高级中断
        IT0=0x01;           //外部中断0为电平触发,低电平有效
        TMOD=0x01;           //设置定时器T0工作方式为方式1,
        TH0=-50000/256;                //装入初始值,定时1秒
        TL0=-50000%256;
        TR0=1;                   //启动定时器
        while(1)
        {
        //如果未执行调整操作则正常读取当前时间
                if(Adjust_Index==-1)        GetTime();
                                                                         }}

图传错了,是这张

图是这张


注意看引脚定义和时序延时时间这些

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top