51单片机1302实时时钟1602显示程序

合集下载

DS1302+LCD1602显示程序

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时钟芯片与液晶1602的程序

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单片机程序

基于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);}}}。

51单片机,DS1302时钟,1602显示,可调时钟剖析

51单片机,DS1302时钟,1602显示,可调时钟剖析

基于proteus的51单片机仿真实例八十一、实时时钟芯片DS1302应用实例1、DS1302引脚排列:如下图引脚说明:1)Vcc1:后备电源,VCC2:主电源。

在主电源关闭的情况下,也能保持时钟的连续运行。

DS1302由Vcc1或Vcc2两者中的较大者供电。

当Vcc2大于Vcc1+0.2V时,Vcc2给DS1302供电。

当Vcc2小于Vcc1时,DS1302由Vcc1供电。

2)X1、X2:振荡源,外接32.768kHz 晶振。

3)RST:复位/片选线,通过把RST输入驱动置高电平来启动所有的数据传送。

RST输入有两种功能:首先,RST接通控制逻辑,允许地址/命令序列送入移位寄存器;其次,RST提供终止单字节或多字节数据的传送手段。

当RST为高电平时,所有的数据传送被初始化,允许对DS1302进行操作。

如果在传送过程中RST置为低电平,则会终止此次数据传送,I/O引脚变为高阻态。

上电运行时,在Vcc>2.0V之前,RST必须保持低电平。

只有在SCLK为低电平时,才能将RST置为高电平。

4)I/O为串行数据输入输出端(双向)。

5)SCLK为时钟输入端。

2、DS1302的控制字节DS1302 的控制字如下图所示。

控制字节的最高有效位(位7)必须是逻辑1,如果它为0,则不能把数据写入DS1302中,位6如果为0,则表示存取日历时钟数据,为1表示存取RAM数据;位5至位1指示操作单元的地址;最低有效位(位0)如为0表示要进行写操作,为1表示进行读操作,控制字节总是从最低位开始输出。

3、数据输入输出(I/O)在控制指令字输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,数据输入从低位即位0开始。

同样,在紧跟8位的控制指令字后的下一个SCLK脉冲的下降沿读出DS1302的数据,读出数据时从低位0位到高位7。

DS1302的寄存器DS1302有12个寄存器,其中有7个寄存器与日历、时钟相关,存放的数据位为BCD码形式,其日历、时间寄存器及其控制字见数据手册。

DS1302实时时钟模块,1602显示

DS1302实时时钟模块,1602显示

/******************* 说明:**************************将实时时钟数据通过LCD1602 显示基于51 单片机**************************************************/#include <reg52.h>#include <intrins.h>#define uchar unsigned char#define uint unsigned int uchar dis_time_buf[16]={0};//LCD1602 引脚定义// 采用8 位并行方式,DB0~DB7 连接至LCDDATA0~LCDDATA7sbit RS=P2A0;sbit RW=P2A1;sbit CS=P2A2;#define LCDDATA P0//DS1302 引脚定义sbit RST=P1A3;sbit IO=P1A2;sbit SCK=P1A1;//DS1302 地址定义#define ds1302_sec_add 0x80 // 秒数据地址#define ds1302_min_add 0x82 // 分数据地址#define ds1302_hr_add 0x84 // 时数据地址#define ds1302_date_add 0x86 // 日数据地址#define ds1302_month_add 0x88 // 月数据地址#define ds1302_day_add 0x8a // 星期数据地址#define ds1302_year_add 0x8c // 年数据地址#define ds1302_control_add 0x8e // 控制数据地址#define ds1302_charger_add 0x90#define ds1302_clkburst_add 0xbe// 初始时间定义uchar time_buf[8] = {0x20,0x10,0x06,0x01,0x23,0x59,0x55,0x02};// 初始时间2010年6月1号23 点59 分55 秒星期二// 功能:延时 1 毫秒// 入口参数:x// 出口参数:无//说明:当晶振为12M时,j<112 ;当晶振为11.0592M时,j<122void Delay_xms(uint x){uint i,j;for(i=0;i<x;i++)for(j=0;j<112;j++);// 功能:12us 延时//STC89C52为1T单片机,即1个时钟/机器周期,速度为AT89C52的12倍void Delay_xus(uint t){for(;t>0;t--){_nop_();}}//控制LCD写时序void LCD_en_write(void){CS=1;Delay_xus(20);CS=0;Delay_xus(20);}// 写指令函数void Write_Instruction(uchar command){RS=0;RW=0;CS=1;LCDDATA=command;LCD_en_write();// 写入指令数据}// 写数据函数void Write_Data(uchar Wdata){RS=1;RW=0;CS=1;LCDDATA=Wdata;LCD_en_write();// 写入数据}// 字符显示初始地址设置void LCD_SET_XY(uchar X,uchar Y){uchar address;if(Y==0) address=0x80+X;//Y=0, 表示在第一行显示,地址基数为0x80elseaddress=0xc0+X;//Y 非 0 时,表时在第二行显示,地址基数为 0xC0 Write_Instruction(address);// 写指令,设置显示初始地址}//在第X 行Y 列开始显示 Wdata 所对应的单个字符 void LCD_write_char(uchar X,uchar Y,uchar Wdata){LCD_SET_XY(X,Y)写 地址Write_Data(Wdata);// 写入当前字符并显示}// 清屏函数 void LCD_clear(void){Write_Instruction(0x01); Delay_xms(5);}// 显示屏初始化函数 void LCD_init(void){Write_Instruction(0x38); // 8bit interface,2line,5*7dotsDelay_xms(5);Write_Instruction(0x38); Delay_xms(5);Write_Instruction(0x38);Write_Instruction(0x08); //关显示,不显光标,光标不闪烁 Write_Instruction(0x01); //清屏 Delay_xms(5);//Write_Instruction(0x05); //Write_Instruction(0x06);//Write_Instruction(0x07);Delay_xms(5); // 写一字符,整屏右移 // 写一字符,整屏显示不移动// 写一字符,整屏左移//Write_Instruction(0x0B); Write_Instruction(0x0C);//Write_Instruction(0x0D); //Write_Instruction(0x0E); //Write_Instruction(0x0F); } //DS1302 初始化函数 void ds1302_init(void){Write_Instruction(0x04); // 写一字符,整屏显示不移动 // 关闭显示(不显示字符,只有背光亮) // 开显示,光标、闪烁都关闭// 开显示,不显示光标,但光标闪烁 // 开显示,显示光标,但光标不闪烁}//向DS1302写入一字节数据void ds1302_write_byte(uchar addr, uchar d){uchar i; RST=1;// 启动 DS1302 总线// 写入目标地址: addraddr = addr & 0xFE; // 最低位置零,寄存器 0 位为 0 时写,为 1 时读 for (i = 0; i < 8; i ++) {if (addr & 0x01) {IO=1;}else {IO=0;}SCK=1; //产生时钟 SCK=0;addr = addr >> 1;}// 写入数据: dfor (i = 0; i < 8; i ++) {if (d & 0x01) {IO=1;}else {IO=0;}SCK=1; // 产生时钟 SCK=0; d = d >> 1;}RST=O;〃停止 DS1302 总线}//从DS1302读出一字节数据uchar ds1302_read_byte(uchar addr) {uchar i,temp; RST=1;// 启动 DS1302 总线// 写入目标地址: addr addr = addr | 0x01;// 最低位置高,寄存器 0 位为 0 时写,为 1 时读for (i = 0; i < 8; i ++) {RST=0; SCK=0;//RST 脚置低 //SCK 脚置低if (addr & 0x01) { IO=1;}else { IO=0;}SCK=1;SCK=0;addr = addr >> 1;}// 输出数据:tempfor (i = 0; i < 8; i ++) { temp = temp >> 1; if (IO) {temp |= 0x80;}else {temp &= 0x7F; }SCK=1;SCK=0;}RST=0;//停止DS1302 总线return temp;}//向DS302写入时钟数据void ds1302_write_time(void) {ds1302_write_byte(ds1302_control_add,0x00); // 关闭写保护ds1302_write_byte(ds1302_sec_add,0x80); // 暂停时钟//ds1302_write_byte(ds1302_charger_add,0xa9); // 涓流充电ds1302_write_byte(ds1302_year_add,time_buf[1]); // 年ds1302_write_byte(ds1302_month_add,time_buf[2]); //月ds1302_write_byte(ds1302_date_add,time_buf[3]); // 日ds1302_write_byte(ds1302_hr_add,time_buf[4]); // 时ds1302_write_byte(ds1302_min_add,time_buf[5]); // 分ds1302_write_byte(ds1302_sec_add,time_buf[6]); // 秒ds1302_write_byte(ds1302_day_add,time_buf[7]); // 周ds1302_write_byte(ds1302_control_add,0x80); //打开写保护}//从DS302读出时钟数据void ds1302_read_time(void){time_buf[1]=ds1302_read_byte(ds1302_year_add); // 年time_buf[2]=ds1302_read_byte(ds1302_month_add); // 月time_buf[3]=ds1302_read_byte(ds1302_date_add); // 日time_buf[4]=ds1302_read_byte(ds1302_hr_add); // 时time_buf[5]=ds1302_read_byte(ds1302_min_add); // 分time_buf[6]=(ds1302_read_byte(ds1302_sec_add))&0x7f;// 秒,屏蔽秒的第7 位,避免超出59time_buf[7]=ds1302_read_byte(ds1302_day_add); // 周}void Display(void){LCD_write_char(3,0,dis_time_buf[0]+'0');LCD_write_char(4,0,dis_time_buf[1]+'0');LCD_write_char(5,0,dis_time_buf[2]+'0');LCD_write_char(6,0,dis_time_buf[3]+'0');LCD_write_char(7,0,'/');LCD_write_char(8,0,dis_time_buf[4]+'0');LCD_write_char(9,0,dis_time_buf[5]+'0');LCD_write_char(10,0,'/');LCD_write_char(11,0,dis_time_buf[6]+'0');LCD_write_char(12,0,dis_time_buf[7]+'0');LCD_write_char(15,0,dis_time_buf[14]+'0'); // 第 2 行显示LCD_write_char(3,1,dis_time_buf[8]+'0');LCD_write_char(4,1,dis_time_buf[9]+'0');LCD_write_char(5,1,':');LCD_write_char(6,1,dis_time_buf[10]+'0');LCD_write_char(7,1,dis_time_buf[11]+'0');LCD_write_char(8,1,':');LCD_write_char(9,1,dis_time_buf[12]+'0');LCD_write_char(10,1,dis_time_buf[13]+'0');}// 定时器中断函数void Timer2() interrupt 5// 定时器 2 是 5 号中断{static uchar t;TF2=0;t++;if(t==4) // 间隔200ms(50ms*4) 读取一次时间{t=0;ds1302_read_time(); // 读取时间dis_time_buf[0]=(time_buf[0]>>4); // 年dis_time_buf[1]=(time_buf[0]&0x0f);dis_time_buf[2]=(time_buf[1]>>4);dis_time_buf[3]=(time_buf[1]&0x0f);dis_time_buf[4]=(time_buf[2]>>4); // 月dis_time_buf[5]=(time_buf[2]&0x0f);dis_time_buf[6]=(time_buf[3]>>4); // 日dis_time_buf[7]=(time_buf[3]&0x0f);dis_time_buf[14]=(time_buf[7]&0x07); // 星期// 第 2 行显示dis_time_buf[8]=(time_buf[4]>>4); // 时dis_time_buf[9]=(time_buf[4]&0x0f);dis_time_buf[10]=(time_buf[5]>>4); // 分dis_time_buf[11]=(time_buf[5]&0x0f);dis_time_buf[12]=(time_buf[6]>>4); // 秒dis_time_buf[13]=(time_buf[6]&0x0f);}}// 定时器 2 初始化void Init_timer2(void){RCAP2H=0x3c;〃赋T2初始值0x3cb0,溢出20次为1秒,每次溢出时间为50ms RCAP2L=0xb0;TR2=1; //启动定时器 2ET2=1; // 打开定时器 2 中断EA=1; // 打开总中断}// 主函数void main(void){Delay_xms(50);// 等待系统稳定LCD_init(); //LCD 初始化LCD_clear(); // 清屏ds1302_init(); //DS1302 初始化Delay_xms(10);ds1302_write_time(); // 写入初始值Init_timer2(); // 定时器 2 初始化while(1){Display();}。

1602液晶显示DS1302实时时钟程序.

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一次,看着清楚。

基于51单片机DS1302LCD1602数字时钟显示

基于51单片机DS1302LCD1602数字时钟显示
#include <reg51.h>
#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在液晶1602显示程序

时钟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();}}}。

基于51单片机DS1302LCD1602数字时钟显示

基于51单片机DS1302LCD1602数字时钟显示
dispaly_string(0x00,lcd_buffer1);
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);

基于51单片机与DS1302时钟芯片和LCD1602液晶显示的数字时钟

基于51单片机与DS1302时钟芯片和LCD1602液晶显示的数字时钟

PROTEUS仿真图:KEIL C程序:#include <REGX52.H>#include "LCD1602.h"#include "DS1302.h"void Delay1ms(unsigned int count) {unsigned int i,j;for(i=0;i<count;i++)for(j=0;j<120;j++);}main(){SYSTEMTIME CurrentTime;LCD_Initial();Initial_DS1302();GotoXY(0,0);Print(" tian ma dian zi");GotoXY(0,1);Print("Time: ");while(1){DS1302_GetTime(&CurrentTime);TimeToStr(&CurrentTime);GotoXY(6,1);Print(CurrentTime.TimeString);Delay1ms(400);}}#ifndef LCD_CHAR_1602_2005_4_9#define LCD_CHAR_1602_2005_4_9#include <intrins.h>//Port Definitions********************************************************** sbit LcdRs = P2^0;sbit LcdRw = P2^1;sbit LcdEn = P2^2;sfr DBPort = 0x80; //P0=0x80,P1=0x90,P2=0xA0,P3=0xB0.数据端口//内部等待函数************************************************************************** unsigned char LCD_Wait(void){LcdRs=0;LcdRw=1; _nop_();LcdEn=1; _nop_();//while(DBPort&0x80);//在用Proteus仿真时,注意用屏蔽此语句,在调用GotoXY()时,会进入死循环,//可能在写该控制字时,该模块没有返回写入完备命令,即DBPort&0x80==0x80//实际硬件时打开此语句LcdEn=0;return DBPort;}//向LCD写入命令或数据************************************************************#define LCD_COMMAND 0 // Command#define LCD_DATA 1 // Data#define LCD_CLEAR_SCREEN 0x01 // 清屏#define LCD_HOMING 0x02 // 光标返回原点void LCD_Write(bit style, unsigned char input){LcdEn=0;LcdRs=style;LcdRw=0; _nop_();DBPort=input; _nop_();//注意顺序LcdEn=1; _nop_();//注意顺序LcdEn=0; _nop_();LCD_Wait();}//设置显示模式************************************************************ #define LCD_SHOW 0x04 //显示开#define LCD_HIDE 0x00 //显示关#define LCD_CURSOR 0x02 //显示光标#define LCD_NO_CURSOR 0x00 //无光标#define LCD_FLASH 0x01 //光标闪动#define LCD_NO_FLASH 0x00 //光标不闪动void LCD_SetDisplay(unsigned char DisplayMode){LCD_Write(LCD_COMMAND, 0x08|DisplayMode);}//设置输入模式************************************************************ #define LCD_AC_UP 0x02#define LCD_AC_DOWN 0x00 // default#define LCD_MOVE 0x01 // 画面可平移#define LCD_NO_MOVE 0x00 //defaultvoid LCD_SetInput(unsigned char InputMode){LCD_Write(LCD_COMMAND, 0x04|InputMode);}//移动光标或屏幕************************************************************ /*#define LCD_CURSOR 0x02#define LCD_SCREEN 0x08#define LCD_LEFT 0x00#define LCD_RIGHT 0x04void LCD_Move(unsigned char object, unsigned char direction){if(object==LCD_CURSOR)LCD_Write(LCD_COMMAND,0x10|direction);if(object==LCD_SCREEN)LCD_Write(LCD_COMMAND,0x18|direction);}*///初始化LCD************************************************************ void LCD_Initial(){LcdEn=0;LCD_Write(LCD_COMMAND,0x38); //8位数据端口,2行显示,5*7点阵LCD_Write(LCD_COMMAND,0x38);LCD_SetDisplay(LCD_SHOW|LCD_NO_CURSOR); //开启显示, 无光标LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN); //清屏LCD_SetInput(LCD_AC_UP|LCD_NO_MOVE); //AC递增, 画面不动}//************************************************************************ void GotoXY(unsigned char x, unsigned char y){if(y==0)LCD_Write(LCD_COMMAND,0x80|x);if(y==1)LCD_Write(LCD_COMMAND,0x80|(x-0x40));}void Print(unsigned char *str){while(*str!='\0'){LCD_Write(LCD_DATA,*str);str++;}}/*void LCD_LoadChar(unsigned char user[8], unsigned char place){unsigned char i;LCD_Write(LCD_COMMAND,0x40|(place*8));for(i=0; i<8; i++)LCD_Write(LCD_DATA,user[i]);}*///************************************************************************ #endif#ifndef _REAL_TIMER_DS1302_2003_7_21_#define _REAL_TIMER_DS1302_2003_7_21_sbit DS1302_CLK = P1^6; //实时时钟时钟线引脚sbit DS1302_IO = P1^7; //实时时钟数据线引脚sbit DS1302_RST = P1^5; //实时时钟复位线引脚sbit ACC0 = ACC^0;sbit ACC7 = ACC^7;typedef struct __SYSTEMTIME__{unsigned char Second;unsigned char Minute;unsigned char Hour;unsigned char Week;unsigned char Day;unsigned char Month;unsigned char Year;unsigned char DateString[9];unsigned char TimeString[9];}SYSTEMTIME; //定义的时间类型#define AM(X) X#define PM(X) (X+12) // 转成24小时制#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 DS1302_RAM(X) (0xC0+(X)*2) //用于计算 DS1302_RAM 地址的宏void DS1302InputByte(unsigned char d) //实时时钟写入一字节(内部函数) {unsigned char i;ACC = d;for(i=8; i>0; i--){DS1302_IO = ACC0; //相当于汇编中的 RRCDS1302_CLK = 1;DS1302_CLK = 0;ACC = ACC >> 1;}}unsigned char DS1302OutputByte(void) //实时时钟读取一字节(内部函数){unsigned char i;for(i=8; i>0; i--){ACC = ACC >>1; //相当于汇编中的 RRCACC7 = DS1302_IO;DS1302_CLK = 1;DS1302_CLK = 0;}return(ACC);}void Write1302(unsigned char ucAddr, unsigned char ucDa) //ucAddr: DS1302地址, ucData: 要写的数据{DS1302_RST = 0;DS1302_CLK = 0;DS1302_RST = 1;DS1302InputByte(ucAddr); // 地址,命令DS1302InputByte(ucDa); // 写1Byte数据DS1302_CLK = 1;DS1302_RST = 0;}unsigned char Read1302(unsigned char ucAddr) //读取DS1302某地址的数据{unsigned char ucData;DS1302_RST = 0;DS1302_CLK = 0;DS1302_RST = 1;DS1302InputByte(ucAddr|0x01); // 地址,命令ucData = DS1302OutputByte(); // 读1Byte数据DS1302_CLK = 1;DS1302_RST = 0;return(ucData);}void DS1302_SetProtect(bit flag) //是否写保护{if(flag)Write1302(0x8E,0x10);elseWrite1302(0x8E,0x00);}void DS1302_SetTime(unsigned char Address, unsigned char Value) // 设置时间函数{DS1302_SetProtect(0);Write1302(Address, ((Value/10)<<4 | (Value%10)));}void DS1302_GetTime(SYSTEMTIME *Time){unsigned char ReadValue;ReadValue = Read1302(DS1302_SECOND);Time->Second = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_MINUTE);Time->Minute = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_HOUR);Time->Hour = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_DAY);Time->Day = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_WEEK);Time->Week = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_MONTH);Time->Month = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_YEAR);Time->Year = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);}void DateToStr(SYSTEMTIME *Time){Time->DateString[0] = Time->Year/10 + '0';Time->DateString[1] = Time->Year%10 + '0';Time->DateString[2] = '-';Time->DateString[3] = Time->Month/10 + '0';Time->DateString[4] = Time->Month%10 + '0';Time->DateString[5] = '-';Time->DateString[6] = Time->Day/10 + '0';Time->DateString[7] = Time->Day%10 + '0';Time->DateString[8] = '\0';}void TimeToStr(SYSTEMTIME *Time){Time->TimeString[0] = Time->Hour/10 + '0';Time->TimeString[1] = Time->Hour%10 + '0';Time->TimeString[2] = ':';Time->TimeString[3] = Time->Minute/10 + '0';Time->TimeString[4] = Time->Minute%10 + '0';Time->TimeString[5] = ':';Time->TimeString[6] = Time->Second/10 + '0';Time->TimeString[7] = Time->Second%10 + '0';Time->DateString[8] = '\0';}void Initial_DS1302(void){unsigned char Second=Read1302(DS1302_SECOND);if(Second&0x80)DS1302_SetTime(DS1302_SECOND,0);}/****************************************************************************** **void BurstWrite1302(unsigned char *pWClock) //往DS1302写入时钟数据(多字节方式) {unsigned char i;Write1302(0x8e,0x00); // 控制命令,WP=0,写操作?DS1302_RST = 0;DS1302_CLK = 0;DS1302_RST = 1;DS1302InputByte(0xbe); // 0xbe:时钟多字节写命令for (i = 8; i>0; i--) //8Byte = 7Byte 时钟数据 + 1Byte 控制{DS1302InputByte(*pWClock); // 写1Byte数据pWClock++;}DS1302_CLK = 1;DS1302_RST = 0;}void BurstRead1302(unsigned char *pRClock) //读取DS1302时钟数据(时钟多字节方式){unsigned char i;DS1302_RST = 0;DS1302_CLK = 0;DS1302_RST = 1;DS1302InputByte(0xbf); // 0xbf:时钟多字节读命令for (i=8; i>0; i--){*pRClock = DS1302OutputByte(); // 读1Byte数据pRClock++;}DS1302_CLK = 1;DS1302_RST = 0;}void DS1302_TimeStop(bit flag) // 是否将时钟停止{unsigned char Data;Data=Read1302(DS1302_SECOND);DS1302_SetProtect(0);if(flag)Write1302(DS1302_SECOND, Data|0x80);elseWrite1302(DS1302_SECOND, Data&0x7F);}******************************************************************************* */#endif。

DS1302+1602时钟程序

DS1302+1602时钟程序

//寄存器选择位,将 RS 位定义为 P2.0 引脚 //读写选择位,将 RW 位定义为 P2.1 引脚 //使能信号位,将 E 位定义为 P2.2 引脚 //忙碌标志位,,将 BF 位定义为 P0.7 引脚
/***************************************************** 函数功能:延时 1ms (3j+2)*i=(3×33+2)×10=1010(微秒),可以认为是 1 毫秒
***************************************************/
void delay1ms()
{
unsigned char i,j;
for(i=0;i<10;i++)
for(j=0;j<33;j++)
;
}
/***************************************************** 函数功能:延时若干毫秒
for(i=0;i<8;i++) //连续读 8 个二进制位数据
{ dat>>=1;
if(DATA==1) //如果读出的数据是 1
dat|=0x80; //将 1 取出,写在 dat 的最高位
SCLK=1;
//将 SCLK 置于高电平,为下降沿读出
delaynus(2); //稍微等待
SCLK=0;
WriteSet1302(0x90,0xa5);
//打开充电功能 选择 2K 电阻充电方式
WriteSet1302(0x8E,0x80);
//根据写状态寄存器命令字,写入保护指令
*/

DS1302时钟 LCD1206 显示 C程序

DS1302时钟 LCD1206 显示 C程序

STC12C5A08AD 单片机DS1302 时钟芯片LCD1602 液晶显示#include <stc12c5a08ad.h> //stc单片机专用的头文件#include <reg52.h>#include <intrins.h>#define uchar unsigned char#define uint unsigned int#define ulong unsigned long#define dat P0 //定义LCD1602的数据口为P0 void delay(unsigned int xms ); //声明延时函数void delay2(unsigned int xms);void display(void); //显示程序void keyscan(void);sbit key0=P2^0;sbit key1=P2^1;sbit key2=P2^2;sbit key3=P2^3;sbit beep=P3^4;/****ds1302****/#define DS1302_SECOND_WRITE 0x80#define DS1302_MINUTE_WRITE 0x82#define DS1302_HOUR_WRITE 0x84#define DS1302_DAY_WRITE 0x86#define DS1302_MONTH_WRITE 0x88#define DS1302_WEEK_WRITE 0x8A#define DS1302_YEAR_WRITE 0x8Cvoid Set_MIN(uchar s);void Set_HR(uchar s);void Init_DS1302(void) ;void DS1302WriteByte(uchar dat);void DS1302Write(uchar cmd,uchar dat);uchar DS1302Read(uchar cmd);uchar DS1302Read_1(uchar cmd);uchar DS1302ReadByte();uchar DS1302ReadByte_1();sbit RST=P1^4;sbit SCLK=P3^6;sbit SDA=P3^7;/*** lcd1206***/sbit rs=P1^0; //定义RS口为P10sbit rw=P1^1; //定义RW口为P11sbit e=P1^2; //定义E口为P12void xianshi_sfm(uchar wei,uchar dat);void shj_1602(uchar a); //液晶写数据程序void int_1602(void); //液晶初始化void zhl_1602(uchar a); //液晶写指令程序uchar a,b,c,d;uchar code table0[7]={"time is"}; //定义LCD1602显示2行的字符uchar code table3[10]={"0123456789"};uchar code table4[1]={":"};/**************延时函数*****************/void delay(unsigned int xms) //延时函数,{unsigned int i,j ;for(i=xms;i>0;i--)for(j=110;j>0;j--);}/*****************LCD1602 显示程序******************************/void zhl_1602(uchar a) //写指令到LCM程序{// busy_1602(); //查询忙碌标志信号程序e=0;rs=0;rw=0;e=1;dat=a;delay(5);e=0;}void shj_1602(uchar a) //写数据到LCM程序{// busy_1602(); //查询忙碌标志信号程序e=0;rs=1;rw=0;e=1;dat=a;delay(5);e=0;}void int_1602(void) //启动LCM程序{zhl_1602(0x38); // 设置显示模式,数据接口位数zhl_1602(0x0c); // 设置显示开关,是否显示光标,是否闪动光标zhl_1602(0x06); // 设置光标移动方向左或右,设置所有文字是否移动}/*****************液晶LCD1602显示主程序程序***********/void display(void) //液晶显示程序{uchar i,ri,yue,nian; //定义计数值int_1602(); //初始化1602zhl_1602(0x80);delay(5); //写指令(11000000) 指定从第一行指针位置开始写for(i=0;i<7;i++) //发送数据第一行time is:{shj_1602(table0[i]);delay(5);}zhl_1602(0x80+10);delay(5); //for(i=0;i<1;i++) //发送数据第一行时间显示的“: ”{shj_1602(table4[i]);delay(5);}zhl_1602(0x80+13);delay(5); //for(i=0;i<1;i++) //发送数据第一行时间显示的“: ”{shj_1602(table4[i]);delay(5);}a=(DS1302Read(0x81)/16)*10+(DS1302Read(0x81)%16); //转换为十进制c=(DS1302Read(0x83)/16)*10+(DS1302Read(0x83)%16);d=(DS1302Read(0x85)/16)*10+(DS1302Read(0x85)%16);ri=(DS1302Read(0x87)/16)*10+(DS1302Read(0x87)%16);yue=(DS1302Read(0x89)/16)*10+(DS1302Read(0x89)%16);nian=(DS1302Read(0x8d)/16)*10+(DS1302Read(0x8d)%16);xianshi_sfm(8,d); // 时钟显示时delay(20);xianshi_sfm(11,c); // 时钟显示分delay(20);xianshi_sfm(14,a); // 时钟显示秒delay(20);xianshi_sfm(0X48,ri); // day 0X48 为换第二行写入显示年月日delay(20);xianshi_sfm(0X45,yue); // yuedelay(20);xianshi_sfm(0X42,nian); // niandelay(20);xianshi_sfm( 0x40,20); // 显示20 xx 年份的前缀}/*****时间显示子程序***/void xianshi_sfm(uchar wei,uchar dat){uchar shi,ge;shi=dat/10;ge=dat%10;zhl_1602(0x80+wei);//第一行显示+位选择delay(5);shj_1602(table3[shi]);delay(5);shj_1602(table3[ge]);delay(5);}/*************DS1302程序*************** /cmd: 要写入的控制字节dat: 读取的数据******uchar DS1302Read_1(uchar cmd)//十二小时制调用{uchar dat;RST=0; //////// 初始CE 线置为0SCLK=0; //////// 初始时钟线置为0RST=1; //////// 初始CE 置为 1 ,传输开始DS1302WriteByte(cmd); //////// 传输命令字,要读取的时间dat=DS1302ReadByte_1(); //////// 读取要得到的时间SCLK=1; //////// 时钟线拉高RST=0; //////// 读取结束,CE 置为0 ,结束数据的传输return dat; //////// 返回得到的时间/ / / / 日期}/********** 读操作************/uchar DS1302ReadByte_1() //十二小时制调用{uchar i,dat,dat1,dat2;delay(2);for(i=0;i<8;i++){dat>>=1; //////// 要返回的数据左移一位if(SDA==1) //////// 当数据线为高时,证明该位数据为1dat|=0x80; //////// 要传输数据的当前值置为1, 若不是则为0SCLK=1; // 拉高时钟线delay(5);SCLK=0; //////// 制造下降沿delay(5);}// RST=0; //////// 初始CE 线置为0dat1=dat-0x80; // -0x80 是设置12小时制后去掉”DS1302_HOUR_WRITE 0x84“设置的最高位1 以免影响取值错误否则时显示错误dat2=dat1/16; //数据进制转换dat1=dat1%16; //十六进制转十dat1=dat1+dat2*10;return (dat1); //////// 返回读取出的数据}/********** 读操作************/uchar DS1302Read(uchar cmd) //二四小时制调用{uchar dat;RST=0; //////// 初始CE 线置为0SCLK=0; //////// 初始时钟线置为0RST=1; //////// 初始CE 置为 1 ,传输开始DS1302WriteByte(cmd); //////// 传输命令字,要读取的时间dat=DS1302ReadByte(); //////// 读取要得到的时间SCLK=1; //////// 时钟线拉高RST=0; //////// 读取结束,CE 置为0 ,结束数据的传输return dat; //////// 返回得到的时间/ / / / 日期}/****写数据***/void DS1302Write(uchar cmd, uchar dat){RST=0; //////// 初始CE 线置为0SCLK=0; //////// 初始时钟线置为0RST=1; //////// 初始CE 置为1 ,传输开始DS1302WriteByte(cmd);DS1302WriteByte(dat); //////// 写入要修改的时SCLK=1; //////// 时钟线拉高RST=0; //////// 读取结束,CE 置为0 ,}/*******写操作*******/void DS1302WriteByte(uchar dat){uchar i;SCLK=0; //////// 初始时钟线置为0delay(5);for(i=0;i<8;i++) //////// 开始传输8 个字节的数据{SDA=dat&0x01; //////// 取最低位,注意DS130的数据和地址都是从最低位开始传输的delay(5);SCLK=1; //////// 时钟线拉高,制造上升沿,SDA 的数据被传输delay(5);SCLK=0; //////// 时钟线拉低,为下一个上升沿做准备dat>>=1; //////// 数据右移一位,准备传输下一位数据}// RST=0; //////// 初始CE 线置为0}/********** 读操作************/uchar DS1302ReadByte() //二四小时制调用{uchar i,dat;delay(2);for(i=0;i<8;i++){dat>>=1; //////// 要返回的数据左移一位if(SDA==1) //////// 当数据线为高时,证明该位数据为1dat|=0x80; //////// 要传输数据的当前值置为1, 若不是则为0SCLK=1; // 拉高时钟线delay(5);SCLK=0; //////// 制造下降沿delay(5);}RST=0; //////// 初始CE 线置为0return (dat); /}/*******DS1302初始化***********/void Init_DS1302(void){DS1302Write(0x8e,0x00); //////// 写保护关DS1302Write(DS1302_SECOND_WRITE,0x55); //////// 初始秒值为55DS1302Write(DS1302_MINUTE_WRITE,0x59); //////// 初始分钟值为59DS1302Write(0x84,0x23);////////24小时模式///若设置(0X84 0X92)初始为12小时模式,初始时间为12点,读程序时调用uchar DS1302Read_1(uchar cmd)DS1302Write(DS1302_DAY_WRITE,0x18); //年月日星期初值设置DS1302Write(DS1302_MONTH_WRITE,0x05);DS1302Write(DS1302_YEAR_WRITE,0x13);DS1302Write(DS1302_WEEK_WRITE,0x06);DS1302Write(0xc0,0xf0); //////// 初始化一次标示DS1302Write(0x8e,0x80); //开启写入保护}//主程序void main(){Init_DS1302();delay(5);while(1){display(); // 显示keyscan();}}/*****键控设置时间程序调整时,分的显示值可对时间校准***/void Set_MIN(uchar s) //1为分钟加,0为分钟减{unsigned char temp;DS1302Write(0x8E,0x00);//去除写保护temp=DS1302Read(0x83);if(s){temp+=1;if(temp>0x59)temp=0;if((temp&0x0f)>0x09) //if(temp%0x10>0x09) 当低四位大于9时temp=(temp+16)&0xf0; // temp=((temp+0x10) & 0xf0);高四位进1位低四位归零}else{if(temp>0) //temp-=1;else //TEMP 等于0 时;·temp=0x59;if((temp%0x10)>0x09) //减到低位为0后再减一次低位为1111,为15 取余运算后大于9 ,同时高位被低位借位减1,降了一个十位数temp=(temp&0xf0+0x09); //temp=((temp/0x10)*0x10 + 0x09) 则取高位值,低位置9,从而达到0至9循环}DS1302Write(0x82,temp);DS1302Write(0x8e,0x80);}void Set_HR(uchar s) //1为小时加,0为小时减{unsigned char temp;DS1302Write(0x8E,0x00);//去除写保护temp=DS1302Read(0x85);//小时数保存在低5位// temp<<=3;// temp>>=3;if(s){temp+=1;if(temp==0x0a) //加到0000 1010 时分位不需要10 手动加一操作时是按照2进制加一,芯片自动运行时按照BCD码进位的即低四位到9后加1 ,进位至高四位加1temp=0x10; //进一至十位BCD码if(temp==0x1a)temp=0x20;if(temp==0x24)temp=0;}else{ temp-=1;if(temp==0xff) //当为00000000 再减一位变成0XFFtemp=0x23; //改变0XFF 为自己需要的0X23 .3.2.1.0.23.22............... 循环调整if(temp==0x1f) //当20 (0010 0000)再减1时其实际值是0X1F(0001 1111 )temp=temp&0xf0+0x09; //舍弃低四位的值将其个位置9if(temp==0x0f)temp=0x09;}DS1302Write(0x84,temp);DS1302Write(0x8e,0x80); //写保护启动}void keyscan(){if(key0==0){delay(2);if(key0==0){ //分减更改Set_MIN(0);while(!key0);}}if(key1==0){delay(2);if(key1==0){ //分加更改Set_MIN(1);while(!key1);}}if(key2==0){delay(2);if(key2==0)Set_HR(0); //时减更改while(!key2);}if(key3==0){delay(2);if(key3==0)Set_HR(1); //时加更改while(!key3);}}。

基于ds1302的51单片机简易实时时钟-1602显示-源程序

基于ds1302的51单片机简易实时时钟-1602显示-源程序

==================主程序================= #include <reg51.h>。

#include "ds1302.h"#include "LCD1602.h"void change();uchar times[9];uchar date[9];main(){LCD_init();//LCD初始化init_1302(time_1302);gotoxy(1,1);LCD_display("Time:");gotoxy(1,2);LCD_display("Date:");times[8]='\0';//date[8]='\0';while(1){get_1302(time_1302);change();gotoxy(7,1);LCD_display(times);gotoxy(7,2);LCD_display(date);}}/*=========================== 转换子程序===========================*/void change(){// 时间的转换times[0]=time_1302[2]/10+'0';times[1]=time_1302[2]%10+'0';times[2]=':';times[3]=time_1302[1]/10+'0';times[4]=time_1302[1]%10+'0';times[5]=':';times[6]=time_1302[0]/10+'0';times[7]=time_1302[0]%10+'0';// 日期的转换date[0]=time_1302[6]/10+'0';date[1]=time_1302[6]%10+'0';date[2]='-';date[3]=time_1302[4]/10+'0';date[4]=time_1302[4]%10+'0';date[5]='-';date[6]=time_1302[3]/10+'0';date[7]=time_1302[3]%10+'0';}======================================================DS1302驱动程序=============#define uchar unsigned charuchar time_1302[7]={0x00,0x00,0x00,0x03,0x07,0x03,0x08};//设置时间初始值数组// 秒分时号月份星期年sbit T_IO=P1^0; //与硬件相关的连线clk为DS1302的时钟信号线sbit T_CLK=P1^1; //DAT为DS1302的I/O数据线sbit T_RST=P1^2; //RST为DS1302的RST信号线uchar bdata datbyte;sbit datbyte0=datbyte^0;sbit datbyte7=datbyte^7;void get_1302(uchar time[]);void write_ds1302(uchar dat);uchar r_1302(uchar add);void w_1302(uchar add,uchar dat);uchar read_ds1302(void);void init_1302(uchar *time);/*==========================================D S 1 3 0 2 初始化===========================================*/void init_1302(uchar *time){uchar i, add;//uchar time_bcd[7];add=0x80;//0写入,1读出w_1302(0x8e,0x00);for(i=0;i<7;i++){w_1302(add,*time);add+=2;time++;}w_1302(0x8e,0x80);}//===========================// 读取当前时间//===========================void get_1302(uchar time[]){uchar i;uchar add=0x81;w_1302(0x8e,0x00);for(i=0;i<7;i++){time[i]=r_1302(add);add+=2;}w_1302(0x8e,0x80);}/*================================= DS1302写入一个字节(上升沿有效)=================================*/void write_ds1302(uchar dat){uchar i;datbyte=dat;for(i=0;i<8;i++){T_IO=datbyte0;T_CLK=1;T_CLK=0;datbyte=datbyte>>1;}}/*======================================= DS1302读取一个字节(下降沿有效)=======================================*/uchar read_ds1302(void){uchar i;for(i=0;i<8;i++){datbyte=datbyte>>1;datbyte7=T_IO;T_CLK=1;T_CLK=0;}return(datbyte);}/*========================================= 指定位置读取数据=========================================*/uchar r_1302(uchar add){uchar temp,dat1,dat2;T_RST=0;T_CLK=0;T_RST=1;write_ds1302(add);temp=read_ds1302();T_CLK=1;T_RST=0;dat1=temp/16;dat2=temp%16;temp=dat1*10+dat2;return(temp);}/*========================================== 指定位置写入数据==========================================*/void w_1302(uchar add,uchar dat){T_RST=0;T_CLK=0;T_RST=1;write_ds1302(add);write_ds1302(dat/10<<4|dat%10);T_CLK=1;T_RST=0;}=========================================== =============LCD1602驱动程序================#define LCD_DB P0//定义LCD的数据端口sbit LCD_RS=P2^0;sbit LCD_RW=P2^1;sbit LCD_E=P2^2;#define uchar unsigned char#define uint unsigned int//===========延时子函数======================== void delay_lcd(uint x){uint i,j;for(i=x;i>0;i--)for(j=0;j<2;j++);}//==================写指令函数================= void LCD_write_command(uchar command){LCD_DB=command;LCD_RS=0;//指令LCD_RW=0;//写入LCD_E=1;LCD_E=0;delay_lcd(1);//等待执行完毕。

DS1302时钟LCD1602显示

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秒。

1602液晶显示DS1302实时时钟程序要点

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一次,看着清楚。

(完整word版)1602液晶时钟程序(51单片机)

(完整word版)1602液晶时钟程序(51单片机)

1602液晶时钟程序程序按郭天袢《新概念51单片机C语言教程》第十四章扩展显示年、月、日、星期调节功能。

1)时间显示在1602液晶上,并按秒实时更新2)能调节按键调整时、分、秒、年、月、日和星期3)每次按键按下时有短滴声响声4)断电后下次上电会接着上次断电前的时间数继续运行原理图如图//原代码如下:#include<reg52.h>//#include"24c02.h"#define uchar unsigned char#define uint unsigned int#include"24c02.h"sbit dula=P2^6;sbit wela=P2^7;sbit LCDEN=P3^4;sbit LCDRS=P3^5;sbit s1=P3^0;//定义按键--功能键sbit s2=P3^1;//定义按键--增大键sbit s3=P3^2;//定义按键--减小键sbit rd=P3^7;//按键公共脚sbit beep=P2^3;//定义蜂鸣器脚uchar count,s1_num;//定义中断次数计数变量功能键按键次数变量uchar week,day,month,year;//定义变量:星期日月年char miao,shi,fen;//定义秒分时变量uchar code table[]=" 2012-11-28 Wed";//void write_week(char we);//显示星期几函数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_com(uchar com) //液晶写命令函数{LCDRS=0;P0=com;delay(5);LCDEN=1;delay(5);LCDEN=0;}void write_date(uchar date) //液晶写数据函数{LCDRS=1;P0=date;delay(5);LCDEN=1;delay(5);LCDEN=0;}void write_week(char we) //写星期几显示函数{write_com(0x80+12);switch(we){case 1: write_date('M');delay(5); //星期一Mondaywrite_date('o');delay(5);write_date('n');delay(5);break;case 2: write_date('T');delay(5); //星期二Tuesdaywrite_date('u');delay(5);write_date('e');delay(5);break;case 3: write_date('W');delay(5); //Wednesdaywrite_date('e');delay(5);write_date('d');delay(5);break;case 4: write_date('T');delay(5); //Thursdaywrite_date('h');delay(5);write_date('u');delay(5);break;case 5: write_date('F');delay(5); //星期五Fridaywrite_date('r');delay(5);write_date('i');delay(5);break;case 6: write_date('S');delay(5); //星期六Saturdaywrite_date('a');delay(5);write_date('t');delay(5);break;case 7: write_date('S');delay(5); //星期日Sundaywrite_date('u');delay(5);write_date('n');delay(5);break;default: break;}}void write_sfm(uchar add,uchar date) //写时分秒函数{uchar shiwei,gewei;shiwei=date/10;gewei=date%10;write_com(0x80+0x40+add);//设置显示位置write_date(0x30+shiwei);//加上0x30是因为数字变成字符串需要加上0x30,看ASCII码值与字符的关系write_date(0x30+gewei);}void write_year_month_day(uchar add,uchar day) //写年月日数函数{uchar shi,ge;shi=day/10;ge=day%10;write_com(0x80+add);//设置显示位置write_date(0x30+shi);//加上0x30是因为数字变成字符串需要加上0x30,看ASCII码值与字符的关系write_date(0x30+ge);}void init() //初始化函数{uchar num;rd=0;beep=1;dula=0;wela=0;LCDEN=0;//将使能端置0以完成高脉冲fen=0;miao=0;shi=0;count=0;//计数初始为0init_24c02();write_com(0x38);//设置16*2显示,5*7点阵,8位数据接口write_com(0x0c);//设置开显示,不显示光标write_com(0x06);//写一个字符后地址指针自动加1write_com(0x01);//显示清0,数据指针清0write_com(0x80); //设置显示初始坐标for(num=0;num<15;num++) //显示年月日{write_date(table[num]);delay(5);}write_com(0x80+0x40+6); //写出时间显示部分的两个冒号write_date(0x3a);delay(5);write_com(0x80+0x40+9);write_date(0x3a);delay(5);miao=read_add(1);//开机上电时读取24c02 IIC的数据赋值fen=read_add(2);shi=read_add(3);week=read_add(4);//读取星期几day=read_add(5);//读取多少日month=read_add(6);year=read_add(7);write_sfm(10,miao);//分别送去液晶显示write_sfm(7,fen);write_sfm(4,shi);write_week(week);//开机从24c02读取的星期几数从新写入液晶显示出来write_year_month_day(9,day);write_year_month_day(6,month);write_year_month_day(3,year);//定时器初始化TMOD=0x01; //设置定时器0工作模式1TH0=(65536-45876)/256; //定时器装初值TL0=(65536-45876)%256;EA=1; //开总中断ET0=1; //打定时器0中断TR0=1; //启动定时器0}void keyscan() //按键扫描函数{if(s1==0){delay(5);if(s1==0){s1_num++; //功能键按下次数记录while(!s1); //按键释放确认di();if(s1_num==1) //只按一次按键时TR0=0; //关闭定时器write_com(0x80+0x40+11);write_com(0x0f); //打开光标闪烁}if(s1_num==2) //第二次按下光标闪烁定位到分钟位置{write_com(0x80+0x40+8);}if(s1_num==3) //第三次按下光标闪烁定位到小时位置{write_com(0x80+0x40+5);}/**************************************if(s1_num==4) //第三四次按下退出{s1_num=0;write_com(0x0c); //取消光标闪栎TR0=1; //启动定时器使时钟开始走}***************************************/if(s1_num==4) //光标处星期{write_com(0x80+14);}if(s1_num==5) //光标处日{write_com(0x80+10);}if(s1_num==6) //光标处月{write_com(0x80+7);}if(s1_num==7) //光标处年{write_com(0x80+4);}if(s1_num==8) //当第八次按功能键时退出光标闪烁及开始计时{s1_num=0;write_com(0x0c); //取消光标闪栎TR0=1; //启动定时器使时钟开始走}}if(s1_num!=0){if(s2==0)//增加键确认按下{delay(5);if(s2==0){while(!s2);di();if(s1_num==1){miao++;if(miao==60)miao=0;write_sfm(10,miao);write_com(0x80+0x40+11);write_add(1,miao);}if(s1_num==2){fen++;if(fen==60)fen=0;write_sfm(7,fen);write_com(0x80+0x40+8);write_add(2,fen);}if(s1_num==3){shi++;if(shi==24)shi=0;write_sfm(4,shi);write_com(0x80+0x40+5);write_add(3,shi);}if(s1_num==4)//按四次功能键后光标至星期几处,可调节星期几{week++;if(week==8)week=1;write_week(week);write_com(0x80+14); //写一个字符后光标会移一位,所以要重新定义光标位置write_add(4,week);}if(s1_num==5) //光标至显示日处,可调节多少日{day++;if(day==32)day=1;write_year_month_day(9,day);write_com(0x80+10);write_add(5,day);}if(s1_num==6) //光标至显示月处调节月份{month++;if(month==13)month=1;write_year_month_day(6,month);write_com(0x80+7);write_add(6,month);}if(s1_num==7){year++;if(year==100)year=00;write_year_month_day(3,year);write_com(0x80+4);write_add(7,year);}}}if(s3==0) //确认减小键被按下{delay(5);//按键防抖延时if(s3==0) //确认减小键被按下{while(!s3);di();if(s1_num==1){miao--;if(miao==-1)miao=59;write_sfm(10,miao);write_com(0x80+0x40+11);write_add(1,miao);}if(s1_num==2){fen--;if(fen==-1)fen=59;write_sfm(7,fen);write_com(0x80+0x40+8);write_add(2,fen);}if(s1_num==3){shi--;if(shi==-1)shi=23;write_sfm(4,shi);write_com(0x80+0x40+5);write_add(3,shi);}if(s1_num==4){week--;if(week==0)week=7;write_week(week);write_com(0x80+14); //写一个字符后光标会移一位,所以要重新定义光标位置write_add(4,week);}if(s1_num==5)//光标至显示日处,可调节多少日{day--;if(day==0)day=31;write_year_month_day(9,day);write_com(0x80+10);//光标位置移回在显示多少日的个位write_add(5,day);}if(s1_num==6) //光标至显示月处调节月份{month--;if(month==0)month=12;write_year_month_day(6,month);write_com(0x80+7);write_add(6,month);}if(s1_num==7){year--;if(year==-1)year=99;write_year_month_day(3,year);write_com(0x80+4);write_add(7,year);}}}}}void main(){init();//首先初始化各数据while(1){keyscan(); //按键扫描函数}}void timer0() interrupt 1 //定时器0中断服务程序{TH0=(65536-45876)/256;TL0=(65536-45876)%256;count++; //中断次数累加,计数if(count==20) //50微秒乘以20等于1秒{count=0;miao++;if(miao==60) //秒加到60则进位分钟{miao=0; //同时秒数清0fen++;if(fen==60) //分钟加到60则进位小时{fen=0; //同时分钟清0shi++;if(shi==24) //小时加到24则小时清0{shi=0;}write_sfm(4,shi);//小时若变化则重新写入write_add(3,shi);//写入24c02存储起来,小时数的写入地址为3 }write_sfm(7,fen);//分钟若变化则重新写入write_add(2,fen);}write_sfm(10,miao);//秒若变化则重新写入write_add(1,miao);}}/***********************************24C02.h头文件,将以下源代码需存为与保存的C代码根目录下。

如何实现DS1302实时时钟表显示在1602LCD液晶

如何实现DS1302实时时钟表显示在1602LCD液晶

如何实现DS1302实时时钟表显示在1602LCD液晶在1602LCD 液晶里显示实时时间:首先在DS1302 实时时钟芯片里写入一个时间,然后在这个芯片里读取这个时间,并显示在液晶里。

现在终于实现了...#include#include sbit SCLK=P3;sb it SDA=P3;sb it RST = P3 ;//unsigned char code Write_Address[]={0x80,0x82,0x84}; unsigned char code Read_Address[]={0x85,0x83,0x81}; unsigned char Time_Table[3];void Write_Byte(unsigned char Data)//写一个字节: 地址或数据{ unsigned char i;for(i=0; i>1;SCLK=1; } }void Write_RTC(unsigned char Address, unsigned char Data) { RST=0; _nop_(); SCLK=0; _nop_(); RST=1; Write_Byte(Address); Write_Byte(Data); RST=0;}unsigned char Read_Byte() //读一个字节: 数据{ unsigned char Data=0; unsigned char i; for(i=0; i>1; _nop_(); SCLK=1; } return Data;}unsigned char Read_RTC(unsigned char Address) //{ unsigned char Data=0; unsigned char Data1,Data2; RST=0; _nop_(); SCLK=0; _nop_(); RST=1; Write_Byte(Address); Data=Read_Byte(); RST=0; Data1=Data/16; Data2=Data%16; Data=Data2+Data1*10; return Data;}void Init_RTC() //初始化实时时钟表RTC{ Write_RTC(0x8e, 0x00); Write_RTC(0x80, 0x56); Write_RTC(0x82, 0x48); Write_RTC(0x84, 0x12); Write_RTC(0x8e, 0x80) }void DisplayTime() //把时间显示1602 液晶{ unsigned char i; InitLCD(); Write_Command(0x80+0x03); for(i=0; i<3; i++) { Time_Table[i]=Read_RTC(Read_Address[i]);Write_Data(0x30+Time_Table[i]/10); Write_Data(0x30+Time_Table[i]%10);if(i!=2) Write_Data(:); } }void main(){Init_RTC(); DisplayTime(); while(1);}其实,写这个程序,也是比较简单的,比在24C02 芯片里读写容易了。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
_nop_();
}
}
}
//判忙
void lcd_mang()
{
rs=0;
rw=1;
e=1;
_nop_();
_nop_();
_nop_();
_nop_();
while(P0&0x80);
e=0;
}
//1602的写
void write_lcd1602(uchar cmd,uchar i)
{
lcd_mang();
write_lcd1602(table[l_tmpdate[2]&0x0f],1);
write_lcd1602(':',1);
write_lcd1602(table[(l_tmpdate[1]>>4)&0x0f],1);
write_lcd1602(table[l_tmpdate[1]&0x0f],1);
void Read_RTC(void)//读取日历
{
unsigned char i,*p;
p=read_rtc_address;//地址传递
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处理
//l_tmpdate[7]用于初始值的设定,设定后,就不用每次上电再次修改了
unsigned char l_tmpdate[7]={0,17,19,16,3,6,12};//秒分时日月周年08-05-15 12:00:00 ,初值
code unsigned char write_rtc_address[7]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c}; //秒分时日月周年最低位读写位
/*******************************************************************************
*标题:试验数码管显示时钟*
**
*通过本例程了解DS1302时钟芯片的基本原理和使用,理解并掌握DS1302时钟芯片*
*驱动程序的编写以及实现数字字符在数码管中的显示。*
void delay(uchar a);//1602分函数声明
void lcd_mang();
void write_lcd1602(uchar cmd,uchar i);
void ini_lcd1602();
/************************************************************
write_lcd1602('0',1);
write_lcd1602(table[(l_tmpdate[6]>>4)&0x0f],1);
write_lcd1602(table[l_tmpdate[6]&0x0f],1);
write_lcd1602('-',1);
write_lcd1602(table[(l_tmpdate[4]>>4)&0x0f],1);
tmp=l_tmpdate[i]/10;
l_tmpdate[i]=l_tmpdate[i]%10;
while(1)
{
Read_RTC();
display();
}
}
/******************************************************************/
/*写一个字节*/
/******************************************************************/
write_lcd1602(':',1);
write_lcd1602(table[(l_tmpdate[0]>>4)&0x0f],1);
write_lcd1602(table[l_tmpdate[0]&0x0f],1);
}
//1602的初始化
void ini_lcd1602()
{
write_lcd1602(0x38,0);
temp>>=1;//右移一位
_nop_();
_nop_();
_nop_();
SCK=1;
}
RST=0;
_nop_();//以下为DS1302复位的稳定时间
_nop_();
RST=0;
SCK=0;
_nop_();
_nop_();
_nop_();
_nop_();
SCK=1;
_nop_();
_nop_();
*注意:JP1302跳线冒要短接。*
*请学员认真消化本例程,懂DS1302在C语言中的操作*
********************************************************************************/
#include<reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
rs=i;
rw=0;
e=0;
_nop_();
_nop_();
e=1;
_nop_();
_nop_();
P0=cmd;
_nop_();
_nop_();
_nop_();
_nop_();
e=0;
}
void display(void)
{
write_lcd1602(0x80+0x01,0);
write_lcd1602('2',1);
/*主函数*/
/******************************************************************/
void main(void)
{
ini_lcd1602();// 1602初始化
Set_RTC(); //写入时钟值,如果使用备用电池时候,不需要没每次上电写入,此程序应该屏蔽
RST=0;
_nop_();
_nop_();
SCK=0;
_nop_();
_nop_();
RST=1;
_nop_();
_nop_();
Write_Ds1302_Byte(address);
for (i=0;i<8;i++)//循环8次读取数据
{
if(SDA)
temp|=0x80;//每次传输低字节
SCK=0;
以下是1602显示模块
*************************************************************/
void delay(uchar a)
{
uchar i;
while(a--)
{
for(i=0;i<250;i++)
{
_nop_();
_nop_();
_nop_();
#define uint unsigned int
uchar temp_buff[9]; //存储读取的字节,read scratchpad为9字节,read rom ID为8字节
uchar *p,TIM;
code unsigned char table[]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
/******************************************************************/
/*函数声明*/
/******************************************************************/
void Write_Ds1302_byte(unsigned char temp);
code unsigned char read_rtc_address[7]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};
//注意,根据需要修改
sbit SCK=P1^0;//时钟
sbit SDA=P1^1;//数据
sbit RST = P1^2;// DS1302复位
write_lcd1602(table[l_tmpdate[4]&0x0f],1);
write_lcd1602('-',1);
write_lcd1602(table[(l_tmpdate[3]>>4)&0x0f],1);
write_lcd1602(table[l_tmpdate[3]&0x0f],1);
相关文档
最新文档