电子时钟(1302芯片)LCD1602
- 格式:doc
- 大小:237.00 KB
- 文档页数:12
《单片机原理实验》考试报告题目:DS1302和1602时钟姓名:学号:班级:专业:电子信息工程指导老师:提交时间:DS1302和1602时钟***(**学院电子信息工程 ***班 **********)摘要:关键词:DS1302 ,液晶1602,89C51。
1.引言我们在日常生活中常常用到时钟来记录时间,有时候还不能准确的记录下时间,这就要用到芯片DS1302了。
时间还远远不够,因为人性化的设计自然是要清楚的显示年、月、日、星期、时间。
而在此用到的DS1302非常好的与时间进行同步,并且在掉电时不会对时间有影响,较理的考虑到了人们的思维模式,从而简单的控制了时钟,结合了常理的理论。
2.原理DS1302引脚X1 X2 32.768KHz 晶振管脚GND 地CE 复位脚I/O 数据输入/输出引脚SCLK 串行时钟Vcc1,Vcc2 电源供电管脚各引脚的功能为:Vcc1:主电源;Vcc2:备份电源。
当Vcc2>Vcc1+0.2V时,由Vcc2向DS1302供电,当Vcc2< Vcc1时,由Vcc1向DS1302供电。
SCLK:串行时钟,输入,控制数据的输入与输出;I/O:三线接口时的双向数据线;CE:输入信号,在读、写数据期间,必须为高。
该引脚有两个功能:第一,CE开始控制字访问移位寄存器的控制逻辑;其次,CE提供结束单字节或多字节数据传输的方法。
DS1302控制字:控制字的最高有效位(位7)必须是逻辑1,如果它为0,则不能把数据写入到DS1302中。
位6:如果为0,则表示存取日历时钟数据,为1表示存取RAM数据;位5至位1(A4~A0):指示操作单元的地址;位0(最低有效位):如为0,表示要进行写操作,为1表示进行读操作。
控制字总是从最低位开始输出。
在控制字指令输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,数据输入从最低位(0位)开始。
同样,在紧跟8位的控制字指令后的下一个SCLK脉冲的下降沿,读出DS1302的数据,读出的数据也是从最低位到最高位。
#include <reg52.h>#define uchar unsigned char#define uint unsigned int#define lcddata P0#define readalarmsecond 0xc7 //定义从DS1302中读闹钟秒值的命令字节.#define writealarmsecond 0xc6 //定义往DS1302中写闹钟秒值的命令字节.#define readalarmminute 0xc5 //定义从DS1302中读闹钟分值的命令字节.#define writealarmminute 0xc4 //定义往DS1302中写闹钟分值的命令字节.#define readalarmhour 0xc3 //定义从DS1302中读闹钟小时值的命令字节. #define writealarmhour 0xc2 //定义往DS1302中写闹钟小时值的命令字节.sbit lcdrs=P1^0; //LCD数据/命令选择端(H/L)sbit lcdrw=P1^1; //LCD读/写选择端(H/L)sbit lcden=P2^5; //LCD使能控制sbit dula=P2^6; //数码管段声明sbit wela=P2^7; //数码管位声明sbit beep=P2^3; //蜂鸣器控制端sbit kmenu=P3^0; //功能键sbit kup=P3^1; //增大键sbit kdown=P3^2; //减小键sbit kalarm=P3^3; //闹钟查看键Ring:显示闹钟需要调到的时间sbit key=P3^7;sbit dsclk=P2^1; //ds1302的时钟信号端sbit dsdata=P2^0; //ds1302的数据I/O端sbit dsrst=P2^4; //ds1302的复位端sbit ACC7=ACC^7; //定义累加器的最高和最低位。
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(); //显示时间}}。
电子系统设计实验报告实验目的:1、能够以DS1302实时时钟芯片和液晶显示屏CD1602为基础设计一款电子钟2、熟悉DS1302芯片的工作过程3、熟悉CD1602芯片的工作过程4、可以进行必要的扩展,如用第三DS18B20新品进行温度采集和显示5、熟悉掌握51的c程序的编写6、掌握用Proteus进行系统设计仿真验证实验仪器、仪表目录1、DS1302实时时钟芯片1片2、LCD1602液晶显示屏1个,3、80C52芯片1片5、DS18B20芯片一片6、晶振、电容、电阻、开关各若干等7、proteus仿真软件8、Keil C51、PC机实验设计任务以DS1302实时时钟芯片和液晶显示屏LCD1602为基础设计一个电子钟,要求:时间和日期可调整,按键采用3个按键;至少在Proteus上调试通过。
扩展:闹钟和重要日期提醒功能(增加蜂鸣器),闹铃音乐功能实验步骤1、打开Keil软件,新建一个工程文件,选择好芯片,并记得在“Options for Target 1”的Output 选项中,将Create HEX Fil选项勾起来。
2、将编写的程序保存成“.C”的形式3、编译保存好的C文件,并根据提示修改程序中的错误,直到编译成功为止4、打开proteus软件,画出实验电路图5、在89C52中,载入原来已生成的HEX文档6、按下运行键,对Proteus进行软件仿真,观察运行结果原理、结果及分析一、设计方案原理与设计特点分析电子钟总的设计模块:各个模块电路原理分析:1、DS1302时钟采集模块:1.1电路原理图:1.2 DS1302分析:首先DS1302是DALLAS公司推出的涓流充电时钟芯片。
内含有一个实时时钟/日历和31字节静态RAM通过简单的串行接口与单片机进行通信实时时钟/日历电路提供秒分时日日期月年的信息每月的天数和闰年的天数可自动调整时钟操作。
DS1302芯片广脚介绍:X1、X2为32.768KHz晶振管脚。
#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);}}。
#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();}}}。
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);}}。
电子工程学院课外学分报告
题目:LCD屏字符显示
班级:XXXX 姓名:XXXX
学号:XX 专业:XXXXXXXX
实验室:开放实验室
设计时间:2013 年月日——2013 年月日审批意见:指导教师:
目录
1、设计题目及要求 (3)
2、设计方案 (3)
2. 1、LCD1602介绍及其特性 (3)
2. 2、特性应用 (3)
2. 3、LCD1602显示模指令集 (4)
2. 4、程序总框图 (5)
3、总结 (6)
4. 调试仿真图 (6)
5.PCB图 (7)
6.元器件清单 (8)
7.主程序 (9)
8. 参考文献 (12)
1.设计题目及方案
利用单片机芯片AT89C52与LCD显示屏,利用LCD1602显示屏显示自己想要的字符,通过控制LCD1602的3个使能/控制端,从而通过程序控制LCD1602实现字符显示,最后达到在LCD 屏上显示“dianzi B1121:I love you”的功能。
2. 设计原理及器件特性
2.1LCD1602介绍及其特性
1602LCD是指显示的内容为16X2,即可以显示两行,每行16个字符液晶模块(显示字符和数字)。
目前市面上字符液晶绝大多数是基于HD44780液晶芯片的,控制原理是完全相同的,因此基于HD44780写的控制程序可以很方便地应用于市面上大部分的字符型液晶。
1602液晶也叫1602字符型液晶,它是一种专门用来显示字母、数字、符号等的点阵型液晶模块。
它由若干个5X7或者5X11等点阵字符位组成,每个点阵字符位都可以显示一个字符,每位之间有一个点距的间隔,每行之间也有间隔,起到了字符间距和行间距的作用,正因为如此所以它不能很好地显示图形(用自定义CGRAM,显示效果也不好)。
1602LCD是指显示的内容为16X2,即可以显示两行,每行16个字符液晶模块(显示字符和数字)。
目前市面上字符液晶绝大多数是基于HD44780液晶芯片的,控制原理是完全相同的,因此基于HD44780写的控制程序可以很方便地应用于市面上大部分的字符型液晶。
1602采用标准的16脚接口,其中:
第1脚:VSS为电源地
第2脚:VCC接5V电源正极
第3脚:V0为液晶显示器对比度调整端,接正电源时对比度最弱,接地电源时对比度最高(对比度过高时会产生“鬼影”,使用时可以通过一个10K的电位器调整对比度)。
第4脚:RS为寄存器选择,高电平1时选择数据寄存器、低电平0时选择指令寄存器。
第5脚:RW为读写信号线,高电平(1)时进行读操作,低电平(0)时进行写操作。
第6脚:E(或EN)端为使能(enable)端。
第7~14脚:D0~D7为8位双向数据端。
第15~16脚:空脚或背灯电源。
15脚背光正极,16脚背光负极。
2.2特性应用
+3.3V电压,对比度可调
内含复位电路
提供各种控制命令,如:清屏、字符闪烁、光标闪烁、显示移位等多种功能
有80字节显示数据存储器DDRAM
内建有192个5X7点阵的字型的字符发生器CGROM
8个可由用户自定义的5X7的字符发生器CGRAM
微功耗、体积小、显示内容丰富、超薄轻巧,常用在袖珍式仪表和低功耗应用系统中。
2.3 LCD1602显示模指令集
(1)清屏功能:清DDROM值和AC值
(2)归位功能:光标复位,光标返回到地址00H
(3)输入方式设置功能:设置光标,画面移动方式。
其中:I/D=1:数据读写操作后,AC 自加一;
I/D=0:数据读写操作后,AC 自减一; S=1:数据读写操作,画面平移; S=0:数据读写操作,画面不动;
(4)显示开关控制功能:设置显示、光标和闪烁开关。
其中:D 表示显示开关,D=1 为开,D=0 为关;
C 表示光标开关,C=1 为开,C=0 为关; B 表示闪烁开关,B=1 为开,B=0 为关。
(5)光标、画面位移功能:光标、画面移动。
其中:S/C=1 画面移动一个字符位;
S/C=0 光标移动一个字符位;R/L=1:右移;R/L=0 左移。
(6)功能设置功能:工作方式设置(初始化指令)。
其中:DL=1,8 位数据接口;
DL=0,4 位数据接口;
N=1,两行显示;N=0,一行显示;
F=1,5*10 点阵显示;F=0,5*7 点阵显示。
(7)CGRAM 地址设置功能:设置CGRAM 地址,A5~A0=0~3FH。
(8)DDRAM 地址设置功能:设置DDRAM 地址。
其中:N=0,一行显示A6~A0=0~4FH;
N=1 两行显示,首行A6~A0=0~2FH,次行A6~A0=40~67H。
(9)读BF 及AC 值功能:读忙BF 和地址计数器AC 的值。
其中:BF=1:忙,BF=0:准备好。
此时AC 值意义为最近一次地址设置(CGRAM 或DDRAM)定义。
(10)写数据功能:根据最近设置的地址性质,数据写入CGRAM 或DDRAM 中。
(11)读数据功能:根据最近设置的地址性质,从CGRAM 或DDRAM 数据读出。
实际器件与引脚图:
2.4程序总体框图如图所示:
总程序框图
3. 总结:
本设计利用单片机AT89C512控制LCD显示屏显示,实现字符显示功能。
该电路使用简单MCU控制,为单片机节省大量的接口资源,可以利用LCD显示屏显示你想要的字符或者数字。
该LCD功能强大,性能优越,能为很多领域,特别是在字符显示方面有优越性。
4.总机图:
5.PCB图
6.元器件清单列表
7.主程序:
#include <reg52.h>
#include <intrins.h>
unsigned char code one[]="DianziB1121:"; unsigned char code two[]="I love you"; sbit RS=P2^0;
sbit RW=P2^1;
sbit E=P2^2;
void busy()
{
unsigned char x;
do {
RW=1;
_nop_();
RS=0;
_nop_();
E=1;
_nop_();
x=P0;
_nop_();
E=0;
_nop_();
RW=0;
_nop_();
x=x&0x80;
}
while(x!=0);
}
void delay(unsigned int ms)
{
unsigned int a,b;
for(a=ms;a>0;a--)
for(b=110;b>0;b--);
}
void write_date(unsigned char shuju) {
RS=1;
P0=shuju;
E=1;
delay(1);
E=0;
}
void write_LCD(unsigned char date) {
busy();
RW=0;
RS=0;
E=1;
P0=date;
delay(1);
E=0;
RW=1;
delay(2);
}
void initLCD()
{
write_LCD(0x38);
write_LCD(0x0c);
write_LCD(0x06);
write_LCD(0x01);
write_LCD(0x80);
}
void main()
{
unsigned char i;
initLCD(); //初始化LCD
write_LCD(0x01);
for(i=0;i<11;i++) //写入第一行数据不变{
busy();
write_date(one[i]);
}
while(1)
{
write_LCD(0x80+0x40);
delay(100);
for(i=0;i<10;i++) //写入第二行数据
{
busy();
write_date(two[i]);
delay(250);}delay(50);
write_LCD(0x80+0x40);
for(i=0;i<10;i++) //显示空格相当于清屏
{
busy();write_date(' ');
}
}
}
8.参考文献:
【1】陈绍尔等编著·电子控制电路实例·电子工业出版社·2004
【2】刘修文等主编·新编电子控制电路300例·机械工业出版社·2005 【3】童诗白等编著·模拟电子技术·高等教育出版社·2006
【4】阎石主编·数字电子技术基础·高等教育出版社·2006
【5】赵建领主编·51系列单片机开发宝典·电子工业出版社·2012。