DS1302+LCD1602显示程序
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
}
return(temp);
}
//向DS1302写一个数据
void write_ds1302_dat( unsigned char add,unsigned char dat )
_nop_();
RST=1;
_nop_();
_nop_();
write_ds1302_byte(add);
dat=read_ds1302_byte();
SCK=1;
RST=0;
uchar t_date,date1,date2; //日,日值的十位,日的个位
uchar t_month,month1,month2; //月,月值的十位,月的个位
uchar t_year,year1,year2; //年,年值的十位,年的个位
write_ds1302_byte(dat); //发送数据
SCK=1;
RST=0; //恢复
}
// 读出DS1302数据
#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
uchar table1[]="RQ:";
uchar table2[]="WE:";
uchar table3[]="0123456789";
{
IO=(bit)(dat&0x01); //每次传输低字节
SCK=1;
_nop_();
_nop_();
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版)万年历(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。
基于LCD1602和DS1302的时间显示程序
/*========================================================== ==使用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为无关项。
DS1302+LCD1602
/*此程序在SP-518USB开发板上测试过 laosong *//****************************************************************程序名称: LCD1602显示时间说明:使用本程序你必须把 SE4设置为OFF(1-2)短接 SE5设置为OFF(1-2)短接否则可能会影响LCD1602的正确显示SE6设置为ON(2-3)短接*****************************************************************//*头文件*/#include <reg52.h>#include <intrins.h>#define uint unsigned int#define uchar unsigned char#define nop() _nop_()sbit lcd_rs_port = P2^7; /*定义LCD控制端口*/sbit lcd_rw_port = P2^6; /*定义LCD控制端口*/sbit lcd_en_port = P2^5; /*定义LCD控制端口*/#define lcd_data_port P0 /*定义LCD控制端口*/sbit T_CLK = P1^2; /*实时时钟时钟线引脚 */sbit T_IO = P1^3; /*实时时钟数据线引脚 */sbit T_RST = P3^5; /*实时时钟复位线引脚 */sbit ACC0 = ACC^0;sbit ACC7 = ACC^7;uchar code mun_to_char[] = {"0123456789ABCDEF"}; /*定义数字跟ASCII码的关系*/ 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 "};uchar code Weeks[][3]={{"SUN"},{"MON"},{"TUE"},{"WED"},{"THU"},{"FRI"},{"SAT"},{"SUN"}};/********************************************************************函数名:W1302()功能:往DS1302写入数据说明:先写地址,后写命令/数据 (内部函数)入口参数:ucAddr: DS1302地址, ucData: 要写的数据返回值:无***********************************************************************/ void W1302(uchar ucAddr, uchar ucDa){uchar i;//写地址T_RST=0;T_CLK=0;//增加T_RST=1;ACC=ucAddr;for(i=8;i>0;i--) //修改了{T_IO=ACC0; //修改了,这里不能用ACC^0,要在前面定义T_CLK=1;T_CLK=0;ACC=ACC>>1;}//写数据ACC=ucDa;for(i=8;i>0;i--) //修改了{T_IO=ACC0; //修改了,这里不能用ACC^0,要在前面定义T_CLK=1;T_CLK=0;ACC=ACC>>1;}T_CLK=1;T_RST=0;}/********************************************************************函数名:R1302()功能:读取DS1302某地址的数据说明:先写地址,后读命令/数据 (内部函数)入口参数:ucAddr: DS1302地址返回值:ACC: 读取的数据***********************************************************************/ uchar R1302(uchar ucAddr){uchar i;ACC=ucAddr;T_RST=0;T_CLK=0;T_RST=1;for(i=8;i>0;i--) //修改了{T_IO=ACC0; //修改了,这里不能用ACC^0,要在前面定义T_CLK=1;T_CLK=0;ACC=ACC>>1;}for(i=8;i>0;i--) //修改了{ACC=ACC>>1;ACC7=T_IO;T_CLK=1;T_CLK=0; //修改了}T_CLK=1;T_RST=0;return(ACC);}/********************************************************************函数名:Set1302()功能:设置初始时间说明:先写地址,后读命令/数据(寄存器多字节方式)调用:W1302()入口参数:pClock: 设置时钟数据地址格式为: 秒分时日月星期年7Byte (BCD码)1B 1B 1B 1B 1B 1B 1B返回值:无***********************************************************************/ void Set1302(uchar *pClock){uchar i;uchar ucAddr = 0x80;EA = 0;W1302(0x8e,0x00); /* 控制命令,WP=0,写操作?*/for(i =7; i>0; i--){W1302(ucAddr,*pClock); /* 秒分时日月星期年 */pClock++;ucAddr +=2;}W1302(0x8e,0x80); /* 控制命令,WP=1,写保护?*/EA = 1;}/********************************************************************函数名:Get1302()功能:读取DS1302当前时间说明:调用:R1302()入口参数:ucCurtime: 保存当前时间地址。
DS1302时钟芯片与液晶1602程序
#include<reg52.h>#define wri_sec 0x80#define wri_min 0x82#define wri_hour 0x84#define wri_day 0x86#define wri_mon 0x88#define wri_week 0x8a#define wri_year 0x8c#define re_sec 0x81#define re_min 0x83#define re_hour 0x85#define re_day 0x87#define re_mon 0x89#define re_week 0x8b#define re_year 0x8d#define wri_pro 0x8e#define uchar unsigned char#define uint unsigned intsbit SCLK=P3^5;sbit DIO=P3^6;sbit CE=P3^7;sbit lcden=P1^0;sbit lcdrs=P1^2;sbit lcdrw=P1^1;uchar weeks[7][3]={"Mon","Tue","Wed","Thu","Fri","Sat","Sun"}; static uchar datatime[7]={0};void delay(uint z){uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}void write1302(uchar addr,dat){uchar i,temp;CE=0;SCLK=0;CE=1;for(i=0;i<8;i++){SCLK=0;temp=addr;DIO=(bit)(temp&0x01);addr>>=1;SCLK=1;}for(i=0;i<8;i++){SCLK=0;temp=dat;DIO=(bit)(temp&0x01);dat>>=1;SCLK=1;}CE=0;}uchar read1302(uchar addr){uchar i,temp, dat1,dat2;dat1=0;CE=0;SCLK=0;CE=1;for(i=8;i>0;i--){SCLK=0;temp=addr;DIO=(bit)(temp&0x01);addr>>=1;SCLK=1;}SCLK=0;for(i=8;i>0;i--){DIO=1;dat1>>=1;if(DIO) dat1|=0x80;SCLK=1;delay(5);SCLK=0;}dat2=dat1/16;dat1=dat1%16;dat1=dat2*10+dat1;return(dat1);}void init1302() //初始化{write1302(wri_pro,0x00); //允许写write1302(wri_sec,0x12);// write1302(wri_min,0x23);// write1302(wri_hour,0x16);// write1302(wri_day,0x17);// write1302(wri_mon,0x11);// write1302(wri_year,0x10);// write1302(wri_week,0x03);write1302(wri_pro,0x80); //禁止写}void write_com(uchar com) //lcd写命令{lcdrw=0;lcdrs=0;P0=com;delay(5);lcden=1;delay(5);lcden=0;}void write_data(uchar date) //lcd{lcdrw=0;lcdrs=1;P0=date;delay(5);lcden=1;delay(5);lcden=0;}void init_lcd() //lcd初始化{uint dat1,dat2;uint i;lcden=0;write_com(0x38);write_com(0x0f);write_com(0x06);write_com(0x01);write_com(0x81);write_data('2');delay(20);write_data('0');delay(20);write1302(wri_pro,0x00);datatime[6]=read1302(re_year);dat2=datatime[6]/10;dat1=datatime[6]%10;write_data(48+dat2);delay(20);write_data(48+dat1);delay(20);write_data(45);delay(20);datatime[5]=read1302(re_mon);dat2=datatime[5]/10;dat1=datatime[5]%10;write_data(48+dat2);delay(20);write_data(48+dat1);delay(20);write_data(45);delay(20);datatime[4]=read1302(re_day);dat2=datatime[4]/10;dat1=datatime[4]%10;write_data(48+dat2);delay(20);write_data(48+dat1);delay(20);write_data(32);delay(20);datatime[3]=read1302(re_week);for (i=0;i<3;i++){write_data(weeks[datatime[3]-1][i]);delay(20);}write_com(0x80+0x43);datatime[2]=read1302(re_hour);dat2=datatime[2]/10;dat1=datatime[2]%10;write_data(48+dat2);delay(20);write_data(48+dat1);delay(20);write_data(58);delay(20);datatime[1]=read1302(re_min);dat2=datatime[1]/10;dat1=datatime[1]%10;write_data(48+dat2);delay(20);write_data(48+dat1);delay(20);write_data(39);delay(20);datatime[0]=read1302(re_sec);dat2=datatime[0]/10;dat1=datatime[0]%10;write_data(48+dat2);delay(20);write_data(48+dat1);delay(20);write_data(34);delay(20);write1302(wri_pro,0x80);}void refresh() //更新时间{uchar sec,min,hou,day,mon,yea,wee,dat1,dat2;uint i;write1302(wri_pro,0x00);sec=read1302(re_sec);if(sec!=datatime[0]){datatime[0]=sec;dat2=datatime[0]/10;dat1=datatime[0]%10;write_com(0x80+0x49);delay(50);write_data(48+dat2);delay(20);write_data(48+dat1);delay(20);if(!sec){min=read1302(re_min);datatime[1]=min;dat2=datatime[1]/10;dat1=datatime[1]%10;write_com(0x80+0x46);delay(5);write_data(48+dat2);delay(20);write_data(48+dat1);delay(20);if(!min){hou=read1302(re_hour);datatime[2]=hou;dat2=datatime[2]/10;dat1=datatime[2]%10;write_com(0x80+0x43);delay(5);write_data(48+dat2);delay(20);write_data(48+dat1);delay(20);if(!hou){wee=read1302(re_week);datatime[3]=wee;write_com(0x80+0x0c);delay(5);for (i=0;i<3;i++){write_data(weeks[datatime[3]-1][i]);delay(20);}day=read1302(re_day);datatime[4]=day;dat2=datatime[4]/10;dat1=datatime[4]%10;write_com(0x80+0x09);delay(5);write_data(48+dat2);delay(20);write_data(48+dat1);delay(20);if(day==1){mon=read1302(re_mon);datatime[5]=mon;dat2=datatime[5]/10;dat1=datatime[5]%10;write_com(0x80+0x06);delay(5);write_data(48+dat2);delay(20);write_data(48+dat1);delay(20);if(mon==1){yea=read1302(re_year);datatime[6]=yea;dat2=datatime[6]/10;dat1=datatime[6]%10;write_com(0x80+0x03);delay(5);write_data(48+dat2);delay(20);write_data(48+dat1);delay(20);}}}}}}write1302(wri_pro,0x80);}void readkey() //查键{uchar key,n,dat1,dat2;uint i;key=P2;delay(10);if(key==0xfe){key=P2;delay(20);n=1;while(1){if(n==1){n=0;write_com(0x83); //修改年write1302(wri_pro,0x00);dat1=read1302(re_year);dat2=dat1/10;dat1=dat1%10;key=P2;delay(10);while(key!=0xf7){delay(200);switch(key){case 0xfd:if(dat2==9) dat2=0;else dat2++;write_data(48+dat2);delay(20);write_com(0x83);break;case 0xfb: if(dat2==0) dat2=9;else dat2--;write_data(48+dat2);delay(20);write_com(0x83);break;default: break;}key=P2;delay(10);}delay(200);write_com(0x84);key=P2;delay(20);while(key!=0xf7){delay(200);switch(key){case 0xfd: if(dat1==9) dat1=0;else dat1++;write_data(48+dat1);delay(20);write_com(0x84);break;case 0xfb: if(dat1==0) dat1=9;else dat1--;write_data(48+dat1);delay(20);write_com(0x84);break;default: break;}key=P2;delay(10);}dat1=(dat2<<4)|dat1;write1302(wri_year,dat1);delay(200);write_com(0x86); //修改月dat1=read1302(re_mon);dat2=dat1/10;dat1=dat1%10;key=P2;delay(10);while(key!=0xf7){delay(200);switch(key){case 0xfd: if(dat2==1) dat2=0;else dat2++;write_data(48+dat2);delay(20);write_com(0x86);break;case 0xfb: if(dat2==0) dat2=1;else dat2--;write_data(48+dat2);delay(20);write_com(0x86);break;default: break;}key=P2;delay(10);}write_com(0x87);delay(200);key=P2;delay(10);while(key!=0xf7){delay(200);switch(key){case 0xfd: if(dat1==9) dat1=0;else dat1++;write_data(48+dat1);delay(20);write_com(0x87);break;case 0xfb: if(dat1==0) dat1=9;else dat1--;write_data(48+dat1);delay(20);write_com(0x87);break;default: break;}key=P2;delay(10);}dat1=(dat2<<4)|dat1;write1302(wri_mon,dat1);delay(200);write_com(0x89); //修改日dat1=read1302(re_day);dat2=dat1/10;dat1=dat1%10;key=P2;delay(10);while(key!=0xf7){delay(200);switch(key){case 0xfd: if(dat2==3) dat2=0;else dat2++;write_data(48+dat2);delay(20);write_com(0x89);break;case 0xfb: if(dat2==0) dat2=3;else dat2--;write_data(48+dat2);delay(20);write_com(0x89);break;default: break;}key=P2;delay(10);}write_com(0x8a);delay(200);key=P2;delay(10);while(key!=0xf7){delay(200);switch(key){case 0xfd: if(dat1==9) dat1=0;else dat1++;write_data(48+dat1);delay(20);write_com(0x8a);break;case 0xfb: if(dat1==0) dat1=9;else dat1--;write_data(48+dat1);delay(20);write_com(0x8a);break;default: break;}key=P2;delay(10);}dat1=(dat2<<4)|dat1;write1302(wri_day,dat1);delay(200);write_com(0x8c); //修改星期dat1=read1302(re_week);key=P2;delay(20);while(key!=0xf7){delay(200);switch(key){case 0xfd: if(dat1==7) dat1=1;else dat1++;for(i=0;i<3;i++){write_data(weeks[dat1-1][i]);delay(20);}write_com(0x8c);break;case 0xfb: if(dat1==1) dat1=7;else dat1--;for(i=0;i<3;i++){write_data(weeks[dat1-1][i]);delay(20);}write_com(0x8c);break;}key=P2;delay(10);}write1302(wri_week,dat1);delay(200);write_com(0x80+0x43); //修改时dat1=read1302(re_hour);dat2=dat1/10;dat1=dat1%10;key=P2;delay(10);while(key!=0xf7){delay(200);switch(key){case 0xfd: if(dat2==2) dat2=0;else dat2++;write_data(48+dat2);delay(20);write_com(0x80+0x43);break;case 0xfb: if(dat2==0) dat2=2;else dat2--;write_data(48+dat2);delay(20);write_com(0x80+0x43);break;default: break;}key=P2;delay(10);}write_com(0x80+0x44);delay(200);key=P2;delay(20);while(key!=0xf7){delay(200);switch(key){case 0xfd: if(dat1==9) dat1=0;else dat1++;write_data(48+dat1);delay(20);write_com(0x80+0x44);break;case 0xfb: if(dat1==0) dat1=9;else dat1--;write_data(48+dat1);delay(20);write_com(0x80+0x44);break;default: break;}key=P2;delay(10);}dat1=(dat2<<4)|dat1;write1302(wri_hour,dat1);delay(250);write_com(0x80+0x46); //修改分dat1=read1302(re_min);dat2=dat1/10;dat1=dat1%10;key=P2;delay(10);while(key!=0xf7){delay(200);switch(key){case 0xfd: if(dat2==5) dat2=0;else dat2++;write_data(48+dat2);delay(20);write_com(0x80+0x46);break;case 0xfb: if(dat2==0) dat2=5;else dat2--;write_data(48+dat2);delay(20);write_com(0x80+0x46);break;default: break;}key=P2;delay(10);}write_com(0x80+0x47);delay(200);key=P2;delay(20);while(key!=0xf7){delay(200);switch(key){case 0xfd: if(dat1==9) dat1=0;else dat1++;write_data(48+dat1);delay(20);write_com(0x80+0x47);break;case 0xfb: if(dat1==0) dat1=9;else dat1--;write_data(48+dat1);delay(20);write_com(0x80+0x47);break;default: break;}key=P2;delay(10);}dat1=(dat2<<4)|dat1;write1302(wri_min,dat1);delay(250);write_com(0x80+0x49); //修改秒dat1=read1302(re_sec);dat2=dat1/10;dat1=dat1%10;key=P2;delay(10);while(key!=0xf7){delay(200);switch(key){case 0xfd: if(dat2==5) dat2=0;else dat2++;write_data(48+dat2);delay(20);write_com(0x80+0x49);break;case 0xfb: if(dat2==0) dat2=5;else dat2--;write_data(48+dat2);delay(20);write_com(0x80+0x49);break;default: break;}key=P2;delay(10);}write_com(0x80+0x4a);delay(200);key=P2;delay(20);while(key!=0xf7){delay(200);switch(key){case 0xfd: if(dat1==9) dat1=0;else dat1++;write_data(48+dat1);delay(20);write_com(0x80+0x4a);break;case 0xfb: if(dat1==0) dat1=9;else dat1--;write_data(48+dat1);delay(20);write_com(0x80+0x4a);break;default: break;}key=P2;delay(10);}dat1=(dat2<<4)|dat1;write1302(wri_sec,dat1);write_com(0x80+0x4d);write1302(wri_pro,0x80);}break;}}}void main(){init1302();init_lcd();while(1){refresh();readkey();write_com(0x80+0x50);}}。
电子时钟程序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();}}}。
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]);
基于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+1602显示
**********************************************************/
void lcd_wcmd(unsigned char cmd)
{
while (lcd_busy())
;
LCD_RS = 0;
LCD_RW = 0;
LCD初始化设定
**********************************************************/
void lcd_init()
{
delayms(50); //延时等待上电稳定
lcd_wcmd(0x38); //16*2显示,5*7点阵,8位数据
us延时子函数 (4.34us)
*********************************************************/
void delayNOP()
{
_nop_();
_nop_();
_nop_();
_nop_();
}
/*********************************************************
BEEP = !BEEP; //BEEP取反
}
BEEP = 1; //关闭蜂鸣器
delayms(150);
}
/**********************************************************
检查LCD忙状态
lcd_busy为1时,忙,等待。lcd-busy为0时,闲,可写指令与数据。
/*******************************************************************
DS1302实时时钟模块,1602显示
/*******************说明:**************************将实时时钟数据通过LCD1602显示--------------------------------------------------基于51单片机**************************************************/#include <reg52.h>#include <intrins.h>#define uchar unsigned char#define uint unsigned intuchar dis_time_buf[16]={0};//LCD1602引脚定义//采用8位并行方式,DB0~DB7连接至LCDDATA0~LCDDATA7 sbit RS=P2^0;sbit RW=P2^1;sbit CS=P2^2;#define LCDDATA P0//DS1302引脚定义sbit RST=P1^3;sbit IO=P1^2;sbit SCK=P1^1;//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;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,表示在第一行显示,地址基数为0x80address=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*7dots Delay_xms(5);Write_Instruction(0x38);Delay_xms(5);Write_Instruction(0x38);Write_Instruction(0x08); //关显示,不显光标,光标不闪烁Write_Instruction(0x01); //清屏Delay_xms(5);Write_Instruction(0x04); //写一字符,整屏显示不移动//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){RST=0; //RST脚置低SCK=0; //SCK脚置低}//向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=0; //停止DS1302总线}//从DS1302读出一字节数据uchar ds1302_read_byte(uchar addr) {uchar i,temp;RST=1; //启动DS1302总线//写入目标地址:addraddr = addr | 0x01; //最低位置高,寄存器0位为0时写,为1时读for (i = 0; i < 8; i ++) {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(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(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();}}。
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时钟1602显示
一、实验原理图:二、程序代码:/*************** writer:shopping.w ******************/ #include <reg52.h>#include <intrins.h>#include <string.h>#define uint unsigned int#define uchar unsigned charsbit IO = P1^0;sbit SCLK = P1^1;sbit RST = P1^2;sbit RS = P2^0;sbit RW = P2^1;sbit EN = P2^2;uchar *WEEK[]={"SUN","***","MON","TUS","WEN","THU","FRI","SAT" };uchar LCD_DSY_BUFFER1[]={"DA TE 00-00-00 "}; uchar LCD_DSY_BUFFER2[]={"TIME 00:00:00 "}; uchar DateTime[7];void DelayMS(uint ms){uchar i;while(ms--){for(i=0;i<120;i++);}}void Write_A_Byte_TO_DS1302(uchar x){uchar i;for(i=0;i<8;i++){IO=x&0x01;SCLK=1;SCLK=0;x>>=1;}}uchar Get_A_Byte_FROM_DS1302(){uchar i,b=0x00;for(i=0;i<8;i++){b |= _crol_((uchar)IO,i);SCLK=1;SCLK=0;}return b/16*10+b%16;}uchar Read_Data(uchar addr){uchar dat;RST = 0;SCLK=0;RST=1;Write_A_Byte_TO_DS1302(addr);dat = Get_A_Byte_FROM_DS1302();SCLK=1;RST=0;return dat;}void GetTime(){uchar i,addr = 0x81;for(i=0;i<7;i++){DateTime[i]=Read_Data(addr);addr+=2;}}uchar Read_LCD_State(){uchar state;RS=0;RW=1;EN=1;DelayMS(1);state=P0;EN = 0;DelayMS(1);return state;}void LCD_Busy_Wait(){while((Read_LCD_State()&0x80)==0x80);DelayMS(5);}void Write_LCD_Data(uchar dat){LCD_Busy_Wait();RS=1;RW=0;EN=0;P0=dat;EN=1;DelayMS(1);EN=0; }void Write_LCD_Command(uchar cmd){LCD_Busy_Wait();RS=0;RW=0;EN=0;P0=cmd;EN=1;DelayMS(1);EN=0; }void Init_LCD(){Write_LCD_Command(0x38);DelayMS(1);Write_LCD_Command(0x01);DelayMS(1);Write_LCD_Command(0x06);DelayMS(1);Write_LCD_Command(0x0c);DelayMS(1);}void Set_LCD_POS(uchar p){Write_LCD_Command(p|0x80);}void Display_LCD_String(uchar p,uchar *s){uchar i;Set_LCD_POS(p);for(i=0;i<16;i++){Write_LCD_Data(s[i]);DelayMS(1);}}void Format_DateTime(uchar d,uchar *a){a[0]=d/10+'0';a[1]=d%10+'0';}void main(){Init_LCD();while(1){GetTime();Format_DateTime(DateTime[6],LCD_DSY_BUFFER1+5);Format_DateTime(DateTime[4],LCD_DSY_BUFFER1+8);Format_DateTime(DateTime[3],LCD_DSY_BUFFER1+11);strcpy(LCD_DSY_BUFFER1+13,WEEK[DateTime[5]]);Format_DateTime(DateTime[2],LCD_DSY_BUFFER1+5);Format_DateTime(DateTime[1],LCD_DSY_BUFFER1+8);Format_DateTime(DateTime[0],LCD_DSY_BUFFER1+11);Display_LCD_String(0x00,LCD_DSY_BUFFER1);Display_LCD_String(0x40,LCD_DSY_BUFFER2);}}。
DS1302芯片 1602液晶显示
DS1302芯片+1602液晶显示网上的DS1302与1602搭配的程序很多都有很大问题。
我写个全的,而且写得很细,让大家看看好了解,端口自己修改即可#include ;#include ;/*********************************端口定义**********************************/sbit sclk = P3^4;sbit io= P3^3;sbit rst= P3^5;sbit rs=P1^0;sbit en=P1^2;sbit rw=P1^1;#define uchar unsigned char#define uint unsigned intucharflag,second,minute,hour,week,day,month,year;//秒、分、时、星期、日、月、年void delay(uint z) //延时子程序{uint x,y;for(x=z;x>;0;x--)for(y=110;y>;0;y--);}void delayus(){_nop_();_nop_();_nop_();_nop_();}void write_1602dat(uchar dat)//定义一个带参数的写数据子程序{rs=1; //1602的rs为0时,接收命令,为1时接收数据P0=dat;//把void write_shu(uchar shu)中的COM中的数据给P0口delay(5);en=1;delay(5);en=0;delay(5);}void write_1602com(uchar com)//定义一个带参数的写命令子程序{rs=0; //1602的rs为0时,接收命令,为1时接收数据P0=com;//把void write_com(uchar com)中的COM中的数据给P0口delay(5);en=1;delay(5);en=0;delay(5);}void Write1602(uchar add,uchar dat){write_1602com(add);write_1602dat(dat);}void init1602()//定义一个初始化子程序{en=0;rw=0;write_1602com(0x38);//调用 write_com子程序并把0x38赋给P0口,显示模式打开write_1602com(0x0e);//调用 write_com子程序并把“开显示,显示光标,光标闪烁”指令码赋给P0口write_1602com(0x06);//调用 write_com子程序并把“地址指针加1,整屏不移动”指令码赋给P0口//write_com(0x80+0x10);//数据指针初始化,让指针指向可显示的最右端write_1602com(0x80);//数据指针初始化,让指针指向最左端,显示从第一行开始write_1602com(0x01);//调用 write_com子程序并把"清零指"令码赋给P0口Write1602(0x80,'2');Write1602(0x81,'0');Write1602(0x80+4,'-');Write1602(0x80+7,'-');Write1602(0x80+0x40+5,':');Write1602(0x80+0x40+8,':');}/********************写一个字节**************/ void write_1302byte(dat){uchar i;sclk=0;delayus();for(i=8;i>;0;i--){io=dat&0x01;//只要是从低位取数,向高位一定要和0X01与delayus();sclk=1;//为写数据制造上升沿。
DS1302电子时钟1602液晶显示
DS1302电子时钟1602液晶显示#include#define uchar unsigned char#define uint unsigned intsbit RS=P2^2; //1602液晶显示器456管脚sbit RW=P2^3;sbit EN=P2^4;sbit SCLK=P1^0; //1302时钟芯片756管脚sbit IO=P1^1;sbit RST=P1^2;uchar time[]=" ";uchar time1[]=" ";uchar time2[2]="--";uchar time3[2]="::";uchar miao,fen,shi,ri,yue,nian,xingqi;void delay(uchar x) //延时{uint i,j;for(i=0;i<x;i++)for(j=0;j<20;j++);}void write_com(uchar com) //写指令{RS=0;RW=0;P0=com; //写指令码delay(1);EN=1; //高脉冲delay(1);EN=0;}void write_dat(uchar dat) //写数据{RS=1;RW=0;P0=dat; //写数据delay(1);EN=1; //高脉冲delay(1);EN=0;}void lcd_init(){write_com(0x38); //初始化液晶write_com(0x0c); //显示开关;不显示光标;光标不闪烁write_com(0x06); //指针+1光标+1;整屏显示不移动write_com(0x01); //显示清屏}void write1302_byte(uchar temp) //传输时钟数据{uchar i;SCLK=0; //初始时钟线置为0delay(1);for(i=0;i<8;i++) //开始传输8个字节的数据{IO=temp&0x01; //取最低位,注意DS1302的数据和地址都是从最低位开始传输的delay(1);SCLK=1; //时钟线拉高,制造上升沿,IO的数据被传输delay(1);SCLK=0; //时钟线被拉低,为下一个上升沿做准备temp=temp>>1; //数据右移一位,准备传输下一位数据}}uchar read1302_byte() //读取时钟数据{uchar i,temp;for(i=0;i<8;i++){temp=temp>>1; //要返回的数据左移一位if(IO==1) //当数据线为高时,证时该位数据为1temp=temp|0x80; //要传输数据的当前值为1,若不是,则为0 SCLK=1; //拉高时钟线delay(1);SCLK=0; //制造下降沿 ,IO的数据被传输delay(1);}return temp; //返回读取的数据}uchar read1302(uchar com) //{uchar dat;RST=0; //初始CE线置为0SCLK=0; //初始时钟线置为0RST=1; //初始CE线置为1,传输开始write1302_byte(com); //传输命令字,要读取的时间/日历地址dat=read1302_byte(); //读取要得到的时间/日期SCLK=1; //时钟线拉高RST=0; //读取结束,CE置为0,结束数据的传输return dat; //返回得到的时间/日期}void write1302(uchar com,uchar dat)//写入的时间/日历{RST=0; //初始CE线置为0SCLK=0; //初始时钟线置为0RST=1; //初始CE线置为1,传输开始write1302_byte(com);//传输命令字,要写入的时间/日历write1302_byte(dat);//写入要修改的时间/日期SCLK=1; //时钟线拉高RST=0; //写入结束,CE置为0,结束数据的传输}void init_1302(){write1302(0x8e,0x00); //关保护write1302(0x80,0x00); //0的话开起秒write1302(0x80,0x35); //秒</x;i++)write1302(0x82,0x00); //分write1302(0x84,0x08); //时write1302(0x86,0x11); //日write1302(0x88,0x01); //月write1302(0x8a,0x01); //星期write1302(0x8c,0x16); //年write1302(0x8e,0x80); //开保护}void disp() //液晶{uchar i;write_com(0x80); //液晶第一行for(i=0;i<16;i++){write_dat(time[i]);}write_com(0xc0); //液晶第二行for(i=0;i<16;i++){write_dat(time1[i]);}}void main() //主函数{lcd_init(); //设置液晶init_1302(); //设置时间while(1) //循环{xingqi=read1302(0x8b); //读取的星期地址time[13]=xingqi+'0'; //数据转换miao=read1302(0x81);time[9]=miao/16+'0';time[10]=miao%16+'0';time[8]=time3[0];fen=read1302(0x83);time[6]=fen/16+'0';time[7]=fen%16+'0';time[5]=time3[1];shi=read1302(0x85);time[3]=shi/16+'0';time[4]=shi%16+'0';ri=read1302(0x87);time1[9]=ri/16+'0';time1[10]=ri%16+'0';time1[8]=time2[0];yue=read1302(0x89);time1[6]=yue/16+'0';time1[7]=yue%16+'0';time1[5]=time2[0];nian=read1302(0x8d);time1[3]=nian/16+'0';time1[4]=nian%16+'0';disp(); //返回时间日期在液晶中的位置及数据}}。
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);}}。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
/*头文件*/
#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 "};
返 回 值:无
设 计:zhaojunjie 日 期:2002-03-19
修 改: 日 期:
***********************************************************************/
pClock++;
ucAddr +=2;
}
W1302(0x8e,0x80); /* 控制命令,WP=1,写保护?*/
EA = 1;
}
/********************************************************************
uchar ucAddr = 0x80;
EA = 0;
W1302(0x8e,0x00); /* 控制命令,WP=0,写操作?*/
for(i =7; i>0; i--)
{
W1302(ucAddr,*pClock); /* 秒 分 时 日 月 星期 年 */
for(j=0;j<250;j++)
{;}
}
}
void lcd_busy_wait() /*LCD1602 忙等待*/
T_CLK = 1;
T_RST = 0;
}
/********************************************************************
函 数 名:R1302()
功 能:读取DS1302某地址的数据
说 明:先写地址,后读命令/数据 (内部函数)
void W1302(uchar ucAddr, uchar ucDa)
{
T_RST = 0;
T_CLK = 0;
T_RST = 1;
RTInputByte(ucAddr); /* 地址,命令 */
RTInputByte(ucDa); /* 写1Byte数据*/
调 用:RTInputByte() , RTOutputByte()
入口参数:ucAddr: DS1302地址
返 回 值:ucData :读取的数据
设 计:zhaojunjie 日 期:2002-03-19
修 改: 日 期:
说明:使用本程序你必须把 SE3设置为1-2短接 SE5设置为2-3短接
*****************************************************************/
ACC7 = T_IO;
T_CLK = 1;
T_CLK = 0;
}
return(ACC);
}
/********************************************************************
函 数 名:Get1302()
功 能:读取DS1302当前时间
说 明:
调 用:R1302()
入口参数:ucCurtime: 保存当前时间地址。当前时间格式为: 秒 分 时 日 月 星期 年
7Byte (BCD码) 1B 1B 1B 1B 1B 1B 1B
入口参数:pClock: 设置时钟数据地址 格式为: 秒 分 时 日 月 星期 年
7Byte (BCD码)1B 1B 1B 1B 1B 1B 1B
返 回 值:无
设 计:zhaojunjie 日 期:2002-03-19
函 数 名:RTInputByte()
功 能:实时时钟写入一字节
说 明:往DS1302写入1Byte数据 (内部函数)
入口参数:d 写入的数据
返 回 值:无
设 计:zhaojunjie 日 期:2002-03-19
修 改: 日 期:
设 计:zhaojunjie 日 期:2002-03-19
修 改: 日 期:
***********************************************************************/
函 数 名:RTOutputByte()
功 能:实时时钟读取一字节
说 明:从DS1302读取1Byte数据 (内部函数)
入口参数:无
返 回 值:ACC
设 计:zhaojunjie 日 期:2002-03-19
修 改: 日 期:
修 改: 日 期:
***********************************************************************/
void Set1302(uchar *pClock)
{
uchar i;
***********************************************************************/
uchar RTOutputByte(void)
{
uchar i;
for(i=8; i>0; i--)
{
ACC = ACC >>1; /*相当于汇编中的 RRC */
}
/********************************************************************
函 数 名:Set1302()
功 能:设置初始时间
说 明:先写地址,后读命令/数据(寄存器多字节方式)
调 用:W1302()
sbit lcd_rw_port = P2^1; /*定义LCD控制端口*/
sbit lcd_en_port = P2^2; /*定义LCD控制端口*/
#define lcd_data_port P0 /*定义LCD控制端口*/
sbit T_CLK = P1^2; /*实时时钟时钟线引脚 */
ucAddr += 2;
}
EA = 1;
}
//---------------------------------------------
void lcd_delay(uchar ms) /*LCD1602 延时*/
{
uchar j;
while(ms--){
***********************************************************************/
void RTInputByte(uchar d)
{
uchar i;
ACC = d;
for(i=8; i>0; i--)
void Get1302(uchar ucCurtime[])
{
uchar i;
uchar ucAddr = 0x81;
EA = 0;
for (i=0; i<7; i+(ucAddr);/*格式为: 秒 分 时 日 月 星期 年 */
***********************************************************************/
uchar R1302(uchar ucAddr)
{
uchar ucData;
T_RST = 0;
T_CLK = 0;
T_RST = 1;
uchar code Weeks[][3]={{"SUN"},{"MON"},{"TUE"},{"WED"},{"THU"},{"FRI"},{"SAT"},{"SUN"}};
/********************************************************************