51单片机万年历

合集下载

基于51单片机的液晶显示万年历设计

基于51单片机的液晶显示万年历设计

基于51单片机的液晶显示万年历设计摘要随着社会的进步和发展,电子万年历作为日常计时工具被广泛地应用。

此电子万年历在硬件方面主要采用STC89C51单片机作为主控核心,由DS1302时钟芯片提供时钟及1602LCD液晶显示屏显示。

STC89C51单片机是由宏晶公司公司生产的,功耗小,电压可选用3.4v~5.5v电压供电;DS1302时钟芯片是美国DALLAS公司推出的低功耗实时时钟芯片,它可以对年、月、日、星期、时、分、秒进行计时,而且DS1302的使用寿命长,误差小;对于数字电子万年历采用直观的数字显示,数字显示是采用的1602LCD液晶显示屏来显示,可以同时显示年、月、日、星期、时、分、秒、温度等信息。

此外,该电子万年历在软件方面主要包括日历程序、时间调整程序,显示程序等。

所有程序编写完成后,在Keil软件中进行调试,确定没有问题后,烧写到单片机上进行测试。

本次课程设计主要由时钟芯片DS1302和温度传感器DS18B20采集数据到单片机进行处理再通过LCD1602显示出来,本设计主要研究了液晶显示器LCD及时钟芯片DS1302,温度传感器DS18B20与单片机之间的硬件互联及通信,对数种硬件连接方案进行了详尽的比较。

关键词:单片机;DS1302;DS18B20;LCD1602ABSTRACTWith the social progress and development, Electronic calendar is widely used as a daily timing tool. The electronic calendar in hardware using STC89C51 microcontroller as the main control center, provided by the DS1302 clock chip and 1602LCD LCD display. STC89C51 microcontroller is produced by the macro crystal company, small power consumption, the voltage can be choosen among 3.4V ~ 5.5V for power supply; DS1302 clock chip is a low power real-time clock chip produced by DALLAS, it can be a time of years,months,days,weeks,hours,minutes,seconds, and DS1302 has a long service life. The error is small; for the digital electronic calendar using visual digital display, 1602LCD digital display is used to display LCD screen that can display years, months, days, weeks, hours, minutes and seconds, temperature and other information. In addition, the electronic calendar mainly includes calendar program,time to adjust procedures,display program etc in sofeware. After the completion of all the procedures, in the Keil software debugging, determine no problem after, and burning to the microcontroller test.The curriculum design mainly by the clock chip DS1302 and temperature sensor DS18B20 collecting data to the microcontroller for processing and then through the LCD1602 display, this design mainly studies the liquid crystal display LCD and the clock chip DS1302, the hardware connection and communication between the temperature sensor DS18B20 and the MCU, a number of hardware connection scheme for a detailed comparison.Key words:SCM,DS1302,DS18B20,LCD1602目录第一章绪论 ------------------------------------------------------------------------------------------------------------ - 1 -1.1 单片机的概述------------------------------------------------------------------------------------------------- - 1 -1.1.1 单片机的概念 --------------------------------------------------------------------------------------- - 1 -1.1.2 单片机的特点 --------------------------------------------------------------------------------------- - 1 -1.2 课题背景 ------------------------------------------------------------------------------------------------------- - 1 -1.3 课题内容 ------------------------------------------------------------------------------------------------------- - 2 - 第二章设计要求和方案 --------------------------------------------------------------------------------------------- - 3 -2.1 设计要求 ------------------------------------------------------------------------------------------------------- - 3 -2.2 设计方案 ------------------------------------------------------------------------------------------------------- - 3 -2.2.1 单片机芯片的选择--------------------------------------------------------------------------------- - 3 -2.2.2 各模块方案选择 ------------------------------------------------------------------------------------ - 3 -2.3 工作原理 ------------------------------------------------------------------------------------------------------- - 4 - 第三章系统的硬件设计及实现------------------------------------------------------------------------------------ - 7 -3.1 电路设计原理框图 ------------------------------------------------------------------------------------------ - 7 -3.2 STC89C51单片机的介绍 ----------------------------------------------------------------------------------- - 7 -3.2.1 主要功能及性能参数 ----------------------------------------------------------------------------- - 7 -3.2.2单片机的引脚功能说明 --------------------------------------------------------------------------- - 8 -3.3 各模块电路的设计及原理图 ----------------------------------------------------------------------------- - 9 -3.3.1 时钟电路模块的设计 ----------------------------------------------------------------------------- - 9 -3.3.2 温度采集模块的设计及原理图 --------------------------------------------------------------- - 11 -3.3.3 显示模块的设计及原理 ------------------------------------------------------------------------- - 11 - 第四章系统的软件设计 -------------------------------------------------------------------------------------------- - 13 -4.1 程序流程框图------------------------------------------------------------------------------------------------ - 13 -4.2 时间调整程序流程图 -------------------------------------------------------------------------------------- - 14 - 第五章系统测试 ------------------------------------------------------------------------------------------------------ - 15 -5.1 硬件测试 ------------------------------------------------------------------------------------------------------ - 15 -5.2 软件测试 ------------------------------------------------------------------------------------------------------ - 15 - 第六章总结与致谢 --------------------------------------------------------------------------------------------------- - 17 -6.1 总结------------------------------------------------------------------------------------------------------------- - 17 -6.2 致谢------------------------------------------------------------------------------------------------------------- - 18 - 参考文献 ------------------------------------------------------------------------------------------------------------------- - 19 - 附录 ------------------------------------------------------------------------------------------------------------------------ - 21 - 附录一:实物图 --------------------------------------------------------------------------------------------------- - 21 - 附录二:源程序 --------------------------------------------------------------------------------------------------- - 23 -第一章绪论1.1 单片机的概述1.1.1 单片机的概念单片机即单片微型计算机,是把中央处理器、存储器、定时/计数器、输入输出接口都集成在一块集成电路芯片上的微型计算机。

51单片机12864万年历(图片+主要程序C语言)

51单片机12864万年历(图片+主要程序C语言)

51单片机做的12864万年历这是我花了一个星期时间做的万年历;一开始是一些图片,后面是这个制作的C语言源程序;希望大家稀饭:Main.c#include "reg52.h"#include "macroconst.h"#include "keyscan.h"#include "screen.h"#include "18b20.h"#include "ds1302.h"#include "atao_12864.h"#include "24c02.h"idata unsigned char state1[1];unsigned char screennum=1;//屏幕号#define time_task_sec 200 //节拍200Hz#define clock 24000000 //晶振#define max_task 4 //最大任务数idata unsigned char task_delay[4];#define task_delay0 time_task_sec/1 //2赫兹18b20 #define task_delay1 time_task_sec/5 //10赫兹屏幕#define task_delay2 time_task_sec/3 //4赫兹1302 #define task_delay3 time_task_sec/20 //20赫兹键盘void init(){unsigned char i;init18b20();ds1302_init();initina1(); //---------------------------LCD字库初始化程序RdFromROM(state1,8,1);state[0]=state1[0]; //-------界面RdFromROM(state1,15,1);state[1]=state1[0];//------- 闹钟RdFromROM(state1,11,1);key_sound=state1[0];//-------按键音// state[2]=state1[2];// state[3]=state1[3];screennum=1;//------默认一号屏for(i=0;i<max_task;i++)//清除任务延时{task_delay[i]=0;}TMOD=0x11;EA=1;TH0=255-clock/time_task_sec/12/526;TL0=255-clock/time_task_sec/12%526;ET0=1;TR0=1;}void main(){init();while(1){ if(task_delay[0]==0){readtemp(); task_delay[0]=task_delay0;} if(task_delay[3]==0){MenuCheckKey();task_delay[3]=task_delay1;}if(task_delay[1]==0){screen_select(screennum);task_delay[1]=task_delay1;} if(task_delay[2]==0){ds1302_read_time(); task_delay[2]=task_delay0;} }}void timer0() interrupt 1{uchar i=0;TH0=255-clock/time_task_sec/12/526;TH1=255-clock/time_task_sec/12%526;for(i=0;i<max_task;i++)if(task_delay[i]) task_delay[i]--; // miao=21,fen=33,xiaomiao=94;if(ma_start==1){tt++;if(tt==8){tt=0;xiaomiao++;if(xiaomiao==99){xiaomiao=0;miao++;if(miao==60){miao=0;fen++;if(fen==99){fen=0;}}}}}}Screen.c:#include "reg52.h"#include "macroconst.h"#include "delay.h"#include "18b20.h"#include "atao_12864.h"#include "ds1302.h"#include "24c02.h"#include "festival.h"#include "keyscan.h"idata unsigned char miao=0,fen=78,xiaomiao=0,tt=0;idata unsigned char bai,shi,ge,shinian,genian,shiyue,geyue,shiri,geri,shishi,geshi,shifen,gefen,shimi ao,gemiao;idata unsigned char Number[4];unsigned char code mainmenu[]={" 主菜单""3.查询 4.温度""1.调时 2.秒表""5.设置 6.返回"};unsigned char code setmenu[]={" 设置""3.查温 4.按键""1.界面 2.闹铃""5.报时 6.返回"};void gettime(){shinian=(time_buf1[1]%100)/10;genian=(time_buf1[1]%100)%10;shiyue=(time_buf1[2])/10;geyue=(time_buf1[2])%10;shiri=(time_buf1[3])/10;geri=(time_buf1[3])%10;shishi=(time_buf1[4])/10;geshi=(time_buf1[4])%10;shifen=(time_buf1[5])/10;gefen=(time_buf1[5])%10;shimiao=(time_buf1[6])/10;gemiao=(time_buf1[6])%10;}void screen_select(uchar num){// initina1();gettime() ;if(num==1) //----------主界面{Lcd_Set_Post(1,0);TransferData(shinian+48,1);//----------------------年TransferData(genian+48,1);TransferData('/',1);TransferData(shiyue+48,1);//----------------------月TransferData(geyue+48,1);TransferData('/',1);TransferData(shiri+48,1);//----------------------日TransferData(geri+48,1);Lcd_Set_Post(1,4);if(state[1]==1)//----------------闹铃的状态图标{TransferData(' ',1);TransferData(14,1);}Lcd_Set_Post(1,5);if(key_sound==1){TransferData(13,1);}if(state[0]==0){Lcd_Set_Post(1,7); //----------------农历年nian(0);Lcd_Set_Post(2,0);//----------------------- 农历日月LCD_WRITE_CHAR("农历");Conversion(0,time_buf[1],time_buf[2],time_buf[3]);TransferData(month_moon/16+'0',1);TransferData(month_moon%16+'0',1);TransferData('/',1);TransferData(day_moon/16+'0',1);TransferData(day_moon%16+'0',1);}if(state[0]==1){Lcd_Set_Post(3,5);}else {Lcd_Set_Post(2,5);}LCD_WRITE_CHAR("星期");//----------------------星期if(time_buf1[7]==7) {LCD_WRITE_CHAR("日");}if(time_buf1[7]==6) {LCD_WRITE_CHAR("六");}if(time_buf1[7]==5) {LCD_WRITE_CHAR("五");}if(time_buf1[7]==4) {LCD_WRITE_CHAR("四");}if(time_buf1[7]==3) {LCD_WRITE_CHAR("三");}if(time_buf1[7]==2) {LCD_WRITE_CHAR("二");}if(time_buf1[7]==1) {LCD_WRITE_CHAR("一");}Lcd_Set_Post(3,0);TransferData(shishi+48,1);//----------------------时TransferData(geshi+48,1);TransferData(58,1);TransferData(shifen+48,1);//----------------------分TransferData(gefen+48,1);TransferData(58,1);TransferData(shimiao+48,1);//----------------------秒TransferData(gemiao+48,1);if(state[0]==0){bai=(temph/100); //---------------------------------温度shi=(temph%100)/10;ge=(temph%100)%10;Lcd_Set_Post(3,4);if(zerotemp==0){TransferData(' ',1);TransferData(' ',1);} Lcd_Set_Post(3,5);TransferData(shi+48,1);TransferData(ge+48,1);TransferData('.',1);TransferData(templ+48,1);TransferData(0xa1,1);TransferData(0xe6,1);Lcd_Set_Post(4,0);festival(time_buf[2],time_buf[3],time_buf[4]);//农历}}if(num==3)//----------主菜单{Lcd_Set_Post(1,0);//--------设置显示位置LCD_WRITE_CHAR(mainmenu);}if(num==4)//----------设置菜单{Lcd_Set_Post(1,0);//--------设置显示位置LCD_WRITE_CHAR(setmenu);}if(num==5)//----------时间设置{Lcd_Set_Post(1,2);//--------设置显示位置LCD_WRITE_CHAR("时间设置");Lcd_Set_Post(2,1);TransferData(shinian+48,1);//----------------------年TransferData(genian+48,1);LCD_WRITE_CHAR("年");TransferData(shiyue+48,1);//----------------------月TransferData(geyue+48,1);LCD_WRITE_CHAR("月");TransferData(shiri+48,1);//----------------------日TransferData(geri+48,1);LCD_WRITE_CHAR("日");TransferData(time_buf1[7]+48,1);//---------------星期Lcd_Set_Post(3,2);TransferData(shishi+48,1);//--------------------时TransferData(geshi+48,1);LCD_WRITE_CHAR("时");TransferData(shifen+48,1);//---------------------分TransferData(gefen+48,1);LCD_WRITE_CHAR("分");TransferData(shimiao+48,1);//--------------------秒TransferData(gemiao+48,1);}if(num==6)//----------秒表{uchar shi1,shi2,shi3,ge1,ge2,ge3;Lcd_Set_Post(1,3);//--------设置显示位置LCD_WRITE_CHAR("秒表");Lcd_Set_Post(3,2);shi1=fen/10;ge1=fen%10;TransferData(shi1+48,1);TransferData(ge1+48,1);TransferData(':',1);shi2=miao/10;ge2=miao%10;TransferData(shi2+48,1);TransferData(ge2+48,1);TransferData(':',1);shi3=xiaomiao/10;ge3=xiaomiao%10;TransferData(shi3+48,1);TransferData(ge3+48,1);}if(num==8){Lcd_Set_Post(1,2);//--------农历查询LCD_WRITE_CHAR("温度查询");Lcd_Set_Post(3,0);//--------农历查询LCD_WRITE_CHAR("最高温度"); TransferData(':',1);RdFromROM(Number,0,4);if(Number[3]==0){TransferData('-',1);}Lcd_Set_Post(3,5);TransferData(Number[0]+48,1); TransferData(Number[1]+48,1); TransferData('.',1);TransferData(Number[2]+48,1); TransferData(0xa1,1);TransferData(0xe6,1); Lcd_Set_Post(4,0);//--------农历查询LCD_WRITE_CHAR("最低温度"); TransferData(':',1);RdFromROM(Number,4,4);if(Number[3]==0){TransferData('-',1);}Lcd_Set_Post(4,5);TransferData(Number[0]+48,1); TransferData(Number[1]+48,1); TransferData('.',1);TransferData(Number[2]+48,1); TransferData(0xa1,1);TransferData(0xe6,1); }if(num==9)//----------界面菜单{Lcd_Set_Post(1,2);//--------设置显示位置LCD_WRITE_CHAR("界面选择");Lcd_Set_Post(2,0);TransferData(1+48,1);TransferData('.',1);LCD_WRITE_CHAR("多功能界面");Lcd_Set_Post(3,0);TransferData(2+48,1);TransferData('.',1);LCD_WRITE_CHAR("简洁界面");}。

51单片机万年历汇编程序 2

51单片机万年历汇编程序 2

;真正的万年历: 84 bytes 的51 ASM;==SUB_WNL=== 万年历==* Deng Miao * 2004-06-01 ***** GuangZhou ****** SJ DA TA30H ; 世纪BCD 00 TO 99NH DA TA31H ; 年号BCD 00 TO 99 0000 TO 9999 年YF DA TA32H ; 月份BCD 01 TO 12org 000hMOV SP, #40HMOV SJ, #21H ;2004-05MOV NH, #01HMOV YF, #4HACALL SUB_WNLSJMP $;===============SUB_WNL===================; 入口:; SJ DA TA30H ; 世纪BCD 00 TO 99; NH DA TA31H ; 年号BCD 00 TO 99 0000 TO 9999 年; YF DA TA32H ; 月份BCD 01 TO 12; 出口; ACC -- 本月天数BCD 28 to 31; B -- 本月1日的星期数1 to 6 == 星期1 to 星期6; 0 -- 星期日; 使用: ACC, B, R5, R6; STACK: 3 bytes (不包括调用)ORG 50HSUB_WNL:PUSH PSWMOV A, SJACALL BCD2BIN_MOD4; x 400年: (大周期); =146097天= 7 * 20871 + 0 天; x 100年:; 000年= 7 * 0 + 0 + 1 - 1 1 = 0 * 2 + 1 ****; 100年= 7 * 5217 + 7 + 1 - 2 2 = 1 * 2; 200年= 7 * 10435 + 7 + 1 - 4 4 = 2 * 2; 300年= 7 * 15653 + 7 + 1 - 6 6 = 3 * 2; {1,2,4,6}MOV A, R6 ; A=R6= SJ_BIN MOD 4RLC A; A=A*2+C A = {1,2,4,6} ****XRL A, #10000111B ; A = 87H - A; 边界调整MOV R5, A; A = {86H, 85H, 83H, 81H} ; R5: 星期MOV A, NHJZ WNL_1ACALL BCD2BIN_MOD4XCH A, R5SUBB A, R5 ; 0 年; 0 = 0 + 0 + 1 + (-1) ***MOV R5, A单片机日记:WNL_1:MOV A, YFADD A, #(WNL_TAB-$-4)MOVC A, @A+PCMOV R6, ASW AP AACALL WNL_F0; 大年对>=3月调整准备ADDC A, R5 ; 月调整MOV B, #7DIV AB ; B = A MOD 7MOV A, R6ACALL WNL_F0; 大年调整准备ADDC A, #28POP PSWRETWNL_TAB:DB 3*2 + 5 * 32+0 ;1 BIT 0 : "2月" 标志DB 0*2+1+1 * 32+0 ;2 ** BIT 1..2: 月大小DB 3*2 + 1 * 32+16 ;3 00:28 天DB 2*2 + 4 * 32+16 ;4 01:----DB 3*2 + 6 * 32+16 ;5 10: 30 天DB 2*2 + 2 * 32+16 ;6 11: 31 天DB 3*2 + 4 * 32+16 ;7 BIT 3: 0 -----DB 3*2 + 7 * 32+16 ;8 BIT 4: 0: 1/2月DB 2*2 + 3 * 32+16 ;9 1: >=3月WNL_F0: ; 6 BYTES ; 大年调整准备RRC A;0AHANL A, #07H ;0BH;0CHANL C, F0 ;0DH;0EHRET ;0FHDB 3*2 + 5 * 32+16 ;10H BIT 5..7: 星期调整数DB 2*2 + 1 * 32+16 ;11H 0:---DB 3*2 + 3 * 32+16 ;12H 1-7: 调整数BCD2BIN_MOD4:; 功能:A. 1 BYTES BCD TO BIN; B. MOD 4; C. MUL 2; 入口:; A: SJ OR NH; F0 : 大世纪; 出口; ACC -- (BIN(A) \ 4) * 2 - (BIN(A) MOD 4) - F0; R6 -- BIN(A) MOD 4; C -- IIF( (BIN(A) MOD 4)=0, 1, 0 ); 使用: ACC, B, R6, PSW; STACK: 0 bytes (不包括调用)MOV R6, A; BCD ==> BINANL A, #0F0H ; 16X+Y ==> 10X+YSW AP AMOV B, #(256-6) ; (256-6)*X + (16X+Y)MUL AB ;ADD A, R6 ; = 256X + (10X+Y)MOV R6, A; MOD4ANL A, #3XCH A, R6 ; R6 = BIN MOD 4 = {0,1,2,3}; X 4年:3 * 365 + 366 = 7*209 + (-2) ** XRL A, R6 ; A = (BIN \ 4)RR A; A = (BIN \4 ) * 2 **MOV C, F0 ; 大世纪调整SUBB A, R6;X 1 年:;0 年0 = 0 + 0 + 1 + (-1) ***;1 年366 = 7*52 + 1 + 1;2 年366 + 365 = 7*104 + 2 + 1;3 年366 + 365 + 365 = 7*156+3 + 1; {-1,1,2,3}CJNE R6, #1, $ + 3 ; C = IIF(R6>=1, 0, 1)MOV F0, C ; C=1 为大年/大世纪RET;-----------------------------END ;======== END OF FILE。

基于51单片机的万年历设计

基于51单片机的万年历设计

基于51单片机的万年历设计一、系统设计方案本万年历系统主要由 51 单片机、时钟芯片、液晶显示屏、按键等部分组成。

51 单片机作为核心控制器,负责整个系统的运行和数据处理。

时钟芯片用于提供精确的时间信息,液晶显示屏用于显示万年历的相关内容,按键则用于设置时间和功能切换。

二、硬件设计1、单片机选型选用常见的 51 单片机,如 STC89C52 单片机,它具有性能稳定、价格低廉、易于编程等优点。

2、时钟芯片选择 DS1302 时钟芯片,该芯片能够提供高精度的实时时钟,具有闰年补偿功能,并且可以通过串行接口与单片机进行通信。

3、液晶显示屏采用 1602 液晶显示屏,能够清晰地显示字符和数字,满足万年历的显示需求。

4、按键电路设计四个按键,分别用于时间设置、功能切换、加和减操作。

三、软件设计1、主程序流程系统上电后,首先进行初始化操作,包括单片机端口初始化、时钟芯片初始化、液晶显示屏初始化等。

然后读取时钟芯片中的时间数据,并在液晶显示屏上显示出来。

接着进入循环,不断检测按键状态,根据按键操作执行相应的功能,如时间设置、功能切换等。

2、时钟芯片驱动程序通过单片机的串行接口向 DS1302 发送命令和数据,实现对时钟芯片的读写操作,获取准确的时间信息。

3、液晶显示屏驱动程序编写相应的函数,实现对1602 液晶显示屏的字符和数字显示控制。

4、按键处理程序采用扫描方式检测按键状态,当检测到按键按下时,执行相应的按键处理函数,实现时间设置和功能切换等操作。

四、时间设置功能通过按键操作进入时间设置模式,可以分别设置年、月、日、时、分、秒等信息。

在设置过程中,液晶显示屏会显示当前设置的项目和数值,并通过加、减按键进行调整。

设置完成后,将新的时间数据保存到时钟芯片中。

五、显示功能万年历的显示内容包括年、月、日、星期、时、分、秒等信息。

通过合理的排版和显示控制,使这些信息在液晶显示屏上清晰、直观地呈现给用户。

六、系统调试在完成硬件和软件设计后,需要对系统进行调试。

51单片机c语言电子万年历完整程序

51单片机c语言电子万年历完整程序

该程序为51单片机c语言电子万年历#include"reg52.h"//#include<stdio.h>#define uchar unsigned char#define uint unsigned intsbit lcden=P3^4;sbit lcdrs=P3^5;sbit DATA=P0^7;sbit RST=P0^5;sbit SCLK=P0^6;sbit menu=P3^0; //菜单sbit add=P3^1; //加一sbit dec=P3^7; //减一sbit led0=P1^0;sbit led1=P1^1;sbit led2=P1^2;sbit led3=P1^3;sbit ds=P3^2;//sbit beep=P3^3;uint temp;float f_temp;uint warn_l1=270;uint warn_l2=250;uint warn_h1=300;uint warn_h2=320;uint get_temp();void delayms(uint x);void write_com(uchar com);void write_data(uchar date);void init();void dis_temp(uint t);void Write1302(uchar dat);void WriteSet1302(uchar Cmd,uchar dat);uchar Read1302(void);uchar ReadSet1302(uchar Cmd);void Init_DS1302(void);void DisplaySecond(uchar x);void DisplayMinute(uchar x);void DisplayHour(uchar x);void DisplayDay(uchar x);void DisplayMonth(uchar x);void DisplayYear(uchar x);void DisplayWeek(uchar x);void dis_temp(uint t);void read_date(void);void turn_val(char newval,uchar flag,uchar newaddr,uchar s1num);void key_scan(void);char code table[]="0123456789" ;uchar code table2[]= "TUEWESTHUFRISATSUNMON"; uchar second,minute,hour,day,month,year,week,count=0; uchar ReadValue,num,time;void delayms(uint x){uint i,j;for(i=x;i>0;i--)for(j=110;j>0;j--);}////////////////////////////////////////////////////////////void write_com(uchar com){lcdrs=0;P2=com;delayms(5);lcden=1;delayms(5);lcden=0;}void write_data(uchar date){lcdrs=1;P2=date;delayms(5);lcden=1;delayms(5);lcden=0;}void init(){lcden=0;write_com(0x38);write_com(0x0c);write_com(0x06);write_com(0x01);}/////////////////////////////////////////////////////////////////void Write1302(uchar dat){uchar i;SCLK=0; //拉低SCLK,为脉冲上升沿写入数据做好准备 delayms(2); //稍微等待,使硬件做好准备for(i=0;i<8;i++) //连续写8个二进制位数据DATA=dat&0x01; //取出dat的第0位数据写入1302delayms(2); //稍微等待,使硬件做好准备SCLK=1; //上升沿写入数据delayms(2); //稍微等待,使硬件做好准备SCLK=0; //重新拉低SCLK,形成脉冲dat>>=1; //将dat的各数据位右移1位,准备写入下一个数据位 }}void WriteSet1302(uchar Cmd,uchar dat){RST=0; //禁止数据传递SCLK=0; //确保写数居前SCLK被拉低RST=1; //启动数据传输delayms(2); //稍微等待,使硬件做好准备Write1302(Cmd); //写入命令字Write1302(dat); //写数据SCLK=1; //将时钟电平置于已知状态RST=0; //禁止数据传递}uchar Read1302(void){uchar i,dat;delayms(2); //稍微等待,使硬件做好准备for(i=0;i<8;i++) //连续读8个二进制位数据dat>>=1; //将dat的各数据位右移1位,因为先读出的是字节的最低位if(DATA==1) //如果读出的数据是1dat|=0x80; //将1取出,写在dat的最高位SCLK=1; //将SCLK置于高电平,为下降沿读出delayms(2); //稍微等待SCLK=0; //拉低SCLK,形成脉冲下降沿delayms(2); //稍微等待}return dat; //将读出的数据返回}uchar ReadSet1302(uchar Cmd){uchar dat;RST=0; //拉低RSTSCLK=0; //确保写数居前SCLK被拉低RST=1; //启动数据传输Write1302(Cmd); //写入命令字dat=Read1302(); //读出数据SCLK=1; //将时钟电平置于已知状态RST=0; //禁止数据传递return dat; //将读出的数据返回}void Init_DS1302(void){WriteSet1302(0x8E,0x00); //根据写状态寄存器命令字,写入不保护指令WriteSet1302(0x80,((0/10)<<4|(0%10))); //根据写秒寄存器命令字,写入秒的初始值WriteSet1302(0x82,((59/10)<<4|(59%10))); //根据写分寄存器命令字,写入分的初始值WriteSet1302(0x84,((23/10)<<4|(23%10))); //根据写小时寄存器命令字,写入小时的初始值WriteSet1302(0x86,((28/10)<<4|(28%10))); //根据写日寄存器命令字,写入日的初始值 WriteSet1302(0x88,((2/10)<<4|(2%10))); //根据写月寄存器命令字,写入月的初始值WriteSet1302(0x8c,((14/10)<<4|(14%10))); //nian//WriteSet1302(0x8a,((4/10)<<4|(4%10)));}/////////////////////////////////////////////////////////////////void DisplaySecond(uchar x){uchar i,j;i=x/10;j=x%10;write_com(0x80+0x46);write_data(i+0x30);write_com(0x80+0x47);write_data(j+0x30);write_com(0x80+0x48);write_data(' ');dis_temp(get_temp());}void DisSecond(uchar x){uchar i,j;ReadValue = ReadSet1302(0x81);second=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);i=x/10;j=x%10;write_com(0x80+0x46);write_data(i+0x30);write_com(0x80+0x47);write_data(j+0x30);}void DisplayMinute(uchar x) {uchar i,j;i=x/10;j=x%10;write_com(0x80+0x43);write_data(i+0x30);write_com(0x80+0x44);write_data(j+0x30);write_com(0x80+0x45);write_data(':');}void DisplayHour(uchar x){uchar i,j;i=x/10;j=x%10;write_com(0x80+0x40);write_data(i+0x30);write_com(0x80+0x41);write_data(j+0x30);write_com(0x80+0x42);write_data(':');}void DisplayDay(uchar x) {uchar i,j;i=x/10;j=x%10;write_com(0x89);write_data(i+0x30);write_com(0x8a);write_data(j+0x30); }void DisplayMonth(uchar x) {uchar i,j;i=x/10;j=x%10;write_com(0x86);write_data(i+0x30); write_com(0x87);write_data(j+0x30);write_com(0x88);write_data('/');}void DisplayYear(uchar x) {uchar i,j;i=x/10;j=x%10;write_com(0x81);write_data(2+0x30);write_com(0x82);write_data(0+0x30);write_com(0x83);write_data(i+0x30);write_com(0x84);write_data(j+0x30);write_com(0x85);write_data('/');}void DisplayWeek(uchar x){ uchar i;x=x*3;// write_com(0x8c);write_data(table2[x]);// write_com(0x8d);write_data(table2[x+1]);// write_com(0x8e);write_data(table2[x+2]);write_com(0x8c);for(i=0;i<3;i++){write_data(table2[x]);x++;}}void read_date(void){ReadValue = ReadSet1302(0x81);second=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); ReadValue = ReadSet1302(0x83);minute=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = ReadSet1302(0x85);hour=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = ReadSet1302(0x87);day=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = ReadSet1302(0x89);month=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = ReadSet1302(0x8d);year=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue=ReadSet1302(0x8b); //读星期week=ReadValue&0x07;DisplayYear(year);DisplayMonth(month);DisplayDay(day);DisplayWeek(week);DisplayHour(hour);DisplayMinute(minute);DisplaySecond(second);dis_temp(get_temp()); ///温度显示key_scan(); ///按键检测}void turn_val(char newval,uchar flag,uchar newaddr,uchar s1num){newval=ReadSet1302(newaddr); //读取当前时间newval=((newval&0x70)>>4)*10+(newval&0x0f); //将bcd码转换成十进制 if(flag) //判断是加一还是减一{newval++;switch(s1num){ case 1: if(newval>99) newval=0;DisplayYear(newval);break;case 2: if(newval>12) newval=1;DisplayMonth(newval);break;case 3: if(newval>31) newval=1;DisplayDay(newval);break;case 4: if(newval>6) newval=0;DisplayWeek(newval);break;case 5: if(newval>23) newval=0;DisplayHour(newval);break;case 6: if(newval>59) newval=0;DisplayMinute(newval);break;case 7: if(newval>59) newval=0;DisplaySecond(newval);break;default:break;}}else{newval--;switch(s1num){ case 1: if(newval==0) newval=99;DisplayYear(newval);break;case 2: if(newval==0) newval=12;DisplayMonth(newval);break;case 3: if(newval==0) newval=31;DisplayDay(newval);break;case 4: if(newval<0) newval=6;DisplayWeek(newval);break;case 5: if(newval<0) newval=23;DisplayHour(newval);break;case 6: if(newval<0) newval=59;DisplayMinute(newval);break;case 7: if(newval<0) newval=59;DisplaySecond(newval);break;default:break;}}WriteSet1302((newaddr-1),((newval/10)<<4)|(newval%10)); //将新数据写入寄存器}//////////////////////////////////////void dsreset(void){uint i;ds=0;i=103;while(i>0)i=4;while(i>0)i--;}bit tempreadbit(void){uint i;bit dat;ds=0;i++;ds=1;i++;i++;dat=ds;i=8;while(i>0)i--;return(dat);}uchar tempread(void){uchar i,j,dat;dat=0;for(i=1;i<=8;i++){j=tempreadbit();dat=(j<<7)|(dat>>1); }return(dat);}void tempwritebyte(uchar dat) {bit testb;for(j=1;j<=8;j++){testb=dat&0x01;dat=dat>>1;if(testb){ds=0;i++;i++;ds=1;i=8;while(i>0)i--;}else{ds=0;i=8;while(i>0)i--;ds=1;i++;i++;}}}void tempchange(void) {dsreset();delayms(1);tempwritebyte(0xcc);tempwritebyte(0x44);key_scan(); //////按键函数}uint get_temp(){uchar a,b;tempchange(); //////温度函数dsreset();delayms(1);tempwritebyte(0xcc);tempwritebyte(0xbe);a=tempread();b=tempread();temp=b;temp<<=8;temp=temp|a;f_temp=temp*0.0625;temp=f_temp*10+0.5;f_temp=f_temp+0.05;return temp;}//////void dis_temp(uint t){uchar n1,n2,n3;n1=t/100;n2=t%100/10;n3=t%100%10;DisSecond(second); ///秒显示 write_com(0x80+0x49);write_data(table[n1]);//delayms(5);write_com(0x80+0x4a);write_data(table[n2]);//delayms(5);write_com(0x80+0x4b);write_data('.');// delayms(5);write_com(0x80+0x4c);write_data(table[n3]);//delayms(5);write_com(0x80+0x4d);write_data('^');//delayms(5);write_com(0x80+0x4e);write_data('C');//delayms(5);DisSecond(second); ////秒显示}/*********************液晶显示*****************/ void warn(uint s,uchar led){uchar i;i=s;// beep=0;P1=~(led);while(i--){dis_temp(get_temp());}// beep=1;P1=0xff;i=s;while(i--){dis_temp(get_temp());}}void deal(uint t){uchar i;if((t>warn_l2)&&(t<=warn_l1)){warn(40,0x01);}else if(t<=warn_l2){warn(10,0x03);}else if((t<warn_h2)&&(t>=warn_h1)) {warn(40,0x04);}else if(t>=warn_h2){warn(10,0x0c);}else{i=40;while(i--){dis_temp(get_temp());DisSecond(second);}}}///////////////////////////////////////void main(){init();Init_DS1302();while(1){tempchange();read_date();deal(temp);key_scan();}}////******************************************* void key_scan(void){// uchar miao,s1num=0;uchar s1num=0;if(menu==0){delayms(5);if(menu==0){while(!menu);s1num++;while(1){if(menu==0){delayms(5);if(menu==0){while(!menu);s1num++;}}// miao=ReadSet1302(0x81);// second=miao;// WriteSet1302(0x80,miao|0x80);write_com(0x0f);//光标闪射if(s1num==1){ //year=ReadSet1302(0x8d);write_com(0x80+4); //年光标if(add==0){delayms(3);if(add==0){ while(!add);turn_val(year,1,0x8d,1);}}if(dec==0){delayms(3);if(dec==0){ while(!dec);turn_val(year,0,0x8d,1);}}}if(s1num==2){//month=ReadSet1302(0x89);write_com(0x80+7); //月光标if(add==0){delayms(3);if(add==0){ while(!add);turn_val(month,1,0x89,2);}}if(dec==0){delayms(3);if(dec==0){ while(!dec);turn_val(month,0,0x89,2);}}}if(s1num==3){ //day=ReadSet1302(0x87);write_com(0x80+10);//日光标{delayms(3);if(add==0){ while(!add);turn_val(day,1,0x87,3);}}if(dec==0){delayms(3);if(dec==0){ while(!dec);turn_val(day,0,0x87,3); //写入日寄存器 }}}if(s1num==4){ //week=ReadSet1302(0x8b);write_com(0x80+14); //星期光标if(add==0){delayms(3);if(add==0){ while(!add);turn_val(week,1,0x8b,4);}}if(dec==0){delayms(3);{ while(!dec);turn_val(week,0,0x8b,4);}}}if(s1num==5){// hour=ReadSet1302(0x85)write_com(0x80+0x40+1); //时光标if(add==0){delayms(3);if(add==0){ while(!add);turn_val(hour,1,0x85,5);}}if(dec==0){delayms(3);if(dec==0){ while(!dec);turn_val(hour,0,0x85,5);}}}if(s1num==6)//调时间分{ // minute=ReadSet1302(0x83);write_com(0x80+0x40+4);if(add==0){delayms(5);if(add==0){ while(!add);turn_val(minute,1,0x83,6); //写入分寄存器}}if(dec==0){delayms(3);if(dec==0){ while(!dec);turn_val(minute,0,0x83,6); //写入分寄存器}}}if(s1num==7)//调时间秒{// second=ReadSet1302(0x81);write_com(0x80+0x40+7);//秒光标if(add==0){delayms(3);if(add==0){ while(!add);if(second==0x60)second=0x00;turn_val(second,1,0x81,7);}}if(dec==0){delayms(3);if(dec==0){ while(!dec);turn_val(second,0,0x81,7);}}}if(s1num==8){// miao=ReadSet1302(0x81);// second=miao;// WriteSet1302(0x80,second&0x7f);s1num=0;//s1num清零//write_com(0x0c);//光标不闪烁//break;}}}}}。

51单片机万年历实验原理

51单片机万年历实验原理

51单片机万年历实验原理1. 概述51单片机万年历实验是一项基于51单片机的实验项目,用于模拟和显示日期和时间信息,使其具备一定的时钟和日历功能。

本文将详细介绍该实验的原理和实现方法。

2. 实验所需材料完成51单片机万年历实验需要以下材料: - 51单片机开发板 - LCD显示屏 - 时钟芯片(如DS1302) - 电容 - 电阻 - 键盘模块 - 连接线等3. 实验原理本实验的原理主要包括三个方面:51单片机的控制逻辑、时钟芯片的数据存储和显示屏的信息展示。

3.1 51单片机的控制逻辑在51单片机中,首先需要定义和初始化各个引脚和功能模块。

通过引脚的输入输出控制、时钟和定时器的设置,实现对时钟芯片和LCD显示屏的控制和数据传输。

3.2 时钟芯片的数据存储时钟芯片一般具有独立的电源供应和存储空间,用于储存日期和时间等信息。

通过与51单片机的通讯接口,读取和写入时钟芯片中的数据,实现对日期和时间信息的读取和更新。

3.3 显示屏的信息展示LCD显示屏作为用户界面,用于展示日期和时间等信息。

通过51单片机的输出控制,将读取到的日期和时间信息通过LCD显示屏进行展示。

具体的显示方式可以根据需求设计,如以年、月、日的格式显示,或者以星期和时间的格式显示等。

4. 实验步骤基于以上原理,可以按照以下步骤进行51单片机万年历实验:4.1 硬件连接按照实验所需材料,将51单片机开发板、LCD显示屏和时钟芯片等进行正确的连接。

根据引脚功能和电平要求,通过连接线将它们连接在一起。

4.2 编写程序使用合适的集成开发环境(如Keil)编写51单片机的程序。

程序主要包括引脚和功能模块的初始化设置、时钟芯片数据的读写和LCD显示屏信息的输出等。

4.3 载入程序将编写好的程序通过USB下载线或其他方式,将程序载入到开发板中。

确保程序可以正确地运行在51单片机上。

4.4 测试实验接通电源,观察LCD显示屏是否正常显示日期和时间信息。

51单片机实现万年历程序

51单片机实现万年历程序

51单片机实现万年历利用AT89S52单片机的P0口来和另外几个口来控制1602液晶的显示和P1口还有其它口来控制ds12887时钟芯片。

设置四个按键,1个定义为时间设置功能键,一个定义为闹钟设置功能键,另外两个用来调节时间的增减。

原理图:pcb图:源程序:#include<reg52.h>#define uint unsigned int#define uchar unsigned charsbit beep=P2^0;//蜂鸣器控制口sbit timeadd=P2^1;//调节时间加sbit timesub=P2^2;//调节时间减sbit timeclk=P2^3;//闹钟设定键sbit timefun=P2^4;//时间设定键sbit lcdrs=P2^5;//液晶的命令和数据控制口sbit ledrw=P2^6;//液晶的写数据口sbit lcden=P2^7;//液晶显示模块的使能端sbit timeds=P3^3;//时钟芯片地址闸sbit timerw=P3^4;//时钟芯片读写sbit timeas=P3^5;//时钟芯片地址闸sbit timeen=P3^6;//时钟芯片片选uchar code table[]="20 - - week ";uchar code table1[]=" : : ";//要显示的字符串char num,shi,fen,miao,nian=2000,yue,ri,week,numfun,anumfun,flag,flag1; uchar leap;void delay(uint x){uchar i,j;for(i=x;i>0;i--)for(j=110;j>0;j--);}void didi(){beep=0;delay(1000);beep=1;delay(1000);}void write_com(uchar com){lcdrs=0;P0=com;delay(5);lcden=1;delay(20);lcden=0;}void write_date(uchar date){lcdrs=1;P0=date;delay(5);lcden=1;delay(20);lcden=0;}void write_sfm(uchar add,uchar date){ uchar shi,ge;shi=date/10;ge=date%10;write_com(0x80+0x40+add);write_date(0x30+shi);write_date(0x30+ge);}void write_nyr(uchar add,uchar date){ uchar shi,ge;shi=date/10;ge=date%10;write_com(0x80+add);write_date(0x30+shi);write_date(0x30+ge);}void write_zhou(uchar add,uchar date) {write_com(0x80+add);write_date(0x30+date);}void write_ds(uchar add,uchar date){ timeen=0;timeas=1;timeds=1;timerw=1;P1=add;timeas=0;timerw=0;P1=date;timerw=1;timeas=1;timeen=1;}uchar read_ds(uchar add){uchar ds_date;timeas=1;timeds=1;timerw=1;timeen=0;P1=add;timeas=0;timeds=0;P1=0xff;ds_date=P1;timeds=1;timeas=1;timeen=1;return ds_date;}void keyscan(){if(flag1==1)//用来关闭闹钟铃声{if(timeadd==0){delay(5);if(timeadd==0){while(!timeadd==0);flag1=0;}}if(timesub==0){delay(5);if(timesub==0){while(!timesub==0);flag1=0;}}}if(timefun==0){delay(5);if(timefun==0){while(!timefun);flag=1;numfun++;if(numfun==1){write_com(0x80+0x40+0x0a);write_com(0x0f);}if(numfun==2){write_com(0x80+0x40+0x07);write_com(0x0f);}if(numfun==3){write_com(0x80+0x40+0x04);write_com(0x0f);}if(numfun==4){write_com(0x80+0x0f);write_com(0x0f);}if(numfun==5){write_com(0x80+0x09);write_com(0x0f);}if(numfun==6){write_com(0x80+0x06);write_com(0x0f);}if(numfun==7){write_com(0x80+0x03);write_com(0x0f);}if(numfun==8){numfun=0;flag=0;}}}if(numfun!=0){if(timeadd==0){delay(5);while(!timeadd);if(numfun==1){miao++;if(miao==60)miao=0;write_sfm(9,miao);write_com(0x80+0x40+9);write_ds(0,miao);}if(numfun==2){fen++;if(fen==60)fen=0;write_sfm(6,fen);write_com(0x80+0x40+6);write_ds(2,fen);}if(numfun==3){shi++;if(shi==24)shi=0;write_sfm(3,shi);write_com(0x80+0x40+3);write_ds(4,shi);}if(numfun==4){week++;if(week==8)week=1;write_zhou(0x0f,week);write_com(0x80+0x0f);write_ds(6,week);}if(numfun==5){if(nian==0){switch(yue){case 1:ri++;if(ri==32) ri=1;break;case 2:ri++;if(ri==30) ri=1;break;case 3:ri++;if(ri==32) ri=1;break;case 4:ri++;if(ri==31) ri=1;break;case 5:ri++;if(ri==32) ri=1;break;case 6:ri++;if(ri==31) ri=1;break;case 7:ri++;if(ri==32) ri=1;break;case 8:ri++;if(ri==32) ri=1;break;case 9:ri++;if(ri==31)ri=1;break;case 10:ri++;if(ri==32)ri=1;break;case 11:ri++;if(ri==31)ri=1;break;case 12:ri++;if(ri==32)ri=1;break;}}else if(leap&&yue==2){ri++;if(ri==30)ri=1;}else if(yue==2&&leap==0){ri++;if(ri==29)ri=1;}elseswitch(yue){case 1:ri++;if(ri==32) ri=1;break;case 3:ri++;if(ri==32) ri=1;break;case 4:ri++;if(ri==31) ri=1;break;case 5:ri++;if(ri==32) ri=1;break;case 6:ri++;if(ri==31) ri=1;break;case 7:ri++;if(ri==32) ri=1;break;case 8:ri++;if(ri==32) ri=1;break;case 9:ri++;if(ri==31) ri=1;break;case 10:ri++;if(ri==32) ri=1;break;case 11:ri++;if(ri==31) ri=1;break;case 12:ri++;if(ri==32) ri=1;break;}write_nyr(8,ri);write_com(0x80+0x08);write_ds(7,ri);}if(numfun==6){yue++;if(yue==13)yue=0;write_nyr(5,yue);write_com(0x80+0x05);write_ds(8,yue);}if(numfun==7){nian++;if(nian==100)nian=0;leap=nian%4==0&&nian%100!=0;write_nyr(2,nian);write_com(0x80+2);write_ds(9,nian);}}if(timesub==0){delay(5);while(!timesub);if(numfun==1){miao--;if(miao==-1)miao=59;write_sfm(9,miao);write_com(0x80+0x40+9);write_ds(0,miao);}if(numfun==2){fen--;if(fen==-1)fen=59;write_sfm(6,fen);write_com(0x80+0x40+6);write_ds(2,fen);}if(numfun==3){shi--;if(shi==-1)shi=23;write_sfm(3,shi);write_com(0x80+0x40+3);write_ds(4,shi);}if(numfun==4){week--;if(week==0)week=7;write_zhou(0x0f,week);write_com(0x80+0x0f);write_ds(6,week);}if(numfun==5){if(nian==0){switch(yue){case 1:ri--;if(ri==0) ri=31;break;case 2:ri--;if(ri==0) ri=29;break;case 3:ri--;if(ri==0) ri=31;break;case 4:ri--;if(ri==0) ri=30;break;case 5:ri--;if(ri==0) ri=31;break;case 6:ri--;if(ri==0) ri=30;break;case 7:ri--;if(ri==0) ri=31;break;case 8:ri--;if(ri==0) ri=31;break;case 9:ri--;if(ri==0) ri=30;break;case 10:ri--;if(ri==0) ri=31;break;case 11:ri--;if(ri==0) ri=30;break;case 12:ri--;if(ri==0) ri=31;break;}}else if(leap&&yue==2){ri--;if(ri==0)ri=29;}else if(yue==2&&leap==0){ri--;if(ri==0)ri=28;}elseswitch(yue){case 1:ri--;if(ri==0) ri=31;break;case 3:ri--;if(ri==0) ri=31;break;case 4:ri--;if(ri==0) ri=30;break;case 5:ri--;if(ri==0) ri=31;break;case 6:ri--;if(ri==0) ri=30;break;case 7:ri--;if(ri==0) ri=31;break;case 8:ri--;if(ri==0) ri=31;break;case 9:ri--;if(ri==0) ri=30;break;case 10:ri--;if(ri==0) ri=31;break;case 11:ri--;if(ri==0) ri=30;break;case 12:ri--;if(ri==0) ri=31;break;}write_nyr(8,ri);write_com(0x80+0x08);write_ds(7,ri);}if(numfun==6){yue--;if(yue==-1)yue=12;write_nyr(5,yue);write_com(0x80+0x05);write_ds(8,yue);}if(numfun==7){nian--;if(nian==-1)nian=99;leap=nian%4==0&&nian%100!=0;write_nyr(2,nian);write_com(0x80+2);write_ds(9,nian);}}}}void set_alarm(){uchar ashi,afen,amiao;if(timeclk==0)//判断是否按下闹钟设定键{delay(5);//延时消抖if(timeclk==0){while(!timeclk);anumfun++;//按键次数加1if(anumfun==1){flag=1;write_com(0x80+0x40+0x0a);write_com(0x0f);}if(anumfun==2){flag=1;write_com(0x80+0x40+0x07);write_com(0x0f);}if(anumfun==3){flag=1;write_com(0x80+0x40+0x04);write_com(0x0f);}if(anumfun==4){flag=0;anumfun=0;}}}if(anumfun!=0){if(timeadd==0)//如果加功能键按下{delay(5);while(!timeadd);if(anumfun==1) //设定秒{amiao++;if(amiao==60)amiao=0;write_sfm(9,amiao);write_com(0x80+0x40+9);write_ds(1,amiao);}if(anumfun==2){afen++;if(afen==60)afen=0;write_sfm(6,afen);write_com(0x80+0x40+6);write_ds(3,afen);}if(anumfun==3){ashi++;if(ashi==24)ashi=0;write_sfm(3,ashi);write_com(0x80+0x40+3);write_ds(5,ashi);}}}if(anumfun!=0){if(timesub==0){delay(5);while(!timesub);if(anumfun==1){amiao--;if(amiao==-1)amiao=59;write_sfm(9,amiao);write_com(0x80+0x40+9);write_ds(1,amiao);}if(anumfun==2){afen--;if(afen==-1)afen=59;write_sfm(6,afen);write_com(0x80+0x40+6);write_ds(3,afen);}if(anumfun==3){ashi--;if(ashi==-1)ashi=23;write_sfm(3,ashi);write_com(0x80+0x40+3);write_ds(5,ashi);}}}}void init(){EA=1;//开总中断EX0=1;//开外部中断0IT0=1;//设定触发方式为负跳变沿有效lcden=0;//选通液晶显示屏ledrw=0;//设定液晶显示屏的读写方式为读write_com(0x38);//设置液晶显示模式为16*2显示,5*7点阵,8位数据接口 write_com(0x0c);//打开显示,并使光标不显示也不闪烁write_com(0x06);//光标指针每次自动加1write_com(1);//清屏write_com(0x80);//送地址指针for(num=0;num<16;num++){write_date(table[num]);delay(5);}write_com(0x80+0x40);//写到第二行for(num=0;num<11;num++){write_date(table1[num]);delay(5);}write_ds(0x0a,0x20);//开启时钟芯片振荡器write_ds(0x0b,0x26);//开启闹钟read_ds(0x0c);//读取时钟芯片c寄存器}void main(){init();while(1){keyscan();set_alarm();if(flag1==1)didi();if(flag==0){//读取时间miao=read_ds(0x00);fen=read_ds(0x02);shi=read_ds(0x04);yue=read_ds(0x08);ri=read_ds(0x07);nian=read_ds(0x09);week=read_ds(0x06);//写入液晶显示屏write_sfm(9,miao);write_sfm(6,fen);write_sfm(3,shi);write_nyr(2,nian);write_nyr(5,yue);write_nyr(8,ri);write_zhou(0x0f,week);}}}void exter() interrupt 0{flag1=1;read_ds(0x0c);//读时钟芯片c寄存器。

基于51单片机的万年历设计流程

基于51单片机的万年历设计流程

基于51单片机的万年历设计流程
基于51单片机的万年历设计流程可以分为以下几个步骤:
1. 确定需求:首先,你需要明确你的万年历需要有哪些功能。

例如,是否需要显示日期、时间、星期,是否需要闹钟功能,是否需要手动或自动校准等。

2. 选择硬件:选择合适的单片机作为主控制器。

常用的单片机有8051系列,如AT89C51、AT89S52等。

此外,还需要选择适当的显示模块、按键模块、实时时钟模块等。

3. 设计硬件电路:根据选择的硬件设备,设计电路原理图和PCB图。

需要
考虑单片机的引脚连接、电源供给、时钟源、外部扩展等问题。

4. 编写软件程序:根据硬件电路和需求,编写相应的软件程序。

这包括初始化程序、主程序、中断服务程序等。

5. 调试和测试:将编写好的程序下载到单片机中,进行实际测试。

根据测试结果,对程序进行调试和修改,直到满足设计要求。

6. 生产:完成调试后,就可以进行批量生产了。

在生产过程中,还需要对产品进行质量检测,确保每个产品都能正常工作。

7. 后期维护:在产品上市后,可能需要对产品进行维护或升级。

例如,如果用户在使用过程中发现了问题,或者有新的需求,就需要对产品进行改进或升级。

以上是基于51单片机的万年历设计的基本流程,但具体的步骤可能会根据具体的需求和硬件设备有所不同。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

目录第1章总体方案论证及工作原理 (5)第2章硬件系统的设计 (6)第3章软件系统的设计 (12)第4章系统测试与仿真 (23)第5章设计总结 (24)参考文献 (24)1总体方案论证及工作原理1.1总体方案选择1.1.1 单片机芯片选择方案和论证采用AT89S52作为硬件核心。

片内ROM全部采用Flash ROM;以3V的超低压工作,与MCS-51系列单片机完全该芯片内部存储器为8KB ROM 存储空间,同样具有AT89C51的功能。

1.1.2 显示模块的选择和论证传统的LED数码管具有:低能耗、低损耗、低压、寿命长、耐老化、防晒、防潮、防火、防高(低)温,对外界环境要求低,易于维护,同时其精度比较高,称重轻,精度可靠,操作简单。

数码管采用BCD编码显示数字,程序编译容易,资源占用较少。

1.1.3 键盘模块的选择和论证独立式键盘是指直接用I/O口线构成的单个按键电路。

独立式按键电路配置灵活,软件结构简单。

1.1.4 总体方案论证该万年历电路由单片机AT98S52、键盘接口电路、显示接口电路及时钟电路和复位电路构成,总原理框图如图1.1所示。

图1.1 总原理图1.2功能要求说明及工作原理1.2.1 功能要求说明本次设计所设计的万年历在功能上具有一般万年历的固有功能,即能比较准确显示时间外,还具有温度计的功能。

1.2.2 工作原理万年历的运行主要是利用单片机定时/计数器的工作和中断服务的作用完成计时功能的。

首先时钟电路产生单片机工作时所需要的时钟信号,这是单片机能够正常工作的前提,而单片机有无定时以及定多长的时间,这些还需要我们人为的确定。

先要有“秒”的计时,而单片机内部定时器是达不到“秒”数量级的定时的,所以我要多次定时,我们人为在确定工作方式的之后,再计算出定时的初值,这就可以实现所谓的定时了。

如果定时时间到了的话,那么单片机会自动地产生中断使程序转向中断服务程序执行,中断服务程序执行完了就会返回原程序,等待下一次定时时间的到来再产生中断。

在此基础上,单片机就会按照人为设定的程序执行下去。

只完成对秒的计数,才能能完成其他时间量的计数。

当然,单片机如果要执行多种不同的计时功能的话,还需要选择多种不同的工作方式,这样才不会使单片机产生混乱。

万年历的基本计时单位是秒,而秒表的基本计时单位却是毫秒了,因而我们把定时器的初始时间设计为50ms,将其乘以20便可得到我们的时间秒单位。

本设计是采用复合定时方式,一个定时间一个就去计数,合作完成一秒的定时。

2 硬件系统的设计2.1硬件系统各模块功能介绍2.1.1 AT89S52芯片介绍AT89S52是一种低功耗高性能CHMOS 8位单片机,管脚如图所示。

片内含4Kbytes ISP的可反复擦写1000次Flash只读程序存储器,128bytes的随机存取数据存储器(RAM)。

AT89S52提供了8K字节Flash ,256字节RAM,32线I/O口,3个16位定时器/计数器,6向量两极中断,一个双工串行口,片内根据振荡器和始终电路等标准功能。

此外,AT89S52设有静态逻辑,并支持软件选择的两种节电运行方式、空闲方式使CPU停止工作,而允许RAM、定时器/计数器、串行口和中断系统继续工作。

掉电方式下,片内振荡器停止工作,由于之中被冻结,一切能都停止,只有片内RAM的内容被保存,直到硬件复位才恢复正常工作。

(1)AT89S52的结构框图AT89S52结构框图如图2.2所示:(2)引脚介绍:/输入/输出口线:P 0.0~P 0.7 :P0口8位双向口线;P 1.0~P 1.7 :P1口8位双向口线;P 2.0~P 2.7 :P2口8位双向口线;P 3.0~P 3.7 :P3口8位双向口线。

/ALE 地址锁存控制信号:在系统扩展时,ALE 用于控制把P 0口输出低8位地址送锁存器锁存起来,以实现低位地址和数据的隔离。

此外由于ALE 是以晶振六分之一的固定频率输出的正脉冲,因此可作为外部时钟或外部定时脉冲使用。

/PSEN 外部程序储器读选取通信号:在读外部ROM 时/PSEN 有效(低电平),以实现外部ROM 单元的读操作。

/EA 访问程序存储器控制信号:当/EA 信号为低电平时,对ROM 的读操作限定在外部程序存储器;而当/EA 信号为高电平时,则对ROM 的读操作是从内部程序存储器开始,并可延至外部程序存储器。

-RST 复位信号:当输入的复位信号延续2个机器周期以上高电平时即为有效,用以完成单片机的复位初始化操作。

-XTAL 1和XTAL 2 外接晶体引线端:当使用芯片内部时钟时,此二引线端用于外接石英晶体和微调电容;当使用外部时钟时,用于拉外部的时钟脉冲信号。

-GND 地线-VCC +5V 电源(3)信号引脚的第二功能:由于工艺及标准化等原因,芯片的引脚数目是有限制的,例如MCS —51系列把芯片引脚数目限定为40条,但单片机为实现其功能所需要的信号数目却远远超过此数,因此就出现了需要与可能的矛盾。

因此,给一些信号引脚赋以双重功能。

P 3的8条口线都定义有第二功能,如表2.1所示:表2.1 P3口第二功能图(4)总线结构AT89S52的管脚除了电源、复位、时钟接入、用户I/O口部分P3外,其余管脚都是为实现系统扩展而设置的。

这些管脚构成了三总线形式,即:1) 地址总线(AB):地址总线宽度为16位,因此,其外部存储器直接地址外围为64K字节。

16位地址总线由P经地址锁存器提供低8位地址(A0~A7);P2口直接提供高8位地址(A8~A15)。

2) 数据总线(DB):数据总线宽度为8位,由P口提供。

3) 控制总线(CB):由部分P3口的第二功能状态和4根独立控制线RESET、EA、ALE、PSEN组成。

2.1.2 时钟电路时钟电路用来产生单片机工作所需要的时钟信号,单片机本身就是一个复杂的同步时序电路,为了保证同步工作方式的实现,电路应在唯一的时钟信号控制下严格地按时序进行工作。

通过在芯片的外部XTAL1和XTAL2两个引脚跨接晶体振荡器和两个微调电容,形成反馈电路,就构成了一个稳定的自激振荡电路。

时钟电路为单片机产生时钟脉冲序列,本设计中采用的晶振频率为12MHz。

如图2.3所示。

图2.3 时钟电路2.1.3 复位电路复位是单片机的初始操作,其主要功能是把PC初始化为0000H,使单片机从0000H单元开始执行程序。

除了进入系统的正常初始化之外,当由于程序运行出错或操作错误使系统处于死锁状态时,为摆脱困境,也需安装复位键以重新启动。

RS T引脚是复位信号的输入端,复位信号是高电平有效,其有效时间应持续24个振荡脉冲周期(即2个机器周期)以上,本设计使用频率为12MHz 的晶振,所以复位信号持续时间应超过2μs才能完成复位操作。

复位操作有上电自动复位和按键手动复位两种方式。

在本设计中采用的是按键复位,按键复位是通过使复位端经电阻与Vcc电源而实现的,如图2.4所示。

图2.4 复位电路2.1.4 显示及显示驱动电路由于七段数码显示器在显示字形代码时需要有足够的功率,单片机口线的驱动能力明显不够,所以需在显示器前加显示驱动器,以提高其输出功率,满足显示器的需求。

LED显示器俗称数码管,在其内部是由8个发光二极管加限流电阻组成,其连接方式有共阴和共阳两种,在共阴极接法中,因公共端接地,只要给某一段加高电平,该段就会亮。

而在本设计中采用的是共阳极接法,公共端接+5V电源,在某一段上加低电平,该段就会亮。

在本次设计中,为了使硬件电路更简单化,我采用四位一体的LED数码管,显示原理与单个LED的显示原理完全相同。

但在它的内部把四个数码管的段控端对应的连在了一起与单个的数码管相比其外部电路连接更加简单,故它只有8个段控端和4个位控端,4个位控端分别对四个数码管进行控制。

如图2.5所示。

图2.5 显示电路2.1.5 控制电路在单片机控制电路中,可把单片机使用的键盘分为独立式和矩阵式两种。

独立式实际上就是一组独立的按键,这些按键可直接与单片机的I/O口连接,即每个按键独占一条口线,这种接法简单。

矩阵式键盘也称行列式键盘,因为键的数目较多,所以键按行列组成矩阵。

本设计中键盘数目较少,且为安装方便,因此在本设计中采用独立式接法。

如图2.6所示。

图2.6 控制电路按从一个键到键的功能被执行主要应包括两项工作:一是键的识别,即在键盘中找出被按的是哪个键,另一项是键功能的实现。

第一项工作是使用接口电路实现的,而第二项工作则是通过执行中断服务程序来完成。

具体来说,独立式键盘接口应完成以下操作功能:a 键盘扫描,以判定是否有键被按下(称之为“闭合键”)。

b 排除多键、串键(复键)及去抖动。

c 键识别,根据各口线的值判断按键的位置。

以上这些内容通常是以软硬件结合的方式来完成的,即在软件的配合下由接口电路来完成。

但具体哪些由硬件哪些由软件完成,要看接口电路的情况。

总的原则是,硬件复杂软件就简单,硬件简单软件就得复杂一些。

3软件系统的设计3.1程序设计流程图图3.1 设计流程图 左图是住程序流程 右图是循环程序流程3.2 程序清单/////////////////////////////////////////////////////////ORG 0000HLJMP STARTORG 0003HLJMP PROINT0 ;int0用来切换时钟调整位置ORG 0013H ;用来调整时间,只加不减LJMP PROINT1ORG 001BH ;50MS 的延迟,计数200次则为1秒LJMP PROTIMEORG 0030H ;主程序TABLE: DB 81H,0DBH,86H,0C2H,0D8H,0E0H,0A0H,0CBH,80H,0C0HORG 0050HSTART: MOV TCON,#05H ;中断初始化MOV IE ,#8DHMOV TMOD,#10HMOV TH1,#3CH ;定时器初始化MOV TL1,#60HMOV 31H,#00H ;00秒MOV 32H,#00H ;00分MOV 33H,#12H ;12点MOV 34H,#21H ;21号MOV 35H,#06H ;6月MOV 36H,#05H ;2005年MOV 37H,#14H;R7 存放切换标志 0 NORMAL , 1 HOUR ,2 MINUTE ,3 SECOND ,4 YEAR,5 MONTH,6 DAYMOV R1,#00H ;确定在调时不按键的最长时间,10秒后返回normal状态MOV R7,#00H ;切换标志MOV 40H,#00H ;十六进制转换BCD的高位MOV 41H,#00H ;十六进制转换BCD的低位MOV R6,#00H ;调时的位闪烁的时间间隔MOV R4,#00H ;用来计数50ms的中断次数,20次则一秒mov r3,#00hSETB TR1 ;开始计时AGAIN:ACALL PROSHOW ;显示AJMP AGAINPROSHOW:CJNE R3,#00H,SHOWDATE ;如果r3等于1就显示日期,等于0就显示时钟CJNE R7,#04H,DATE1 ;显示程序AJMP SHOWDATE ;showdate显示年月日DATE1: CJNE R7,#05H,DATE2AJMP SHOWDATEDATE2: CJNE R7,#06H,SHOWCLOCKAJMP SHOWDATEshowCLOCK:MOV R0,33H ;showclock显示时分秒,先显示时ACALL PROHTODCJNE R7,#01H,CLK1INC R6CJNE R6,#03H,CLK2 ;若处于调时状态,则该位闪烁MOV R6 ,#00HCLK1: clr P0.1mov a,41HMOV P2, a ;显示时的低位ACALL DELAY3MSCLK2: SETB P0.1CLR P0.0mov a,40HMOV P2,a ;显示时的高位ACALL DELAY3MSSETB P0.0MOV R0,32H ;显示分ACALL PROHTODCJNE R7,#02H,CLK3INC R6CJNE R6,#03H,CLK4 ;若处于调时状态,则该位闪烁MOV R6,#00HCLK3: CLR P0.3mov a,41HMOV P2, a ;显示分的低位ACALL DELAY3MSCLK4: SETB P0.3CLR P0.2mov a,40hMOV P2,a ;显示分的高位ACALL DELAY3MSSETB P0.2MOV R0,31H ;显示秒ACALL PROHTODCJNE R7,#03H,CLK5INC R6CJNE R6,#03H,CLK6 ;若处于调时状态,则该位闪烁MOV R6,#00HCLK5: CLR P0.5mov a,41HMOV P2, a ;显示秒的低位ACALL DELAY3MSCLK6: SETB P0.5CLR P0.4mov a,40hMOV P2,a ;显示秒的高位ACALL DELAY3MSSETB P0.4RETSHOWDATE:MOV R0,36H ;显示年ACALL PROHTODCJNE R7,#04H,DAY1INC R6CJNE R6,#03H,DAY2 ;若处于调时状态,则该位闪烁MOV R6,#00HDAY1: CLR P0.1MOV P2,41H ;显示年的低位ACALL DELAY3MSDAY2: SETB P0.1CLR P0.0MOV P2,40H ;显示年的高位ACALL DELAY3MSSETB P0.0MOV R0,35H ;显示月ACALL PROHTODCJNE R7,#05H,MONTH1INC R6CJNE R6,#03H,MONTH2 ;若处于调时状态,则该位闪烁MOV R6,#00HMONTH1: CLR P0.3MOV P2,41H ;显示月的低位ACALL DELAY3MSMONTH2: SETB P0.3CLR P0.2MOV P2,40H ;显示月的高位ACALL DELAY3MSSETB P0.2MOV R0,34H ;显示日ACALL PROHTODCJNE R7,#06H,YEAR1INC R6CJNE R6,#03H,YEAR2 ;若处于调时状态,则该位闪烁MOV R6,#00HYEAR1: CLR P0.5MOV P2,41HACALL DELAY3MSYEAR2: SETB P0.5CLR P0.4MOV P2,40HACALL DELAY3MSSETB P0.4RETPROHTOD:PUSH ACC ;十六进制数转换成bcd码,且可以直接输出p0口MOV A,R0DIV ABMOV DPTR,#0030HMOVC A,@A+DPTRMOV 40H,AMOV A,BMOVC A,@A+DPTRMOV 41H,APOP ACCRETDELAY3MS: ;DELAY3MSMOV 45H,#05HDELAY1: MOV 46H,#0FFHDELAY2: DJNZ 46H,DELAY2DJNZ 45H,DELAY1RETPROINT0:CLR EX0 ;切换键中断程序ACALL PROSHOWMOV C,P3.2JC IEXIT0MOV R1,#00HINC R7CJNE R7,#07H,IEXIT0MOV R7,#00HINT01: MOV C,P3.2JC INT02ACALL PROSHOWAJMP INT01INT02: ACALL PROSHOWIEXIT0: SETB EX0RETIPROINT1:CLR EX1ACALL PROSHOWJC IEXIT1LCALL ISYEAR ;判断平年闰年LCALL ISMONTH ;判断月份,确定最大日数MOV R1,#00HCJNE R7,#00H,NEXT1 ;若不是调时状态,按此键就是切换显示日期、时钟 INC R3CJNE R3,#02H,IEXIT1MOV R3,#00HAJMP IEXIT1NEXT1: mov r3,#00hCJNE R7,#03H,NEXT2 ;修改秒位INC 31HMOV A,31HCJNE A,#3CH,INT11 ;遇60变0MOV 31H,#00HAJMP IEXIT1NEXT2: CJNE R7,#02H,NEXT3 ;修改分位INC 32HMOV A,31HCJNE A,#3CH,INT11 ;遇60变0MOV 31H,#00HAJMP IEXIT1NEXT3: CJNE R7,#01H,NEXT4 ;修改时位INC 33HMOV A,33HCJNE A,#18H,INT11 ;遇24变0MOV 33H,#00HAJMP IEXIT1NEXT4: CJNE R7,#06H,NEXT5 ;修改日INC 34HMOV A,34HCJNE A,49H,INT11 ;到月底就返回月初MOV 34H,#01HAJMP IEXIT1NEXT5: CJNE R7,#05H,NEXT6 ;修改月INC 35HMOV A,35HCJNE A,#0DH,INT11 ;十二月过后就跳回1月MOV 35H,#01HAJMP IEXIT1NEXT6: CJNE R7,#04H,INT11 ;修改年INC 36HMOV A,36HCJNE A,#64H,INT11MOV 36H,#00HINT11: MOV C,P3.3JC INT12ACALL PROSHOWAJMP INT11INT12: ACALL PROSHOWIEXIT1: setb EX1RETI;/////////////////////////////////////PROTIME:MOV TMOD,#10HMOV TH1,#3CH ;定时器初始化MOV TL1,#60Hsetb tr1INC R4CJNE R4,#15H,EXITMOV R4,#00H ;计满1秒则清零CJNE R7,#00H,DIAOSHIAJMP NORMALDIAOSHI:INC R1 ;调时不按键的最长时间为10秒,在此期间又键按下重新计时CJNE R1,#0AH,EXITMOV R7,#00H ;到10秒则返回正常显示状态MOV R1,#00HAJMP EXITNORMAL: ACALL ISYEAR ;判断平闰年,返回标志48h,0为平年,1为闰年ACALL ISMONTH ;判断哪个月,返回该月的最大日数,存放在49hINC 31HMOV A,31H ;秒加一CJNE A,#3CH,EXITMOV 31H,#00HINC 32H ;分加一MOV A,32HCJNE A,#3CH,EXITMOV 32H,#00HINC 33H ;时加一MOV A,33HCJNE A,#18H,EXITMOV 33H,#00HINC 34H ;日加一MOV A,34HCJNE A,49H,EXITMOV 34H,#01HINC 35H ;月加一MOV A,35HCJNE A,#0DH,EXITMOV 35H,#01HINC 36H ;年加一MOV A,36HCJNE A,#64H,EXITMOV 36H,#00HEXIT:RETIISYEAR: MOV A,36H ;判断平闰年MOV B,#04HDIV ABMOV A,BCJNE A,#00H,EXITYEAR1MOV 48H,#01H ;闰年SJMP EXITYEAREXITYEAR1:MOV 48H,#00H ;平年EXITYEAR:RETIISMONTH:MOV A,35H ;开始检查月份CJNE A,#02H,NEXTMON1 ;判断二月MOV R2,48HCJNE R2,#00H,RUNNIANMOV 49H,#1DH ;平年为28天,赋29给49hAJMP EXITMONTHRUNNIAN:MOV 49H,#1EH ;闰年为29天,赋30天给49h AJMP EXITMONTHNEXTMON1:CJNE A,#04H,NEXTMON2AJMP XIAOYUENEXTMON2:CJNE A,#06H,NEXTMON3AJMP XIAOYUENEXTMON3:CJNE A,#09H,NEXTMON4AJMP XIAOYUENEXTMON4:CJNE A,#0BH,DAYUEXIAOYUE: MOV 49H,#1FH ;四,六,九,十一月是小月,30天,但应该赋31天给比较值49h,AJMP EXITMONTHDAYUE: MOV 49H,#20H ;其他月份为大月,31天,赋32天给49h EXITMONTH:RETIEND4 系统测试与仿真4.1仿真仿真原理图4.2测试电子万年历是多功能的数字型单片机应用产品,它可以显示当前日期,时间,还有温度。

相关文档
最新文档