51单片机 万年历

发布者:温馨小筑最新更新时间:2017-01-05 来源: eefocus关键字:51单片机  万年历 手机看文章 扫描二维码
随时随地手机看文章

这个小项目自己做了5天,小有成就感。。。感谢前辈们多多提意见。。


12864液晶、DS12C887时钟芯片、DS18B20温度传感器。。。


#define uchar unsigned char

#define uint unsigned int


uint temp;

float f_temp;


sbit Ds=P2^2;

sbit Dula=P2^6;

sbit Wela=P2^7;


sbit LcdCS=P3^5;        //寄存器选择输入 通过rs确定是写数据还是写命令

sbit LcdSID=P3^6;        //液晶读/写控制 因为不从液晶读取任何数据,所以rw一直为0

sbit LcdSCLK=P3^4;        //液晶使能控制 给en一个高脉冲将数据送入液晶控制器

sbit LcdPSB=P3^7;        //串并方式控制


sbit DSCS=P1^4;            //片选信号,低电平有效

sbit DSAS=P1^5;            //地址选通输入端 AS的上升沿将AD0~AD7上出现的地址信息锁存到DS12C887上,下降沿清除地址信息

sbit DSRW=P1^6;            //

sbit DSDS=P1^7;            //


uchar code table1[]={" CHPAVC 天若海愚"};

uchar code table3[]={"星期一"};

uchar code table4[]={"星期二"};

uchar code table5[]={"星期三"};

uchar code table6[]={"星期四"};

uchar code table7[]={"星期五"};

uchar code table8[]={"星期六"};

uchar code table9[]={"星期日"};

uchar code table10[]={"°C"};


uchar buff[4];    


char year,month,day,week,miao,fen,shi;

uchar nyrsfm[17];        //Write_nyrsfm函数中,方法二nyrsfm只需申明成nyrsfm[16]




/***************************************************************

文件名称:    wannianli

作者    :    天若海愚

版本号    :    V1.0

说明    :    

创建时间:    2013年9月17日13:30:38

修改记录:    无

备注    :    在12864液晶屏上显示从DS12C887采集到的年、月、日、时、分数据,并且利用DS18B20采集温度显示在12864上

***************************************************************/


#include

#include

#include

#include


/***********************************

函数名称:    Delay()

函数功能:    延时

入口参数:    z

备注    :

***********************************/

void Delay(uint z)

{

    uint x,y;

    for(x=z;x>0;x--)

        for(y=110;y>0;y--);

}


/**********************************

函数名称:    Ds_reset()

函数功能:    DS18B20复位,初始化函数

入口参数:    无

备注    :

**********************************/

void Ds_reset()

{

    uint i;

    Ds=1;        //书P348,时序图,先将数据线置高电平1

    _nop_();    //延时,尽可能短一点

    Ds=0;

    i=103;

    while(i>0)

        i--;    //当总线停留在低电平超过480us,总线上所以器件都将被复位,这里

                //延时约680us总线停留在低电平超过480μs,总线上的所有器件都将被复位

    _nop_();    //延时,尽可能短一点

    

    Ds=1;

    i=5;

    while(i>0)

        i--;    //释放总线后,如果初始化成功则在15~60us内产生一个由DDS18B20返回的低电平0,据

                //该状态可以确定它的存在,但是不能无限制地等

}


/**********************************

函数名称:    Ds_read_bit()

函数功能:    读一位数据函数

入口参数:    无

备注    :

**********************************/

bit Ds_read_bit()

{

    uint i;

    bit dat;

    

    Ds=0;        //单片机(微处理器)将总线拉低

    _nop_();    //读时隙起始于微处理器将总线拉低至少1us

    Ds=1;        //拉低总线后接着释放总线,让从机18b20能够接管总线,输出有效数据

    _nop_();

    _nop_();    //小延时一下,读取18b20上的数据 ,因为从ds18b20上输出的数据,在读"时间隙"下降沿出现15us内有效

    dat=Ds;           //主机读从机18b20输出的数据,这些数据在读时隙的下降沿出现15us内有效 

    i=10;

    while(i>0)

        i--;       //所有读"时间隙"必须60~120us,这里77us

    return(dat);

}



/**********************************

函数名称:    Ds_read_byte()

函数功能:    读一个字节数据函数

入口参数:    无

备注    :

**********************************/

uchar Ds_read_byte()

{

    uchar i,j,dat;

    dat=0;        //初值不能忘

    for(i=1;i<=8;i++)    //此句曾写成for(i=0;i<=8;i++),导致程序显示结果出错,细节。。。

    {

        j=Ds_read_bit();

        dat=(j<<7)|(dat>>1);    //读出的数据最低位在最前面,这样刚好一个字节在dat里

    }

    return(dat);

}


/**********************************

函数名称:    Ds_write_byte()

函数功能:    向DS18B20写一个字节函数

入口参数:    

备注    :

**********************************/

void Ds_write_byte(uchar dat)

{

    uchar i;

    uint j;

    bit testb;

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

    {

        testb=dat&0x01;

        dat=dat>>1;

        if(testb)

        {

            Ds=0;

            _nop_();

            _nop_();      //看时序图,至少延时1us,才产生写"时间隙"  

            Ds=1;         //写时间隙开始后的15μs内允许数据线拉到高电平

            j=8;

            while(j>0)

                j--;         //所有写时间隙必须最少持续60us

        }

        else

        {

            Ds=0;

            j=8;

            while(j>0)

                j--;         //主机要生成一个写0 时间隙,必须把数据线拉到低电平并保持至少60μs,

            Ds=1;

            _nop_();

            _nop_();        

        }

    }

}


/**********************************

函数名称:    Ds_change()

函数功能:    18b20开始获取温度并转换

入口参数:

备注    :

**********************************/

void Ds_change()

{

    Ds_reset();        //初始化

    Delay(1);

    Ds_write_byte(0xcc);    //跳过ROM.直接向18b20发温度 转换指令,适用于一个从机工作

    Ds_write_byte(0x44);    //写温度转换指令

}


/**********************************

函数名称:    Get_temp()

函数功能:    读取寄存器中存储的温度数

入口参数:    无

备注    :

**********************************/

uint Get_temp()

{

    uchar a,b;

    Ds_reset();

    Delay(1);

    Ds_write_byte(0xcc);        //写跳过读ROM指令

    Ds_write_byte(0xbe);        //读暂存器。读内部RAM中9字节的温度数据

    a=Ds_read_byte();     //读低8位

    b=Ds_read_byte();     //读高8位

    temp=b;

    temp<<=8;        //两个字节组合为一个字

    temp=temp|a;

    f_temp=temp*0.0625;     //得到真实十进制温度值,因为DS18B20可以精确到0.0625 度,所以读回数据的最低位代表的是0.0625 度。

    temp=f_temp*10+0.5;     //乘以10不是小数点后面只取1位,加0.5是四舍五入

    f_temp=f_temp+0.05;

    

    return temp;        //temp是整型

}


/**********************************

函数名称:    init_com()

函数功能:    串口初始化

入口参数:    无

备注    :

**********************************/

void init_com()

{

    TMOD=0x20;        //定时器1,方式2

    PCON=0x00;

    SCON=0x50;        //等价于REN=1;SM0=0;SM1=1;

    TH1=0xFD;

    TL1=0xFD;        //设置波特率 9600

    TR1=1;            //启动定时器1

}


/**********************************

函数名称:    comm()

函数功能:    串口发送数据

入口参数:    

备注    :

**********************************/

void comm(uchar *parr)

{

    do

    {

        SBUF=*parr++;

        while(!TI);        //发送完毕,TI由硬件置1

        TI=0;

    }while(*parr);        //保持循环直到字符为'\0'

}


/***********************************

函数名称:    Send_byte()

函数功能:    发送一个字节

入口参数:    bbyte

备注    :

***********************************/

void Send_byte(uchar bbyte)

{

    uchar i;

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

    {

        LcdSID=bbyte&0x80;        //取出最高位

        LcdSCLK=1;

        LcdSCLK=0;        //sclk由低电平变为高电平的瞬间,液晶控制器将sid上数据读入或输出

        bbyte<<=1;        //左移1位

    }

}


/***********************************

函数名称:    Write_char()

函数功能:    写数据或写命令

入口参数:    start,ddata

备注    :

***********************************/

void Write_char(bit start,uchar ddata)

{

    uchar start_data,Hdata,Ldata;

    if(start==0)

    {

        start_data=0xf8;        //写指令

    }

    else

    {

        start_data=0xfa;        //写数据

    }

    

    Hdata=ddata&0xf0;        //取高4位

    Ldata=(ddata<<4)&0xf0;    //取低4位

    Send_byte(start_data);    //发送起始信号

    Delay(5);        //延时是必须的

    Send_byte(Hdata);        //发送高4位

    Delay(1);        //延时是必须的

    Send_byte(Ldata);

    Delay(1);

}


/***********************************

函数名称:    Lcd_pos()

函数功能:    设置显示位置

入口参数:    X,Y

备注    :

***********************************/

void Lcd_pos(uchar X,uchar Y)

{

    uchar pos;

    if(X==0)

    {

        X=0x80;

    }

    else if(X==1)

    {

        X=0x90;

    }

    else if(X==2)

    {

        X=0x88;

    }

    else if(X==3)

    {

        X=0x98;

    }

    pos=X+Y;

    Write_char(0,pos);

}


/***********************************

函数名称:    Lcd_init()

函数功能:    液晶初始化

入口参数:    无

备注    :

***********************************/

void Lcd_init()

{

    Delay(5);        //启动等待,等LCD进入工作状态

    LcdPSB=0;        //串口驱动

    Write_char(0,0x30);        //基本指令操作

    Delay(5);

    Write_char(0,0x0c);        //显示开,关光标,反白关

    Delay(5);

    Write_char(0,0x01);        //清屏,将DDRAM的地址计数器归零

    Delay(5);

}



/**********************************

函数名称:    Display_temp()

函数功能:    在12864上显示温度

入口参数:

备注    :    小数点后保留一位

**********************************/

void Display_temp()

{

    uchar i;

    Lcd_pos(2,4);

    Write_char(1,buff[0]);

    Write_char(1,buff[1]);

    Write_char(1,buff[2]);

    Write_char(1,buff[3]);        


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

    {

        Write_char(1,table10[i]);    //显示符号°C 

        Delay(5);

    }

}


/*********以下是操作DS12C87时钟芯片***********/

/***********************************

函数名称:    Write_ds()

函数功能:    写12C8887函数

入口参数:    add,date

备注    :

***********************************/

void Write_ds(uchar add,uchar date)

{

    DSCS=0;

    DSAS=1;

    DSDS=1;

    DSRW=1;

    P0=add;

    DSAS=0;     //dsas的下降沿将AD0~~AD7上的地址信息锁存到DS12C887上

    DSRW=0;

    P0=date;

    DSAS=1;

    DSRW=1;        //INTER模式,dsrw的上升沿锁存数据

    DSCS=1;

}


/***********************************

函数名称:    Read_ds()

函数功能:    读12C8887函数

入口参数:    add

备注    :

***********************************/

uchar Read_ds(uchar add)

{

    uchar ds_date;

    DSAS=1;

    DSDS=1;

    DSRW=1;

    DSCS=0;

    P0=add;        //先写地址

    DSAS=0;

    DSDS=0;

    P0=0xff;

    ds_date=P0;        //再读数据

    DSDS=1;

    DSCS=1;

    DSAS=1;

    return ds_date;

}


/**********************************

函数名称:    Write_nyrsfm()

函数功能:    将年、月、日、时、分显示在12864液晶上

入口参数:

备注    :    不能通过下面的/*   中的函数来实现

**********************************/

void Write_nyrsfm(char year,char month,char day,char shi,char fen)

{

    //方法一:

    

    /*uchar i;

    Lcd_pos(1,0);

    

    nyrsfm[0]=0x32;

    nyrsfm[1]=0x30;

    nyrsfm[2]=year/10+0x30;

    nyrsfm[3]=year%10+0x30;

    nyrsfm[4]='-';

    nyrsfm[5]=month/10+0x30;

    nyrsfm[6]=month%10+0x30;

    nyrsfm[7]='-';

    nyrsfm[8]=day/10+0x30;

    nyrsfm[9]=day%10+0x30;

    nyrsfm[10]=' ';

    nyrsfm[11]=shi/10+0x30;

    nyrsfm[12]=shi%10+0x30;    

    nyrsfm[13]=':';

    nyrsfm[14]=fen/10+0x30;

    nyrsfm[15]=fen%10+0x30;

    nyrsfm[16]='\0';

    

    //while(nyrsfm[i]!='\0')        //while()循环不显示,是错误的

    //{

    //    Write_char(1,nyrsfm[i]);        

    //    i++;

    //}

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

    {

        Write_char(1,nyrsfm[i]);

        Delay(5);

    }*/



    //方法二:

    

    Lcd_pos(1,0);

    

    nyrsfm[0]=0x32;

    Write_char(1,0x32);

    

    nyrsfm[1]=0x30;

    Write_char(1,0x30);

    

    nyrsfm[2]=year/10+0x30;

    Write_char(1,nyrsfm[2]);

    

    nyrsfm[3]=year%10+0x30;

    Write_char(1,nyrsfm[3]);

    

    nyrsfm[4]='-';

    Write_char(1,nyrsfm[4]);

    

    nyrsfm[5]=month/10+0x30;

    Write_char(1,nyrsfm[5]);


    nyrsfm[6]=month%10+0x30;

    Write_char(1,nyrsfm[6]);

    

    nyrsfm[7]='-';

    Write_char(1,nyrsfm[7]);

    

    nyrsfm[8]=day/10+0x30;

    Write_char(1,nyrsfm[8]);

    

    nyrsfm[9]=day%10+0x30;

    Write_char(1,nyrsfm[9]);

    

    nyrsfm[10]=' ';

    Write_char(1,nyrsfm[10]);

    

    nyrsfm[11]=shi/10+0x30;

    Write_char(1,nyrsfm[11]);

    

    nyrsfm[12]=shi%10+0x30;

    Write_char(1,nyrsfm[12]);

    

    nyrsfm[13]=':';

    Write_char(1,nyrsfm[13]);

    

    nyrsfm[14]=fen/10+0x30;

    Write_char(1,nyrsfm[14]);

    

    nyrsfm[15]=fen%10+0x30;

    Write_char(1,nyrsfm[15]);

}


/**********************************

函数名称:    Write_week()

函数功能:    星期显示

入口参数:    xq

备注    :

**********************************/

void Write_week(char xq)

{

    uchar i;


    Lcd_pos(2,0);

    switch(xq)

    {

        case 1:

            i=0;

            while(table3[i]!='\0')

            {

                Write_char(1,table3[i]);

                i++;

            }

            break;

        case 2:

            i=0;

            while(table4[i]!='\0')

            {

                Write_char(1,table4[i]);

                i++;

            }

            break;

        case 3:

            i=0;

            while(table5[i]!='\0')

            {

                Write_char(1,table5[i]);

                i++;

            }

            break;

        case 4:

            i=0;

            while(table6[i]!='\0')

            {

                Write_char(1,table6[i]);

                i++;

            }

            break;

        case 5:

            i=0;

            while(table7[i]!='\0')

            {

                Write_char(1,table7[i]);

                i++;

            }

            break;

        case 6:

            i=0;

            while(table8[i]!='\0')

            {

                Write_char(1,table8[i]);

                i++;

            }

            break;

        case 7:

            i=0;

            while(table9[i]!='\0')

            {

                Write_char(1,table9[i]);

                i++;

            }

            break;

    }

}


/**********************************

函数名称:    Set_time()

函数功能:    DS12C887首次上电初始化时间函数

入口参数:    无

备注    :

**********************************/

void Set_time()

{

    Write_ds(2,25);

    Write_ds(4,10);

    Write_ds(6,3);

    Write_ds(7,18);

    Write_ds(8,9);

    Write_ds(9,13);

}


/***********************************

函数名称:    init()

函数功能:    初始化

入口参数:    无

备注    :

***********************************/

void init()

{

    uchar i;

    i=0;

    Wela=0;

    Dula=0;

    EA=1;

    EX1=1;

    IT1=1;


    Set_time();        //首次上电时使用,只需执行一次

    Lcd_pos(3,0);    

    while(table1[i]!='\0')

    {

        Write_char(1,table1[i]);

        i++;

    }

}



/**********************************

函数名称:    Main()

函数功能:    

入口参数:

备注    :

**********************************/

void Main()

{

    init_com();            //串口初始化

    Lcd_init();            //LCD初始化

    init();                //不能放在Lcd_init()函数前面,,只有在液晶初始化之后才能够显示init()函数的内容

    

    while(1)

    {

        Ds_change();        //读取寄存器中存储的温度数

        Get_temp();            //获取温度并转换

        

        sprintf(buff,"%.1f",f_temp);        //将浮点型温度格式化为字符型,并保留一位,需声明#include

        Delay(1000);

        comm(buff);            //串口发送数据,在串口调试助手上显示,这里主要是为了测试buff的内容而加上这句的

        Display_temp();        //在12864液晶上显示温度

        

        Delay(5);

        year=Read_ds(9);    //从DS12C887上读取数据

        month=Read_ds(8);

        day=Read_ds(7);

        week=Read_ds(6);

        shi=Read_ds(4);

        fen=Read_ds(2);


        Write_nyrsfm(year,month,day,shi,fen);        //在12864液晶显示

        Write_week(week);                            //显示星期

    }

}


关键字:51单片机  万年历 引用地址:51单片机 万年历

上一篇:[51单片机学习笔记FIVE]----独立按键
下一篇:51单片机堆栈深入剖析

推荐阅读最新更新时间:2024-03-16 15:28

51单片机实验18:蜂鸣器
关于蜂鸣器的内容参考:https://blog.csdn.net/cax1165/article/details/87634433 开发板蜂鸣器模块原理图如下: #include reg52.h #define uc unsigned char sbit beep=P1^5; void delay(uc x) { uc i,j; for(i=1;i =x;i++) for(j=1;j =110;j++); } void main() { while(1) { beep=~beep; delay(5);//调节音调 } }
[单片机]
<font color='red'>51单片机</font>实验18:蜂鸣器
51单片机—单片机扩展外部RAM—6264—08
今天这个是是以前做过的,没做成,扩展ROM的时候失败了~~ 不过今天主要的就是扩展外部的RAM,这个相对比较简单点,不想外部的ROM还要设置太多的编译器~~ 单片机扩展外部RAM 一、扩展总线 1、简介(这种扩展是基于总线扩展的,所以,P0、P2口就已经不可以再做它用了) 1)数据总线宽度为8位,由P0口提供; 2)地址总线宽度为16位,可寻址范围2的16次,也就是64K。低8位A7~A0由P0口经地址锁存器提供,高8位A15~A8由P2口提供。由于P0口是数据、地址分时复用,所以P0口输出的低8位必须用地址锁存器进行锁存; 3)控制总线由RD、WR、PSEN、ALE和EA等信号组成,用于读/写控制、片外RAM选通、地址锁存控制和片
[单片机]
<font color='red'>51单片机</font>—单片机扩展外部RAM—6264—08
采用51单片机的金卤灯控制器的设计
1 概论 目前,大部分照明设备仍以传统能源来照明,充分利用太阳能作为照明设备的能源供给,在节约能源、保护环境等方面具有重要意义。 2 控制器整体结构 太阳能光伏板接入光伏信号处理电路,光伏电压经PWM充电控制电路送到12 V蓄电池内。正常工作时,12 V蓄电池输出电压经高频平面变压器次级感应升压、整流后到全桥电路。同时12 V输出电压与电压变换电路相连接,向控制器其他电路供电。 2.1 太阳能充电系统 光伏信号处理电路包括防信号反接电路、光伏电压取样电路和雷击保护电路。其中,防信号反接电路可以阻止光伏信号反接输入对控制器电路造成损坏。电压取样电路提供给C8051F920采样后的光伏电压信号。
[单片机]
采用<font color='red'>51单片机</font>的金卤灯控制器的设计
51单片机串口打印不管是中文还是英文都是乱码的问题
讲道理都tm大三暑假了还搞51单片机而且关键是还遇到了一个问题解决了一天才解决出来真的是很丢人了。 不过我会珍惜这个机会的,毕竟这有可能是我辈子最后一次跟着老师搞这个破玩意了。 好了不废话了 收! 昨天遇到的问题是单片机用串口给电脑发数据,本人用串口助手查看时乱码了,发送的数据是英文和数字,没有存在中文,马上进行问题排除: 解决方案一:printf的原因吗? 代码里用piintf函数来进行串口发送数据,可能printf只适合于stm32不能适用于51,但是仔细一想又不对啊,我tm大三上的单片机大作业就是用printf函数进行串口发送数据的啊,怎么当时就可以啊。于是我把当时的代码拿过来修改,还是不行。 解决方
[单片机]
51单片机指令系统寻址方式
指令给出参与运算的数据方式称为寻址方式。换句话说,寻址方式就是寻找确定参与操作的数的真正地址。 在MCS-51系列单片机的指令系统中寻址方式共有7种, 立即寻址方式,mcs-51单片机的一种寻址方式,操作数就写在指令中,和操作码一起放在程序存贮器中。把“#”号放在立即数前面,以表示该寻址方式为立即寻址,如#20H,立即寻址方式通常用于对通用寄存器或内存单元赋初值。 直接寻址方式,指令操作数域给出的是参加运算的操作数地址。在MCS-51单片机中,直接地址只能用来表示特殊功能寄存器、内部数据寄存器和位地址空间。其中,特殊功能寄存器和位地址空间只能用直接寻址方式访问。 寄存器寻址方式,操作数在寄存器中,由指令操作码中的rrr
[单片机]
51单片机与计算机通讯,51单片机与PC通信方法总结
51单片机的串口,是个全双工的串口,发送数据的同时,还可以接收数据。 当串行发送完毕后,将在标志位 TI 置 1,同样,当收到了数据后,也会在 RI 置 1。 无论 RI 或 TI 出现了 1,只要串口中断处于开放状态,单片机都会进入串口中断处理程序。 在中断程序中,要区分出来究竟是发送引起的中断,还是接收引起的中断,然后分别进行处理。 常用的方法有: 接收数据时,使用“中断方式”,清除 RI 后,用一个变量通知主函数,收到新数据。 发送数据时,也用“中断方式”,清除 TI 后,用另一个变量通知主函数,数据发送完毕。 这样一来,收、发两者基本一致,编写程序也很规范、易懂。 更重要的是,主函数中,不用在那儿死等发
[单片机]
AT89C51单片机数字逻辑无环流可逆调速系统设计
1 引言 生产中有许多机械要求既能正转,又能反转,而且常需要快速起动和制动,即需要可逆调速系统。由模拟电路实现的可逆调速系统,线路复杂,调整困难,可靠性低,缺乏灵活的控制。因此,这里给出一种基于单片机的逻辑无环流可逆调速控制系统设计方案。该系统设计采用全数字电路,实现数字脉冲触发、数字转速给定检测和数字PI算法等功能,由软件实现转速、电流调节及逻辑判断和复杂运算,具有不同于一般模拟电路的最优化、自适应、非线性、智能化等控制规律,而且更改灵活方便。 2 系统组成和控制原理 2.1 系统组成 该数字逻辑无环流可逆调速系统是由AT89C51单片机实现双闭环控制、无环流逻辑控制、触发脉冲的形成及相位控制,如图1所示。图1中,ASR为速
[单片机]
AT89C<font color='red'>51单片机</font>数字逻辑无环流可逆调速系统设计
51单片机驱动1602液晶汇编语言程序
LCMRS EQU P2.4 LCMRW EQU P2.5 LCMEN EQU P2.6 LCMDATA EQU P0 ORG 0000H LJMP MAIN ORG 0030H MAIN: MOV SP,#60H LCALL LCMSET LCALL LCMCLR MOV A,#80H LCALL LCMWR0 MOV DPTR,#TAB0 LCALL LCMWR2 MOV A,#0C0H LCALL LCMWR0 MOV DPTR,#TAB1 LCALL LCMWR2 SJMP $ TAB0: DB I AM YUAN MING ,00H TAB1: DB NICE TO MEET YOU ,00H LCMLAY:
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved