4.用DS1302与12864LCD设计的可调式中文电子日历

更新时间:2023-08-26 00:51:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

用DS1302与12864LCD设计的可调式中文电子日历

学习情境5-可调式数字钟

之 用DS1302与12864LCD设计的可调式中文电子日历

☆ 点名,复习

1、DS1302的引脚及其功能,以及DS1302与单片机的硬件连接? 2、如何编写基于1602LCD的显示驱动程序? ☆ 新课讲授

5.3 基于DS1302与LCD12854设计的可调数字钟

上节课我们详细介绍了LCD1602的显示控制指令,掌握了如何编写该种型号的LCD的显示驱动程序。这节课我们学习另外一种液晶显示模块—12864(KS0108) 5.3.1 LCD12864技术资料

5.3.1.1 12864(KS0108)字符型LCD简介

12864D使用KS0108(或其兼容芯片)作为控制器,适配M6800系列时序,具有8位标准数据总线。6条控制线及电源线可显示各种字符及图形。每个KS0108拥有64×64位(512字节)的显示RAM,12864D显示屏上的64×64点,显示RAM中的数据直接作为显示驱动信号。具有操作指令简单,低功耗的特点。 5.3.1.2、引脚说明

1、指令列表

2、指令功能详解

用DS1302与12864LCD设计的可调式中文电子日历

(1)读状态字(read status)

格式

★ BUSY=1,表示能接受除读状态字以外的任何操作。BUSY=0表示KS0108接口控制电路已处于“准备好”状态,等待计算机的访问。

★ ON/OFF:表示当前的显示状态。ON/OFF=1表示关显示状态;ON/OFF=0表示开显示状态。

★ RESET表示当前KS0108的工作状态,即反映RST

端的电平状态。当RST为低电平状态时KS0108处于复位工作状态,RESET=1。当RST为高电平状态时,KS0108为正常工作状态,RESET=0。

★ 在占领设置和数据读写时要注意状态字中的BUSY标志。只有在BUSY=0时,计算机对KS0108的操作才能有效。因此计算机在每次对KS0108操作之前,都要读出状态字判断BUSY是否为“0”。若不为“0”,则计算机需要等待,直至BUSY=0为止。 (2)显示开关(display on/off)

格式

该指令设置显示开关/从而控制显示上的显示状态。

D位为显示开/关的控制位。当D=1为显示设置,显示数据锁存器正常工作,显示屏上呈现所许的效果。此时在状态字中ON/OFF=0。当D=0为关显示设置,显示数据锁存器被置零,显示屏呈不显示状态,但显示存储器并没有被破坏,在状态组中ON/OFF=1。 (3)显示起始行设置(Display start line)

格式

L5~L0为显示起始行的地址,取值在00~3FH(1~64)范围内,它规定了显示屏上最顶一行所对应的显示存储器的行地址。如果定时间隔地,等间距地修改(如加一或减一)显示起始行寄存器的内容,则显示屏将呈现显示内容向上或向下平滑滚动的显示效果。 (4)页面地址设置[Set page(X address)]

格式

该指令设置了页面地址8页,指令代码中P2~P0就是要确定当前所要选择的页面地址,取值范围为00~07H,代表第1~8页。该指令规定了以后的读/写操作将在哪一个页面上进行。执行本指令后,下面的读写操作将在指定页内,直到重新设置。页地址就是DDRAM 的行地址,页地址存储在X地址计数器中,P2-P0可表示8页,读写数据对页地址没有影响,除本指令可改变页地址外,复位信号(RST)可把页地址计数器内容清零。

Y1

表2 DDRAM地址映像表 Y2 Y3 Y4 ………… Y62 Y63 Y64

DB0 DB1 DB2 DB3

Line 0

Line 1 Line 2 Line 3

用DS1302与12864LCD设计的可调式中文电子日历

X=0 Line 4

Line 5 Line 6 Line 7 DB4 DB5 DB6 DB7

………… ………… …………

X=7

Line60 Line61 Line62 Line63

DB4

DB5

DB6

DB7

(5)列地址设置(Set Y address)

格式

该指令设置了Y地址,随后的一次读或写数据将在这个单元上进行。Y地址计数器具有自动加一功能,在每一次读/写数据后它将自动加一,所以在连续进行读/写数据时,Y地址计数器不必每次都设置一次。页面地址的设置和列地址的设置将显示存储器单元唯一地确定下来,为后来的显示数据的读/写作了地址的选通。

(6)写显示数据(Write display data)

格式

该操作将8操作完成后列地址计数器自动加1。

(7)读显示数据(Read display data)

格式

该操作将KS01081。 5.3.2 硬件电路设计

硬件主要使用了DS1302和LCD12864,电路结构简单,具体如下图所示:

用DS1302与12864LCD设计的可调式中文电子日历

图 1 硬件电路

5.3.3 软件设计

软件设计中主要是针对DS1302芯片和LCD12864进行程序的设计,而DS1302的驱动程序在上个项目中我们已经作了详细介绍,在此不再赘述。我们主要编制LCD12864的驱动程序。根据对LCD12864资料的分析,程序编制主要有:读取LCD的状态,忙检查,向LCD写入命令,向LCD写入数据,LCD初始化,设置LCD液晶的显示位置,显示字符等。除此之外,我们把要显示的字符和汉字用一个专门的程序来编写,命名为DotMatrix.c。

1、LCD12864显示驱动程序 (1)检查LCD是否忙

bit LCD_IS_BUSY() {

LCD_DB_PORT=0xFF; RW=1; _nop_(); DI=0; E=1; _nop_(); E=0;

return (bit)(P0&0x80); }

(2)向LCD写入一个字节(一般用于发送命令)

void Write_Byte_To_LCD(uchar comand)

用DS1302与12864LCD设计的可调式中文电子日历

{

while(LCD_IS_BUSY()); LCD_DB_PORT=0xFF; RW=0; _nop_(); DI=0;

LCD_DB_PORT=comand; E=1; _nop_(); E=0; }

(3)向LCD写入数据

void Write_Data_To_LCD(uchar dat) {

while(LCD_IS_BUSY()); LCD_DB_PORT=0xFF; RW=0; _nop_(); DI=1;

if(!Reverse_Display) //根据Reverse_Display决定是否反相显示 LCD_DB_PORT=dat; else

LCD_DB_PORT=~dat; E=1; _nop_(); E=0; }

(4)初始化LCD

void LCD12864_Initialization() {

CS1=1; CS2=1;

Write_Byte_To_LCD(0x38); Write_Byte_To_LCD(0x0F); Write_Byte_To_LCD(0x01); Write_Byte_To_LCD(0x06);

Write_Byte_To_LCD(LCD_START_ROW); }

(5)通用显示函数 从第P页第L列显示W个字节数据,具体显示的数据在r所指的数组中

void LCD_Show(uchar P,uchar L,uchar W,uchar *r) reentrant {

uchar i; if(L<64) {

用DS1302与12864LCD设计的可调式中文电子日历

CS1=1; CS2=0;

Write_Byte_To_LCD(LCD_PAGE+P); Write_Byte_To_LCD(LCD_COL+L); if(L+W<64) {

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

Write_Data_To_LCD(r[i]); } else {

for(i=0;i<64-L;i++)

Write_Data_To_LCD(r[i]); CS1=0; CS2=1;

Write_Byte_To_LCD(LCD_PAGE+P); Write_Byte_To_LCD(LCD_COL); for(i=64-L;i<W;i++)

Write_Data_To_LCD(r[i]); } } else {

CS1=0; CS2=1;

Write_Byte_To_LCD(LCD_PAGE+P); Write_Byte_To_LCD(LCD_COL+L-64); for(i=0;i<W;i++)

Write_Data_To_LCD(r[i]); } }

(6) 显示一个8×16点阵字符

void Display_char(uchar P1,uchar L1,uchar *M) reentrant {

LCD_Show(P1,L1,8,M);

LCD_Show(P1+1,L1,8,M+8); }

(7) 显示一个16×16点阵字符 (汉字上半部分与下半部分分别处在相邻两页中)

void Display_Word(uchar P2,uchar L2,uchar *M) reentrant { LCD_Show(P2,L2,16,M);

LCD_Show(P2+1,L2,16,M+16); }

2、DS1302时钟程序

用DS1302与12864LCD设计的可调式中文电子日历

DS1302时钟程序上一项目有详细介绍,在此忽略。 3、字符汉字显示程序

在此程序中,我们主要定义了3个数组,分别为: (1)年、月、日、星期、时、分、秒等汉字点阵(16×16) 数组uchar code DATE_TIME_WORDS[]; (2)一、二、三、四、五、六和天等汉字点阵(16×16)uchar code WEEK_WORDS[]; (3)0-9等数字点阵(8×16)uchar code Digits[];

各个汉字数字的具体字模可用专门的取字模软件得到,在文后的完整程序代码中有它们的具体字模数组。 4、主程序

主程序较简单,有初始化子程序Initialization(),其中包括LCD的初始化、显示初始化以及中断初始化工作。有2个中断服务子程序:一个用来刷新显示,一个用来处理4个按键。

☆ 课堂小结

本文主要针对不含字库的LCD12864进行了时钟和日期的显示,具体的介绍了LCD12864显示程序的设计。同时我们在程序设计时也要善于把程序分解,分解成一个一个的小程序,这对于C程序的应用大有好处。当然通过这个项目的学习,我们也学习到了如何应用字模软件得到我们所要显示的汉字和数字的字模。

希望同学们仔细研究文后的完整程序代码。 ☆ 完整程序代码

1、 LCD12864显示驱动程序

//--------------------------LCD_12864.c------------------------- // 名称 :12864LCD显示驱动程序(不带字库)

//----------------------------------------------------------------- #include <reg52.h> #include <intrins.h>

#define uchar unsigned char #define uint unsigned int

#define LCD_DB_PORT P0 // 液晶数据线端口DB0-DB7 #define LCD_START_ROW 0xc0 //起始行命令 #define LCD_PAGE 0xB8 // 页指令 #define LCD_COL 0x40 // 列指令

bit Reverse_Display=0;//是否反相显示(白底黑字/黑底白字) //液晶引脚定义 sbit DI=P2^0; sbit RW=P2^1; sbit E=P2^2; sbit CS1=P2^3; sbit CS2=P2^4; sbit RST=P2^5;

//--------------------------------------------------------------- // 检查LCD是否忙

//-------------------------------------------------------------- bit LCD_IS_BUSY() {

用DS1302与12864LCD设计的可调式中文电子日历

LCD_DB_PORT=0xFF; RW=1; _nop_(); DI=0; E=1; _nop_(); E=0;

return (bit)(P0&0x80); }

//--------------------------------------------------------------- // 向LCD写入一个字节(一般用于发送命令)

//-------------------------------------------------------------- void Write_Byte_To_LCD(uchar comand) {

while(LCD_IS_BUSY()); LCD_DB_PORT=0xFF; RW=0; _nop_(); DI=0;

LCD_DB_PORT=comand; E=1; _nop_(); E=0; }

//--------------------------------------------------------------- // 向LCD写入数据

//-------------------------------------------------------------- void Write_Data_To_LCD(uchar dat) {

while(LCD_IS_BUSY()); LCD_DB_PORT=0xFF; RW=0; _nop_(); DI=1;

if(!Reverse_Display) //根据Reverse_Display决定是否反相显示 LCD_DB_PORT=dat; else

LCD_DB_PORT=~dat; E=1; _nop_(); E=0; }

//--------------------------------------------------------------- // 初始化LCD

用DS1302与12864LCD设计的可调式中文电子日历

//-------------------------------------------------------------- void LCD12864_Initialization() {

CS1=1; CS2=1;

Write_Byte_To_LCD(0x38); Write_Byte_To_LCD(0x0F); Write_Byte_To_LCD(0x01); Write_Byte_To_LCD(0x06);

Write_Byte_To_LCD(LCD_START_ROW); }

//---------------------------------------------------------------

// 通用显示函数 从第P页第L列显示W个字节数据,具体显示的数据在r所指的数组中 //-------------------------------------------------------------- void LCD_Show(uchar P,uchar L,uchar W,uchar *r) reentrant {

uchar i; if(L<64) {

CS1=1; CS2=0;

Write_Byte_To_LCD(LCD_PAGE+P); Write_Byte_To_LCD(LCD_COL+L); if(L+W<64) {

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

Write_Data_To_LCD(r[i]); } else {

for(i=0;i<64-L;i++)

Write_Data_To_LCD(r[i]); CS1=0; CS2=1;

Write_Byte_To_LCD(LCD_PAGE+P); Write_Byte_To_LCD(LCD_COL); for(i=64-L;i<W;i++)

Write_Data_To_LCD(r[i]); } } else {

CS1=0; CS2=1;

用DS1302与12864LCD设计的可调式中文电子日历

Write_Byte_To_LCD(LCD_PAGE+P); Write_Byte_To_LCD(LCD_COL+L-64); for(i=0;i<W;i++)

Write_Data_To_LCD(r[i]); } }

//--------------------------------------------------------------- // 显示一个8×16点阵字符

//-------------------------------------------------------------- void Display_char(uchar P1,uchar L1,uchar *M) reentrant {

LCD_Show(P1,L1,8,M);

LCD_Show(P1+1,L1,8,M+8); }

//-------------------------------------------------------------------- // 显示一个16×16点阵字符 (汉字上半部分与下半部分分别处在相邻两页中) //---------------------------------------------------------------------- void Display_Word(uchar P2,uchar L2,uchar *M) reentrant { LCD_Show(P2,L2,16,M);

LCD_Show(P2+1,L2,16,M+16); }

2、 DS1302时钟程序 #include <reg51.h> #include <string.h> #include <intrins.h>

#define uchar unsigned char #define uint unsigned int

sbit SDA=P1^0; //DS1302数据线 sbit CLK=P1^1; //DS1302时钟线 sbit RST=P1^2; // DS1302 复位线

char Adjust_Index=-1; //当前调节的时间对象:秒,分,时,日,月,年(0,1,2,3,4,6) uchar MonthsDays[]={0,31,0,31,30,31,30,31,31,30,31,30,31}; // 一年中每个月的天数,二月的天数由年份决定

uchar DateTime[7];//所读取的日期时间 //函数声明

void Write_Byte_TO_DS1302(uchar X); // 向DS1302写入一个字节 uchar Read_Byte_FROM_DS1302(); //从DS1302中读取一个字节

uchar Read_Data_FROM_DS1302(uchar addr); //从DS1302指定位置读取数据 , 读数据

void Write_Data_TO_DS1302(uchar addr,uchar dat); // 向DS1302指定位置写入数据, 写数据 void SET_DS1302(); // 设置时间 void GetTime(); // 读取当前时间

uchar Is_Leapyear(uint year);// 判断是否为闰年

//*--------写字节函数,向DS1302写入一个字节--------*//

用DS1302与12864LCD设计的可调式中文电子日历

void Write_Byte_TO_DS1302(uchar X) // 向DS1302写入一个字节 {

uchar i;

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

SDA=X&1; CLK=1; CLK=0; X>>=1; } }

//*--------读字节函数,从DS1302读取一个字节--------*//

uchar Read_Byte_FROM_DS1302() //从DS1302中读取一个字节 {

uchar i,byte,t; for(i=0;i<8;i++) {

byte>>=1; t=SDA;

byte|=t<<7; CLK=1; CLK=0; }

//BCD码转换

return byte/16*10+byte%16; }

//------------------------------------------------------------- //从DS1302指定位置读取数据 , 读数据

//---------------------------------------------------------------

uchar Read_Data_FROM_DS1302(uchar addr) //从DS1302指定位置读取数据 {

uchar dat; RST=0; CLK=0; RST=1;

Write_Byte_TO_DS1302(addr); //向DS1302写入一个地址

dat=Read_Byte_FROM_DS1302(); //在上面写入的地址中读取数据 CLK=1; RST=0;

return dat; }

//------------------------------------------------------------- //向DS1302指定位置写入数据, 写数据

//---------------------------------------------------------------

, 读数据

用DS1302与12864LCD设计的可调式中文电子日历

void Write_Data_TO_DS1302(uchar addr,uchar dat) // 向DS1302指定位置写入数据, 写数据 {

CLK=0; RST=1;

Write_Byte_TO_DS1302(addr); Write_Byte_TO_DS1302(dat); CLK=1; RST=0; }

//----------------------------------------------------------- // 设置时间

//--------------------------------------------------------- void SET_DS1302() // 设置时间 {

uchar i;

Write_Data_TO_DS1302(0x8E,0x00); //写控制字,取消写保护 // 分,时,日,月,年依次写入 for(i=1;i<7;i++) {

// 分的起始地址是10000010(0x82),后面依次是时,日,月,周,年,写入地址每次递增2 Write_Data_TO_DS1302(0x80+2*i,(DateTime[i]/10<<4)|(DateTime[i]%10)); }

Write_Data_TO_DS1302(0x8E,0x80); //写控制字,加写保护 }

//-------------------------------------------------------- // 读取当前时间

//------------------------------------------------------- void GetTime() // 读取当前时间 {

uchar i;

for(i=0;i<7;i++) {

DateTime[i]=Read_Data_FROM_DS1302(0x81+2*i); } }

//------------------------------------------------------------------- // 判断是否为闰年

//------------------------------------------------------------------- uchar Is_Leapyear(uint year) {

return (year%4==0&&year%100!=0)||(year%400==0) ; }

//------------------------------------------------------------------ // 求自2000.1.1开始的任何一天是星期几?

用DS1302与12864LCD设计的可调式中文电子日历

//---------------------------------------------------------------------- void Refresh_Week_Day() {

uint i,d,w=5; //已知1999年12.31是星期五 for(i=2000;i<2000+DateTime[6];i++) {

d=Is_Leapyear(i)?366:365; w=(w+d)%7; } d=0;

for (i=1;i<DateTime[4];i++) {d+=MonthsDays[i];} 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]=Is_Leapyear(2000+DateTime[6])?29:28; //如果年份变化后当前月份的天数大于上限则设为上限 if(DateTime[3]>MonthsDays[DateTime[4]]) {

DateTime[3]=MonthsDays[DateTime[4]]; }

Refresh_Week_Day(); //刷新星期 break;

case 4: //月调整 01-12

if(X==1&&DateTime[4]<12) {

用DS1302与12864LCD设计的可调式中文电子日历

DateTime[4]++; }

if(X==-1&&DateTime[4]>1) {

DateTime[4]--; }

//获取2月天数

MonthsDays[2]=Is_Leapyear(2000+DateTime[6])?29:28; //如果年份变化后当前月份的天数大于上限则设为上限 if(DateTime[3]>MonthsDays[DateTime[4]]) {

DateTime[3]=MonthsDays[DateTime[4]]; }

Refresh_Week_Day(); //刷新星期 break;

case 3: // 日调整00-28或00-29或00-30或00-31

//调节之前首先根据当前年份得出该年中2月的天数 MonthsDays[2]=Is_Leapyear(2000+DateTime[6])?29:28; //根据当前月份决定调节日期的上限

if(X==1&&DateTime[3]<MonthsDays[DateTime[4]]) {

DateTime[3]++; }

if(X==-1&&DateTime[3]>0) {

DateTime[3]--; }

Refresh_Week_Day(); //刷新星期 break;

case 2: // 时调整

if(X==1&&DateTime[2]<23) {

DateTime[2]++; }

if(X==-1&&DateTime[4]>0) {

DateTime[2]--; } break;

case 1: // 分调整

if(X==1&&DateTime[1]<59) {

DateTime[1]++; }

用DS1302与12864LCD设计的可调式中文电子日历

if(X==-1&&DateTime[4]>0) {

DateTime[1]--; } break;

case 0: // 秒调整

if(X==1&&DateTime[1]<59) {

DateTime[0]++; }

if(X==-1&&DateTime[4]>0) {

DateTime[0]--; } break; } }

3、 字符汉字显示程序

//------------------------------------------------- // 与本程序有关的数字和汉字的点阵编码 DotMatrix.c // ----------------------------------------------- #include <reg51.h> #include <string.h> #include <intrins.h>

#define uchar unsigned char #define uint unsigned int

//年、月、日、星期、时、分、秒等汉字点阵(16×16) uchar code DATE_TIME_WORDS[]={

0x40,0x20,0x10,0x0C,0xE3,0x22,0x22,0x22,0xFE,0x22,0x22,0x22,0x22,0x02,0x00,0x00, //年 0x04,0x04,0x04,0x04,0x07,0x04,0x04,0x04,0xFF,0x04,0x04,0x04,0x04,0x04,0x04,0x00, 0x00,0x00,0x00,0x00,0x00,0xFF,0x11,0x11,0x11,0x11,0x11,0xFF,0x00,0x00,0x00,0x00,//月 0x00,0x40,0x20,0x10,0x0C,0x03,0x01,0x01,0x01,0x21,0x41,0x3F,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0xFE,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0xFE,0x00,0x00,0x00,0x00,//日 0x00,0x00,0x00,0x3F,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x3F,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0xBE,0x2A,0x2A,0x2A,0xEA,0x2A,0x2A,0x2A,0x2A,0x3E,0x00,0x00,0x00,//星 0x00,0x48,0x46,0x41,0x49,0x49,0x49,0x7F,0x49,0x49,0x49,0x49,0x49,0x41,0x40,0x00, 0x00,0x04,0xFF,0x54,0x54,0x54,0xFF,0x04,0x00,0xFE,0x22,0x22,0x22,0xFE,0x00,0x00,//期 0x42,0x22,0x1B,0x02,0x02,0x0A,0x33,0x62,0x18,0x07,0x02,0x22,0x42,0x3F,0x00,0x00, 0x00,0xFC,0x44,0x44,0x44,0xFC,0x10,0x90,0x10,0x10,0x10,0xFF,0x10,0x10,0x10,0x00,//时 0x00,0x07,0x04,0x04,0x04,0x07,0x00,0x00,0x03,0x40,0x80,0x7F,0x00,0x00,0x00,0x00, 0x80,0x40,0x20,0x98,0x87,0x82,0x80,0x80,0x83,0x84,0x98,0x30,0x60,0xC0,0x40,0x00,//分 0x00,0x80,0x40,0x20,0x10,0x0F,0x00,0x00,0x20,0x40,0x3F,0x00,0x00,0x00,0x00,0x00, 0x12,0x12,0xD2,0xFE,0x91,0x11,0xC0,0x38,0x10,0x00,0xFF,0x00,0x08,0x10,0x60,0x00,//秒 0x04,0x03,0x00,0xFF,0x00,0x83,0x80,0x40,0x40,0x20,0x23,0x10,0x08,0x04,0x03,0x00

用DS1302与12864LCD设计的可调式中文电子日历

};

//一、二、三、四、五、六和天等汉字点阵(16×16) uchar code WEEK_WORDS[]={

0x00,0x40,0x42,0x42,0x42,0x42,0x42,0xFE,0x42,0x42,0x42,0x42,0x42,0x42,0x40,0x00,//天 0x00,0x80,0x40,0x20,0x10,0x08,0x06,0x01,0x02,0x04,0x08,0x10,0x30,0x60,0x20,0x00, 0x00,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,//一 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x06,0x04,0x00,0x00,0x00,//二 0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x18,0x10,0x00, 0x00,0x04,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x04,0x00,0x00,//三 0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00, 0x00,0xFE,0x02,0x02,0x02,0xFE,0x02,0x02,0xFE,0x02,0x02,0x02,0x02,0xFE,0x00,0x00,//四 0x00,0x7F,0x28,0x24,0x23,0x20,0x20,0x20,0x21,0x22,0x22,0x22,0x22,0x7F,0x00,0x00, 0x00,0x02,0x82,0x82,0x82,0x82,0xFE,0x82,0x82,0x82,0xC2,0x82,0x02,0x00,0x00,0x00,//五 0x20,0x20,0x20,0x20,0x20,0x3F,0x20,0x20,0x20,0x20,0x3F,0x20,0x20,0x30,0x20,0x00, 0x10,0x10,0x10,0x10,0x10,0x91,0x12,0x1E,0x94,0x10,0x10,0x10,0x10,0x10,0x10,0x00,//六 0x00,0x40,0x20,0x10,0x0C,0x03,0x01,0x00,0x00,0x01,0x02,0x0C,0x78,0x30,0x00,0x00, }; //0-9等数字点阵(8×16) uchar code Digits[]={

0x00,0x00,0xF0,0xF8,0x08,0x68,0xF8,0xF0,0x00,0x00,0x07,0x0F,0x0B,0x08,0x0F,0x07, //0 0x00,0x20,0x20,0x30,0xF8,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x0F,0x00,0x00, //1 0x00,0x30,0x38,0x08,0x88,0xF8,0x70,0x00,0x00,0x0C,0x0E,0x0B,0x09,0x08,0x08,0x00, // 2 0x00,0x30,0x38,0x88,0x88,0xF8,0x70,0x00,0x00,0x06,0x0E,0x08,0x08,0x0F,0x07,0x00, //3 0x00,0x00,0xF8,0xF8,0x00,0xE0,0xE0,0x00,0x00,0x03,0x03,0x02,0x02,0x0F,0x0F,0x02,//4 0x00,0xF8,0xF8,0x88,0x88,0x88,0x08,0x00,0x00,0x08,0x08,0x08,0x0C,0x07,0x03,0x00,//5 0x00,0xC0,0xE0,0x78,0x58,0xC8,0x80,0x00,0x00,0x07,0x0F,0x08,0x08,0x0F,0x07,0x00,//6 0x00,0x08,0x08,0x88,0xE8,0x78,0x18,0x00,0x00,0x00,0x0E,0x0F,0x01,0x00,0x00,0x00,//7 0x00,0x70,0xF8,0xC8,0x88,0xF8,0x70,0x00,0x00,0x07,0x0F,0x08,0x09,0x0F,0x07,0x00,//8 0x00,0xF0,0xF8,0x08,0x08,0xF8,0xF0,0x00,0x00,0x00,0x09,0x0D,0x0F,0x03,0x01,0x00,//9 }; 4、 主程序

#include <reg51.h> #include <string.h> #include <intrins.h>

#define uchar unsigned char #define uint unsigned int

extern void LCD12864_Initialization();

extern void Display_char(uchar P1,uchar L1,uchar *M) reentrant; extern void Display_Word(uchar P2,uchar L2,uchar *M) reentrant; extern void Datetime_Adjust(char X);

extern void SET_DS1302(); // 设置时间 extern GetTime();

用DS1302与12864LCD设计的可调式中文电子日历

//函数声明

void Initialization();//初始化函数

extern bit Reverse_Display;//是否反相显示(白底黑字/黑底白字) extern uchar code Digits[]; extern uchar code WEEK_WORDS[]; extern uchar code Digits[];

extern uchar code DATE_TIME_WORDS[];

extern char Adjust_Index; //当前调节的时间对象:秒,分,时,日,月,年(0,1,2,3,4,6) extern uchar MonthsDays[]; // 一年中每个月的天数,二月的天数由年份决定 extern uchar DateTime[7];//所读取的日期时间 sbit k1=P3^4; // 选择按键 sbit k2=P3^5; // 加 sbit k3=P3^6; // 减 sbit k4=P3^7; // 确定 uchar tcount=0; //水平与垂直偏移 uchar H_Offset=10; // uchar V_page_Offset=0;

//---------------------------------------------------- // 主程序

//---------------------------------------------------- void main() {

Initialization(); while(1) {

if(Adjust_Index==-1) GetTime(); } }

void Initialization()//初始化函数 {

IE=0x83; IP=0x01; IT0=0X01;

TH0=-50000/256; // 写入初值 TL0=-50000%256; // 写入初值 TR0=1;

LCD12864_Initialization();//液晶初始化函数 //显示年的前面固定的两位

Display_char(V_page_Offset,0+H_Offset,Digits+2*16); Display_char(V_page_Offset,8+H_Offset,Digits); //----------------------------------------------- //在12864屏幕上固定显示汉字:年月日,星期,时分秒 //---------------------------------------------------

用DS1302与12864LCD设计的可调式中文电子日历

Display_Word(V_page_Offset,32+H_Offset,DATE_TIME_WORDS+0*32); Display_Word(V_page_Offset,64+H_Offset,DATE_TIME_WORDS+1*32); Display_Word(V_page_Offset,96+H_Offset,DATE_TIME_WORDS+2*32); Display_Word(V_page_Offset+3,56+H_Offset,DATE_TIME_WORDS+3*32); Display_Word(V_page_Offset+3,72+H_Offset,DATE_TIME_WORDS+4*32); Display_Word(V_page_Offset+6,32+H_Offset,DATE_TIME_WORDS+5*32); Display_Word(V_page_Offset+6,64+H_Offset,DATE_TIME_WORDS+6*32); Display_Word(V_page_Offset+6,96+H_Offset,DATE_TIME_WORDS+7*32); }

//-------------------------------------------------------------- // 定时器0刷新LCD显示函数

//------------------------------------------------------------- void T0_INT()interrupt 1 {

TH0=-50000/256; // 写入初值 TL0=-50000%256; // 写入初值 if(++tcount!=2) return; tcount=0; //年(后两位)

Reverse_Display=Adjust_Index==6;

Display_char(V_page_Offset,16+H_Offset,Digits+DateTime[6]/10*16); Display_char(V_page_Offset,24+H_Offset,Digits+DateTime[6]%10*16); //星期

Reverse_Display=Adjust_Index==5;

Display_Word(V_page_Offset+3,96+H_Offset,WEEK_WORDS+(DateTime[5]%10-1)*32); //月

Reverse_Display=Adjust_Index==4;

Display_char(V_page_Offset,48+H_Offset,Digits+DateTime[4]/10*16); Display_char(V_page_Offset,56+H_Offset,Digits+DateTime[4]%10*16); // 日

Reverse_Display=Adjust_Index==3;

Display_char(V_page_Offset,80+H_Offset,Digits+DateTime[3]/10*16); Display_char(V_page_Offset,88+H_Offset,Digits+DateTime[3]%10*16); //时

Reverse_Display=Adjust_Index==2;

Display_char(V_page_Offset+6,16+H_Offset,Digits+DateTime[2]/10*16); Display_char(V_page_Offset+6,24+H_Offset,Digits+DateTime[2]%10*16); //分

Reverse_Display=Adjust_Index==1;

Display_char(V_page_Offset+6,48+H_Offset,Digits+DateTime[1]/10*16); Display_char(V_page_Offset+6,56+H_Offset,Digits+DateTime[1]%10*16); // 秒

Reverse_Display=Adjust_Index==0;

Display_char(V_page_Offset+6,80+H_Offset,Digits+DateTime[0]/10*16);

用DS1302与12864LCD设计的可调式中文电子日历

Display_char(V_page_Offset+6,88+H_Offset,Digits+DateTime[0]%10*16); }

//---------------------------------------------------------- // 键盘中断处理函数

//--------------------------------------------------------- void EX_INT0()interrupt 0 {

if(k1==0) {

if(Adjust_Index==-1||Adjust_Index==-1) {Adjust_Index=7;} Adjust_Index--; if(Adjust_Index==5)

{Adjust_Index=4;} //跳过对星期的调节 }

else if(k2==0) // 加 {

Datetime_Adjust(1); }

else if(k3==0) // 减 {

Datetime_Adjust(-1); }

else if(k4==0) {

SET_DS1302();

Adjust_Index=-1; //操作索引重设为-1,时间继续正常显示 } }

本文来源:https://www.bwwdw.com/article/66ei.html

Top