lcd实时日历时钟报告
实时时钟设计试验报告

实验报告5.按下Key4 Key3执行时,该按键执行加一操作,Led灯按照5秒顺时针一个一个亮。
6.按下Key5 Key3执行时,该按键执行减一操作,Led灯按照5秒顺时针一个一个亮。
7.按下Key6 Key3执行时,该按键执行确定操作,Led灯按照5秒顺时针一个一个亮。
8.按下INT 闹钟关闭。
5、实验总结本次实验是对课本上“电子日历钟设计”的加深。
通过本次试验我对led和led显示有了更加熟悉的认识,能熟练应用它们的功能。
同时我对时钟计数器也有了一定的认识,可以使用定时中断实现实时时钟,更重要的是我的实践能力有很大的提高。
程序设计中遇到的问题(1)、问题:初始完成程序后秒针走的时间很快,不是精确的一秒走一次。
原因:单片机只能用主系统时间,修改fprs后可以真确显示。
(2)、问题:时间切换函数与显示函数和设计的不一样,如只需要显示时,却多显示分。
原因:在仔细看代码后发现每次按键中断都在调用time1()函数,而seeond++在里面,所以每次都会加快秒的运行。
把seeond++移到外面放入time()函数后这个问题就解决了。
(3)、问题:运行时发现按键中断总会加快秒的运行,不是很精确。
原因:最后设置了一个虚拟的key7,当执行完时间指向ease7,然后调用Freshddisplaybuffer函数,这样就很好的解决了这个问题。
在程序调试过程中,设置断点并且在断点处增加一个LED灯,通过判断灯是否亮可以判断程序是否执行到该位置,对程序调试有很大的帮助。
开始WhileKey? 6 1 3 2 4 结束主程序流程图附件程序流程图:Yd_c_inter() Freshddisp laybuffer(); Set_D_T(); noise(); key=7; , 5 NDownNum() ; Freshddispl aybuffer(); Set_D_T(); noise(); key=7; FreshddisplaybufferTime1();Show_Time();Show_Time(); Time1() Freshddis playbuffer ();; Display_D ate(); noise(); 初始化蜂鸣器并关闭蜂鸣器BZOE = 0;初始化 INT 按键 Init_Inter();初始化 Lcd 和 Led; Init_Lcd(),Init_Led();UpNum(); Freshddis playbuffer (); Set_D_T(); noise(); key=7; key = 0; noise(); Time1(); Freshddis playbuffer (); Set_D_T(); noise();初始化按键中断InitKey_INTKR();Time1(); noise();关中断DI ()关中断EI()开中断EI();源代码:#pragma sfr#pragma EI#pragma DI#pragma access#pragma interrupt INTTM000 Time#pragma interrupt INTKR OnKeyPress#pragma interrupt INTP5 OnKeyOver void Init_Led();void InitKey_INTKR();void Init_Lcd();void Init_Inter();void LightOneLed(unsigned char ucNum);void LightOff();int Count_Day(int month);〃定义变量i,是切换时间的标志//定义 key=0 〃用于存放当前月的天数 〃默认的秒second=0 〃默认的分minute=0 〃默认的时hour=12 〃默认的天day=1 〃默认的月month=5 〃默认的年year=2014 〃默认的闹钟时=1 〃默认的闹钟分=1 〃秒的数码显示缓存区 〃分的数码显示缓存区 〃时的数码显示缓存区 〃天的数码显示缓存区 〃月的数码显示缓存区 〃年的数码显示缓存区 〃月,天的数码显示缓存区 〃时,分的数码显示缓存区 〃分,秒的数码显示缓存区 〃闹钟时的数码显示缓存区 〃闹钟分的数码显示缓存区 //INT 中断中间变量LCD_num[10]={0X070d,0x0600,0x030e,0x070a,0x0603,0x050b,0x050f,0x0700,0x070f,0x070b);//数字0〜〜9的显示码unsigned char Scond;// ......................................................... 延时函数1 .............................................. //void Delay(int k){int i,j;for(i=0;i<k;i++){for(j=0;j<k;j++){〃使用特殊功能寄存器 〃开中断 〃关中断 〃使用绝对地址指令 〃定义时间中断函数为Time 〃定义按键中断为OnKeyPress //定义INT 中断为OnKeyOverchar i=0;int key=0;int temp=1;int temp1 = 1;int second=0;int minute=0;int hour=12;int day=1;int month=5;int year=2014;int c_hour=1;int c_minute=1;int buffs[2];int buffm[2];int buffh[2];int buffday[2];int buffmonth[2];int buffyear[4];int buffmd[4];int buffhm[4];int buffms[4];int buffch[2];int buffcm[2];unsigned char Que = 0;int// .................................................. 初始化Led函数................ //void Init_Led(){PM13=0XF0; 〃端口13的第四位为输出模式PM14=0XF0; 〃端口14的第四位为输出模式PM15=0XF0; 〃端口15的第四位为输出模式)// ............................................................. 按键中断函数............... •//void InitKey_INTKR(){PM4 = 0x3F; //P4的六个端口设置为输入模式PU4 = 0x3F; 〃接通上拉电阻KRM = 0x3F; 〃允许六个按键中断KRMK = 0;PM3.0 = 1;PU3.0 = 1;EGP.5 = 1;PMK5 = 0;PPR5 = 0;KRPR = 1;)// ............................... 初始化lcd函数............... //void Init_Lcd(){ PFALL=0x0F; 〃所有接lcd引脚指定为lcd引脚LCDC0=0x34; 〃设置原时钟和时钟频率LCDMD=0x30; //设置lcd电压为3/5电压LCDM=0xC0; //4分时1/3偏压模式)// ............................... 初始化定时器Inter函数.............. 〃void Init_Inter(){ CRC00)=0; //CR000为比较寄存器PRM00=0X04; 〃计数时钟为fprs/2A8 CR000=0X7FFF;//时间间隔为1s TMMK010=1;//TMMK010 中断屏蔽TMMK000=0; //TMMK000 中断允许TMC00=0X0C; //TM00和CR000相等时进入清零&启动模式)void Time(){ second++;)// ............................................................. 按键中断函数............... •//void OnKeyPress(){DI();switch(P4&0x3F) 〃判断哪个按键按下{case 0x3e:key=1; //按键keyl按下break;case 0x3d:key=2; //按键key2按下break;case 0x3b:key=3; //按键key3按下break;case 0x37:key=4; //按键key4按下break;case 0x2f:key=5; //按键key5按下break;case 0x1f:key=7; //按键key6按下break;default:break;)EI();)// ............................................................... I NT按键中断函数............... //void OnKeyOver(){DI();Que = 0; //判断Que是否为0BZOE = 0; 〃蜂鸣器关闭EI();)// ................................................... Led小灯函数............... //void LightOneLed(unsigned char ucNum){switch(ucNum){ 〃检测变量ucNumcase 0:case 1:case 2:case 3:P13 |= (unsigned char) 1 << (ucNum);〃如果为0到3中的一个值则让LED1到LED4中的一个亮break;case 4:case 5:case 6:case 7:P14 |= (unsigned char) 1 << (ucNum - 4);〃如果为4到7中的一个值则让LED5到LED8中的一个亮break;case 8:case 9:case 10:case 11:P15 |= (unsigned char) 1 << (ucNum - 8);〃如果为8至U 11中的一个值则让LED9至U LED12中的一个亮break;default:break;))// ................................................... Led小灯熄灭函数............... 〃void LightOff(){P13 = 0;P14 = 0;P15 = 0;)// ............................................. 时间函数.............. 〃void Time1(){if((second % 5) == 0){ 〃秒大于 5 变为0Scond = second / 5 + 1;LightOff(); 〃调用小灯亮函数LightOneLed(Scond % 12);)if(second>=60){minute++; //秒大于60时分加1second=0;if(minute>=60){minute=0;hour++; //分大于60时时加1if(hour>=24){hour=0;day++; 〃时大于24时天加1temp=Count_Day(month);if(day>=temp){day=1;month++; 〃天大于当前月份的天数时月加1if(month>=13){month=1;year++; //月大于12时年加1))))))// ...................................... 计算当前月的天数.............. •//int Count_Day(int month){int day;if((month==4)||(month==6)||(month==9)||(month==11))//4,6,9,11 月为30 天day=30;else if(month==2){if((year%4==0&&year%100==0)||(year%400==0))day=29; 〃闰年2月29天elseday=28; //平年2月28天)elseday=31; //1,3,5,7,8,10,12 月为31 天return (day);)// ................................ 倒计时函数 ...... //void Show_Time(){ pokew(0xFA40,0x00); pokew(0xFA42,0x00); pokew(0XFA48,buffs[1]); pokew(0XFA4A,buffs[0]); pokew(0XFA44,buffm[1]); pokew(0XFA46,buffm[0]); pokew(0xFA4C,0x00); pokew(0xFA4E,0x00); Delay(100);) // ..................................................................... 日期显示函数 ................. •// void Display_Date(){buffm[0]|=0x0800;pokew(0xFA40,buffyear[3]);〃显示年 pokew(0xFA42,buffyear[2]);pokew(0xFA44,buffyear[1]);pokew(0xFA46,buffyear[0]);pokew(0xFA48,buffmonth[1]);〃显示月 pokew(0xFA4A,buffmonth[0]);pokew(0xFA4C,buffday[1]);〃显示日pokew(0xFA4E,buffday[0]);temp1=0;) // .................................................................... 时间显示函数 .............. •//void Display_Time(){ pokew(0xFA40,0x00);pokew(0xFA42,0x00);pokew(0xFA44,buffh[1]);〃显示时 pokew(0xFA46,buffh[0]);pokew(0xFA48,buffm[1]);〃显示分 pokew(0xFA4A,buffm[0]);pokew(0xFA4C,buffs[1]);〃显示秒 pokew(0xFA4E,buffs[0]);)// ..................................................................... 设定时间函数 .............. •//void Set_D_T(){int lcd_addr;lcd_addr = 0xFA40;switch(i){case 1:pokew(lcd_addr,buffyear[3]);〃时间年 pokew(lcd_addr+2,buffyear[2]);pokew(lcd_addr+4,buffyear[1]);pokew(lcd_addr+6,buffyear[0]);pokew(lcd_addr+8,0x00);pokew(lcd_addr+10,0x00);pokew(lcd_addr+12,0x00);pokew(lcd_addr+14,0x00);break;case 2:pokew(lcd_addr,0x00);pokew(lcd_addr+2,0x00);pokew(lcd_addr+4,0x00);pokew(lcd_addr+6,0x00);pokew(lcd_addr+8,buffmonth[1]);〃时间月 pokew(lcd_addr+10,buffmonth[0]);pokew(lcd_addr+12,0x00);pokew(lcd_addr+14,0x00);break;case 3:pokew(lcd_addr,0x00); //在lcd 右边显示1〃在lcd 右边显示0 〃在lcd 右边显示1 〃在lcd 右边显示0pokew(lcd_addr+2,0x00);pokew(lcd_addr+4,0x00);pokew(lcd_addr+6,0x00);pokew(lcd_addr+8,0x00);pokew(lcd_addr+10,0x00);pokew(lcd_addr+12,buffday[1]); 〃时间日pokew(lcd_addr+14,buffday[0]);break;case 4:pokew(lcd_addr,0x00);pokew(lcd_addr+2,0x00);pokew(lcd_addr+4,buffh[1]); 〃时间时pokew(lcd_addr+6,buffh[0]);pokew(lcd_addr+8,0x00);pokew(lcd_addr+10,0x00);pokew(lcd_addr+12,0x00);pokew(lcd_addr+14,0x00);break;case 5:pokew(0xFA40,0x00);pokew(0xFA42,0x00);pokew(0xFA44,0x00);pokew(0xFA46,0x00);pokew(0xFA48,buffm[1]); 〃时间分pokew(0xFA4A,buffm[0]);pokew(0xFA4C,0x00);pokew(0xFA4E,0x00);break;case 6:pokew(0xFA40,0xd1);pokew(0xFA42,0xd0);pokew(0xFA44,0xd7);pokew(0xFA46,0xd1);pokew(0xFA48,0x50);pokew(0xFA4A,0x56);pokew(0xFA4C,buffch[1]); 〃闹钟时pokew(0xFA4E,buffch[0]);break;case 7:pokew(0xFA40,0xd1);pokew(0xFA42,0xd0);pokew(0xFA44,0xd7);pokew(0xFA46,0xd1);pokew(0xFA48,0x50);pokew(0xFA4A,0x00);pokew(0xFA4C,buffcm[1]); 〃闹钟分pokew(0xFA4E,buffcm[0]);break;default:break;))// ........................................................ 切换时间函数 .............. …// void d_c_inter(){DI(); 〃关中断i++;if(i>7) 〃切换标志>7, i=1,否则i++i=1;EI(); 〃开中断)// ........................................................ 调整时间加函数 .............. •// void UpNum(){ switch(i){ case 1:year++;case 2:month++;if(month > 12){month = 1;)break;case 3:temp = Count_Day(month);day++;if(temp < day)day = 1;break;case 4:hour++;if(hour > 23)hour = 1;break;case 5:minute++;if(minute > 59)minute = 0;break;case 6:c_hour++;if(c_hour > 23)c_hour = 1;break;case 7:c_minute++;if(c_minute > 59)c_minute = 0;break;default:break;))// ........................................................ 调整时间减函数.............. …// void DownNum(){switch(i){case 1:year--;case 2:month--;if(month < 1){month = 12;)break;case 3:temp = Count_Day(month);day--;if(day < 1)day = temp;break;case 4:hour--;if(hour < 1)hour = 23;break;case 5:minute--;if(minute < 0)minute = 59;break;case 6:c_hour--;if(c_hour < 1)c_hour = 23;break;case 7:c_minute--;if(c_minute < 0)c_minute = 59;break;default: break;))// .................................................. 闹铃以及小灯函数.............. •//void noise(){if(c_hour == hour && c_minute == minute && Que == 1){ 〃闹铃的时,分与系统时,分相等,并且闹钟标志开启CKS=0XE0; 〃开启蜂鸣器输出,输出频率为0.98khz的音频Time1(); 〃调用时间函数))// ........................................................ 显示缓存区刷新时间函数.............. •//void Freshddisplaybuffer(){buffs[1]=LCD_num[second/10];/期的显示码放入秒的数码显示缓存区buffs[0]=LCD_num[second%10];buffm[1]=LCD_num[minute/10];//分的显示码放入分的数码显示缓存区buffm[0]=LCD_num[minute%10];buffm[0]|=0x0800; 〃分的后面显示一个"."buffh[1]=LCD_num[hour/10]; 〃时的显示码放入时的数码显示缓存区buffh[0]=LCD_num[hour%10];buffh[0]|=0x0800; 〃时的后面显示一个"."buffday[1]=LCD_num[day/10];//天的显示码放入天的数码显示缓存区buffday[0]=LCD_num[day%10];buffmonth[1]=LCD_num[month/10];//月的显示码放入月的数码显示缓存区buffmonth[0]=LCD_num[month%10];buffmonth[0]|=0x0800; 〃月的后面显示一个"."buffyear[3]=LCD_num[year/100/10];/^的显示码放入年的数码显示缓存区buffyear[2]=LCD_num[(year/100)%10];buffyear[1]=LCD_num[(year%100)/10];buffyear[0]=LCD_num[(year%100)%10];buffyear[0]|=0x0800; 〃年的后面显示一个"."buffmd[3]=LCD_num[month/10];//月,天的显示码放入月,天的数码显示缓存区buffmd[2]=LCD_num[month%10];buffmd[2]|=0x0800; 〃月,天后显示一个"."buffmd[1]=LCD_num[day/10];buffmd[0]=LCD_num[day%10];buffhm[3]=LCD_num[hour/10];//时,分的显示码放入时,分的数码显示缓存区buffhm[2]=LCD_num[hour%10];buffhm[2]|=0x0800; 〃时,分的后显示一个"."buffhm[1]=LCD_num[minute/10];buffhm[0]=LCD_num[minute%10];buffms[3]=LCD_num[minute/10];/^,秒的显示码放入分,秒的数码显示缓存区buffms[2]=LCD_num[minute%10];buffms[2]|=0x0800; 〃分,秒的后显示一个"."buffms[1]=LCD_num[second/10];buffms[0]=LCD_num[second%10];buffch[1]=LCD_num[c_hour/10];//闹钟时的显示码放入闹钟时的数码显示缓存区buffch[0]=LCD_num[c_hour%10];buffcm[1]=LCD_num[c_minute/10];//闹钟分的显示码放入闹钟分的数码显示缓存区buffcm[0]=LCD_num[c_minute%10];)// ................................. 主函数............... 〃void main(){DI(); 〃关中断PM3.4 = 0; //P3.3,P3.4端口设置为输出模式P3.4 = 1; //led灯初始化为点亮状态PM3.3 = 0;P3.3 = 0;BZOE = 0; 〃蜂鸣器初始化为熄灭Init_Lcd(); 〃初始化lcdInit_Led(); 〃初始化ledInitKey_INTKR(); 〃初始化按键EI(); 〃开中断Init_Inter(); //初始化中断while(1){ Time1(); noise(); switch(key){ case 0: Freshddisplaybuffer(); Time1(); Show_Time();Show_Time(); break; case 1:Time1();Freshddisplaybuffer(); Display_Date(); noise();break;case 2:Time1();Freshddisplaybuffer(); Display_Time(); noise();break;case 3:d_c_inter();Freshddisplaybuffer(); Set_D_T();noise();key=7; break;case 4:UpNum();Freshddisplaybuffer(); Set_D_T();noise();key=7; break;case 5:DownNum();Freshddisplaybuffer(); Set_D_T();noise();key=7; break;case 6:key = 0;if(i > 5)Que = 1;1 = 0;noise();case 7:Time1();Freshddisplaybuffer(); Set_D_T(); 〃调用计算时间函数 〃调用闹钟函数 〃没有按键执行 〃调用刷新函数 〃计算时间 〃调用显示时间函数 //按键1执行 〃计算时间 〃调用刷新函数 〃调用显示日期函数 〃调用闹钟函数 //按键2执行 //计算时间 //调用刷新函数 //调用时间显示函数 //调用闹钟函数 //按键3执行 〃调用时间切换函数 //调用刷新函数 〃调用时间设置函数 //调用闹钟函数 //按键4执行 〃调用时间加函数 //调用刷新函数 //调用时间设置函数 //调用闹钟函数 //按键5执行〃调用时间减函数 //调用刷新函数 //调用时间设置函数//调用闹钟函数//按键6执行〃判断是否确认 //调用闹钟函数〃虚拟按键7 //调用刷新函数//调用时间设置函数〃调用闹钟函数noise();break;。
LCD显示实时时钟

1 仿真实验环境1.1采用Proteus6_9_SP5实现单片机及外围器件的仿真如图:1.2使用Keil uVision3编写本日历程序(C语言)如图:2 原理图2.1各部分功能实现:1.以AT89C52作为控制核心,通过P0口连接LM016L液晶的并行数据输入/输出端进行显示数据以及命令的发送与接收。
P2.0、P2.1和P2.2分别连接液晶的数据/命令选择端、读/写控制以及使能端。
通过对这三个端口的操作,来实现液晶的正确显示。
2.DS18B20数字温度传感器以单总线的方式连接到P2.3口,通过正确的时序操作,与单片机进行双向通信,把温度值以串行数字形式发送给单片机。
再正确显示在LCD上。
3.LED灯连接P2.4口,在相应的时间或温度触发下通过电平的高低变化闪烁。
4.单片机的P2.5、P2.6、P2.7分别连接DS1302时钟芯片的复位端、时钟信号以及I/O端。
在相应时序信号的控制下,读出芯片中的内容,并显示在LCD上。
5.该日历的功能操作通过连接在P3.0~P3.3的四个按键实现,四个按键分别为:进入/退出模式键、功能选择键、时加/温度加一键、分加/温度减一键。
6.因为P0口没有上拉电阻,所以加了排阻。
3 程序分析及代码3.1程序分析:3.1.1 程序的优点:1.以模块化的形式把程序分为若干个独立部分。
2.在程序中使用了指针、数组、函数等结合的方法,简化了部分程序。
3.程序中首次使用了二维字符数组的相关操作。
3.1.2 程序的缺点:1.程序总体上写的不够简练。
2.程序的部分功能操作麻烦,如调时或闹钟设置时对时、分的操作只能加。
3.程序的稳定性有待于提高。
4.过多的变量、标志位的定义降低了程序的可读性。
3.1.3 总结:通过该日历程序的编写,自身发现了许多的问题,现总结如下:1.在编写程序的过程中一定要做好程序的备份。
2.在编写某功能函数之前要想好流程再写,最好写出流程图。
3.一定要多写注释,不然连自己都读不懂自己的程序。
单片机电子时钟(LCD显示)综合实验报告

单片机综合实验报告题目:电子时钟(LCD)显示一、实验内容:以AT89C51单片机为核心的时钟,在LCD显示器上显示当前的时间:●使用字符型LCD显示器显示当前时间。
●显示格式为“时时:分分:秒秒”。
●用4个功能键操作来设置当前时间,4个功能键接在P1.0~P1.3引脚上。
功能键K1~K4功能如下。
●K1—进入设置现在的时间。
●K2—设置小时。
●K3—设置分钟。
●K4—确认完成设置。
程序执行后工作指示灯LED闪动,表示程序开始执行,LCD显示“00:00:00”,然后开始计时。
二、实验电路及功能说明1)单片机主控制模块以AT89C51单片机为核心进行一系列控制。
2)时钟显示模块用1602为LCD显示模块,把对应的引脚和最小系统上的引脚相连,连接后用初始化程序对其进行简单的功能测试。
测试成功后即可为实验所用,如图:3)时间调整电路用4个功能键操作来设置当前时间,4个功能键接在P1.0~P1.3引脚上。
功能键K1~K4功能如下。
K1—进入设置现在的时间。
K2—设置小时。
K3—设置分钟。
K4—确认完成设置。
如图:三、实验程序流程图:主程序:时钟主程序流程子程序:四、实验结果分析实验结果及分析:单片机的晶振可以根据要求设定。
6MHZ为和现实时间显示相同。
实验采用12MHZ晶振采用方式1定时,选取50ms采用20次中断达到一秒,采用查表方式控制LCD显示。
当烧入程序后开始运行,根据初始值设定可以观察到显示的时间,这里为了更明显观察显示数据变化把起始值设为23:59:50 运行后显示,K1为进入现在设置时间,当按下K1后显示,和实验要求相比较,实现了按下K1进入现在时间设置,按下K4确认完成时间设置的功能;不同之处: 当进入时间设置时在按下K1设置小时,再次按下K1是设置分钟。
增加功能:进入时间设置并选择设置位置后K2键位数字增加功能,K3键为数字减小功能。
根据仿真结果能够确定编程正确,基本实现了所有功能,而且有所改进。
实时日历时钟显示毕业设计

湖南工程职业技术学院HUNAN ENGINEERING POLYTECHNIC 毕业设计(论文)设计(论文)题目:实时日历时钟显示信息工程系二○一二年五月制2012年5月21日2.选题依据、主要研究内容、研究思路及方案。
在当代繁忙的工作与生活中,时间与我们每一个人都有非常亲密的关系,每个人都受到时间的影响,为了更好的利用我们自己的时间,我们必须对时间有一个度量,因此产生了钟表。
随着社会、科技的发展,人类不断研究、创新。
为了在观测时间的同时能够了解其他与人类密切相关的信息,比如星期、日期等,实时日历时钟诞生了。
随着生活水平的提高,人们越来越追求人性化的事物,传统的时钟已不能满足人们的需求。
单片机技术,增加了调时的功能。
其电路可以由实时时钟模块、人机接口模块,、时钟模块数码管显示模块等部分组成。
利用软件编程尽量做到硬件电路简单稳定,减小电磁干扰和其他环境干扰,充分发挥软件编程的优点。
减小因元器件精度不够引起的误差,但是数字钟还是可以改进和提高如选用更精密的元器件,但与机械式时钟相比已经具有更高的准确性和直观性,且无机械装置具有更长的使用寿命,因此广泛应用于个人家庭、车站、办公室等公共场所,成为人们日常生活中的必需品。
单片机由于体积小、价格低、功耗低、控制功能强且控制逻辑可由软件来实现,可以很方便地完成由一般数字电路很难实现的控制逻辑。
因此,本课题研究的主要目的就是设计一个基于单片机的日历时钟系统,完成对日历时钟的显示,以及在正常工作情况下随时可进行调时、调分、调秒和日期的设置,所设计的实时日历时钟系统将具有以下功能:可以对每月天数进行调整,时钟运行的是 24 小时制,显示满刻度为23时59分59秒。
其中调时功能通过按键实现。
课题需要完成单片机与时钟芯片之间的通信,以及单片机对调时键盘的扫描,以及控制显示电路进行时间显示功能。
本设计采用AT89S52 芯片作为硬件核心,具有功耗小,能以 3V 的超低电压工作,该芯片内部存储器为 8KB ROM 存储空间,同时具有 AT89C51 的功能,且具有在线编程可擦除技术,所以不会对芯片造成损坏。
LCD显示的定时闹钟设计方案

LCD显示的定时闹钟设计方案1.设计要求使用AT89C51单片机结合字符型LCD显示器设计一个简易的定时闹钟LCD 时钟,若LCD选择有背光显示的模块,在夜晚或黑暗的场合中也可使用。
定时闹钟的基本功能如下:显示格式为“时时:分分”。
由LED闪动来做秒计数表示。
一旦时间到则发出声响,同时继电器启动,可以扩充控制家电开启和关闭。
程序执行后工作指示灯LED闪动,表示程序开始执行,LCD显示“ 00:00”,按下操作键K1〜K4动作如下:(1)K1 —设置现在的时间。
(2)K2 —显示闹钟设置的时间。
(3)K3 —设置闹铃的时间。
⑷K4 —闹铃ON/OFF勺状态设置,设置为ON时连续三次发出“哗”的一声,设置为OFF发出“哗”的一声。
设置当前时间或闹铃时间如下。
(1)K1 —时调整。
(2)K2 —分调整。
(3)K3 —设置完成。
(4)K4 —闹铃时间到时,发出一阵声响,按下本键可以停止声响。
本项目的难点在于4 个按键每个都具有两个功能,以最终实现菜单化的输入功能。
采用通过逐层嵌套的循环扫描,实现嵌套式的键盘输入。
2.设计方案2.1 原理本LCD定时闹钟,是以单片机及外围接口电路为核心硬件,辅以其他外围硬件电路,用汇编语言设计的程序来实现的。
根据C51单片机的外围接口特点扩展相应的硬件电路,然后根据单片机的指令设计出数字钟相应的软件,再利用软件执行一定的程序来实现数字钟的功能。
由于采用集成芯片性的单片机来制作电子钟,这样设计制作简单而且功能多、精确度高,也可方便扩充其他功能,实现也十分简单。
本设计是利用AT89C51单片机为主控芯片,由LCD晶振、电阻、电容、发光二极管、开关、喇叭等元件组成硬件电路,通过编写软件程序来实现和控制的数字定时闹钟2.2系统总框图2.3原理及工作过程说明(1)定时闹钟的基本功能如下:(a)启动仿真软件,使用LCD液晶显示器来显示现在的时间。
(b)程序执行之后显示“ 00:00”并且LED闪烁,表示开始已经计时。
LCD12864显示实时时钟例程可运行

DS1302是美国DALLAS公司推出的一种高性能、低功耗的实时时钟芯片,附加31字节静态RAM,采用SPI三线接口与CPU进行同步通信,并可采用突发方式一次传送多个字节的时钟信号和RAM数据。
实时时钟可提供秒、分、时、日、星期、月和年,一个月小与31天时可以自动调整,且具有闰年补偿功能。
下面是一段12864液晶显示实时时钟的程序:/****************************************************************************** *********时间:2012.11.30晶振:11.0592MHz芯片:STC89C52RC功能描述:在12864上显示年、月、日、星期、时、分和秒等时间信息******************************************************************************* ********/#include<reg52.h>#define uchar unsigned charsbit CLK=P1^4; //DS1302引脚定义sbit IO=P1^5;sbit CE=P1^6;sbit ACC0=ACC^0;sbit ACC7=ACC^7;sbit RS=P2^4; //12864引脚定义数据口为P0sbit RW=P2^5;sbit EN=P2^6;sbit PSB=P2^1;sbit RET=P2^3;void Input_1byte(uchar TD) //DS1302输入一字节数据{uchar i;ACC=TD;for(i=8;i>0;i--){IO=ACC0;CLK=1;CLK=0;ACC=ACC>>1;}}uchar Output_1byte(void) //DS1302输出一字节数据{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)//向DS1302写{CE=0;CLK=0;CE=1;Input_1byte(add);Input_1byte(dat);CE=0;}uchar Read_DS1302(uchar add) //从DS1302读{uchar inf; //信息临时存储变量CE=0;CLK=0;CE=1;Input_1byte(add);inf=Output_1byte();CE=0;return(inf);}/**********************DS1302初始化*****************************/void init_1302(){if(Read_DS1302(0xd1)==0x55) //判断内存单元的内容,是否进行初始化 {return;}else{Write_DS1302(0x8e,0x00); //关闭写保护Write_DS1302(0x90,0x00); //电池充电设置Write_DS1302(0x80,0x00); //秒Write_DS1302(0x82,0x54); //分Write_DS1302(0x84,0x20); //时Write_DS1302(0x86,0x30); //日Write_DS1302(0x88,0x11); //月Write_DS1302(0x8a,0x05); //星期Write_DS1302(0x8c,0x12); //年Write_DS1302(0xd0,0x55); //写RAMWrite_DS1302(0x8e,0x80); //打开写保护}}/**********************延时函数*****************************/ void DelayUs2x(unsigned char t){while(--t);}void DelayMs(unsigned char t){while(t--){//大致延时1mSDelayUs2x(245);DelayUs2x(245);}}/**********************12864判忙*****************************/ void check_busy(){RS=0;RW=1;EN=1;while((P0&0x80)==0x80);EN=0;}/**********************12864写指令*****************************/ void write_com(uchar com){check_busy();RS=0;RW=0;EN=1;P0=com;DelayUs2x(250);EN=0;DelayUs2x(250);}/**********************12864写数据*****************************/void write_data(uchar dat){check_busy();RS=1;RW=0;EN=1;P0=dat;DelayUs2x(250);EN=0;DelayUs2x(250);}/**********************12864初始化函数*****************************/void init(){DelayMs(40); //大于40MS的延时程序PSB=1; //设置为8BIT并口工作模式DelayMs(1); //延时RET=0; //复位DelayMs(1); //延时RET=1; //复位置高DelayMs(200);write_com(0x30); //选择基本指令集DelayUs2x(250); //延时大于100uswrite_com(0x30); //选择8bit数据流DelayUs2x(200); //延时大于37uswrite_com(0x0c); //开显示(无游标、不反白)DelayUs2x(250); //延时大于100uswrite_com(0x01); //清除显示,并且设定地址指针为00HDelayMs(200); //延时大于10mswrite_com(0x06); //指定在资料的读取及写入时,设定游标的移动方向及指定显示的移位,光标从右向左加1位移动DelayUs2x(250); //延时大于100us}/**********************清屏*****************************/void clrscreen(){write_com(0x01);DelayMs(15);}/*********************************************************主函数********************************************************/void main(){uchar sec,sec1,sec2;uchar min,min1,min2;uchar hour,hour1,hour2;uchar date,date1,date2;uchar mon,mon1,mon2;uchar day;uchar year,year1,year2;uchar table1[]="年月日时分秒星期温度摄氏"; //长度24uchar table2[]={0XD2,0XBB, 0XB6,0XFE, 0XC8,0XFD, 0XCB,0XC4, 0XCE,0XE5, 0XCE,0XF9, 0XC8,0XD5}; //长度14 uchar table3[]="0123456789"; //长度10init(); //液晶初始化clrscreen();DelayMs(200);init_1302(); //1302初始化只初始化一下就可以需要下载两次DelayMs(50);write_com(0x80); //显示20write_data('2');write_data('0');write_com(0x82); //显示年write_data(table1[0]);write_data(table1[1]);write_com(0x84); //显示月write_data(table1[2]);write_data(table1[3]);write_com(0x86); //显示日write_data(table1[4]);write_data(table1[5]);write_com(0x91); //显示时write_data(table1[6]);write_data(table1[7]);write_com(0x93); //显示分write_data(table1[8]);write_data(table1[9]);write_com(0x95); //显示秒write_data(table1[10]);write_data(table1[11]);write_com(0x88); //显示星期write_data(table1[12]);write_data(table1[13]);write_data(table1[14]);write_data(table1[15]);while(1){sec=Read_DS1302(0x81); ////读秒sec1=sec&0x0f; //个位sec2=sec>>4; //十位min=Read_DS1302(0x83); ////读分min1=min&0x0f; //个位min2=min>>4; //十位hour=Read_DS1302(0x85); ////读时hour1=hour&0x0f; //个位hour2=hour>>4; //十位date=Read_DS1302(0x87); ////读日date1=date&0x0f; //个位date2=date>>4; //十位mon=Read_DS1302(0x89); ////读月mon1=mon&0x0f; //个位mon2=mon>>4; //十位year=Read_DS1302(0x8d); ////读年year1=year&0x0f; //个位year2=year>>4; //十位day=Read_DS1302(0x8b); ////读星期write_com(0x94); //送显示内容write_data(table3[sec2]); //秒write_data(table3[sec1]);write_com(0x92);write_data(table3[min2]); //分write_data(table3[min1]);write_com(0x90);write_data(table3[hour2]); //时write_data(table3[hour1]);write_com(0x85);write_data(table3[date2]); //日write_data(table3[date1]);write_com(0x83);write_data(table3[mon2]); //月write_data(table3[mon1]);write_com(0x81);write_data(table3[year2]); //年write_data(table3[year1]);write_com(0x8a);write_data(table2[2*day-2]); //星期write_data(table2[2*day-1]);}}。
用DS与LCD设计的可调式电子日历时钟的设计与实现PPT课件

7 D0 数据
15 BLA 背光源正极
8 D1 数据
16 BLK 背光源负极
第12页/共22页
LCD1
LM016L
R2
10k
K1
第13页/共22页
1 2 3
VSS VDD VEE
RS 4 RW 5 EN 6
RS RW E
D0 7 D1 8 D2 9 D3 10 D4 11 D5 12 D6 13 D7 14
P3.4/T0 P3.5/T1 P3.6/WR P3.7/RD
39 D0 38 D1 37 D2 36 D3 35 D4 34 D5 33 D6 32 D7
21
RS
22
RW
23
EN
24
25
26
27
28
10 11 12 13 14 15 16 17
U3
AND_4
R2
10k
K1 K2 K3 K4
RS 4 RW 5 EN 6
VSS VDD VEE
D0 7 D1 8 D2 9 D3 10 D4 11 D5 12 D6 13 D7 14
RS 4 RW 5 EN 6
1 2 3
R2
10k
K1
第2页/共22页
RP1
1
D0 2 D1 3 D2 4 D3 5 D4 6 D5 7 D6 8 D7 9
RESPACK-8
(2)显示日历时钟初始值:年、月、日、星期、时、分、秒
第9页/共22页
第10页/共22页
◆液晶显示模块
LCD是一种功耗极低的显示器件,广泛应 用于便携式电子产品中。它不仅省电,而且能 够显示大量的信息,是一种专门用于显示字母、 数字、符号等点阵式LCD,目前常用16*1, 16*2,20*2和40*2行等模块。
实时时钟设计试验报告

实时时钟设计试验报告一、实验目的本实验的目的是设计一个实时时钟系统,具有实时显示时间、日期和闹钟功能。
通过该实验,我们可以了解实时时钟的设计原理、硬件电路连接及软件程序编写方法。
二、实验原理实时时钟系统由时钟芯片、显示模块、按键模块和控制模块组成。
时钟芯片负责计时和日期的记录,显示模块用于显示时间和日期,按键模块用于设置时间和日期,控制模块用于控制各模块之间的协作。
三、实验器材1.STM32开发板2.DS3231时钟模块3.数码管显示模块4.按键模块5.连接线四、实验步骤1.连接硬件电路。
将STM32开发板与DS3231时钟模块、数码管显示模块和按键模块进行连接,确保电路连接正确无误。
2.编写程序。
使用C语言编写程序,通过读取DS3231时钟模块的寄存器获取时间和日期数据,并将其显示在数码管模块上。
同时,设置按键模块的功能,使其可以进行时间和日期的设置。
3.烧录程序。
使用烧录器将编写好的程序烧录到STM32开发板上,并进行调试。
4.运行实验。
接通电源,启动实时时钟系统,观察数码管是否正确显示时间和日期,按下按键模块进行时间和日期的设置,并观察设置是否生效。
五、实验结果经过实验,我们成功设计出了一个实时时钟系统。
系统能够实时地显示当前的时间和日期,并且可以通过按键进行时间和日期的设置。
在设置新的时间和日期后,系统能够正确地更新并显示。
六、实验总结通过本次实验,我们深入地了解了实时时钟系统的设计原理和实现方法。
我们熟悉了DS3231时钟模块的使用方法,并学会了通过C语言编写程序来实现实时时钟系统的功能。
同时,我们也发现了实时时钟系统的一些问题,并加以解决。
我们对实时时钟系统的稳定性和精确性进行了测试,发现系统的计时精度较高,能够达到亚秒级的准确度。
然而,在用户进行时间和日期的设置时,可能由于误操作导致时间和日期出错。
需要在后续的工作中进一步优化系统的操作界面,提高用户设置的便捷性和准确性。
总而言之,实时时钟系统是一种非常有实用价值的设计,可以广泛应用于各种计时需求的场合,如办公室、实验室、车载设备等。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
课程设计说明书课程名称:单片机原理及应用设计题目:LCD日历院系:学生姓名:学号:专业班级:2011年3月1日目录摘要 (4)一.设计任务和要求 (4)二.方案论证 (4)三.核心元件的性能 (4)1.AT89C51 (4)1.1 功能特性概括: (5)1.2 管脚说明: (5)2.DS1302 (7)2.1 DS1302引脚功能 (7)2.2 DS1302的控制字 (8)2.3 DS1302的寄存器 (9)2.4 DS1302的数据输入输出 (10)四.理论分析与计算 (12)五.电路与程序设计 (12)1.系统硬件设计 (12)1.1系统总原理图 (12)1.2 主控部分(单片机MCS-51) (12)1.3 计时部分(实时时钟芯片DS1302) (13)1.4 Proteus仿真图 (13)2.系统软件设计 (14)2.1 程序流程图 (13)2.2 程序源代码 (13)六.结果分析 (23)七.设计体会总结 (24)参考文献 (25)摘要此次课程设计的要求是通过LCD与单片机的连接模块能够显示数字(如时间)、字符(如英文)和图形等,这就需要专门的时钟芯片-----DS1302。
DS1302是一种高性能、低功耗、带RAM的实时时钟芯片,它能够对时,分,秒进行精确计时,它与单片机的接口使用同步串行通信,仅用3条线与之相连接,就可以实现MCS-51单片机对其进行读写操作,把读出的时间数据送到LM044L上显示。
程序运行时,必须先对LM044L进行初始设置,然后,通过单片机从DS1302中获取时间并通过LM044L显示。
同时,进行循环赋值,使LCD 动态显示当前的时间。
关键字:AT89C51、DS1302,LM044L显示器一.设计任务和要求1.利用DS1302实现年月日时分秒,并用LCD显示。
2.通过LCD模块与单片机的接口,能显示数字(如时间)、字符(如英文)。
3. 硬件设计部分,根据设计的任务选定合适的单片机,根据控制对象设计接口电路。
设计的单元电路必须有工作原理,器件的作用,分析和计算过程;4. 软件设计部分,根据电路工作过程,画出软件流程图,根据流程图编写相应的程序,进行调试并打印程序清单;5.原理图设计部分,根据所确定的设计电路,利用Protel工具软件绘制电路原理图,提供元器件清单。
6计算说明书部分包括方案论证报告打印版或手写版,程序流程图具体程序等7. 图纸部分包括具体电路原理图打印版8. 设计要求还包括利用一天时间进行资料查阅与学习讨论,利用5天时间在实验室进行分散设计,最后三天编写报告。
最后一天进行成果验收。
二.方案论证实现数字电子钟的设计有以下两种基本方案,现就两种基本方案的优劣进行具体论证,从而说明选择方案二的理由。
方案一:直接用单片机的内部定时器来实现时间。
该方案以MCS-51单片机为主控芯片,以MCS-51的内部定时器产生的1s中断作为时钟的驱动,然后再通LCD液晶显示器来组成数字钟电路。
但是此方案最大的缺点在于单片机89C51产生的1s中断存在误差,如果工作时间长的话,数字时钟显示的时间将会出现严重的偏差,不够精确。
方案二:使用串行接口时钟芯片DS1302设计时钟电路。
该设计方案以MCS-51单片机为主控芯片,以串行时钟芯片DS1302为核心计时芯片,然后再通过一个LCD液晶显示器组成数字时钟电路。
更重要的是,DS1302时钟芯片的加入大大提高了数字钟时间的准确性,而且该电路在断电后不丢失时间和数据信息时也使得该方案的研究与提升更具有开发的意义。
三.核心芯片功能介绍1.AT89C52AT89S52[3]美国ATMEL公司生产的低功耗,高性能CMOS 8位单片机,片内含4K BytesISP(In-system programmable)的可反复擦写1000次的Flash只读程序存储器,器件采用ATMEL公司的高密度、非易失性存储技术制造,兼容标准MCS-51指令系统及AT89C51引脚结构,芯片内集成了通用8位中央处理器和ISP Flash存储单元。
单片机AT89S51强大的功能可为许多嵌入式控制应用系统提供高性价比的解决方案。
AT89C51芯片的引脚结构如图1所示:1.1 功能特性概括:AT89S51提供以下标准功能:40个引脚、4K Bytes Flash片内程序存储器、128 Bytes的随机存取数据存储器(RAM)、32个外部双向输入/输出(I/O)口、5个中断优先级2层中断嵌套中断、2个数据指针、2个16位可编程定时/计数器、2个全双工串行通信口、看门狗(WDT)电路、片内振荡器及时钟电路。
此外,AT89S51可降至0Hz的静态逻辑操作,并支持两种软件可选的节电工作模式。
空闲模式下,图1 AT89C51引脚图CPU暂停工作,而RAM、定时/计数器、串行通信口、外中断系统可继续工作。
掉电模式冻结振荡器而保存RAM的数据,停止芯片其它功能直至外中断激活或硬件复位。
同时该芯片还具有PDIP、TQFP和PLCC等三种封装形式,以适应不同产品的需求。
1.2 管脚说明:P0口:P0口为一个8位漏级开路双向I/O口,也即地址/数据总线复用口。
作为输出口用时,能驱动8个TTL逻辑门电路。
对端口写“1”时,被定义为高阻输入。
在访问外部数据存储器或程序存储器时,这组口线分时转换地址(低8位)和数据总线复用,在访问期间激活内部上拉电阻。
在Flash编程时,P0口接收指令字节,而在程序校验时,输出指令字节,校验时,要求外接上拉电阻。
P1口:P1口是一个带内部上拉电阻的8位双向I/O口,P1口的输出缓冲级可驱动(吸收或输出电流)4个TTL逻辑门电路。
对端口写“1”,通过内部的上拉电阻把端口拉到高电平,此时可作输入口。
作输入口使用时,因为内部存在上拉电阻,某个引脚被外部信号拉低时会输出一个电流(I)。
IL在Flash编程和程序校验期间,P1接收低8位地址。
部分端口还有第二功能,如表1所示:表1 P1口部分引脚第二功能P2口:P2口是一个带有内部上拉电阻的8位双向I/O口, P2口的输出缓冲级可驱动(吸收或输出电流)4个TTL逻辑门电路。
对端口写“1”,通过内部的上拉电阻把端口拉到高电平,此时可作输入口。
作输入口使用时,因为内部存在上拉电阻,某个引脚被外部信号拉低时)。
会输出一个电流(IIL在访问外部程序存储器或16位地址的外部数据存储器(例如执行MOVX@DPTR指令)时,P2口送出高8位地址数据。
在访问8位地址的外部数据寄存器(例如执行MOVX@Ri指令)时,P2口线上的内容(也即特殊功能寄存器(SFR)区中P2寄存器的内容),在整个访问期间不改变。
在Flash编程或校验时,P2亦接收高位地址和其它控制信号。
P3口: P3口是一个带有内部上拉电阻的双向8位I/O口, P3口的输出缓冲级可驱动(吸收或输出电流)4个TTL逻辑门电路。
对P3口写“1”时,它们被内部的上拉电阻拉高并可作)。
为输入端口。
作输入口使用时,被外部信号拉低的P3口将用上拉电阻输出电流(IIL P3口除了作为一般的I/O口线外,更重要的用途是它的第二功能,如表2所示:P3口还接收一些用于Flash闪速存储器编程和程序校验的控制信号。
表2 P3口引脚第二功能RST:复位输入。
当振荡器工作时,RST引脚出现两个机器周期以上的高电平时间将使单片机复位。
WDT溢出将使该引脚输出高电平,设置SFR AUXR的DISRTO位(地址8EH)可打开或关闭该功能。
DISRTO位缺省为RESET输出高电平打开状态。
ALE/PROG:当访问外部存储器或数据存储器时,ALE(地址锁存允许)输出脉冲用于锁存地址的低8位字节。
即使不访问外部寄存器,ALE仍以时钟振荡频率的1/6输出固定的正脉冲信号,因此它可对外输出时钟或用于定时目的。
值得注意的是:每当访问外部数据存储器时将跳过一个ALE脉冲。
对Flash存储器编程期间,该引脚还用于输入编程脉冲(PROG)。
如有必要,可通过对特殊功能寄存器(SFR)区中的8EH单元的D0位置位,可禁止ALE操作。
该位置位后,只要一条MOVX和MOVC指令才会激活ALE。
此外,该引脚会被微弱拉高,单片机执行外部程序时,应设置ALE无效。
PSEN:程序存储允许(PSEN)输出是外部程序存储器的读选通信号,当AT89S51由外部程序存储器取指令(或数据)时,每个机器周期两次PSEN有效,即输出两个脉冲。
当访问外部数据存储器时,没有两次有效的PSEN信号。
EA/VPP:外部访问允许。
欲使CPU仅访问外部程序存储器(地址为0000H-FFFFH),EA 端必须保持低电平(接地)。
需要注意的是:如果加密位LB1被编程,复位时内部会锁存EA端状态。
如EA端保持高电平(接VCC端),CPU则执行内部程序存储器中的指令。
Flash存储器编程期间,该引脚用于施加+12V编程电压(VPP)。
XTAL1:反向振荡放大器的输入及内部时钟工作电路的输入端。
XTAL2:反向振荡放大器器的输出端。
2.DS1302DS1302[1]是美国DALLAS公司推出的一种高性能、低功耗、带RAM的实时时钟芯片,它可以对年、月、日、周日、时、分、秒进行计时,且具有闰年补偿功能,工作电压宽达2.5~5.5V。
时钟可工作在24小时格式或12小时(AM/PM)格式。
DS1302与单片机的接口使用同步串行通信,仅用3条线与之相连接。
可采用一次传送一个字节或突发方式一次传送多个字节的时钟信号或RAM数据。
DS1302内部有一个31×8的用于临时性存放数据的RAM寄存器。
DS1302是DS1202的升级产品,与DS1202兼容,但增加了主电源/后背电源双电源引脚,同时提供了对后背电源进行涓细电流充电的能力。
2.1 DS1302引脚功能DS1302的引脚功能如表3所示,管脚图如图2所示表3 DS1302引脚功能表CR图2 DS1302管脚图通过把RST输入驱动置高电平来启动所有的数据传送。
RST输入有两种功能:首先,RST接通控制逻辑,允许地址/命令序列送入移位寄存器;其次,RST提供了终止单字节或多字节数据的传送手段。
当RST为高电平时,所有的数据传送被初始化,允许对DS1302进行操作。
如果在传送过程中置RST为低电平,则会终止此次数据传送,并且I/O引脚变为高阻态。
上电运行时,在Vcc≥2.5V之前,RST必须保持低电平。
只有在SCLK为低电平时,才能将RST置为高电平。
2.2DS1302的控制字DS1302的控制字节如图3所示:图3控制字节如图控制字节的最高有效位(位7)必须是逻辑1,如果它为0,则不能把数据写入到DS1302中。
位6如果为0,则表示存取日历时钟数据,为1表示存取RAM数据;位5至位1指示操作单元的地址;最低有效位(位0)如为0表示要进行写操作,为1表示进行读操作,控制字节总是从最低位开始输出。