DS1302时钟与LCD1602液晶显示

发布者:西周以前的最新更新时间:2018-06-25 来源: eefocus关键字:DS1302时钟  LCD1602  液晶显示 手机看文章 扫描二维码
随时随地手机看文章

    DS1302是一个实时时钟芯片,它在实时显示时间中应用。它可以对年、月、日、周、时、分、秒进行计时。

DS1302的引脚及原理图如下:


    它与CPU的连接需要SCLK(7)、I/O(6)和RST(5)三个引脚,VCC2和VCC1分别为主电源和备份电源,X1和X2分别接外部振荡器。在于CPU的通信中I/O用来传输数据,RST作为复位信号,SCLK用来控制数据字节的读写。


DS1302的读写时序如下:


    程序中对芯片的操作主要是参考芯片的时序状态,时序中说明只要有对数据的操作RST就需要置1,在读数据的前8个时钟中在SCLK处于高电平的过程中会获取控制字信息,此过程I/O数据不会变化,而在低电平的过程中I/O数据进行改变;而到后8个时钟会读数据,对于SCLK的控制与前8个时钟相反。对于写数据的过程与读的过程相似只是后面读写的SCLK时钟控制信号不同。


DS1302的时钟寄存器如下:


    第6位用来选择时钟或RAM,第0位用来做读写的选择,对于第1、2、3为从000到111依次对应秒、分、时、日、月、周、年和控制字地址。


LCD1602液晶

    LCD1602它是一种专门用来显示字母、数字、符号等的点阵型液晶模块。用它来显示需要的字母、数字和符号等会比数码管和LED点阵都要方便。

LCD1602的引脚图如下:


    引脚1、2为地和电源,引脚4为RS用来控制数据和命令选择,引脚5为R/W用来控制读写的选择控制,引脚6为使能控制信号。从第7到14分别对应数据的8个位。


LCD1602的读写时序如下:

写时序:


读时序:


    RS控制数据和命令的选择,读写数据时置高电平否则置低电平;R/W用来控制读写的选择,写操作时为低电平(第1个图),读操作时为高电平(第2个图);读写过程需要E给一个高脉冲。


LCD1602的状态字和相应指令:

    状态字

    前6位对应数据的地址,第7位为读写的使能控制位。


    相应指令:

    模式设定指令为:0x38。清屏显示为0x01;数据指针清零为0x02。

    显示开关及光标的设置:


程序


下边是利用LCD1602显示DS1302时钟信息的例程。

    程序分为4个文件信息分别如下,对于其中的内容可以参考相关注释信息:

1、1602.h文件(在1602.c中作为引用),用来定义LCD1602的相关引脚和函数声明。

typedef bit bool;  

  

sbit RS = P2^6;    //复位端  

sbit RW = P2^5;    //写数据端  

sbit EN = P2^7;    //使能端  

#define uint unsigned int   

#define uchar unsigned char  

  

void delay(int i);  

bit lcd_bz();  

void lcd_wcmd(int cmd);  

void lcd_showstring(uchar r,uchar c,uchar *str);  

void lcd_wdat(uchar dat);  

void lcd_init();  


2、1602.c文件,其中含有对LCD1602初始化和数据及命令的读写控制。



#include   

#include  

#include "1602.h"  

  

//延时函数  

void delay(int i)  

{  

    int j;  

    while(i--)  

    {  

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

        {  

            _nop_();  

            _nop_();  

            _nop_();  

            _nop_();  

        }  

    }  

}  

  

//侧忙,判断LCD是否为忙。  

bool lcd_bz()  

{  

    bool result;  

    RS = 0;  

    RW = 1;  

    EN = 1;  

    _nop_();  

    _nop_();  

    _nop_();  

    _nop_();  

    result = (bool)(P0 & 0x80);//检测P0最高位是否为1.  

    EN = 0;  

    return result;  //返回判断的结果。    

}  

  

//写命令函数。  

void lcd_wcmd_8bit(int cmd)  

{  

    while(lcd_bz());  

    RS = 0;  

    RW = 0;  

    EN = 0;     //先为低电平。  

    _nop_();  

    _nop_();  

    P0 = cmd;    //获得数据。  

    _nop_();  

    _nop_();  

    _nop_();  

    _nop_();  

    EN = 1;      //将电平拉高。  

    _nop_();  

    _nop_();  

    _nop_();  

    _nop_();  

    EN = 0;      //再拉低。  

}    

  

//写命令函数。  

void lcd_wcmd(int cmd)  

{  

    while(lcd_bz());  

    RS = 0;  

    RW = 0;  

    EN = 0;    //先为低电平。  

    _nop_();  

    _nop_();  

    P0 = cmd;   //获得高四位数据。  

    _nop_();  

    _nop_();  

    _nop_();  

    _nop_();  

    EN = 1;     //拉高。  

    _nop_();  

    _nop_();  

    _nop_();  

    _nop_();  

    EN = 0;     //再拉低。  

  

    P0 = (cmd & 0x0f)<<4;  //再获得低四位数据。  

    _nop_();  

    _nop_();  

    _nop_();  

    _nop_();  

    EN = 1;      //将电平拉高。  

    _nop_();  

    _nop_();  

    _nop_();  

    _nop_();  

    EN = 0;       //再拉低。  

}  

  

  

void lcd_showstring(uchar r,uchar c,uchar *str)  

{  

    uchar i=0;  

    code uchar DDRAM[] = {0x80,0xc0};    //设定显示的位置。  

    lcd_wcmd(DDRAM[r] | c);  

    for(i=0;str[i] && i<16;i++)  

        lcd_wdat(str[i]);  

    for(;i<16;i++)  

        lcd_wdat(' ');  

}  

  

//数据写入的函数。  

void lcd_wdat(uchar dat)  

{  

    while(lcd_bz());  

    RS = 1;  

    RW = 0;  

    EN = 0;     //先处于低电平。  

    P0 = dat;    //获得数据高四位。  

    _nop_();  

    _nop_();  

    _nop_();  

    _nop_();  

    EN = 1;  

    _nop_();  

    _nop_();      //再产生一个负脉冲。  

    _nop_();  

    _nop_();  

    EN = 0;  

  

    RS = 1;  

    RW = 0;  

    EN = 0;  

    _nop_();  

    _nop_();  

    _nop_();  

    _nop_();  

    P0 = (dat & 0x0f)<<4; //同理获得低四位。  

    _nop_();  

    _nop_();  

    _nop_();  

    _nop_();  

    EN = 1;  

    _nop_();  

    _nop_();  

    _nop_();  

    _nop_();  

    EN = 0;  

}  

  

//LCD初始化。  

void lcd_init()  

{  

    lcd_wcmd_8bit(0x38);  

    delay(1);  

    lcd_wcmd_8bit(0x38);  

    delay(1);  

    lcd_wcmd_8bit(0x38);  

    delay(1);  

    lcd_wcmd(0x38);  

    delay(1);  

    lcd_wcmd(0x0c);  

    delay(1);  

    lcd_wcmd(0x02);  

    delay(1);  

    lcd_wcmd(0x01);  

    delay(1);  

}  


3、DS1302时钟.c文件,其中含有DS1302时钟的引脚定义及时钟信息的读写等相关操作。


#include  

#include  

  

sbit SCK = P3^6;  //时钟线  

sbit IO = P3^4;   //数据线  

sbit RST = P3^5;  //DS1302复位线。  

  

bit ReadRTC_Flag; //读DS1302的标志。  

  

//七项数据:秒分时日月周年。  

unsigned char l_tmpdate[7] = {0,0,12,15,5,3,8};  

//用来存放转化好的时间数据。  

unsigned char l_tmpdisplay[8];  

  

//7个数据的写地址。  

code unsigned char write_rtc_add[7] = {0x80,0x82,0x84,0x86,0x88,0x8a,0x8c};  

//7个数据的读地址。  

code unsigned char read_rtc_add[7] = {0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};  

  

//函数的声明。  

void Write_Ds1302_byte(unsigned char temp);  

void write_Ds1302(unsigned char add,unsigned char dat);  

unsigned char Read_Ds1302(unsigned char add);  

void Read_RTC(void);  

void Set_RTC(void);  

void InitTIMER0(void);  

  

//定时器的初始化。  

void InitTIMER0(void)  

{  

    TMOD |= 0x01;  

    TH0 = 0xef;  

    TL0 = 0xf0;  

    ET0 = 1;  

    TR0 = 1;  

    EA = 1;  

}  

  

//向1302中发送一个字节数据。  

void Write_Ds1302_Byte(unsigned char temp)  

{  

    unsigned char i;  

    for(i=0;i<8;i++)  //循环8位依次写入数据。  

    {  

        SCK = 0;  

        IO = temp & 0x01;   //传输时从低到高。  

        temp>>=1;   //右移1位。  

        SCK = 1;  

  

    }  

}  

  

//向1302中写入数据。参数有要写入的地址和数据。  

void Write_Ds1302(unsigned char add,unsigned char dat)  

{  

    RST = 0;  

    _nop_();  

    SCK = 0;  

    _nop_();  

    RST = 1;  

    _nop_();  

    Write_Ds1302_Byte(add); //发送地址。  

    Write_Ds1302_Byte(dat); //发送数据。  

    RST = 0;  

}  

  

//从1302中的读出数据。  

unsigned char Read_Ds1302(unsigned char add)  

{  

    unsigned char i,temp=0x00;  

    RST = 0;  

    _nop_();  

    _nop_();  

    SCK = 0;  

    _nop_();  

    _nop_();  

    RST = 1;  

    _nop_();  

    _nop_();  

    Write_Ds1302_Byte(add);  //发送地址,找到地址。  

    for(i=0;i<8;i++)   //循环8次读出数据。  

    {  

        if(IO)      //传输从低到高。  

            temp |= 0x80;  

        SCK = 0;  

        temp>>=1; //右移1位。  

        _nop_();  

        _nop_();  

        _nop_();  

        SCK = 1;  

    }  

    RST = 0;            //之后为DS1302复位。  

    _nop_();  

    _nop_();  

//  RST = 0;    //试验时去掉该句没有影响。  

    SCK = 0;  

    _nop_();  

    _nop_();  

    _nop_();  

    _nop_();  

    SCK = 1;  

    _nop_();  

    _nop_();  

    IO = 0;  

    _nop_();  

    _nop_();  

    IO = 1;  

    _nop_();  

    _nop_();  

    return temp;    //将读到的数据返回。  

}  

  

//从时钟中读取数据。  

void Read_RTC(void)  

{  

    unsigned char i,*p;  

    p = read_rtc_add;  //读日历数据对应的地址。  

    for(i=0;i<7;i++) //分7次分别将:时分秒日月周年读出。  

    {  

        l_tmpdate[i] = Read_Ds1302(*p);  

        p++;  

    }  

}  

  

//设定时钟的时间数据。  

void Set_RTC(void)  

{  

    unsigned char i,*p,tmp;  

    for(i=0;i<7;i++)   //将数从BCD码转化出来,因为1302中用BCD码表示数值。  

    {  

        tmp = l_tmpdate[i]/10;  

        l_tmpdate[i] = l_tmpdate[i]%10;  

        l_tmpdate[i] = l_tmpdate[i] + tmp*16;  

    }  

  

    Write_Ds1302(0x8e,0x00);  //清除写入保护。  

  

    p = write_rtc_add;      //传送地址。  

    for(i=0;i<7;i++)     //将数据依次写入。  

    {  

        Write_Ds1302(*p,l_tmpdate[i]);  

        p++;  

    }  

  

    Write_Ds1302(0x8e,0x80);  //打开写入保护,不能再写入。  

}  

  

  

//定时器中断函数。  

void tim(void) interrupt 1 using 1  

{  

    static unsigned char i,num;  

    TH0 = 0xf5;  

    TL0 = 0xe0;  

  

    i++;  

  

    if(i==8)  

    {  

        i=0;  

        num++;  

        if(10==num)       //间隔一定时间读取1302中数据,更新数码管数据。  

        {  

            ReadRTC_Flag = 1;    //置标志位,从而进行判断。  

            num = 0;  

        }  

    }  

}  


4、LCD显示1302时钟.c文件,这是主函数所在文件,用来将从DS1302获得的信息在LCD1602中显示的操作。



#include  

#include  

#include  

  

#define uchar unsigned char  

#define uint unsigned int  

  

uchar *week[] = {"sun","mon","tus","wes","thu","fri","sat"}; //周信息,周一到周日。  

uchar lcd_buf1[] = "date 00-00-00   ";    //日期信息。  

uchar lcd_buf2[] = "time 00:00:00   ";    //时间信息。  

  

//从其他文件引进的函数。  

extern void InitTIMER0(void);  

extern void lcd_init();  

extern void lcd_showstring(uchar ,uchar ,uchar *);  

extern uchar l_tmpdate[7];  

extern bit ReadRTC_Flag;  

extern void delay(int i);  

extern void Read_RTC();             

extern void Set_RTC();  

  

//将日期和时间信息转化为数字字符。  

void format_datetime(int d,uchar * a)  

{  

    *a = (d >> 4) + '0';  

    *(a+1) = (d & 0x0f) + '0';  

}  

  

void main()  

{  

    lcd_init();   //LCD的初始化。  

    InitTIMER0(); //初始化定时器0。  

//  Set_RTC();  //写入时钟值(写入时钟初值),如果不用改时间可以不用这一项。  

  

    while(1)  

    {  

        if(ReadRTC_Flag)  

        {  

            ReadRTC_Flag = 0;  

            Read_RTC();  

      

            //日期转换。  

            format_datetime(l_tmpdate[6],lcd_buf1+5);  

            format_datetime(l_tmpdate[4],lcd_buf1+8);  

            format_datetime(l_tmpdate[3],lcd_buf1+11);  

            //星期转换。  

            strcpy(lcd_buf1 + 13,week[l_tmpdate[5]-1]);  

            //定义一个字符串char a[20],和一个字符串c[]="i am a teacher!";  

            //把c复制到a中就可以这样用:strcpy(a,c);  

      

            //时间转换。  

            format_datetime(l_tmpdate[2],lcd_buf2+5);  

            format_datetime(l_tmpdate[1],lcd_buf2+8);  

            format_datetime(l_tmpdate[0],lcd_buf2+11);  

      

            lcd_showstring(0,0,lcd_buf1);        //将lcd_buf1和lcd_buf2字符输出。  

            lcd_showstring(1,0,lcd_buf2);  

  

        }  

    }  

}  


关键字:DS1302时钟  LCD1602  液晶显示 引用地址:DS1302时钟与LCD1602液晶显示

上一篇:DS1302+AT24C02+按键数码管显示程序
下一篇:51单片机产生2KHZ方波程序

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

pic16f877连接LCD1602液晶显示
//#include picme1687x.h #include pic.h #define uchar unsigned char #define rs RC0 #define rw RC1 #define en RC2 #define data PORTD const uchar tab = Welcometo Earth! ; void delay(uchar y) { uchar x; for(;y 0;y--) for(x=110;x 0;x--); } void check_busy() { uchar temp; do { data=
[单片机]
pic16f877连接<font color='red'>LCD1602</font><font color='red'>液晶显示</font>
GXM12864图形液晶显示模块驱动程序
GXM12864是一种采用低功耗CMOS技术实现的点阵图形LCD模块,内含KS0108B/HD61202控制器,CSA与KS0108B(1)连通!CSB与KS0108B(2)连通!CSA/CSB为01时选通KS0108B(1);为10时选通CSB与KS0108B(2),为其他值时!禁止选通!总线处于高阻状态! 硬件原理为PO口接DB0-DB7的8位双向数据总线! KS0108B 指令集 1:显示开关指令: R/W=0;D/I=0; 开:0X3F; 关:0X3E 2:显示起始行指令:R/W=0;D/I=0;8位数据高2位为1 后6位位起始巷(0-63) 3:页设置指令:R/W=0;D/I=0; 前5位恒定为10111!后三位为页号(
[单片机]
lcd1602 屏驱动(自定义字符)
1、时序图 2、代码 3、自定义字符 时序图 代码: #include reg51.h #include intrins.h sbit RS = P2^4; //定义端口 sbit RW = P2^5; sbit EN = P2^6; void Delayus(unsigned char t) // us级别延时 { while(--t); } void Delayms(unsigned char t)// ms级别延时 { while(t--) { //大致延时1mS Delayus(245); Delayus(245)
[单片机]
<font color='red'>lcd1602</font> 屏驱动(自定义字符)
LCD1602液晶显示模块的单片机驱动深入详解之软件篇(AVR)
LCD1602液晶显示模块的驱动虽然比七段数码管之类的显示要复杂一些,但实际上也并不是很难,最主要的还是初始化,为什么这么说呢?我们在调试一块新液晶屏的时候,都会先初始化看看有没有光标在闪,没有光标前是一番努力(PROTEUS上也是这么做的),光标出来之后就相对很容易了,因为光标出来了,至少说明硬件连接是没有问题的,模块也已经成功接收到了指令,后面就是啃数据手册、改程序、烧录程序观察显示的循环了。 那初始化的流程是怎么样的呢?我们还是看看HD44780的数据手册吧,如下图所示: 可以看到,初始化的主要步骤如下: (1)上电:这特么也算是一个步骤么?是的!如果你用的是其它液晶模块,比如LCD12864,会发现有一个复位引脚,LC
[单片机]
<font color='red'>LCD1602</font><font color='red'>液晶显示</font>模块的单片机驱动深入详解之软件篇(AVR)
SMC1602A液晶显示器子程序
; LCD SMC1602A显示模块 ; *************************************************************************** ;连线图: *LCM---8031* *LCM---8031* *RS-------- P2.6* ; *DB0----P0.0* *DB4---P0.4* *RW--------P2.5* ; *DB1----P0.1* *DB5---P0.5* *GATE-----P2.7* ; *DB2----P0.2* *DB6---P0.6* *E--------NAND* ; *DB3----P0.3*
[单片机]
单片机:矩阵键盘和LCD1602
一、矩阵键盘 1、检测按键的方法: (1)先使1-4全部赋低电平,5-8赋高电平。当有按键按下时,5-8中会有某个点平被拉低。 (2)然后依次将1-4中的某一位置0,其他位置1,观察对应返回值,即可确定哪个按键被按下。 2、对应程序 unsigned char bsp_mkeyscan() { unsigned char keyvalue = 0x99; KEYPORT = 0xF0; if (KEYPORT != 0xF0) { KEYPORT = 0xFE; if (KEYPORT != 0xFE) { keyvalue = KEYPORT; while(key
[单片机]
C8051F020在液晶显示控制系统中的应用
在单片机系统设计中,LCM(液晶显示模块)人机交互界面的设计往往是很重要的一个环节。LCM可以用于智能仪器上的显示设定参数、状态提示符、检测结果和待输入参数等功能。本文结合电解质分析仪的设计要求,采用深圳市烨新达实业有限公司生产的YXD—12864A2LCM,研究并实现了以C8051F020为基础的液晶显示的接口电路和程序设计,添加了按键系统,从而达到方便用户使用的目的。 1 电解质分析仪简介 本系统所设计的电解质分析仪(Electrolyte Analyzer)是一种具有高分辨率和高精度的仪器,可以与多种离子选择电极配套使用,可用自动方法测定样品中钾、钠、氯、钙离子的浓度和pH值。其结构方框图如图1所示。仪器采用单片机C80
[电源管理]
C8051F020在<font color='red'>液晶显示</font>控制系统中的应用
1602液晶显示模块的应用
液晶显示器以其微功耗、体积小、显示内容丰富、超薄轻巧的诸多优点,在各类仪表和低功耗系统中得到广泛的应用。 根据显示内容可以分为字符型液晶,图形液晶。根据显示容量又可以分为单行16字,2行16字,两行20字等等。 这里介绍常用的字16字X2行的字符型液晶模块的使用方法。这是一种通用模块。与数码管相比该模块有如下优点: 1.位数多,可显示32位,32个数码管体积相当庞大了 2.显示内容丰富,可显示所有数字和大、小写字母 3.程序简单,如果用数码管动态显示,会占用很多时间来刷新显示,而1602自动完成此功能。 1602采用标准的16脚接口,其中:(模块背面有标注) 第1脚:VSS为地电源 第2脚:VDD接5V正电源
[单片机]
1602<font color='red'>液晶显示</font>模块的应用
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
热门活动
换一批
更多
设计资源 培训 开发板 精华推荐

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

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

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