想做个51单片机定时开关1602液晶显示AT24C02存储,大家看看我画的图有问题吗?

2019-07-15 14:42发布

本帖最后由 agy518 于 2016-3-19 23:09 编辑

2.png

大家好,我刚刚学习单片机不久,想做个51单片机定时开关1602液晶显示AT24C02存储,我是在网上找的程序,照程序画的图,大家看看我画的图有问题吗?还有为什么没有DS1302时钟模块,哪来的时间
程序
#include <reg52.h>

#include <string.h>

#include <intrins.h>


#define uchar unsigned char

#define uint  unsigned int


#define LCM_Data P0

#define Busy 0x80 //用于检测LCM状态字中的Busy标识

sbit LCM_RS = P3^3;

sbit LCM_RW = P3^4;//定义引脚

sbit LCM_E  = P3^5;


sbit key1  = P1^4;        //-

sbit key2  = P1^3;        //+

sbit key3  = P1^2;        //set

sbit key4  = P1^5;        //run

sbit key5  = P1^6;        //off

sbit key6  = P1^7;        //on


sbit scl   = P1^0;

sbit sda   = P1^1;


sbit jdq  = P3^6;


uchar id,timecount,fl=0;

int r_hour,r_min,r_sec,r_hour2,r_min2,r_sec2;


int hour,min,sec,hour2,min2,sec2,mode=1,aa;


bit flag,sflag; //flag是时钟冒号闪烁标志,sflag是温度负号显示标志

void Disp_line1(void); //显示屏幕第一行

void Disp_line2(void); //显示屏幕第二行

void id_case1_key();


void WriteDataLCM(uchar WDLCM);

void WriteCommandLCM(uchar WCLCM,BuysC);

uchar ReadStatusLCM(void);

void LCMInit(void);

void DisplayOneChar(uchar X, uchar Y, uchar DData);

void DisplayListChar(uchar X, uchar Y, uchar code *DData);

void Delay5Ms(void);

void Delay400Ms(void);

void runtime();

void ScanKey();

void LedDisplay();


void delay()        //延时5us

{  ; ; }


void init()           //总线初始化

{

        sda=1;

        scl=1;

}


void start()   //开始信号

{

        sda=1;

        delay();

        scl=1;

        delay();

        sda=0;

        delay();        

}


void stop()                 //停止信号

{

        sda=0;

        delay();

        scl=1;

        delay();

        sda=1;

        delay();

}


void respons()          //应答信号

{

        uchar i=0;

        scl=1;

        delay();

        while((sda==1)&&(i<250)) i++; //若sda为0,退出,若sda在250us内sda一直为1,则表示未收到应答,也退出。

        scl=0;

        delay();

}


void write_byte(uchar date)//向sda数据线上写一字节数据

{

        uchar i,temp;

        temp=date;

        scl=0;

        delay();

        for(i=0;i<8;i++)

        {

                temp=temp<<1;

                sda=CY;

                delay();

                scl=1;          //和数码管类似,都是先送数据再打开开关

                delay();

                scl=0;

                delay();

        }

        sda=1;//释放总线,为读取应答的低电平信号

        delay();         

}


uchar read_byte() //从sda数据线上读一字节数据

{

        uchar i,j,k;

        scl=0;

        delay();

        sda=1;

        delay();

        for(i=0;i<8;i++)

        {

                  scl=1;

                  delay();

                  j=sda;

                  k=(k<<1)|j;

                  scl=0;

                  delay();

        }

        return k;

}


void write_add(uchar add,uchar date)//向24C02指定存储地址写入指定1字节数据

{

          start();                           //s

          write_byte(0xa0);           //器件地址+0:0xa0=1010 0000 B,板子硬件设计地址为1010 000

          respons();                   //A

          write_byte(add);           //写入首地址

          respons();                   //A

          write_byte(date);           //写入数据

          respons();                   //A

          stop();                           //p

}


uchar read_add(uchar add)//从24C02指定存储地址中读取1字节数据

{

          uchar date;

        

          start();                           //s

           write_byte(0xa0);           //器件地址+0,表示主机要传送

          respons();                   //A

          write_byte(add);           //要读出数据的首地址

          respons();                   //A

          start();                           //s

          write_byte(0xa1);           //器件地址+1,表示主机要接受

          respons();                   //A

          date=read_byte();           //读出数据

          stop();                           //p

          return date;

}




void ScanKey(void)  //按键判断程序

{

        if(key3==0)  //判断是否按下键盘

        {

                Delay5Ms();

                if(key3==0)   //确认按键按下

                {

                        mode++;     //按键计数加1        

                        if(mode>=5) //计4次重新计数

                        {  

                                mode=1;  

                        }   //将mode清零

                }

                while(key3==0);//按键锁定,每按一次mode只加1

        }

        if(key4==0)  //判断是否按下键盘

        {

                Delay5Ms();

                if(key4==0)   //确认按键按下

                {

                        WriteCommandLCM(0x01,1); //显示清屏

                        write_add(3,hour);

                        Delay5Ms();

                        write_add(4,min);

                        Delay5Ms();

                        write_add(5,sec);        

                        Delay5Ms();

                        write_add(6,hour2);

                        Delay5Ms();

                        write_add(7,min2);

                        Delay5Ms();

                        write_add(8,sec2);

                                        r_min=min;

                                        r_sec=sec;

                                        r_hour=hour;


                                        r_min2=min2;

                                        r_sec2=sec2;

                                        r_hour2=hour2;

                                        fl=0;

                                        runtime();

                }

        }

}


void setonhour()

{

                TR0=0;

                sec=0;

                jdq=1;

                DisplayListChar(0,0,"Set ON Time  ");

                DisplayListChar(10,1,"hour");

            DisplayOneChar(8,1,hour/10+0x30);

                DisplayOneChar(9,1,hour%10+0x30);

                if (key2==0) // 设置和选择项目键

              {

                        Delay5Ms();

                       if(key2==0)

                       {

                               hour=hour+1;

                               if(hour>10)

                                       hour=0;

                       }

                       while(key2==0);

                }


                if (key1==0) // 设置和选择项目键

              {

                        Delay5Ms();

                       if(key1==0)

                       {

                               hour=hour-1;

                                if(hour<0)

                                       hour=10;

                       }

                       while(key1==0);

                }            

}


void setonmin()

{

                TR0=0;

                jdq=1;

                sec=0;

                DisplayListChar(0,0,"Set ON Time ");

                DisplayListChar(10,1,"min  ");

            DisplayOneChar(8,1,min/10+0x30);

                DisplayOneChar(9,1,min%10+0x30);

                if (key2==0) // 设置和选择项目键

              {

                        Delay5Ms();

                       if(key2==0)

                       {

                               min=min+1;

                               if(min>60)

                                       min=0;

                       }

                       while(key2==0);

                }


                if (key1==0) // 设置和选择项目键

              {

                        Delay5Ms();

                       if(key1==0)

                       {

                               min=min-1;

                                if(min<0)

                                       min=60;

                       }

                       while(key1==0);

                }            

}


void setoffhour()

{

                TR0=0;

                jdq=1;

                sec=0;

                DisplayListChar(0,0,"Set OFF Time");

                DisplayListChar(10,1,"hour");

            DisplayOneChar(8,1,hour2/10+0x30);

                DisplayOneChar(9,1,hour2%10+0x30);

                if (key2==0) // 设置和选择项目键

              {

                        Delay5Ms();

                       if(key2==0)

                       {

                               hour2=hour2+1;

                               if(hour2>10)

                                       hour2=0;

                       }

                       while(key2==0);

                }


                if (key1==0) // 设置和选择项目键

              {

                        Delay5Ms();

                       if(key1==0)

                       {

                               hour2=hour2-1;

                                if(hour2<0)

                                       hour2=10;

                       }

                       while(key1==0);

                }            

}


void setoffmin()

{

                TR0=0;

                jdq=1;

                sec=0;

                DisplayListChar(0,0,"Set OFF Time");

                DisplayListChar(10,1,"min ");

            DisplayOneChar(8,1,min2/10+0x30);

                DisplayOneChar(9,1,min2%10+0x30);


                if (key2==0) // 设置和选择项目键

              {

                        Delay5Ms();

                       if(key2==0)

                       {

                               min2=min2+1;

                               if(min2>60)

                                       min2=0;

                       }

                       while(key2==0);

                }


                if (key1==0) // 设置和选择项目键

              {

                        Delay5Ms();

                       if(key1==0)

                       {

                               min2=min2-1;

                                if(min2<0)

                                       min2=60;

                       }

                       while(key1==0);

                }            

}


void runontime()

{

        DisplayListChar(0,0,"Run ON Time ");        

        DisplayOneChar(1,1,r_hour/10+0x30); //显示固定字符

          DisplayOneChar(2,1,r_hour%10+0x30);

        DisplayListChar(3,1,":");

        DisplayOneChar(4,1,r_min/10+0x30); //显示固定字符

          DisplayOneChar(5,1,r_min%10+0x30);

        DisplayListChar(6,1,":");

        DisplayOneChar(7,1,r_sec/10+0x30); //显示固定字符

          DisplayOneChar(8,1,r_sec%10+0x30);

        TR0=1;

        jdq=0;

}


void runofftime()

{

        DisplayListChar(0,0,"Run OFF Time");        

        DisplayOneChar(1,1,r_hour2/10+0x30); //显示固定字符

          DisplayOneChar(2,1,r_hour2%10+0x30);

        DisplayListChar(3,1,":");

        DisplayOneChar(4,1,r_min2/10+0x30); //显示固定字符

          DisplayOneChar(5,1,r_min2%10+0x30);

        DisplayListChar(6,1,":");

        DisplayOneChar(7,1,r_sec2/10+0x30); //显示固定字符

          DisplayOneChar(8,1,r_sec2%10+0x30);

        TR0=1;

        jdq=1;

}


void set()

{

        WriteCommandLCM(0x01,1); //显示清屏

        while(1)

        {

                ScanKey();

                  LedDisplay();         

        }

}


void allon()

{

        WriteCommandLCM(0x01,1); //显示清屏

        TR0=0;

        while(1)

        {

            DisplayListChar(0,0,"Always ON  ");

                jdq=0;

                if(key5==0)  //判断是否按下键盘

                {

                        Delay5Ms();

                        if(key5==0)   //确认按键按下

                        {

                                TR0=1;

                                fl=1;

                                        r_min=min;

                                        r_sec=sec;

                                        r_hour=hour;


                                        r_min2=min2;

                                        r_sec2=sec2;

                                        r_hour2=hour2;

                        

                        }

                        while(key5==0);//按键锁定,每按一次mode只加1

                                runtime();

                }

        }        

}


void alloff()

{

        WriteCommandLCM(0x01,1); //显示清屏

        TR0=0;

        while(1)

        {

            DisplayListChar(0,0,"Always OFF");

                jdq=1;

                if(key6==0)  //判断是否按下键盘

                {

                        Delay5Ms();

                        if(key6==0)   //确认按键按下

                        {

                                TR0=1;

                                fl=0;

                                        r_min=min;

                                        r_sec=sec;

                                        r_hour=hour;


                                        r_min2=min2;

                                        r_sec2=sec2;

                                        r_hour2=hour2;

                        

                        }

                        while(key6==0);//按键锁定,每按一次mode只加1

                                runtime();

                }

        }        

}


void runtime()

{

        while(1)

        {

                if(fl==0)

                        runontime();

                if(fl==1)

                        runofftime();


                if(key3==0)  //判断是否按下键盘

                {

                        Delay5Ms();

                        if(key3==0)   //确认按键按下

                        {

                                mode=1;

                                set();   //将mode清零

                        }

                        while(key3==0);//按键锁定,每按一次mode只加1

                }

                if(key5==0)  //判断是否按下键盘

                {

                        Delay5Ms();

                        if(key5==0)   //确认按键按下

                        {

                        

                        }

                        while(key5==0);//按键锁定,每按一次mode只加1

                                allon();   //将mode清零

                }


                if(key6==0)  //判断是否按下键盘

                {

                        Delay5Ms();

                        if(key6==0)   //确认按键按下

                        {

                        

                        }

                        while(key6==0);//按键锁定,每按一次mode只加1

                                alloff();   //将mode清零

                }


        }

}


void LedDisplay(void)

{

        if(mode==1)

        {

                setonhour();

        }

        else if(mode==2)

        {

                setonmin();

        }

        else if(mode==3)

        {

                setoffhour();

        }

        else if(mode==4)

        {

                setoffmin();

        }

}


void main(void)

{  

          jdq=1;

        Delay400Ms(); //启动等待,等LCM讲入工作状态

          LCMInit(); //LCM初始化

          Delay5Ms(); //延时片刻(可不要)

        TMOD=0x01;

        TH0=(65536-50000)/256;

        TL0=(65536-50000)%256;

        EA=1;

        ET0=1;

        init();        


        Delay5Ms();

        hour=read_add(3);

        Delay5Ms();

        min=read_add(4);

        Delay5Ms();

        sec=read_add(5);

        Delay5Ms();

        hour2=read_add(6);

        Delay5Ms();

        min2=read_add(7);

        Delay5Ms();

        sec2=read_add(8);

                                        r_min=min;

                                        r_sec=sec;

                                        r_hour=hour;


                                        r_min2=min2;

                                        r_sec2=sec2;

                                        r_hour2=hour2;

          while(1)

           {              

                runtime();


        }

                 

}




void WriteDataLCM(uchar WDLCM)

{

          ReadStatusLCM(); //检测忙

          LCM_Data = WDLCM;

          LCM_RS = 1;

          LCM_RW = 0;

          LCM_E = 0; //若晶振速度太高可以在这后加小的延时

          LCM_E = 0; //延时

          LCM_E = 1;

}


void WriteCommandLCM(uchar WCLCM,BuysC) //BuysC为0时忽略忙检测

{

          if(BuysC) ReadStatusLCM(); //根据需要检测忙

          LCM_Data = WCLCM;

          LCM_RS = 0;

          LCM_RW = 0;

          LCM_E = 0;

          LCM_E = 0;

          LCM_E = 1;

}


uchar ReadStatusLCM(void)

{

          LCM_Data = 0xFF;

          LCM_RS = 0;

          LCM_RW = 1;

          LCM_E = 0;

          LCM_E = 0;

          LCM_E = 1;

          while (LCM_Data & Busy); //检测忙信号

          return(LCM_Data);

}


void LCMInit(void)

{

          LCM_Data = 0;

          WriteCommandLCM(0x38,0); //三次显示模式设置,不检测忙信号

          Delay5Ms();

          WriteCommandLCM(0x38,0);

          Delay5Ms();

          WriteCommandLCM(0x38,0);

          Delay5Ms();

          WriteCommandLCM(0x38,1); //显示模式设置,开始要求每次检测忙信号

          WriteCommandLCM(0x08,1); //关闭显示

          WriteCommandLCM(0x01,1); //显示清屏

          WriteCommandLCM(0x06,1); // 显示光标移动设置

          WriteCommandLCM(0x0C,1); // 显示开及光标设置

}


void DisplayOneChar(uchar X, uchar Y, uchar DData)

{

          Y &= 0x1;

          X &= 0xF; //限制X不能大于15,Y不能大于1

          if (Y) X |= 0x40; //当要显示第二行时地址码+0x40;

          X |= 0x80; //算出指令码

          WriteCommandLCM(X, 0); //这里不检测忙信号,发送地址码

          WriteDataLCM(DData);

}


void DisplayListChar(uchar X, uchar Y, uchar code *DData)

{

          uchar ListLength,j;

          ListLength = strlen(DData);

          Y &= 0x1;

          X &= 0xF; //限制X不能大于15,Y不能大于1

    if (X <= 0xF) //X坐标应小于0xF

      {

                    for(j=0;j<ListLength;j++)

                      {

             DisplayOneChar(X, Y, DData[j]); //显示单个字符

             X++;

           }

       }

}


void Delay5Ms(void)

{

          uint TempCyc = 5552;

          while(TempCyc--);

}


void Delay400Ms(void)

{

          uchar TempCycA = 5;

          uint TempCycB;

          while(TempCycA--)

           {

            TempCycB=7269;

            while(TempCycB--);

           };

}




void timer0() interrupt 1

{

        TH0=(65536-50000)/256;

        TL0=(65536-50000)%256;

        aa++;

        if(fl==0)

        {

                if(aa==20)

                {

                        aa=0;

                        r_sec--;

                        if(r_sec<0)

                        {

                                r_min--;

                                r_sec=59;

                                if(r_min<0)

                                {

                                        r_hour--;

                                        r_min=59;

                                }

                                if(r_hour<0)

                                {

                                        r_min=0;

                                        r_sec=0;

                                        r_hour=0;

                                        jdq=1;

                                        fl=1;

                                        r_min2=min2;

                                        r_sec2=sec2;

                                        r_hour2=hour2;

                                }

                        }

                }

                return;

        }


        if(fl==1)

        {

                if(aa==20)

                {

                        aa=0;

                        r_sec2--;

                        if(r_sec2<0)

                        {

                                r_min2--;

                                r_sec2=59;

                                if(r_min2<0)

                                {

                                        r_hour2--;

                                        r_min2=59;

                                }

                                if(r_hour2<0)

                                {

                                        r_min2=0;

                                        r_sec2=0;

                                        r_hour2=0;

                                        jdq=0;

                                        fl=0;

                                        r_min=min;

                                        r_sec=sec;

                                        r_hour=hour;

                                }

                        }

                }

                return;

        }


}


友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
8条回答
agy518
2019-07-16 04:50
wling597074509 发表于 2016-3-20 07:24
51单片机EA端口要接电源,那个黑圈圈L1是电源吧,不过看写的12v,是不能直接用作单片机电源的,如果12v是用于控制继电器的话,继电器的驱动电路不对,把三极管发射级与地相连的那根线换成二极管。按键一般要接上拉电阻,1602供电没接。不用DS1302产生时间却得到时间是因为用的51定时器,也可以做时间的。 ...

你好,看来你详细的解答,非常满意,辛苦了,再次请教个问题,是不是用51定时器的时间,那么断电后,在开启,时间是不是就从初始值开始走时间,AT24C02存储的应该使我们设置的时间吧,如果是请指定点改用DS1302时间加个纽扣电池,这样设备断电了,时间走起,也不用每次设置时间,

一周热门 更多>