基于LCD1602和DS1302的时间显示程序
DS1302+LCD1602显示程序
/*头文件*/
#include <reg52.h>
#include <intrins.h>
#define uint unsigned int
#define uchar unsigned char
#define nop() _nop_()
sbit lcd_rs_port = P2^0; /*定义LCD控制端口*/
/****************************************************************
程序名称: LCD1602显示时间
函 数 名:W1302()
功 能:往DS1302写入数据
说 明:先写地址,后写命令/数据 (内部函数)
调 用:RTInputByte() , RTOutputByte()
入口参数:ucAddr: DS1302地址, ucData: 要写的数据
返 回 值:无
RTInputByte(ucAddr); /* 地址,命令 */
ucData = RTOutputByte(); /* 读1Byte数据 */
T_CLK = 1;
T_RST = 0;
return(ucData);
uchar data time_data_buff[7]={0x00,0x00,0x09,0x01,0x01,0x04,0x09};/*格式为: 秒 分 时 日 月 星期 年 */
uchar data lcd1602_line1[]={" 2000/00/00 000"};
uchar data lcd1602_line2[]={" 00:00:00 "};
用DS1302+LCD1602制作的时钟
{
uchar i,*p;
p = RTC_RADD; //地址传递
for(i = 0 ; i < 7 ; i++) //分7次读取 秒分时日月周年
{
SJ[i] = Read_Ds1302(*p);
p++;
}
}
/*************************************************/
}
/*****************************************************/
/****LCD定位******************************************/
void LOCATE(uchar H , uchar L)
{
if(H == 1) //如果是第一行
{
LCD_RS = rs; //写指令/数据选择:低电平写指令,高电平写数据
LCD_RW = 0; //读写选择:低电平写,高电平读
LCD_E = 0; //关使能
LCD_DAT = c_d; //把指令/数据写入P1口
delay(5); //延时5ms
{
if(SDA)
temp |= 0x80; //每次传输低字节
SCK = 0;
temp>>=1; //右移一位
_nop_();
_nop_();
_nop_();
SCK = 1;
}
RST = 0;
_nop_(); //以下为DS1302复位的稳定时间
基于DS1302和LCD1602的可调数字钟
学习情境2-可调式数字钟之基于DS1302和LCD1602的可调数字钟☆点名,复习1、DS1302的引脚及其功能,以及DS1302与单片机的硬件连接?2、如何对DS1302读写数据,如何得到DS1302的时钟?☆新课讲授2.3 基于DS1302与LCD1602设计的可调数字钟上堂课程我们学会了使用DS1302,知道了如何在单片机系统中的连接,也详细的学习了如何得到DS1302的时钟,并且我们使用了16个数码管把年月日和时分秒实时地显示出来。
但数码管的显示毕竟有其自身的缺陷,现在在工业控制的各个环节,都使用液晶进行人机联系。
在日常生活中,我们对液晶显示器并不陌生。
液晶显示模块已作为很多电子产品的通用器件,如在计算器、万用表、电子表及很多家用电子产品中都可以看到,显示的主要是数字、专用符号和图形。
在单片机的人机交流界面中,一般的输出方式有以下几种:发光管、LED 数码管、液晶显示器。
发光管和LED数码管比较常用,软硬件都比较简单,在单片机系统中应用液晶显示器作为输出器件有以下几个优点:(1)显示质量高,由于液晶显示器每一个点在收到信号后就一直保持那种色彩和亮度,恒定发光,而不像阴极射线管显示器(CRT)那样需要不断刷新新亮点。
因此,液晶显示器画质高且不会闪烁。
(2)数字式接口,液晶显示器都是数字式的,和单片机系统的接口更加简单可靠,操作更加方便。
(3)体积小、重量轻,液晶显示器通过显示屏上的电极控制液晶分子状态来达到显示的目的,在重量上比相同显示面积的传统显示器要轻得多。
(4)功耗低,相对而言,液晶显示器的功耗主要消耗在其内部的电极和驱动IC上,因而耗电量比其它显示器要少得多。
2.3.1 LCD1602技术资料2.3.1.1 液晶显示简介1、液晶显示原理:液晶显示的原理是利用液晶的物理特性,通过电压对其显示区域进行控制,有电就有显示,这样即可以显示出图形。
液晶显示器具有厚度薄、适用于大规模集成电路直接驱动、易于实现全彩色显示的特点,目前已经被广泛应用在便携式电脑、数字摄像机、PDA移动通信工具等众多领域。
DS1302时钟芯片与液晶1602的程序
DS1302测试程序晶振:11.0592MHZ/*********************************包含头文件********************************/#include "reg51.h"#include <intrins.h>/*********************************端口定义**********************************/ sbit DS1302_CLK = P1^0;sbit DS1302_IO = P1^1;sbit DS1302_RST = P1^2;/******************************定义全局变量*********************************/ unsigned char second,minute,hour,week,day,month,year; //秒、分、时、星期、日、月、年unsigned char time[]={0x06,0x03,0x14,0x03,0x12,0x30,0x00}; //初始时间数组/**************************************************************************** 函数功能:数码管扫描延时子程序入口参数:出口参数:****************************************************************************/ void delay1(void){int k;for(k=0;k<400;k++);}/***************************************************************************** 函数功能:向DS1302送一字节数据子程序入口参数:出口参数:*****************************************************************************/ void InputByte(unsigned char byte1){char i;for(i=8;i>0;i--){DS1302_IO=(bit)(byte1&0x01);DS1302_CLK=1;_nop_();DS1302_CLK=0;byte1>>=1;}return;}/***************************************************************************** 函数功能:读DS1302一个字节子程序入口参数:出口参数:*****************************************************************************/ unsigned char outputbyte(void){unsigned char i;unsigned ucdat=0;for(i=8;i>0;i--){DS1302_IO=1;ucdat>>=1;if(DS1302_IO)ucdat|=0x80;DS1302_CLK=1;_nop_();DS1302_CLK=0;}return(ucdat);}/***************************************************************************** 函数功能:向DS1302某地址写一字节数据子程序入口参数:addr,TDat出口参数:*****************************************************************************/ void write_ds1302(unsigned char addr,unsigned char TDat){DS1302_RST=0;_nop_();DS1302_CLK=0;_nop_();DS1302_RST=1;InputByte(addr);_nop_();InputByte(TDat);DS1302_CLK=1;_nop_();DS1302_RST=0;}/***************************************************************************** 函数功能:读DS1302地址子程序入口参数:add出口参数:timedata*****************************************************************************/ unsigned char read_ds1302(unsigned char addr){unsigned char timedata;DS1302_RST=0;_nop_();DS1302_CLK=0;_nop_();DS1302_RST=1;InputByte(addr);timedata=OutputByte();DS1302_CLK=1;_nop_();DS1302_RST=0;return(timedata);}/***************************************************************************** 函数功能:初始化DS1302子程序入口参数:time[](全局变量)出口参数:*****************************************************************************/ void initial_ds1302(){write_ds1302(0x8e,0x00); //写保护寄存器,在对时钟或RAM写前WP一定要为0write_ds1302(0x8c,time[0]); //年write_ds1302(0x88,time[1]); //月write_ds1302(0x86,time[2]); //日write_ds1302(0x8A,time[3]); //星期write_ds1302(0x84,time[4]); //时write_ds1302(0x82,time[5]); //分write_ds1302(0x80,time[6]); //秒write_ds1302(0x8e,0x80); //写保护寄存器}/***************************************************************************** 函数功能:读DS1302时间子程序入口参数:出口参数:全局变量(second,minute,hour,week,day,month,year)*****************************************************************************/ void read_time(){second=read_ds1302(0x81); //秒寄存器minute=read_ds1302(0x83); //分hour=read_ds1302(0x85); //时week=read_ds1302(0x8B); //星期day=read_ds1302(0x87); //日month=read_ds1302(0x89); //月year=read_ds1302(0x8d); //年}void write_com(uchar com){P0=com;rs=0;lcden=0;delay(10);lcden=1;delay(10);lcden=0;}//液晶读写程序//void write_date(uchar date){P0=date;rs=1;lcden=0;delay(10);lcden=1;delay(10);lcden=0;}void init(){dula=0;wela=0;write_com(0x38);delay(20);write_com(0x0f);delay(20);write_com(0x06);delay(20);write_com(0x01);delay(20);}//液晶显示时间程序//void time_display(){void write_com(0x80);void write_date(year);void write_com(0x80+5);void write_date(month);void write_com(0x80+8);void write_date(day);void write_com(0x80+11);void write_date(week);}/***************************************************************************** 函数功能:主程序入口参数:出口参数:*****************************************************************************/ void main(void){initial_ds1302(); //初始化DS1302while(1){read_time(); //读取时间time_display(); //显示时间}}。
基于ds1302和LCD1602的日历时钟51单片机程序
#include <reg52.h>#include <intrins.h>#include <string.h>#define uint unsigned int#define uchar unsigned charsbit led = P2^3;//led代替闹铃sbit IO = P1^3; //定义1302管脚//6sbit SCLK = P1^4;//7sbit RST = P1^5; //5sbit RS = P2^2;//定义1602管脚sbit RW = P2^1;sbit EN = P2^0;sbit key1=P3^4;//选择//调时键盘sbit key2=P3^5;//加sbit key3=P3^6;//减sbit key4=P3^7;//确定sbit key11=P1^6;//选择//闹钟键盘sbit key22=P1^7;//加sbit key33=P3^0;//减sbit key44=P3^1;//确定uchar x1=0,x;int hour=8,minute=0;//闹钟的初始时间8:00uchar DateTime[9]; //秒,分,时,日,周,月,年 address,uchar lcd1[]={"DATE 00-00-00 "};uchar lcd2[]={"TIME 00:00:00 "};/***************延时*************/void delayms(uchar x)//延时毫秒程序{ uchar i,j;for(i=x;i>0;i--)for(j=110;j>0;j--);}void delayus(uchar x)//延时微秒程序{ uchar i;for(i=0;i<x;i++);}/********1302的驱动程序***********///写入数据,dat:要写入的数据void DS1302WriteByte(uchar dat){uchar i;SCLK=0;//初始时钟线置为0delayus(2);for(i=0;i<8;i++)//开始传输8个字节的数据{IO=dat&0x01;//取最低位,注意DS1302的数据和地址都是从最低位开始传输的delayus(2);SCLK=1;//时钟线拉高,制造上升沿,SDA的数据被传输delayus(2);SCLK=0;//时钟线拉低,为下一个上升沿做准备dat>>=1;//数据右移一位,准备传输下一位数据}}/********1302的驱动程序**********///功能: 读取数据,dat:读取的数据uchar DS1302ReadByte(){ uchar i;uchar dat;delayus(2);for(i=0;i<8;i++){dat>>=1;//要返回的数据左移一位if(IO==1)//当数据线为高时,证明该位数据为1dat|=0x80;//要传输数据的当前值置为1,若不是,则为0SCLK=1;//拉高时钟线delayus(2);SCLK=0;//制造下降沿delayus(2);}return dat;//返回读取出的数据/16*10+dat%16}/*********1302的驱动程序*********///从cmd相应地址中读取一个字节的数据uchar DS1302Read(uchar cmd)//cmd:要写入的控制字节,dat:读取的数据{uchar dat;RST=0;//初始CE线置为0SCLK=0;//初始时钟线置为0RST=1;//初始CE置为1,传输开始DS1302WriteByte(cmd);//传输命令字,要读取的时间/日历地址dat=DS1302ReadByte();//读取要得到的时间/日期SCLK=1;//时钟线拉高RST=0;//读取结束,CE置为0,结束数据的传输return dat;//返回得到的时间/日期}/**********1302的驱动程序*********///向cmd相应地址中写一个字节的数据void DS1302Write(uchar cmd, uint dat)//cmd:要写入的控制字,dat:要写入的数据{RST=0; //初始CE线置为0SCLK=0; //初始时钟线置为0RST=1; //初始CE置为1,传输开始DS1302WriteByte(cmd); //传输命令字,要写入的时间/日历地址DS1302WriteByte(dat); //写入要修改的时间/日期SCLK=1; //时钟线拉高RST=0; //读取结束,CE置为0,结束数据的传输}/*************初始化ds1302********///给1302写入日期和时钟的值void chushihuaDS1302(void){DS1302Write(0x8e,0x00);//写保护关DS1302Write(0x80,0x10); //初始秒DS1302Write(0x82,0x02);//初始分钟DS1302Write(0x84,0x15); //初始为24小时模式,初始时DS1302Write(0x86,0x01); //1日DS1302Write(0x88,0x08);//8月DS1302Write(0x8c,0x13);//2013年DS1302Write(0x8a,0x04);//星期4// DS1302Write(0x90,0x01); //充电//DS1302Write(0xc0,0xf0); //初始化一次标示//DS1302Write(0x8e,0x80);//写保护开}/************以下是1602的程序******************//******************************///向1602内写命令void write_order(uchar order){RS=0;P0=order;delayms(5);EN=1;delayms(5);EN=0;}/******************************///向1602内写数据void write_date(uchar date){RS=1;P0=date;delayms(5);EN=1;delayms(5);EN=0;}/******************************///lcd1602的初始化void chushihuaLCD1602(){ EN=0;write_order(0x38);write_order(0x0c);write_order(0x06);write_order(0x01);}/*************其他操作*****************/void gettime(){ uchar i,n;for(i=0,n=1;i<7,n<15;i++,n=n+2){ DateTime[i]=DS1302Read(0x80+n);delayus(1);}}void zhuanhuan(){ gettime();lcd1[5]=((DateTime[6]>>4)+0x30);lcd1[6]=((DateTime[6]&0x0f)+0x30);delayus(2);//年lcd1[14]=((DateTime[5]>>4)+0x30);lcd1[15]=((DateTime[5]&0x0f)+0x30);delayus(2);//周lcd1[11]=((DateTime[3]>>4)+0x30);lcd1[12]=((DateTime[3]&0x0f)+0x30);delayus(2);//日lcd1[8]=((DateTime[4]>>4)+0x30);lcd1[9]=((DateTime[4]&0x0f)+0x30);delayus(2);//月lcd2[5]=((DateTime[2]>>4)+0x30);lcd2[6]=((DateTime[2]&0x0f)+0x30);delayus(2);//时lcd2[8]=((DateTime[1]>>4)+0x30);lcd2[9]=((DateTime[1]&0x0f)+0x30);delayus(2);//分lcd2[11]=((DateTime[0]>>4)+0x30);lcd2[12]=((DateTime[0]&0x0f)+0x30);delayus(2);//秒if(DateTime[7]==DateTime[2] & DateTime[8]==DateTime[1]){led = 1;delayms(150);led = 0;}/**/}/***********************/void jianpan() //键盘调时{ uchar x2,address,max,min;int item;if(key1==0){ delayms(10);if(key1==0){ x1++;if(x1>=7) x1=1;switch(x1){ case 1: lcd2[15]='Y';x2=1;address=0x8c; max=99;min=0;break;//年case 2: lcd2[15]='M';x2=2;address=0x88; max=12;min=1;break;//月case 3: lcd2[15]='D';x2=3;address=0x86; max=31;min=1;break;//天case 4: lcd2[15]='H';x2=4;address=0x84; max=23;min=0;break;//时case 5: lcd2[15]='F';x2=5;address=0x82; max=59;min=0;break;//分case 6: lcd2[15]='W';x2=6;address=0x8A; max=7;min=1;break;//周}}while(!key1);}item=(DS1302Read(address+1)/16)*10 + (DS1302Read(address+1))%16;if(key2==0){ delayms(10);if(key2==0){ if(x2==1) {item++;}else if(x2==2) {item++;}else if(x2==3) {item++;}else if(x2==4) {item++;}else if(x2==5) {item++;}else if(x2==6) {item++;}}while(!key2);}if(key3==0){ delayms(10);if(key3==0){ if(x2==1) {item--;}else if(x2==2) {item--;}else if(x2==3) {item--;}else if(x2==4) {item--;}else if(x2==5) {item--;}else if(x2==6) {item--;}}while(!key3);}if(key4==0){ delayms(10);if(key4==0){ lcd2[15]=' ';x1=0;x2=0;}while(!key4);}//led=0;delayms(5000);led=1;if(item>max) item=min;if(item<min) item=max;DS1302Write(0x8e,0x00);//允许写操作delayms(10);DS1302Write(address,(item/10)*16+item%10); //写入DS1302 //转成BCD码delayms(20);DS1302Write(0x8e,0x80);//写保护,禁止写操作}void naozhong()//设定闹钟{ uchar da,xiao,i;if(key11==0){ delayms(10);if(key11==0){ x++;if(x>=4) x=1;switch(x){case 2: lcd2[13]='H';i=1;da=23;xiao=0;lcd2[14]=((hour>>4)+0x30);lcd2[15]=((hour&0x0f)+0x30);delayus(2);break;//时case 1: lcd2[13]='M';i=2;da=59;xiao=0;lcd2[14]=((minute>>4)+0x30);lcd2[15]=((minute&0x0f)+0x30);delayus(2);break;//分case 3: lcd2[13]=' ';lcd2[14]=' ';lcd2[15]=' ';x=0;i=0;break;}}while(!key11);}if(key22==0){ delayms(10);if(key22==0){ if(i==1){ hour=((hour/16)*10)+(hour%16);hour++;if(hour>da) hour=xiao;hour=(hour/10)*16+hour%10;lcd2[14]=((hour>>4)+0x30);lcd2[15]=((hour&0x0f)+0x30);delayus(2);}else if(i==2){ minute=((minute/16)*10)+(minute%16);minute++;if(minute>da) minute=xiao;minute=(minute/10)*16+minute%10;lcd2[14]=((minute>>4)+0x30);lcd2[15]=((minute&0x0f)+0x30);delayus(2);}}while(!key22);}if(key33==0){ delayms(10);if(key33==0){ if(i==1){ hour=((hour/16)*10)+(hour%16);hour--;if(hour<xiao) hour=da;hour=(hour/10)*16+hour%10;lcd2[14]=((hour>>4)+0x30);lcd2[15]=((hour&0x0f)+0x30);delayus(2);}else if(i==2){ minute=((minute/16)*10)+(minute%16);minute--;if(minute<xiao) minute=da;minute=(minute/10)*16+minute%10;lcd2[14]=((minute>>4)+0x30);lcd2[15]=((minute&0x0f)+0x30);delayus(2);}}while(!key33);}DateTime[7]=hour;DateTime[8]=minute;}/**/void wzd0() interrupt 0//外部中断0{jianpan();//}void wzd1() interrupt 2//外部中断1{naozhong();}void main(){uchar k;EA=1;EX0=1;IT0=1;PX0=1;EX1=1;IT1=1;PX1=0;RW=0;led=0;chushihuaLCD1602();if( (DS1302Read(0x81) & 0x80) ) chushihuaDS1302();//chushihuaDS1302();while(1){zhuanhuan();write_order(0x80);//lcd的第一行for(k=0;k<16;k++){ write_date(lcd1[k]);delayus(2);}write_order(0x80+0x40);//lcd的第二行for(k=0;k<16;k++){ write_date(lcd2[k]);delayus(2);}}}。
(完整word版)万年历(DS1302+LCD1602【程序、仿真、完整】)
基于52单片机的万年历显示(采用实时芯片DS1302芯片+LCD1602液晶显示)仿真图:/************************************************************-- THE LCD1602 DISPLAY LIB -—COPYRIGHT (C) 2014 BY LLH-— ALL RIGHTS RESERVED —-ATTENTION:延时不能过长,否则无法与DS1302同步(最好小于1ms)*************************************************************/#ifndef __LCD1602_DIS_H__#define __LCD1602_DIS_H__#define uint unsigned int#define uchar unsigned charsbit lcd_rs=P2^0;sbit lcd_rw=P2^1;sbit lcd_en=P2^2;/**********延时子程序************/void delay(uint z){uint x,y;for(x=z;x〉0;x—-)for(y=65;y〉0;y--);//60刚好和DS1302同步}/***********写命令子程序**********/void write_com(uchar com){lcd_rs=0;lcd_rw=0;P0=com;delay(1);lcd_en=1;delay(1);lcd_en=0;}/***********写数据子程序**********/void write_data(uchar date){lcd_rs=1;lcd_rw=0;P0=date;delay(1);lcd_en=1;delay(1);lcd_en=0;}/**********初始化子程序************/void init_LCD1602(){lcd_en=0;write_com(0x38); //显示模式设置:16*2显示,5*7点阵,8位数据接口write_com(0x0c); //开显示,不显示光标write_com(0x06); //指针、光标自动加一,整屏不移动write_com(0x80); //初始位置设置}/*********显示子程序***********/void display(uchar *str){while(*str!='\0’){write_data(*str);str++;}}#endifDS1302的H文件:/******************************************************************—— THE DS1302 REAL_TIME LIB —-COPYRIGHT (C) 2014 BY LLH-- ALL RIGHTS RESERVED ——ATTENTION:不能使用(i=0;i<8;i++),否则,液晶无法显示确切的时间(???);星期的显示多了一天(???)********************************************************************/#ifndef __DS1302_REAL_TIME_H__#define __DS1302_REAL_TIME_H__#define uint unsigned int#define uchar unsigned charsbit DS1302_RST=P1^5;sbit DS1302_SCLK=P1^6;sbit DS1302_IO=P1^7;sbit ACC0=ACC^0;sbit ACC7=ACC^7;typedef struct{uchar second;uchar minute;uchar hour;uchar week;uchar day;uchar month;uchar year;uchar date_str[11];uchar time_str[9];}date_time;/**************写数据定义*****************/#define DS1302_SECOND 0x80#define DS1302_MINUTE 0x82#define DS1302_HOUR 0x84#define DS1302_WEEK 0x8A#define DS1302_DAY 0x86#define DS1302_MONTH 0x88#define DS1302_YEAR 0x8C#define ST 0x00/*************单字节写数据子程序**************/void single_byte_write(uchar date){uchar i;ACC=date;for(i=8;i〉0;i--) //不能使用(i=0;i〈8;i++),否则,液晶只显示00000{DS1302_IO=ACC0;DS1302_SCLK=1;DS1302_SCLK=0;ACC=ACC>>1;}}/*************单字节读数据子程序**************/uchar single_byte_read( ){uchar i;for(i=8;i>0;i--){ACC=ACC>〉1;ACC7=DS1302_IO;DS1302_SCLK=1;DS1302_SCLK=0;}return ACC;}/**************控制字的写入****************/void write_command(uchar addr,uchar dat){DS1302_SCLK=0;DS1302_RST=0;DS1302_RST=1;single_byte_write(addr);single_byte_write(dat);DS1302_SCLK=1;DS1302_RST=0;}/**************读取芯片内部的数据****************/uchar read_data(uchar address){uchar r_data;DS1302_SCLK=0;DS1302_RST=0;DS1302_RST=1;single_byte_write(address|0x01);//若没加(或0x01)ds1302和lcd1602都无法正常显示(?)r_data=single_byte_read();DS1302_SCLK=1;DS1302_RST=0;return r_data;}/************初始化子程序************/void init_DS1302(){uchar temp;temp=read_data(DS1302_SECOND);if(temp&0x80){write_command(0x8e,0x00); //启动读写write_command(0x84,0x00);//设置24小时模式write_command(DS1302_SECOND,ST); //写入当前时间数据}}/*************读取时间、并实现BCD和十进制间的转化***************//****************************************************************十进制转8421编码:32/10 = 3*16= 48(十进制)= 30(16进制)32%10 = 230+2 = 32 * 16 + 32 % 10 = 32(8421编码)(即:a/10*10+a%10)8421编码转十进制:51 / 16 = 5 * 10(16进制) = 50(十进制)51 % 16 = 150 + 1 = 51 / 16 + 51 % 16 = 51(十进制)(即:a/16*10+a%16)*****************************************************************/void get_time(date_time *Time){uchar value;value=read_data(DS1302_SECOND);Time—〉second=(value/16)*10+(value%16);value=read_data(DS1302_MINUTE);Time—〉minute=(value/16)*10+(value%16);value=read_data(DS1302_HOUR);(完整word版)万年历(DS1302+LCD1602【程序、仿真、完整】) Time-〉hour=(value/16)*10+(value%16);value=read_data(DS1302_WEEK);Time—〉week=(value/16)*10+(value%16-1);//星期的显示数值比正确值多一value=read_data(DS1302_DAY);Time-〉day=(value/16)*10+(value%16);value=read_data(DS1302_MONTH);Time—>month=(value/16)*10+(value%16);value=read_data(DS1302_YEAR);Time-〉year=(value/16)*10+(value%16);}/**************年-月-日-星期“字符”显示***************/void date_to_str(date_time *Time){Time-〉date_str[0]=Time-〉year/10+’0’; //加’0’转化成字符Time—〉date_str[1]=Time—〉year%10+’0';Time->date_str[2]='—’;Time->date_str[3]=Time->month/10+'0';Time->date_str[4]=Time-〉month%10+'0’;Time—>date_str[5]=’—’;Time-〉date_str[6]=Time-〉day/10+'0';Time—>date_str[7]=Time—>day%10+’0’;Time-〉date_str[8]=’-’;Time->date_str[9]=Time—〉week%10+’0’;Time-〉date_str[10]='\0';}/**************时-分-秒“字符”显示***************/void time_to_str(date_time *Time){Time—>time_str[0]=Time->hour/10+’0';Time-〉time_str[1]=Time—〉hour%10+’0';Time—>time_str[2]=’-';Time—>time_str[3]=Time—>minute/10+'0’;Time—>time_str[4]=Time—>minute%10+'0’;Time->time_str[5]='—';Time->time_str[6]=Time->second/10+'0';Time->time_str[7]=Time—>second%10+'0';Time-〉time_str[8]=’\0';}#endif万年历C文件:/********************************************************* TITLE: 实时时钟FUNCTION: DS1302+LCD1602显示实时时钟WRITER: LINLIANHUO(完整word版)万年历(DS1302+LCD1602【程序、仿真、完整】) TIME: 2014-07-30REMARK: matters need attention**********************************************************/#include 〈reg51.h〉#include <string.h〉#include ”DS1302。
基于51单片机DS1302LCD1602数字时钟显示
#include <intrins.h>
#include <string.h>
#define uint unsigned int
#define uchar unsigned char
uchar code table[]="I LIKE MCU!";
sbit RS=P2^0;
dispaly_string(0x00,lcd_buffer1);
dispaly_string(0x40,lcd_buffer2);
}
}
delay(5);
}
void write_a_byte_tods1302(uchar x)
{
uchar i;
for(i=0;i<8;i++)
{
IO=x&0x01;
sclk=1;
sclk=0;
x=x>>1;
}
}
uchar get_a_byte_fromds1302()
{
uchar i,b=0x00;
for(i=0;i<8;i++)
uchar lcd_buffer2[]={"TIME 00:00:00 "};
uchar datetime[7];
void delay(uchar ms)
{
uchar i;
while(ms--)
for(i=0;i<120;i++);
}
//忙检测
uchar busy()
{
uchar test;
RW=1;
{
电子时钟程序DS1302时钟芯片lcd1602
date=Read1302();
SCLK=1;
REST=0;
return date;
}
void IntDS1302(void) //DS1302初始化
{
unsigned char flag;
flag= ReadSet1302(0x81);
/*液晶忙检测*/
bit BusyTest(void)
{
bit result;
RS=0;
RW=1;
E=1;
_nop_();
_nop_();
_nop_();
result=BF;
_nop_();
_nop_();
_nop_();
E=0;
return result;
delay1ms(1);
Write_com(0x0c);
delay1ms(1);
Write_com(0x01);
}
void displaymainpart(void)//显示液晶主要部分(不变化部分)
{
Write_Address(0x01);
delay1ms(1);
{
unsigned char i,j;
i=day/10;
j=day%10;
Write_Address(0x0E);
Write_Date(dit[j]);
delay1ms(1);
}
void display_Month(unsigned char month) //在液晶上显示月
_nop_();
E=1;
_nop_();
时钟DS1302在液晶1602显示程序
#include <reg52.h>#define uchar unsigned char#define uint unsigned intuchar code table[]="ziye334"; uchar code table1[]="0123456789"; uchar code table2[]="DAY-";sbit rs=P2^5;sbit rw=P2^6;sbit en=P2^7;sbit rst=P1^7;sbit io=P3^5;sbit clk=P1^6;sbit ACC0=ACC^0;sbit ACC7=ACC^7;sbit key1=P1^0;sbit key2=P1^1;sbit key3=P1^2;sbit key4=P1^3;sbit key5=P1^4;uchar num;uchar t_sec,sec1,sec2;uchar t_min,min1,min2;uchar t_hr,hr1,hr2;uchar t_mon,mon1,mon2; uchar t_date,date1,date2; uchar t_year,year1,year2; uchar t_day,day1,flag;void input_1byte(uchar TD) {uchar i;ACC=TD;for(i=8;i>0;i--){io=ACC0;clk=1;clk=0;ACC=ACC>>1;}}uchar output_1byte(void) {uchar i;for(i=8;i>0;i--){ACC=ACC>>1;ACC7=io;clk=1;clk=0;}return(ACC);}void write_ds1302(uchar add,uchar dat) {rst=0;clk=0;rst=1;input_1byte(add);input_1byte(dat);clk=1;rst=0;}uchar read_ds1302(uchar add){uchar inf;rst=0;clk=0;input_1byte(add);inf=output_1byte();clk=1;rst=0;return(inf);}void delay(uchar z) //延时{uint x,y;for(x=110;x>0;x--)for(y=z;z>0;z--);}void write_com(uchar com) //写指令{rs=0;rw=0;en=0;P0=com;delay(5);en=1;delay(5);}void write_date(uchar date) //写数据{rs=1;rw=0;en=0;P0=date;delay(5);en=1;delay(5);en=0;}void init_lcd(){en=0;write_com(0x38); //显示write_com(0x0c); //光标不显示write_com(0x06); //指针加1,整屏不移动write_com(0x01); //清屏write_com(0x80);}void init_1302(){write_ds1302(0x8e,0x00);//关闭写保护write_ds1302(0x90,0xaa); //定义充电write_ds1302(0x80,0x30); //秒write_ds1302(0x82,0x59);//分write_ds1302(0x84,0x23);//时write_ds1302(0x86,0x31);//日write_ds1302(0x88,0x12);//月write_ds1302(0x8a,0x04);//星期write_ds1302(0x8c,0x11);//年write_ds1302(0x8e,0x80);//打开写保护}void display(){t_sec=read_ds1302(0x81);sec1=t_sec&0x0f;sec2=(t_sec>>4);t_min=read_ds1302(0x83);min1=t_min&0x0f;min2=(t_min>>4);t_hr=read_ds1302(0x85); hr1=t_hr&0x0f;hr2=(t_hr>>4);t_date=read_ds1302(0x87); date1=t_date&0x0f;date2=(t_date>>4);t_mon=read_ds1302(0x89); mon1=t_mon&0x0f;mon2=(t_mon>>4);t_day=read_ds1302(0x8b); day1=t_day&0x0f;t_year=read_ds1302(0x8d); year1=t_year&0x0f;year2=(t_year>>4);write_com(0x80+0x4e);write_date(table1[sec2]); write_com(0x80+0x4f); write_date(table1[sec1]); write_com(0x80+0x4d); write_date(':');write_com(0x80+0x4c); write_date(table1[min1]); write_com(0x80+0x4b); write_date(table1[min2]); write_com(0x80+0x4a); write_date(':');write_com(0x80+0x49); write_date(table1[hr1]); write_com(0x80+0x48); write_date(table1[hr2]);write_com(0x80+0x0f); write_date(table1[date1]); write_com(0x80+0x0e); write_date(table1[date2]);write_com(0x80+0x0d);write_date('/');write_com(0x80+0x0c);write_date(table1[mon1]);write_com(0x80+0x0b);write_date(table1[mon2]);write_com(0x80+0x0a);write_date('/');write_com(0x80+0x09);write_date(table1[year1]);write_com(0x80+0x08);write_date(table1[year2]);write_com(0x80+0x40+5);write_date(table1[day1]); }void main(){init_lcd();delay(5);init_1302();delay(5);for(num=0;num<7;num++) {write_date(table[num]);delay(10);}write_com(0x80+0x41);for(num=0;num<4;num++) {write_date(table2[num]);delay(10);}while(1){if(flag==0){display();}}}。
LCD1602显示DS1302时钟时间
/******************************************************************* DS1302ºÍLCD1602£¬C51µ¥Æ¬»úCÓïÑÔ*****************************************************************/ #include<AT89x51.h>#define uchar unsigned char/**********DS1302******************/#define write_second 0x80#define write_minute 0x82#define write_hour 0x84#define read_second 0x81#define read_minute 0x83#define read_hour 0x85#define write_day 0x86#define read_day 0x87#define write_month 0x88#define read_month 0x89#define write_week 0x8A#define read_week 0x8B#define write_year 0x8C#define read_year 0x8D#define write_protect 0x8E/******DS1302*************/sbit ACC_7=ACC^7;sbit SCLK =P1^2;sbit DIO =P1^3;sbit CE =P1^4;sbit P3_add=P3^0;sbit P3_OK =P3^1;//////LCD1602//////////////#define LCD_DB P0sbit LCD_RS=P2^0;sbit LCD_RW=P2^1;sbit LCD_E=P2^2;/******¶¨Ò庯Êý****************/#define uchar unsigned char#define uint unsigned intvoid LCD_init(void);//ÉùÃ÷³õʼ»¯º¯Êývoid LCD_write_command(uchar command);//дָÁÊývoid LC D_write_data(uchar dat);//дÊý¾Ýº¯Êývoid delay_n40us(uint n);//ÑÓʱº¯Êý//*******³õʼ»¯º¯Êý***************void LCD_init(void){LCD_write_command(0x38);//ÉèÖÃ8λ¸ñʽ£¬2ÐУ¬5x7LCD_write_command(0x0c);//ÕûÌåÏÔʾ£¬¹Ø¹â±ê£¬²»ÉÁ˸LCD_write_command(0x06);//É趨ÊäÈ뷽ʽ£¬ÔöÁ¿²»ÒÆλ--------------LCD_write_command(0x01);//Çå³ýÆÁÄ»ÏÔʾ----------------delay_n40us(100);//ʵ¼ùÖ¤Ã÷£¬ÎÒµÄLCD1602ÉÏ£¬ÓÃfor Ñ»·200 ´Î¾ÍÄÜ¿É¿¿Íê³ÉÇåÆÁÖ¸Áî¡£}//********дָÁÊý***********ÉèÖÃÏÈÏò1602дÈëµÄÊý¾ÝΪµØÖ·*void LCD_write_command(uchar dat){LCD_DB=dat;LCD_RS=0;//Ö¸ÁîLCD_RW=0;//дÈëLCD_E=1;//ÔÊÐíLCD_E=0;//²úÉúϽµÑØdelay_n40us(1);//ʵ¼ùÖ¤Ã÷£¬ÎÒµÄLCD1602 ÉÏ£¬ÓÃfor Ñ»·1 ´Î¾ÍÄÜÍê³ÉÆÕͨдָÁî¡£}//дÈë×Ö·û´®º¯Êývoid writeDataLcd(unsigned ch ar dat)// дÈëÊý¾Ý{LCD_RS=1;LCD_RW=0;LCD_E=0;LCD_DB = dat;LCD_E=1;delay_n40us(10);LCD_E=0;}//********ÑÓʱº¯Êý***************void delay_n40us(uint n){ uint i;uchar j;for(i=n;i>0;i--)for(j=0;j<2;j++); //ÔÚÕâ¸öÑÓʱѻ·º¯ÊýÖÐÎÒÖ»×öÁË2´ÎÑ»·}//**********DS1302*************************//void write1302(unsigned char addr,dat){unsigned char i,temp;CE=0;SCLK=0;CE=1;for(i=0;i<8;i++) //????{SCLK=0;temp=addr;if(temp&0x01==0x01)DIO=1;elseDIO=0;addr>>=1;SCLK=1;}for(i=0;i<8;i++) //????{SCLK=0;temp=dat;if(temp&0x01==0x01)DIO=1;elseDIO=0;dat>>=1;SCLK=1;}}unsigned char read1302(unsigned char addr) {unsigned char i,temp;CE=0;SCLK=0;CE=1;for(i=8;i>0;i--)//?????????{SCLK =0;temp =addr;if(temp&0x01==0x01)DIO=1;elseDIO=0;addr>>=1;SCLK=1;}for(i=8;i>0;i--)//???{ACC_7=DIO;SCLK=1;ACC>>=1;SCLK=0; //???????}CE=0;return(ACC);}///////////////////////////////////// void Initial(void){write1302(write_protect,0x00);write1302(write_second,0x56);write1302(write_minute,0x34);write1302(write_hour,0x12);write1302(write_protect,0x80);}//*********Ö÷º¯Êý*****************void main(void){uint i;uchar sec,min,hour,week,year,month,day;EA=1;EX0=1;Initial();LCD_init();write1302(write_hour,0x23);write1302(write_minute,0x58);write1302(write_year,15);write1302(write_month,11);write1302(write_day,20);write1302(write_week,5);while(1){sec=read1302(read_second);min=read1302(read_minute);hour=read1302(read_hour);week= read1302(read_week);year =read1302(read_year);month= read1302(read_month);day=read1302(read_day);LCD_write_command(0x80);writeDataLcd(0x00);if(hour<12)writeDataLcd(0x41);elsewriteDataLcd(0x70);writeDataLcd(0x6d);writeDataLcd(0x3a);writeDataLcd(0x30+(0x03 & (hour>>4))); writeDataLcd(0x30+(0x0f & hour)); writeDataLcd(0x3a);writeDataLcd(0x30+(0x07 & (min>>4)));writeDataLcd(0x30+(0x0f & min));writeDataLcd(0x3a);writeDataLcd(0x30+(0x07 & (sec>>4))); writeDataLcd(0x30+(0x0f & sec)); writeDataLcd(0x00);writeDataLcd(0x00);writeDataLcd(0x30+week);for(i=0;i<49;i++)writeDataLcd(0x00);writeDataLcd(0x00);writeDataLcd(0x00);writeDataLcd(0x00);writeDataLcd(0x32);writeDataLcd(0x30);writeDataLcd(0x30+year/10); writeDataLcd(0x30+year%10); writeDataLcd(0x2d);writeDataLcd(0x30+month/10);writeDataLcd(0x30+month%10);writeDataLcd(0x2d); writeDataLcd(0x30+day/10); writeDataLcd(0x30+day%10);}}void intsvr0(void) interrupt 0 using 3 {}。
ds1302+lcd1602程序
#define uint unsigned int #define uchar unsigned char /***************************** 1602液晶显示位定义 *****************************/ #define lcd_data P0 sbit rs=P1^7; sbit rw=P1^6; sbit en=P2^4; void write_1602_cmd(uint); void write_1602_dat(uint); void delay1ms(uint); void lcd1602_init(); uchar nyx[16]=" 2011-00-00 MON "; uchar sfm[13] =" 00:00:00 "; /****************************** ds1302的位定义 ******************************/ sbit rst=P2^2; sbit sclk=P1^4; sbit io=P1^5; void write_ds1302_byte(uint); void lcd_busy_wait(); void write_ds1302(uint,uint); uint read_ds1302(uint); void init_time();
shu>>=1; sclk=0; if(io) shu|=0x80; sclk=1; } rst=0; _nop_(); io=1; sclk=1; return shu; } void init_time() { uint i,a,b; for(i=0;i<7;i++) { a=time_init[i]/10; b=time_init[i]%10; time_init[i]=a*16+b; } write_ds1302(0x8e,0x00); for(i=0;i<7;i++) { write_ds1302(time_wadd[i],time_init[i]); } write_ds1302(0x8e,0x80); } void read_time() { uint i; for(i=0;i<7;i++) { time_shuzhi[i]=read_ds1302(time_radd[i]);
基于51单片机DS1302LCD1602数字时钟显示
dispaly_string(0x40,lcd_buffer2);
}
}
sbit RW=P2^1;
sbit EN=P2^2;
sbit IO=P1^0;
sbit sclk=P1^1;
sbit rst=P1^2;
uchar *week[]={"SUN","****","MON","TUS","WEN","THU","FRI","SAT"};
uchar lcd_buffer1[]={"DATE 00-00-00 "};
delay(5);
}
void write_a_byte_tods1302(uchar x)
{
uchar i;
for(i=0;i<8;i++)
{
IO=x&0x01;
sclk=1;
sclk=0;
x=x>>1;
}
}
uchar get_a_byte_fromds1302()
{
uchar i,b=0x00;
for(i=0;i<8;i++)
a[1]=d%10+'0';
}
void main()
{
init();
while(1)
{
gettime();
zhuanhuan(datetime[6],lcd_buffer1+5);
zhuanhuan(datetime[4],lcd_buffer1+8);
电子万年历(DS1302)(LCD1602显示)程序
LCD1602_E = 1;//写入时序
Lcd1602_Delay1ms(5);
LCD1602_E = 0;
LCD1602_DATAPINS = dat << 4; //写入低四位
Lcd1602_Delay1ms(1);
LCD1602_E = 1;//写入时序
LCD1602_DATAPINS = com;//由于4位的接线是接到P0口的高四位,所以传送高四位不用改
Lcd1602_Delay1ms(1);
LCD1602_E = 1;//写入时序
Lcd1602_Delay1ms(5);
LCD1602_E = 0;
//Lcd1602_Delay1ms(1);
LCD1602_DATAPINS = com << 4; //发送低四位
* 函数功能: 主函数
* 输入 : 无
* 输出: 无
*******************************************************************************/
void main()
{
unsigned char i;
Int0Configuration();
LcdWriteData('-');
LcdWriteData('0'+TIME[4]/16);//月
LcdWriteData('0'+(TIME[4]&0x0f));
LcdWriteData('-');
LcdWriteData('0'+TIME[3]/16);//日
DS1302+LCD1602时钟
DS1302+LCD1602时钟1.实验目的效果:做一个不怕掉电的LCD显示时钟。
学习DS1302时钟芯片的读写,加强字符型液晶LCD1602的应用。
在LCD屏上显示格式:1)按一下SW1进入时间调整,关标会闪烁2)按一下SW2光标会在年份上闪烁,表明可以对年份进行调整,接着按SW3年份将加一,按SW4年份将减一;2)再按一下SW2,光标闪烁移到月份上,同样按SW3月份加一,按SW4月份减一;3)再按一下SW2,光标有下移到星期上,同样按SW3星期加一,按SW4星期减一;4)同样的道理可以调整时,分,秒。
5)调整完毕按一下SW1,光标闪烁退出,时间调整结束。
DS1302:1)读写时序:2)DS1302相关寄存器:(详细DS1302资料请查看ds1302.pdf文档)2.原理图:DS1302连接原理图LCD1602连接原理图3.实验板上操作:1)用三个短路冒将SCLK-P3.5,I/O-P3.6,CE-P3.7短接起来。
2)将板上的相应拨码开关拨到拨到ON上。
(建议把原来做过数码管显示的那个拨码开关全部拨到OFF那边)3)把LCD1602液晶插到实验板上的LCD1602液晶插槽上。
(提示:程序烧进单片机后,液晶上没有显示,请调节板子上左上角那个电位器)4)按一下SW1进入时间调整,关标会闪烁按一下SW2光标会在年份上闪烁,表明可以对年份进行调整,接着按SW3年份将加一,按SW4年份将减一;再按一下SW2,光标闪烁移到月份上,同样按SW3月份加一,按SW4月份减一;再按一下SW2,光标有下移到星期上,同样按SW3星期加一,按SW4星期减一;同样的道理可以调整时,分,秒。
调整完毕按一下SW1,光标闪烁退出,时间调整结束。
4.实物连接图如下:5.C语言程序:#include "A T89X51.h"#include "intrins.h"#define HIGH 1#define LOW 0#define TRUE 1#define ZERO 0#define MSB 0x80#define LSB 0x01// ds1302 PreDefinition#define DS1302_WP0x8E#define DS1302_RESET RST=LOW;SCL=LOW;RST=HIGH#define DS1302_WP_ENABLE Write_Ds1302(DS1302_WP,0X00)#define DS1302_WP_DISENABLE Write_Ds1302(DS1302_WP,0x00) #define LCDPORT P0sbit SCL = P3^5;// DS1302 Serial-Clock Input pin 5sbit SDA = P3^6;// DS1302 Serial-Data Input pin 6sbit RST = P3^7;// DS1302 Chip-Seclet Input pin 7sbit RS=P1^0;sbit RW=P1^1;sbit EN=P1^2;code unsigned char set_rtc_code[7]={0x07,0x03,0x29,0x02,0x21,0x07,0x40};code unsigned char write_rtc_address[7]={0x8c,0x88,0x86,0x8a,0x84,0x82,0x80};code unsigned char read_rtc_address[7]={0x8d,0x89,0x87,0x8b,0x85,0x83,0x81}; unsigned char read_rtc_code[7]; //DS1302读出信息(年份,星期,时间)暂存数组,/********1ms延时子程序***********/delay_nms(unsigned int n){unsigned int i;unsigned char j;for(i=0;i<n;i++)for(j=0;j<120;j++); //空操作}//*************LCD1602驱动程序***************************//void lcd_delay(unsigned char delaytime){while(delaytime)delaytime--;}void write_lcd_command(unsigned char write_command){lcd_delay(40);RS=0;RW=0;LCDPORT=write_command;EN=1;EN=0;}void write_lcd_data(unsigned char write_data){lcd_delay(40);RS=1;RW=0;LCDPORT=write_data;EN=1;EN=0;}void LCD_write_char( unsigned x,unsigned char y,unsigned char dat) //x表示行,y表示该行的位置(也就是列){//LCD_set_xy( x, y );switch(x){case 0:write_lcd_command(0x80+y);break;case 1:write_lcd_command(0xc0+y);break;}// LCD_en_dat(dat);write_lcd_data(dat|0x30); //dat或上0x30,就时把数字0123456789转换成ASIIC码}void lcd_displaystr(unsigned char x,unsigned char y,unsigned char code *str){switch(x){case 0:write_lcd_command(0x80+y);break;case 1:write_lcd_command(0xc0+y);break;}while (*str){write_lcd_data(*str);str++;}}void initial_lcd1602(void) //初始化LCD1602{unsigned char i;EN=0;for(i=200;i>0;i--)lcd_delay(248);write_lcd_command(0x38);for(i=4;i>0;i--)lcd_delay(248);write_lcd_command(0x38);for(i=4;i>0;i--)lcd_delay(248);write_lcd_command(0x0f);for(i=4;i>0;i--)lcd_delay(248);write_lcd_command(0x06);for(i=4;i>0;i--)lcd_delay(248);write_lcd_command(0x01);for(i=4;i>0;i--)lcd_delay(248);}//********************lcd1602驱动程序到此完********************/////////////////////////////////////////////////////////////////////////**************ds1302读写程序*************************//void Write_Ds1302_Byte(unsigned char temp) //写一个字节{unsigned char i;for (i=0;i<8;i++){SCL=LOW;SDA=temp&LSB;temp>>=1;SCL=HIGH;}}/****************************************************************************/ void Write_Ds1302( unsigned char address,unsigned char dat ) //写ds1302{DS1302_RESET;Write_Ds1302_Byte(address);Write_Ds1302_Byte(dat);RST=LOW;}/****************************************************************************/ unsigned char Read_Ds1302 ( unsigned char address ) //读ds1302{unsigned char i,temp=0x00,temp_temp;DS1302_RESET;Write_Ds1302_Byte(address);for (i=0;i<8;i++){if(SDA)temp|=0x80;SCL=LOW;temp>>=1;SCL=HIGH;}RST=LOW;temp_temp=temp/16;temp=temp%16;temp=temp+temp_temp*10;return (temp);}/****************************************************************************/ void Read_RTC(void) //读出DS1302里的相关信息,存放在read_rtd_code[]数组中{unsigned char i,*p;p=read_rtc_address;for(i=0;i<7;i++){read_rtc_code[i]=Read_Ds1302(*p);p++;}}/***********************************************************************/void Set_RTC(void) //初始化设置DS1302{unsigned char i,*p;p=write_rtc_address;for(i=0;i<7;i++){Write_Ds1302(*p,set_rtc_code[i]);p++;}}/******************************************************/void initial_ds1302(void) //初始化ds1302{DS1302_WP_ENABLE;Set_RTC();}/**************ds1302读写程序到此完************************//////////////////////////////////////////////////////系统初始化void system_initial(void){initial_ds1302();initial_lcd1602();}/****************************************************************************/void main(void){unsigned char count,staus;system_initial();//输出显示lcd_displaystr(0,0x00,"20");delay_nms(10);lcd_displaystr(0,0x04,"-");delay_nms(10);lcd_displaystr(0,0x07,"-");lcd_displaystr(0,0x0b,"Week:");lcd_displaystr(1,0x00,"Time:");lcd_displaystr(1,0x07,":");lcd_displaystr(1,0x0a,":");while(1){//按键扫描,实现对时间的调整,对应实验板的独立按钮//开始时间设置,staus=1if(P2_0==0){delay_nms(10);if(P2_0==0){staus^=1;count=0;while(P2_0==0);}}if(P2_1==0){delay_nms(10);if(P2_1==0){count++; //光标移位if(count==8)count=1;while(P2_1==0);}}if(P2_2==0) //加按钮{delay_nms(10);if(P2_2==0){switch(count){case 0x01:read_rtc_code[0]++;DS1302_WP_ENABLE;Write_Ds1302(write_rtc_address[0],(read_rtc_code[0]+(read_rtc_code[0]/10)*6));LCD_write_char(0,0x02,(read_rtc_code[0]/10)); //年十位LCD_write_char(0,0x03,(read_rtc_code[0]%10)); //年个位break;case 0x02:read_rtc_code[1]++;if(read_rtc_code[1]==13)read_rtc_code[1]=1;DS1302_WP_ENABLE;Write_Ds1302(write_rtc_address[1],(read_rtc_code[1]+(read_rtc_code[1]/10)*6));LCD_write_char(0,0x05,(read_rtc_code[1]/10)); //月十位LCD_write_char(0,0x06,(read_rtc_code[1]%10)); //月个位break;case 0x03:read_rtc_code[2]++;if(read_rtc_code[2]==31)read_rtc_code[2]=1;DS1302_WP_ENABLE;Write_Ds1302(write_rtc_address[2],(read_rtc_code[2]+(read_rtc_code[2]/10)*6));LCD_write_char(0,0x08,(read_rtc_code[2]/10)); //日十位LCD_write_char(0,0x09,(read_rtc_code[2]%10)); //日个位break;case 0x04:read_rtc_code[3]++;if(read_rtc_code[3]==8)read_rtc_code[3]=1;DS1302_WP_ENABLE;Write_Ds1302(write_rtc_address[3],(read_rtc_code[3]+(read_rtc_code[3]/10)*6));LCD_write_char(0,0x0f,(read_rtc_code[3]%10)); //星期break;case 0x05:read_rtc_code[4]++;if(read_rtc_code[4]==25)read_rtc_code[4]=0;DS1302_WP_ENABLE;Write_Ds1302(write_rtc_address[4],(read_rtc_code[4]+(read_rtc_code[4]/10)*6));LCD_write_char(1,0x05,(read_rtc_code[4]/10)); //时十位LCD_write_char(1,0x06,(read_rtc_code[4]%10)); //时个位break;case 0x06:read_rtc_code[5]++;if(read_rtc_code[5]==60)read_rtc_code[5]=0;DS1302_WP_ENABLE;Write_Ds1302(write_rtc_address[5],(read_rtc_code[5]+(read_rtc_code[5]/10)*6));LCD_write_char(1,0x08,(read_rtc_code[5]/10)); //分十位LCD_write_char(1,0x09,(read_rtc_code[5]%10)); //分个位break;case 0x07:read_rtc_code[6]++;if(read_rtc_code[6]==60)read_rtc_code[6]=0;DS1302_WP_ENABLE;Write_Ds1302(write_rtc_address[6],(read_rtc_code[6]+(read_rtc_code[6]/10)*6));LCD_write_char(1,0x0b,(read_rtc_code[6]/10)); //秒十位LCD_write_char(1,0x0c,(read_rtc_code[6]%10)); //秒个位break;default:break;}while(P2_2==0);}}if(P2_3==0) //减按钮{delay_nms(10);if(P2_3==0){switch(count){case 0x01:if(read_rtc_code[0]==0){lcd_displaystr(0,0x00,"19");read_rtc_code[0]=99;}elseread_rtc_code[0]--;DS1302_WP_ENABLE;Write_Ds1302(write_rtc_address[0],(read_rtc_code[0]+(read_rtc_code[0]/10)*6));LCD_write_char(0,0x02,(read_rtc_code[0]/10)); //年十位LCD_write_char(0,0x03,(read_rtc_code[0]%10)); //年个位break;case 0x02:if(read_rtc_code[1]==1)read_rtc_code[1]=12;elseread_rtc_code[1]--;DS1302_WP_ENABLE;Write_Ds1302(write_rtc_address[1],(read_rtc_code[1]+(read_rtc_code[1]/10)*6));LCD_write_char(0,0x05,(read_rtc_code[1]/10)); //月十位LCD_write_char(0,0x06,(read_rtc_code[1]%10)); //月个位break;case 0x03:if(read_rtc_code[2]==1)read_rtc_code[2]=30;elseread_rtc_code[2]--;DS1302_WP_ENABLE;Write_Ds1302(write_rtc_address[2],(read_rtc_code[2]+(read_rtc_code[2]/10)*6));LCD_write_char(0,0x08,(read_rtc_code[2]/10)); //日十位LCD_write_char(0,0x09,(read_rtc_code[2]%10)); //日个位break;case 0x04:if(read_rtc_code[3]==1)read_rtc_code[3]=7;elseread_rtc_code[3]--;DS1302_WP_ENABLE;Write_Ds1302(write_rtc_address[3],(read_rtc_code[3]+(read_rtc_code[3]/10)*6));LCD_write_char(0,0x0f,(read_rtc_code[3]%10)); //星期break;case 0x05:if(read_rtc_code[4]==0)read_rtc_code[4]=24;elseread_rtc_code[4]--;DS1302_WP_ENABLE;Write_Ds1302(write_rtc_address[4],(read_rtc_code[4]+(read_rtc_code[4]/10)*6));LCD_write_char(1,0x05,(read_rtc_code[4]/10)); //时十位LCD_write_char(1,0x06,(read_rtc_code[4]%10)); //时个位break;case 0x06:if(read_rtc_code[5]==00)read_rtc_code[5]=59;elseread_rtc_code[5]--;DS1302_WP_ENABLE;Write_Ds1302(write_rtc_address[5],(read_rtc_code[5]+(read_rtc_code[5]/10)*6));LCD_write_char(1,0x08,(read_rtc_code[5]/10)); //分十位LCD_write_char(1,0x09,(read_rtc_code[5]%10)); //分个位break;case 0x07:if(read_rtc_code[6]==0)read_rtc_code[6]=59;elseread_rtc_code[6]--;DS1302_WP_ENABLE;Write_Ds1302(write_rtc_address[6],(read_rtc_code[6]+(read_rtc_code[6]/10)*6));LCD_write_char(1,0x0b,(read_rtc_code[6]/10)); //秒十位LCD_write_char(1,0x0c,(read_rtc_code[6]%10)); //秒个位break;default:break;}while(P2_3==0);}}if(staus==0){//读出DS1302寄存器里的时间信息RST=HIGH;Read_RTC();LCD_write_char(0,0x02,(read_rtc_code[0]/10)); //年十位LCD_write_char(0,0x03,(read_rtc_code[0]%10)); //年个位LCD_write_char(0,0x05,(read_rtc_code[1]/10)); //月十位LCD_write_char(0,0x06,(read_rtc_code[1]%10)); //月个位LCD_write_char(0,0x08,(read_rtc_code[2]/10)); //日十位LCD_write_char(0,0x09,(read_rtc_code[2]%10)); //日个位LCD_write_char(0,0x0f,(read_rtc_code[3]%10)); //星期LCD_write_char(1,0x05,(read_rtc_code[4]/10)); //时十位LCD_write_char(1,0x06,(read_rtc_code[4]%10)); //时个位LCD_write_char(1,0x08,(read_rtc_code[5]/10)); //分十位LCD_write_char(1,0x09,(read_rtc_code[5]%10)); //分个位LCD_write_char(1,0x0b,(read_rtc_code[6]/10)); //秒十位LCD_write_char(1,0x0c,(read_rtc_code[6]%10)); //秒个位}else{RST=LOW;switch(count){case 0x01:write_lcd_command(0x83);break;case 0x02:write_lcd_command(0x86);break;case 0x03:write_lcd_command(0x89);break;case 0x04:write_lcd_command(0x8f);break;case 0x05:write_lcd_command(0xc6);break;case 0x06:write_lcd_command(0xc9);break;case 0x07:write_lcd_command(0xcc);break;default:break;}}}}。
LCD1602+DS1302完整版C程序(可调时)
LCD1602+DS1302完整版C程序(可调时)#include#includesbit k2=P3^5; // 修改模式sbit k3=P3^6; //数据加sbit k4=P3^7; //数据减sbit beep=P2^3; //蜂鸣器#define uchar unsigned char#define uint unsigned int#define DS1302_W_ADDR 0xBE#define DS1302_R_ADDR 0xBFuint s2num=0;uchar num;uint time[7]={0,13,20,12,8,2,14};//秒分时日月周年10-08-15 23:59:50sbit lcdrs = P1^0 ;sbit lcdrw = P1^1 ;sbit lcden = P2^5 ;sbit SCK = P2^1; //时钟sbit SDA = P2^0; //数据sbit RST = P2^4; //DS1302复位(片选)sbit dula=P2^6;sbit wela=P2^7;void delay(uint z) //毫秒级延时{uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}void di(){beep=0;delay(100);beep=1;}void write_ds1302_byte(uint dat) //1302写数据{uint i;for (i=0;i<8;i++){SDA = dat & 0x01;SCK = 1;dat >>= 1;SCK = 0;}}uint read_ds1302_byte(void) //1302读数据{uint i, dat=0;for (i=0;i<8;i++){dat >>= 1;if (SDA)dat |= 0x80;SCK = 1;SCK = 0;}return dat;}void reset_ds1302(void) //1302复位{RST = 0;SCK = 0;RST = 1;}/*** 清除写保护*/void clear_ds1302_WP(void){reset_ds1302();RST = 1;write_ds1302_byte(0x8E);write_ds1302_byte(0);SDA = 0;RST = 0;}/*** 设置写保护*/void set_ds1302_WP(void){reset_ds1302();RST = 1;write_ds1302_byte(0x8E);write_ds1302_byte(0x80);SDA = 0;RST = 0;}/*** 设定时钟数据*/void set_time(uint *timedata){uint i, tmp;for (i=0; i<7; i++) // 转化为BCD格式{tmp = timedata[i] / 10;timedata[i] = timedata[i] % 10; timedata[i] = timedata[i] + tmp*16; }clear_ds1302_WP();reset_ds1302();RST = 1;write_ds1302_byte(DS1302_W_ADDR);for (i=0; i<7; i++){write_ds1302_byte(timedata[i]);delay(10);}write_ds1302_byte(0);SDA = 0;RST = 0;set_ds1302_WP();}/*** 读时钟数据(BCD格式)*/void read_time(uint *timedata) //1302时钟读数据{uint i;clear_ds1302_WP();reset_ds1302();RST = 1;write_ds1302_byte(DS1302_R_ADDR);for (i=0; i<7; i++){timedata[i] = read_ds1302_byte();delay(1);}SDA = 0;RST = 0;set_ds1302_WP();}void write_zhiling(uchar zhiling){lcden=0;lcdrs=0;P0=zhiling; //1602写指令lcden=1;delay(5);lcden=0;}void write_shuju(uchar shuju){lcdrs=1;lcden=0;P0=shuju;lcden=1; //1602写不带地址数据delay(5);lcden=0;}void write_add(uchar add,uchar shuju) {uint shi,ge;shi=shuju/10;ge=shuju%10;write_zhiling(0x02); //1602写带地址数据write_zhiling(0x80+add);write_shuju(0x30+shi);write_shuju(0x30+ge);}void init(){lcden=0;dula=0;wela=0;lcdrw=0; //1602液晶初始化write_zhiling(0x38);write_zhiling(0x08);write_zhiling(0x01);write_zhiling(0x06);write_zhiling(0x0c);}void write_guangbiao(uchar add){// write_zhiling(0x02); //1602写光标闪烁地址write_zhiling(0x80+add);write_zhiling(0x0f);}void xianshi(){// read_time(&time);for(num=0;num<7;num++)time[num]=((time[num]/16)*10+(time[num]%16));write_add(2,time[2]);write_shuju(':');write_add(5,time[1]);write_shuju(':');write_add(8,time[0]);write_shuju(' ');num=time[5];switch(num){case1:{write_shuju('M');write_shuju('O');write_shuju('N');}break;case2:{write_shuju('T');write_shuju('U');write_shuju('E');}break;case3:{write_shuju('W');write_shuju('E');write_shuju('D');}break;case4:{write_shuju('T');write_shuju('H');write_shuju('U');}break;case 5:{write_shuju('F');write_shuju('R');write_shuju('I');}break;case6:{write_shuju('S');write_shuju('A');write_shuju('T');}break;case7:{write_shuju('S');write_shuju('U');write_shuju('N');}break;}write_add(0x40+4,time[6]);write_shuju('/');write_add(0x40+7,time[4]);write_shuju('/');write_add(0x40+10,time[3]);switch(s2num){case 1:write_guangbiao(3);break;case 2:write_guangbiao(6);break;case 3:write_guangbiao(9);break;case 4:write_guangbiao(13);break; case 5:write_guangbiao(0x40+5);break; case 6:write_guangbiao(0x40+8);break; case 7:write_guangbiao(0x40+11);break; }}void keyscan(){if(k2==0) //调节功能键{delay(5);if(k2==0){s2num++;while(!k2);di();}}switch(s2num){case 1:write_guangbiao(3);break;case 2:write_guangbiao(6);break;case 3:write_guangbiao(9);break;case 4:write_guangbiao(13);break; case 5:write_guangbiao(0x40+5);break;case 6:write_guangbiao(0x40+8);break; case 7:write_guangbiao(0x40+11);break; }if(s2num>=8){s2num=0;}if(s2num!=0){time[0]=((time[0]/16)*10+(time[0]%16)); time[1]=((time[1]/16)*10+(time[1]%16)); time[2]=((time[2]/16)*10+(time[2]%16)); time[3]=((time[3]/16)*10+(time[3]%16)); time[4]=((time[4]/16)*10+(time[4]%16)); time[5]=((time[5]/16)*10+(time[5]%16)); time[6]=((time[6]/16)*10+(time[6]%16));if(k3==0){delay(5);if(k3==0){while(!k3);di();if(s2num==1){time[2]++;time[0]=0;if(time[2]>=24)time[2]=0;}if(s2num==2){time[1]++;time[0]=0;if(time[1]>=60) {time[1]=0;time[2]++;} }if(s2num==3){time[0]++;if(time[0]>=60)time[0]=0;}if(s2num==4){time[5]++;if(time[5]>=8)time[5]=1;}if(s2num==5){time[6]++;}if(s2num==6){time[4]++;if(time[4]>=13) time[4]=1;}if(s2num==7) {time[3]++;if(time[3]>=32) time[3]=1;}set_time(&time); xianshi();}}if(k4==0){delay(5);if(k4==0){while(!k4);di();if(s2num==1) {time[2]--;time[0]=0;if(time[2]==-1) time[2]=23;}if(s2num==2){time[1]--;time[0]=0;if(time[1]==-1) {time[1]=59;time[2]--;} }if(s2num==3){time[0]--;if(time[0]==-1)time[2]=59;}if(s2num==4){time[5]--;if(time[5]==0)time[5]=7;}if(s2num==5){time[6]--;}if(s2num==6){time[4]--;if(time[4]<=0)time[4]=12;}if(s2num==7){time[3]--;if(time[3]<=0) time[3]=31;}set_time(&time); xianshi();}}}}void main(){init();s2num=0;// set_time(&time); while(1){read_time(&time); keyscan();if(s2num==0) xianshi();}}。
DS1302时钟LCD1602显示
/**************************************************************** ** DS1302时钟******************************************************************/ #include<reg51.h>#include<intrins.h>#define uchar unsigned char#define uint unsigned int//--定义矩阵键盘使用的IO口--//#define GPIO_DIG P0#define GPIO_KEY P1//---定义lcd1602使用的IO口---//#define DB P0//--定义全局变量--//uchar error[]="Error!!!" ;//存放字符串“Error!!!”char KeyValue=-1;//用来存放读取到的键值uchar flag=0;//用来检测是否更改过时间uchar tt0=0;//中断里面的参数uchar beeflag=0;//看看有没有开闹钟//---定义蜂鸣器使用的IO口---//sbit bee=P2^3;//定义LCD1602使用的IO口//sbit LCDE=P2^7;sbit RS=P2^6;sbit RW=P2^5;//---定义ds1302使用的IO口---//sbit DSIO=P3^4; //数据传输口sbit RST=P3^5; //进行传输时,RST必须置高sbit SCLK=P3^6; //上沿读数据,下沿写数据//---DS1302写入和读取时分秒的地址命令---////---秒分时日月周年最低位读写位;-------//uchar code READ_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d}; uchar code WRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};//---键盘写入地址-------//uchar kyewrite[] = {0x82, 0x83, 0x85, 0x86, 0x88, 0x89, 0x8d,0xc0,0xc1,0xc3,0xc4,0xc6,0xc7};//用于判断增减//char addorm[]={0x01,0x10,-0x01,-0x10};//---DS1302时钟初始化2013年1月1日星期二12点00分00秒。
用DS1302与LCD1602设计的可调式电子日历时钟的设计与实现
中州大学信息工程学院毕业设计(论文)2011— 2012学年第二学期题目:用DS1302与LCD1602设计的可调式电子日历时钟的设计与实现学生姓名(学号)梁慧萍田萌萌宋书倩指导教师刘爱荣职称教授评阅教师职称时间中州大学信息工程学院毕业设计(论文)开题报告课题名称(来源、类型):用 DS1302 与 1602LCD 设计的可调式电子日历与时钟的设计指导教师:刘爱荣学生姓名:梁慧萍田萌萌宋书倩开题报告内容:(调研资料的准备,设计/论文的目的、要求、思路与预期成果;任务完成的阶段内容及时间安排;小组内其他成员的分工;完成设计(论文)所具备的条件因素等。
)1.目的:实现日历和时钟的显示并且能够调整2.要求:完成可调式电子日历和时钟的软件和硬件的设计,包括单片机的相关内容;日历时钟模块的设计,液晶显示模块的设计,按键模块的设计。
控制程序的编写等。
3.预期成果:仿真成功,做出实物。
(1)显示初始值日历时钟初始值;(2)用按键调整日历时钟。
4.时间安排:第1周:熟悉课题的基本要求,查阅相关资料,初步拟定设计的整体方案,完成开题报告。
第2-3周:自学这次课题所涉及的相关内容,包括器件基础知识、单片机,DS1302时钟芯片工作原理和相关软件的使用以及LCD1602液晶显示屏的相关内容。
并设计一些简单的实际电路,熟练所学内容并加以巩固。
第4-6周:设计DS1302时钟模块的控制电路、LCD1602液晶显示电路、电源电路等硬件电路,并用Proteus仿真第7周:焊接调试电路,根据个部分的作用对硬件进行调试,最后联机调试。
第8周:写毕业设计论文,完成全部毕业设计5.小组成员分工:梁慧萍负责日历时钟模块的设计和控制程序的编写宋书倩负责液晶显示模块的设计田萌萌负责按键模块的设计指导教师签名:日期:2012年2月20日备注:(1)来源:A—教师拟订;B—学生建议;C—企业和社会征集;D—实习单位提供(2)类型:X—真实课题;Y—模拟课题;Z—虚拟课题中州大学信息工程学院毕业设计(论文)任务书指导教师:刘爱荣职称:教授学生人数: 3人学生姓名(学号、专业):梁慧萍田萌萌宋书倩毕业设计(论文)题目(来源、类型)用DS1302与LCD1602设计的可调式电子日历时钟的设计与实现毕业设计(论文)工作内容与基本要求(目标、任务、途径、方法、成果形式,应掌握的原始资料(数据)、参考资料(文献)以及设计技术要求、注意事项等)(纸张不够可加页)基本要求:(1)显示:年、月、日、时、分、秒;(2)具有年、月、日、时、分、秒的设置功能。
1602液晶显示DS1302实时时钟程序
#include <reg51.h>#include <intrins.h>unsigned char code dis_week[]={"SUN,MON,TUE,WED,THU,FRI,SAT"}; unsigned char code para_month[13]={0,0,3,3,6,1,4,6,2,5,0,3,5}; //星期月参变数unsigned char data dis_buf1[16]; //lcd上排显示缓冲区unsigned char data dis_buf2[16]; //lcd下排显示缓冲区unsigned char data year,month,date,week;//年、月、日、星期unsigned char data armhour,armmin,armsec;//闹钟时、分、秒unsigned char data hour,min,sec,sec100; //时、分、秒、百分之一秒unsigned char data flag,vkey,skey;//设置状态计数标志、按键先前值、按键当前值bit alarm; //标识是否启用闹钟,1--启用,0--关闭sbit rs = P2^0; //LCD数据/命令选择端(H/L)sbit rw = P2^1; //LCD读/写选择端(H/L)sbit ep = P2^2; //LCD使能控制sbit PRE = P1^6; //调整键(k3)sbit SET = P1^7; //调整键(k4)sbit SPK = P3^7;void delayms(unsigned char ms); //延时程序bit lcd_busy(); //测试LCD忙碌状态程序void lcd_wcmd(char cmd); //写入指令到LCD程序void lcd_wdat(char dat); //写入数据到LCD程序void lcd_pos(char pos); //LCD数据指针位置程序void lcd_init(); //LCD初始化设定程序void pro_timedate(); //时间日期处理程序void pro_display(); //显示处理程序void pro_key(); //按键处理程序void time_alarm(); //定时报警功能(闹钟) unsigned char scan_key(); //按键扫描程序unsigned char week_proc(); //星期自动计算与显示函数bit leap_year(); //判断是否为闰年void lcd_sef_chr(); //LCD自定义字符程序void update_disbuf(unsigned char t1,unsigned char t2[],unsigned char dis_h,unsigned char dis_m,unsigned char dis_s);//更新显示缓冲区函数// 延时程序void delay(unsigned char ms){ while(ms--){ unsigned char i;for(i = 0; i 250; i++){_nop_(); //执行一条_nop_()指令为一个机器周期_nop_();_nop_();_nop_();}}}//测试LCD忙碌状态bit lcd_busy(){bit result;rs = 0;rw = 1;ep = 1;_nop_();_nop_();_nop_();_nop_();result =(bit)(P0&0x80); //LCD的D0--D7中,D7=1为忙碌,D7=0为空闲ep = 0;return result;}//写入指令到LCDvoid lcd_wcmd(char cmd){while(lcd_busy()); //当lcd_busy为1时,再次检测LCD忙碌状态,lcd-busy为0时,开始写指令rs = 0;rw = 0;ep = 0;_nop_();_nop_();P0 = cmd;_nop_();_nop_();_nop_();_nop_();ep = 1;_nop_();_nop_();_nop_();_nop_();ep = 0;}//写入数据到LCDvoid lcd_wdat(char dat){while(lcd_busy()); //当lcd_busy为1时,再次检测LCD忙碌状态,lcd-busy为0时,开始写数据rs = 1;rw = 0;ep = 0;P0 = dat;_nop_();_nop_();_nop_();_nop_();ep = 1;_nop_();_nop_();_nop_();_nop_();ep = 0;}//LCD数据指针位置程序void lcd_pos(char pos){lcd_wcmd(pos|0x80); //数据指针=80+地址码(00H~27H,40H~67H)}//设定二个自定义字符,(注意:LCD1602中自定义字符的地址为0x00--0x07,即可定义8个字符)//这里我们设定把一个自定义字符放在0x00位置(000),另一个放在0x01位子(001)void lcd_sef_chr(){ //第一个自定义字符lcd_wcmd(0x40); //"01 000 000" 第1行地址 (D7D6为地址设定命令形式 D5D4D3为字符存放位置(0--7),D2D1D0为字符行地址(0--7))lcd_wdat(0x1f); //"XXX 11111" 第1行数据(D7D6D5为XXX,表示为任意数(一般用000),D4D3D2D1D0为字符行数据(1-点亮,0-熄灭) lcd_wcmd(0x41); //"01 000 001" 第2行地址lcd_wdat(0x11); //"XXX 10001" 第2行数据lcd_wcmd(0x42); //"01 000 010" 第3行地址lcd_wdat(0x15); //"XXX 10101" 第3行数据lcd_wcmd(0x43); //"01 000 011" 第4行地址lcd_wdat(0x11); //"XXX 10001" 第4行数据lcd_wcmd(0x44); //"01 000 100" 第5行地址lcd_wdat(0x1f); //"XXX 11111" 第5行数据lcd_wcmd(0x45); //"01 000 101" 第6行地址lcd_wdat(0x0a); //"XXX 01010" 第6行数据lcd_wcmd(0x46); //"01 000 110" 第7行地址lcd_wdat(0x1f); //"XXX 11111" 第7行数据lcd_wcmd(0x47); //"01 000 111" 第8行地址lcd_wdat(0x00); //"XXX 00000" 第8行数据//第二个自定义字符lcd_wcmd(0x48); //"01 001 000" 第1行地址lcd_wdat(0x01); //"XXX 00001" 第1行数据lcd_wcmd(0x49); //"01 001 001" 第2行地址lcd_wdat(0x1b); //"XXX 11011" 第2行数据lcd_wcmd(0x4a); //"01 001 010" 第3行地址lcd_wdat(0x1d); //"XXX 11101" 第3行数据lcd_wcmd(0x4b); //"01 001 011" 第4行地址lcd_wdat(0x19); //"XXX 11001" 第4行数据lcd_wcmd(0x4c); //"01 001 100" 第5行地址lcd_wdat(0x1d); //"XXX 11101" 第5行数据lcd_wcmd(0x4d); //"01 001 101" 第6行地址lcd_wdat(0x1b); //"XXX 11011" 第6行数据lcd_wcmd(0x4e); //"01 001 110" 第7行地址lcd_wdat(0x01); //"XXX 00001" 第7行数据lcd_wcmd(0x4f); //"01 001 111" 第8行地址lcd_wdat(0x00); //"XXX 00000" 第8行数据}//LCD初始化设定void lcd_init(){lcd_wcmd(0x38); //设置LCD为16X2显示,5X7点阵,八位数据借口delay(1);lcd_wcmd(0x0c); //LCD开显示及光标设置(光标不闪烁,不显示"-")delay(1);lcd_wcmd(0x06); //LCD显示光标移动设置(光标地址指针加1,整屏显示不移动)delay(1);lcd_wcmd(0x01); //清除LCD的显示内容delay(1);}//闰年的计算bit leap_year(){bit leap;if((year%4==0&&year%100!=0)||year%400==0)//闰年的条件leap=1;elseleap=0;return leap;}//星期的自动运算和处理unsigned char week_proc(){ unsigned char num_leap;unsigned char c;num_leap=year/4-year/100+year/400;//自00年起到year所经历的闰年数if( leap_year()&& month=2 ) //既是闰年且是1月和2月c=5;elsec=6;week=(year+para_month[month]+date+num_leap+c)%7;//计算对应的星期return week;}//更新显示缓冲区void update_disbuf(unsigned char t1,unsigned char t2[],unsigned char dis_h,unsigned char dis_m,unsigned char dis_s){ dis_buf1[0]=t1; //dis_buf1[1]=0x20; //空格dis_buf1[2]=50; //'2'dis_buf1[3]=48; //'0'dis_buf1[4]=year/10+48;dis_buf1[5]=year%10+48;dis_buf1[6]=0x2d;dis_buf1[7]=month/10+48;dis_buf1[8]=month%10+48;dis_buf1[9]=0x2d; //'-'dis_buf1[10]=date/10+48;dis_buf1[11]=date%10+48;dis_buf1[12]=0x20;dis_buf1[13]=dis_week[4*week];dis_buf1[14]=dis_week[4*week+1];dis_buf1[15]=dis_week[4*week+2];dis_buf2[0]=t2[0];dis_buf2[1]=t2[1];dis_buf2[2]=t2[2];dis_buf2[3]=t2[3];dis_buf2[4]=t2[4];dis_buf2[5]=t2[5];dis_buf2[6]=0x20; //空格if (alarm)dis_buf2[7]=0x01; //alarm=1,显示闹钟启用标致(第二个自定义字符)elsedis_buf2[7]=0x20; //alarm=0,不显示闹钟启用标致dis_buf2[8]=dis_h/10+48;dis_buf2[9]=dis_h%10+48;dis_buf2[10]=0x3a; //':'dis_buf2[11]=dis_m/10+48;dis_buf2[12]=dis_m%10+48;dis_buf2[13]=0x3a;dis_buf2[14]=dis_s/10+48;dis_buf2[15]=dis_s%10+48;}//时间和日期处理程序void pro_timedate(){sec++;if(sec > 59){sec = 0;min++;if(min>59){min=0;hour++;if(hour>23){hour=0;date++;if(month==1||month==3||month==5||month==7||month==8||month==10||month== 12)if (date>31){date=1;month++;} //大月31天if(month==4||month==6||month==9||month==11)if (date>30){date=1;month++;} //小月30天if (month==2){if( leap_year())//闰年的条件{if (date>29){date=1;month++;}} //闰年2月为29天else{if (date>28){date=1;month++;}} //平年2月为28天}if (month>12) {month=1;year++;}if (year>99) year=0;}}}week_proc();if (sec==armsec && min==armmin &&hour==armhour){if (alarm)TR1=1; //闹钟启用时,报警时间到,启动Timer1}}//显示处理程序void pro_display(){ unsigned char i;lcd_pos(0x00);for (i=0;i=15;i++){lcd_wdat(dis_buf1[i]);}lcd_pos(0x40);for (i=0;i=15;i++){lcd_wdat(dis_buf2[i]);}}//Timer0中断处理程序,秒的产生void timer0() interrupt 1{TH0=0xdc; //Timer0置10ms定时初值dc00H(2^16=65536D,dc00H=56320D)TL0=0x00; //定时时间=(65536-56320)*(1/11.0592)*12=10ms (f0=11.0592Mhz)sec100++;if(sec100 >= 100) //1秒时间 (100*10ms=1000ms=1s){sec100 = 0;pro_timedate();//调用时间和日期处理程序}if(sec&0x01) / /"willar"闪一秒,停一秒update_disbuf(0x00," ",hour,min,sec); //0x0 0表示显示00位置的自定义字符elseupdate_disbuf(0x00,"willar",hour,min,sec);pro_display(); //调用显示处理函数}//按键扫描程序unsigned char scan_key(){skey=0x00; //给变量vkey置初值skey|=PRE; //读取PRE键的状态skey=skey<<1; //将PRE键的状态存于skey的B1位skey|=SET; //读取SET键的状态,并存于skey的B0位return skey; //返回skey的键值(即PRE,SET的状态)//外部中断INT0中断处理程序void int0() interrupt 0{TR0=0;//禁止Timer0IE=0;//禁止中断lcd_wcmd(0x0e); //显示光标"_",整个光标不闪烁alarm=1;update_disbuf(0x50,"alarm:",armhour,armmin,armsec); //更新显示数据,0x50表示要显示"P"pro_display(); //调用显示处理程序lcd_pos(0x47); //使光标位于第一个调整项下flag=0;vkey=0x03;while(flag^0x0a){skey = scan_key(); //扫描按键状态if (skey^vkey) //若skey与vkey相同,跳出循环,相异执行循环体{ delay(10); //去按键抖动skey = scan_key(); //转回扫描按键状态if (skey^vkey) //若skey与vkey相同,跳出循环,相异执行循环体{ vkey=skey; //将skey的值付给vkeyif (skey==0x01) //PRE 键按下{ flag++; / /调整标志位加1switch (flag) //将光标置于相应调整位置{cas e 1: lcd_pos(0x49);break; //光标置小时报警设置位置cas e 2: lcd_pos(0x4c);break; //光标置分钟报警设置位置cas e 3: lcd_pos(0x4f);break; //光标置秒时报警设置位置cas e 4: update_disbuf(0x50,"time: ",hour,min,sec);pro_display();lcd_pos(0x05);break; //光标置年调整位置cas e 5: lcd_pos(0x08);break; //光标置月调整位置cas e 6: lcd_pos(0x0b);break; //光标置日调整位置cas e 7: lcd_pos(0x49);break; //光标置时调整位置cas e 8: lcd_pos(0x4c);break; //光标置分调整位置cas e 9: lcd_pos(0x4f);break; //光标置秒调整位置def ault:break;}}if(skey==0x02) //SET键按下{ pro_key();//转设置按键处理程序}}}}lcd_wcmd(0x0c); //设置LCD开显示及光标不闪烁,不显示"-"lcd_wcmd(0x01); //清除LCD的显示内容IE=0x8f; / /CPU开中断,INT0,INT1,开中断TR0=1;//Timer0启动}//主程序,初始化及初值设定void main(){lcd_init(); //初始化LCDlcd_sef_chr(); //写入自定义字符号hour=0;min=0;sec=0; //开机时的时,分,秒显示armhour=0;armmin=0;armsec=0; //开机时的时,分,秒报警初值year= 5; month=1;date=1; //开机时的年,月,日,星期显示week_proc();alarm=1; //初始开机,启用闹钟IE = 0x8f; //CPU开中断,INT0,INT1,Timer0,Timer1开中断IP = 0x04; //设置INT0为中断最高优先级IT0=0;IT1=0; //外部INT0,INT1设置为电平触发方式(注意,触发不要选边沿方式,易误动) TMOD = 0x11; //Timer0,Timer1工作于模式1, 16位定时方式TH0 = 0xdc;TL0 = 0x00; //Timer0置10ms定时初值TH1 = 0xff;TL1 = 0x00; //Timer1置初值TR0 = 1; //Timer0启动TR1 = 0;while(1);}//设置按键处理程序void pro_key(){switch (flag){case 0:alarm=!alarm; //启用或关闭闹钟(alarm=1:启用,alarm=0:关闭)update_disbuf(0x50,"alarm:",armhour,armmin,ar msec); //更新显示数据pro_display();//调用显示处理lcd_pos(0x47);break;//光标回到原调整位置case 1:armhour++;if (armhour>23) armhour=0;update_disbuf(0x50,"alarm:",armhour,armmin,ar msec); //更新显示数据pro_display();//调用显示处理lcd_pos(0x49);break;//光标回到原调整位置case 2:armmin++;if (armmin>59) armmin=0;update_disbuf(0x50,"alarm:",armhour,armmin,ar msec);pro_display();lcd_pos(0x4c);break;case 3:armsec++;if (armsec>59) armsec=0;update_disbuf(0x50,"alarm:",armhour,armmin,ar msec);pro_display();lcd_pos(0x4f);break;case 4:year++;if (year> 99) year= 0;week_proc();//星期自动运算update_disbuf(0x50,"time:",hour,min,sec);pro_display();lcd_pos(0x05);break;case 5:month++;if (month>12) month=1;week_proc();//星期自动运算update_disbuf(0x50,"time:",hour,min,sec);pro_display();lcd_pos(0x08);break;case 6:date++;if(month==1||month==3||month==5||month==7||month==8||month==10||month== 12)if (date>31) date=1; //大月31天if(month==4||month==6||month==9||month==11)if (date>30) date=1; //小月30天if (month==2){if(leap_year())//闰年的条件{if (date>29) date=1;} //闰年2月为29天else{if (date>28) date=1;}} //平年2月为28天week_proc();//星期自动运算update_disbuf(0x50,"time:",hour,min,sec);pro_display();lcd_pos(0x0b);break;case 7:hour++;if (hour>23) hour=0;update_disbuf(0x50,"time:",hour,min,sec);pro_display();lcd_pos(0x49);break;case 8:min++;if (min>59) min=0;update_disbuf(0x50,"time:",hour,min,sec);pro_display();lcd_pos(0x4c);break;case 9:sec++;if (sec>59) sec=0;update_disbuf(0x50,"time: ",hour,min,sec);pro_display();lcd_pos(0x4f);break;default:break ;}}//Timer1中断处理程序,产生报警的声音void timer1() interrupt 3{TH1=0xff;TL1=0x00;SPK=~SPK;}//外部中断INT1中断处理程序,停止报警声音void int1() interrupt 2{if(TR1)TR1=0;}//DS1302时钟程序#include <stc89c52.h>#include <intrins.h>#define uchar unsigned char#define uint unsigned int/******************************************************************** ///少占鱼制作河北正定欢迎您长沙航空职业技术学院//2010 年QQ:411656434//版权所有:#define LCD1602_RS P2_5 //定义引脚#define LCD1602_RW P2_6#define LCD1602_E P2_7#define LCD1602_IO P0#define Busy 0x80 //用于检测LCD1602状态字中的Busy标识const uchar num[]=" 3456789+";uchar code a[] = {" E N v"};void WriteData(uchar DAT);void WriteCommand(uchar command,BuysC);uchar ReadData(void);void Readbusy(void);void LCD1602_Init(void);void DisplayOneChar(uchar X, uchar Y, uchar DData);void Displaystring(uchar X, uchar Y, uchar *DData);void Delay5Ms(void);void Delay400Ms(void);void delayms(uint);void delays(uint m) ;void delayus(uchar x) ;sbit DS1302_CLK =P2^0;// P1^0;sbit DS1302_IO =P2^1;// P1^1;sbit DS1302_RST =P2^2;// P1^2;uchar shuju;unsigned char time[]={0x11,0x03,0x28,0x01,0x12,0x39,0x00};// 初始化时间年月日星期时分秒uchar Display_Buffer[12]={"12:25:00"};//时、分、秒的格式uchar riqi[12]={"11-03-28"};//年、月、日的格式uchar xingqi[5]="week";//星期unsigned char second,minute,hour,week,day,month,year;/******************1602函数********************************//******************************************************************** /void delays(uint m){uint i,j;for(i=0;i<m;i++){for(j=0;j<1000;j++){;}}}void Delay(void){unsigned char i;unsigned int j;for(i=0;i<200;i++)for(j=300;j>0;j--);/******************************************************************** *********函数功能:向DS1302送一字节数据子程序入口参数:出口参数:********************************************************************* ********/void InputByte(unsigned char BYTE){char i;for(i=8;i>0;i--){ //前面在read_ds1302()函数里已经把CLK清0了DS1302_CLK=0;//这里再清0一次,看着清楚。
用DS1302与LCD1602可调数字万年历课程设计
数字开发与实践课程设计题目:用DS1302与LCD1602设计可调式电子日历时钟班级:姓名:学号:学院:二O一二年六月五日用DS1302与LCD1602设计的可调式电子日历时钟一、总体设计1.1、设计目的为巩固所学的单片机知识,把所学理论运用到实践中,用LCD1602与DS1302 设计可调式电子日历时钟。
1.2、设计要求(1)显示:年、月、日、时、分、秒和星期;(2)设置年、月、日、时、分、秒和星期的初始状态;(3)能够用4个按键调整日历时钟的年、月、日、时、分、秒和星期;完成可调式电子日历时钟的硬件和软件的设计,包括单片机的相关内容;日历时钟模块的设计,液晶显示模块的设计,按键模块的设计。
控制程序的编写等。
备注:本程序另外添加了每到上午8:10和下午2:10的闹钟提醒功能。
1.3、系统基本方案选择和论证1.3.1、单片机芯片的选择方案方案一:采用89C51芯片作为硬件核心,采用Flash ROM,内部具有4KB ROM 存储空间,能于3V的超低压工作,而且与MCS-51系列单片机完全兼容。
方案二:采用STC12C5A60S2系列单片机是宏晶科技生产的单时钟/机器周期(1T)的单片机,是高速/低功耗/超强抗干扰的新一代8051单片机,指令代码完全兼容传统8051,但速度快8-12倍。
内部集成MAX810专用复位电路,2路PWM,8路高速10位A/D转换(250K/S),针对电机控制,强干扰场合。
但造价较高。
1.3.2 、显示模块选择方案和论证:方案一:采用点阵式数码管显示,点阵式数码管是由八行八列的发光二极管组成,对于显示文字比较适合,如采用显示数字显得太浪费,且价格也相对较高。
所以不用此种作为显示。
方案二:采用LED数码管动态扫描,虽然LED数码管价格适中,但要显示多个数字所需要的个数偏多,功耗较大,显示出来的只是拼音,而不是汉字。
所以也不用此种作为显示。
方案三:采用LCD液晶显示屏,液晶显示屏的显示功能强大,可显示大量字符,且视觉效果较好,外形美观。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
/*========================================================== ==使用1602液晶显示DS1302+S51时钟+温度显示zhaojun 2007/06/29=========================================================== ===声明:1. 1602驱动程序照搬明皓的,非常好用2. DS1302驱动程序是参考网友修改而来NS1602R(16*2)模拟口线接线方式连接线图:---------------------------------------------------| LCM-----51 | LCM-----51|LCM------51 || ----------------------------------------------- || DB0-----P0.0 | DB4-----P0.4 | RS-------P2.0 || DB1-----P0.1 | DB5-----P0.5 | RW-------P2.1 || DB2-----P0.2 | DB6-----P0.6 | E--------P2.2 || DB3-----P0.3 | DB7-----P0.7 | VLCD接1K电阻到GND |---------------------------------------------------DS1302 接线图Vcc2 CLK I/O /RST| | | |---------------| 8 7 6 5 || DS1302 || || 1 2 3 4 |---------------| | | |VCC1 GND1. 脚接+5V 2,3. 脚32768HZ晶振4. 脚接地5. 脚接S51的P1.2 6. 脚接S51的P1.1 7. 接S51的P1.08. 脚接后备电源,可以接老计算机主板上的3.6V电池,也可以通过二级管隔离接一个大容量电解电容电压在2.5V以上即可维持按键说明:1. 共三个键,低电平有效2. P1.4 和P1.5 同时按:初始化3. P1.6 端口按键:选择要调整的项目4. P1.5 端口按键:增加;P1.4端口按键:减少[注:AT89S51使用12M晶振]源代码:=================定义与申明=========================================================== ==*/#include "regx51.h"#include "string.h"#include "intrins.h"#define uchar unsigned char#define uint unsigned inttypedef unsigned char byte;typedef unsigned int word;//*********** 1602引脚定义引脚#define LCM_RS P2_0 // 数据/命令选择信号#define LCM_RW P2_1 // 读/写选择信号#define LCM_E P2_2 // 使能信号//*********** DS1302 时间显示定义部分sbit T_CLK=P1^0; //串行时钟输入sbit T_IO =P1^1; //串行数据端口sbit T_RST=P1^2; //复位端口//*********** 18B20温度显示定义部分sbit DQ=P3^3; //18B20 接P33口sbit ACC0=ACC^0;sbit ACC7=ACC^7;#define LCM_Data P0 //显示数据端口#define Busy 0x80 //用于检测LCM状态字中的Busy标识uchar id,timecount; //全局变量bit flag,sflag; //flag是时钟冒号闪烁标志,sflag是温度负号显示标志bit sec,min,hour,year,mon,day,weekk; //闪烁标志位//*********************函数申明void Disp_line1(void); // 显示屏幕第一行void Disp_line2(void); // 显示屏幕第二行void id_case1_key(); // id为1时的下一级选择void Set(uchar,uchar); // 根据选择调整相应项目void RTInputByte(uchar); /* 输入1Byte */uchar RTOutputByte(void); /* 输出1Byte */void W1302(uchar, uchar); // 向DS1302写入一个字节uchar R1302(uchar); // 从DS1302读出一个字节void Set1302(uchar * ); // 设置时间//******* 1602LCD驱动********************************************************** void WriteDataLCM(uchar WDLCM); //写数据void WriteCommandLCM(uchar WCLCM,BuysC); //写指令uchar ReadStatusLCM(void); //读状态void LCMInit(void); //LCM初始化void DisplayOneChar(uchar X, uchar Y, uchar DData); //按指定位置显示一个字符void DisplayListChar(uchar X, uchar Y, uchar code *DData); //按指定位置显示一串字符void Delay5Ms(void); //5ms延时void Delay400Ms(void); //400ms延时Read_Temperature(char,char);//温度显示void mychar(void); //显示自定义字符void adjust_res(char res); //res 分别等于0x1f, 0x3f, 0x5f 温度读数分辨率分别对应// 0.5, 0.25, 0.125//初始化后设置为:07年07月04日星期3 12点00分00秒// 12:00:00 XX. C// 07/07/04 Week.3unsigned char inittime[7]={0x00,0x00,0x12,0x04,0x07,0x03,0x07};// 秒分钟小时日月星期年uchar code week[]={"Week."};//星期显示//========================= 主函数======================================================= /*****************************************************函数名:main()功能:主函数说明:入口参数:无返回值:无*****************************************************/void main(void){Delay400Ms(); //启动等待,等LCM讲入工作状态LCMInit(); //LCM初始化Delay5Ms(); //延时片刻(可不要)mychar(); //显示自定义字符TMOD=0x01; //选择定时模式TH0=(65535-50000)/256;//取定时初值TL0=(65535-50000)%256;EA=1; //开中断TR0=1;ET0=1;W1302(0x90,0xa5); //打开充电二级管一个二级管串联一个2K电阻W1302(0x8e,0x80); //写保护,禁止写操作adjust_res(0x5f); //调整18B20的分辨率0x1f:0.5; 0x3f:0.25; 0x5f:0.125 while(1){if ((P1_4|P1_5)==0) // 初始化同时按下P1_4、P1_5{Delay5Ms(); // 适当延时,消除抖动if ((P1_4|P1_5)==0) Set1302(inittime); // 显示初始值}if (P1_6==0) // 设置和选择项目键{Delay5Ms(); // 适当延时,消除抖动if(P1_6==0){id++;if(id>7) id=0;} // 7个可调节项目循环调节while(P1_6==0);}switch(id) // 跳转到对应的项目进行设置{case 0:sec=0;Disp_line1(); Disp_line2();break;case 1: //调节年year=1;//设置年闪烁标志位Disp_line1(); Disp_line2();id_case1_key();break;case 2: //调节月year=0;mon=1;//设置月闪烁标志位Disp_line1(); Disp_line2();id_case1_key();break;case 3: //调节日mon=0;day=1;//设置日闪烁标志位Disp_line1(); Disp_line2();id_case1_key();break;case 4: //调节星期day=0;weekk=1;//设置星期闪烁标志位Disp_line1(); Disp_line2();id_case1_key();break;case 5: //调节小时weekk=0;hour=1;//设置小时闪烁标志位Disp_line1(); Disp_line2();id_case1_key();break;case 6: //调节分钟hour=0;min=1;//设置分钟闪烁标志位Disp_line1(); Disp_line2();id_case1_key();break;case 7: //调节秒min=0;sec=1;//设置秒钟闪烁标志位Disp_line1(); Disp_line2();id_case1_key();break;}}}//================================== 定时中断============================================= /*****************************************************函数名:void t0()功能:时间工作时,冒号闪烁说明:T0中断入口,方式1入口参数:无返回值:无*****************************************************/void t0(void) interrupt 1 using 0{TH0=(65535-50000)/256; //取50ms定时初值TL0=(65535-50000)%256;timecount++;if(timecount>9){timecount=0; //计时到,从先开始flag=~flag; //标志位取反}}//==================================== 项目设置=========================================== /*****************************************************函数名:void id_case1_key()功能:项目设置加减控制说明:P1.5和P1.4 <==> +和-入口参数:无返回值:无*****************************************************/ //id为1时的下一级选择void id_case1_key(){if (P1_5==0) //P1_5有按下,则数值增加(+){Delay5Ms(); //适当延时,消除抖动if(P1_5==0) Set(id,0); //根据选择调整相应项目if(id!=7) while(P1_5==0);}if (P1_4==0) //P1_4有按下,则数值减少(-){Delay5Ms(); //适当延时,消除抖动if(P1_4==0) Set(id,1); //根据选择调整相应项目if(id!=7) while(P1_4==0);}}/***************************************************** 函数名:void Set()功能:项目设置说明:sel_1=0时,数值加;sel_1=1时,数值减入口参数:sel和sel_1返回值:无*****************************************************/ //根据选择调整相应项目并写入DS1302void Set(uchar sel,uchar sel_1){signed char address,item;signed char max,mini;//偶数指令是写,奇数指令是读//最大值与最小值限定if(sel==7) {address=0x80; max=00;mini=0;} //秒if(sel==6) {address=0x82; max=59;mini=0;} //分钟if(sel==5) {address=0x84; max=23;mini=0;} //小时if(sel==3) {address=0x86; max=31;mini=1;} //日if(sel==2) {address=0x88; max=12;mini=1;} //月if(sel==1) {address=0x8c; max=99;mini=0;} //年if(sel==4) {address=0x8a; max=07;mini=1;} //星期//先从1302中读出数据,把数据转换成十进制进行加减设置;后从先转换回来写入1302中item=R1302(address+1)/16*10+R1302(address+1)%16;//从1302中读出1字节,再转换成十进制if (sel_1==0) item++; else item--; //sel_1=0则加,sel_1=1则减if(item>max) item=mini; //大于最大值,则赋最小值(循环)if(item<mini) item=max; //小于最小值,则赋最大值(循环)W1302(0x8e,0x00); //允许写操作W1302(address,item/10*16+item%10);//把调节好的十进制数据转换成十六进制后写入1302中W1302(0x8e,0x80); //写保护,禁止写操作}//========================================================== =============================/*****************************************************函数名:void Disp_line1()功能:显示时间和温度(XX:XX:XX XX.X C)说明:第一行显示数据处理入口参数:无返回值:无*****************************************************///屏幕显示第一行: 时间和温度显示void Disp_line1(void){Read_Temperature(10,0); //温度显示//冒号闪烁if(flag==0){DisplayOneChar(3,0,0x3a); DisplayOneChar(6,0,0x3a);} else{DisplayOneChar(3,0,0x20); DisplayOneChar(6,0,0x20);}if(sec==1) //秒闪烁标志位{if(flag==1){DisplayOneChar(7,0,R1302(0x81)/16+0x30); //显示秒十位DisplayOneChar(8,0,R1302(0x81)%16+0x30); //显示秒个位}else{DisplayOneChar(7,0,0x20); //显示秒十位DisplayOneChar(8,0,0x20); //显示秒个位}}else{DisplayOneChar(7,0,R1302(0x81)/16+0x30); //显示秒十位DisplayOneChar(8,0,R1302(0x81)%16+0x30); //显示秒个位}if(min==1) //分钟闪烁标志位{if(flag==1){DisplayOneChar(4,0,R1302(0x83)/16+0x30); //显示分钟十位DisplayOneChar(5,0,R1302(0x83)%16+0x30); //显示分钟个位}else{DisplayOneChar(4,0,0x20); //显示分钟十位DisplayOneChar(5,0,0x20); //显示分钟个位}}else{DisplayOneChar(4,0,R1302(0x83)/16+0x30); //显示分钟十位DisplayOneChar(5,0,R1302(0x83)%16+0x30); //显示分钟个位}if(hour==1) //小时闪烁标志位{if(flag==1){DisplayOneChar(1,0,R1302(0x85)/16+0x30);//显示小时十位DisplayOneChar(2,0,R1302(0x85)%16+0x30);//显示小时个位}else{DisplayOneChar(1,0,0x20); //显示小时十位DisplayOneChar(2,0,0x20); //显示小时个位}}else{DisplayOneChar(1,0,R1302(0x85)/16+0x30);//显示小时十位DisplayOneChar(2,0,R1302(0x85)%16+0x30);//显示小时个位}}/*****************************************************函数名:void Disp_line2()功能:显示日期和星期(XX/XX/XX Week.X)说明:第二行显示数据处理入口参数:无返回值:无*****************************************************/// 屏幕显示第二行日期和星期void Disp_line2(void){DisplayOneChar(3,1,0x2f); //显示固定字符DisplayOneChar(6,1,0x2f);DisplayListChar(10,1,week);if(year==1) //年闪烁标志位{if(flag==1){DisplayOneChar(1,1,R1302(0x8d)/16+0x30);//显示年十位DisplayOneChar(2,1,R1302(0x8d)%16+0x30);//显示年个位}else{DisplayOneChar(1,1,0x20); //显示年十位DisplayOneChar(2,1,0x20); //显示年个位}}else{DisplayOneChar(1,1,R1302(0x8d)/16+0x30);//显示年十位DisplayOneChar(2,1,R1302(0x8d)%16+0x30);//显示年个位}if(mon==1) //月闪烁标志位{if(flag==1){DisplayOneChar(4,1,R1302(0x89)/16+0x30);//显示月十位DisplayOneChar(5,1,R1302(0x89)%16+0x30);//显示月个位}else{DisplayOneChar(4,1,0x20); //显示月十位DisplayOneChar(5,1,0x20); //显示月个位}}{DisplayOneChar(4,1,R1302(0x89)/16+0x30);//显示月十位DisplayOneChar(5,1,R1302(0x89)%16+0x30);//显示月个位}if(day==1) //日闪烁标志位{if(flag==1){DisplayOneChar(7,1,R1302(0x87)/16+0x30);//显示日十位DisplayOneChar(8,1,R1302(0x87)%16+0x30);//显示日个位}else{DisplayOneChar(7,1,0x20); //显示日十位DisplayOneChar(8,1,0x20); //显示日个位}}else{DisplayOneChar(7,1,R1302(0x87)/16+0x30);//显示日十位DisplayOneChar(8,1,R1302(0x87)%16+0x30);//显示日个位}if(weekk==1) //星期闪烁标志位{if(flag==1){DisplayOneChar(15,1,R1302(0x8b)%16+0x30);//显示星期}else{DisplayOneChar(15,1,0x20); //显示星期}}{DisplayOneChar(15,1,R1302(0x8b)%16+0x30);//显示星期}}//================================ LCM1602控制部分=======================================/*****************************************************函数名:void WriteDataLCM()功能:向LCM1602中写入数据说明:将形参WDLCM中的数据写入LCM中入口参数:WDLCM返回值:无*****************************************************///写数据void WriteDataLCM(uchar WDLCM){ReadStatusLCM(); //检测忙LCM_Data = WDLCM;//写入数据到LCMLCM_RS = 1;LCM_RW = 0;LCM_E = 0; //若晶振速度太高可以在这后加小的延时LCM_E = 0; //延时LCM_E = 1;}/*****************************************************函数名:void WriteCommandLCM()功能:向LCM1602中写入指令说明:向LCM中写入指令;如果BuysC=0时,忽略忙检测,如果BuysC=1时,不忽略忙检测入口参数:WCLCM,BuysC返回值:无*****************************************************///写指令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()功能:读状态说明:判断LCM的工作状态;也可以不用此函数,用一段延时程序代替入口参数:无返回值:LCM_Data*****************************************************///读状态uchar ReadStatusLCM(void){LCM_Data = 0xFF; //LCM数据口先置1LCM_RS = 0;LCM_RW = 1;LCM_E = 0;LCM_E = 0;LCM_E = 1;while (LCM_Data & Busy); //检测忙信号.如果忙,则不执行return(LCM_Data);//不忙返回读取数据}/*****************************************************函数名:void LCMInit()功能:初始化LCM1602说明:LCM在工作前先要对显示屏初始化,否则模块无法正常工作入口参数:无返回值:五*****************************************************///LCM初始化void LCMInit(void){LCM_Data = 0;WriteCommandLCM(0x38,0); // 三次显示模式设置,不检测忙信号Delay5Ms();WriteCommandLCM(0x38,0); // 0x38指令表示:8位数据显示模式,俩行多显示Delay5Ms();WriteCommandLCM(0x38,0);Delay5Ms();WriteCommandLCM(0x38,1); // 显示模式设置,开始要求每次检测忙信号WriteCommandLCM(0x08,1); // 关闭显示WriteCommandLCM(0x01,1); // 显示清屏WriteCommandLCM(0x06,1); // 显示光标移动设置WriteCommandLCM(0x0C,1); // 显示开及光标设置}/*****************************************************函数名:void DisplayOneChar()功能:按指定坐标中写入数据说明:X-横坐标,Y-纵坐标入口参数:X,Y,DData返回值:*****************************************************///按指定位置显示一个字符void DisplayOneChar(uchar X, uchar Y, uchar DData){Y &= 0x01;X &= 0x0F; //限制X不能大于15,Y不能大于1if (Y) X |= 0x40; //当要显示第二行时地址码+0x40;X |= 0x80; //算出指令码WriteCommandLCM(X, 0); //这里不检测忙信号,发送地址码WriteDataLCM(DData);}/*****************************************************函数名:void DisplayListChar()功能:向指定坐标中写入字符串说明:X-横坐标,Y-纵坐标入口参数:X,Y,*DData返回值:*****************************************************///按指定位置显示一串字符***原来的遇到空格0x20就不显示***void DisplayListChar(uchar X, uchar Y, uchar code *DData){uchar ListLength,j;ListLength = strlen(DData);//strlen:读取字符串的长度Y &= 0x1;X &= 0xF; //限制X不能大于15,Y不能大于1if (X <= 0xF) //X坐标应小于0xF{for(j=0;j<ListLength;j++){DisplayOneChar(X, Y, DData[j]); //显示单个字符X++;//横坐标加1,纵坐标不变}}}//=================================== 自定义字符==========================================/*****************************************************函数名:void mychar()功能:自定义字符--CGRAM说明:LCM1602字符库中没有温度符号,自定义温度符号入口参数:无返回值:无定义形式:1602中定义CGRAM的形式如下:---------------------------------------------------------------------------| CGRAM地址设置| 自定义的代码|| DB7 DB6 | DB5 DB4 DB3 | DB2 DB1 DB0 | DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 || 0 1 | 0 0 0 | X X X | 0 0 0 0 * 0 0 0 || 0 1 | 0 0 1 | X X X | 0 0 0 0 * 0 0 1 || ... | ... | ... | ... ... || 0 1 | 1 1 0 | X X X | 0 0 0 0 * 1 1 0 || 0 1 | 1 1 1 | X X X | 0 0 0 0 * 1 1 1 |---------------------------------------------------------------------------1. 1602共能定义8个5x8字符;2. CGRAM地址设置: X X X--DB2 DB1 DB0对应写入地址,1~8行;DB5 DB4 DB3对应自定义字符代码;DB7 DB6为指令码,不可变.3. 自定义的代码: 高4位DB7 DB6 DB5 DB4为0000时它的低3位DB2 DB1 DB0对应于第1-8个,DB3为无关项。