(原创)51单片机C语言程序设计--速学教本实例(进阶篇)跟可调电子日历资料精
51单片机及C语言入门教程

51单片机及C语言入门教程本教程将介绍51单片机及C语言的入门知识,帮助初学者快速掌握这两个方面的基本内容。
以下是本教程的详细内容:一、51单片机概述(200字)51单片机是由Intel公司推出的一种常见的单片机芯片,具有广泛应用的特点。
它采用了Harvard结构,具有8位数据总线和16位地址总线。
其主要特点是结构简单、易于学习、应用广泛,适用于各种嵌入式系统。
二、C语言基础(300字)C语言是一种高级编程语言,具有跨平台、可移植性强等特点,被广泛应用于各种软件开发和嵌入式系统中。
学习C语言的基础知识是学习51单片机编程的必要前提。
C语言基础知识主要包括数据类型、变量、常量、运算符、表达式、流程控制语句等内容。
这些知识是学习C语言和51单片机编程的基础,需要仔细理解和掌握。
三、51单片机编程入门(400字)1. 搭建开发环境:首先需要安装51单片机的开发工具,如KeilC51等。
然后,连接单片机开发板和电脑,确保硬件连接正确。
2.了解开发板:学习使用51单片机的开发板是学习51单片机编程的第一步。
具体包括开发板上各个接口的功能和使用方法。
3.编写第一个程序:根据教材或教程,编写第一个简单的程序,如让LED灯闪烁等。
学习如何通过C语言编写程序,将其烧录到单片机中,并运行和调试。
四、C语言与51单片机的应用(300字)在学习了C语言和51单片机的基础知识之后,可以进一步学习它们的应用。
1.输入输出操作:学习如何通过51单片机与外部设备进行输入输出操作,如控制LED灯的亮灭、读取按键输入等。
2.定时器和中断:学习如何使用51单片机的定时器和中断功能来实现定时任务和外部事件处理。
3.串口通信:学习如何通过51单片机的串口通信功能与其他设备进行数据交换和通信。
五、实例项目及拓展应用(200字)完成了基础学习后,可以尝试一些实例项目,如温度测量系统、遥控器、电子钟等。
同时,可以进一步学习其他相关知识,如LCD显示、SPI 通信等,以扩展自己的应用能力。
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("简洁界面");}。
《单片机C51项目设计与开发》电子教案 项目5 万年历的控制和制作

任务1 PG160128A液晶显示
上一页 下一页 返回
任务1 PG160128A液晶显示
上一页 下一页 返回
任务1 PG160128A液晶显示
上一页 下一页 返回
任务1 PG160128A液晶显示
上一页 下一页 返回
任务1 PG160128A液晶显示
上一页 下一页 返回
上一页 下一页 返回
任务1 PG160128A液晶显示
上一页 下一页 返回
任务1 PG160128A液晶显示
上一页 下一页 返回
任务1 PG160128A液晶显示
上一页 下一页 返回
任务1 PG160128A液晶显示
上一页 下一页 返回
任务1 PG160128A液晶显示
上一页 下一页 返回
• 任务分析
• 1.硬件电路分析 • 使用单片机的P1口传送数据DO~D7, P2.0, P2.1, P2.2, P2.3分别控
制PG160128A的CD, CE, WR和RD引脚,电路原理图如图5-1所示。 • 2.软件设计思路 • 软件程序设计需要按照PG160128A液晶显示器的读写操作时序来编
上一页 下一页 返回
任务1 PG160128A液晶显示
• SS:控制器运行检测可能性,1:可能,0:不能 • S6:屏读/拷贝出错状态,1:出错,0:正确 • S7:闪烁状态检测,1:正常显示,0:关显示 • 由于状态位作用不一样,因此执行不同指令必须检测不同状态位。在
CPU每一次读、写指令和数据时,S0和S1要同时有效,处于“准备 好”状态。 • 当CPU读、写数组时,判断S2或S3状态。 • 屏读、屏拷贝指令使用S6。 • SS和S7反映T6963C内部运行状态。 • (2)地址指针设置指令
《C语言程序设计》教学日历

实验十文件
注:因教学改革需要,课程上课时间与内容可能调整
教研室主任签字:教学科长签字:
说明:1、采用方式可分为:课堂讲授、讨论以及使用多媒体、投影仪、CAI、电子教案、录像
等现代化教学手段;
2、作业可注明作业内容、实验报告篇数等需要学生课外完成的作业;
3、每次课的内容占一格;
本科生教学日历
上课时间
计划教学内容
授课内容
授课方式
作业(实验)
第
1
周
第一章概述
1.1计算机语言和计算机程序
1.2程序设计方法
1.3程序的实现环境
1.4C语言和C++的发展
自主学习内容:计算机硬件和软件的相关概念和知识
课堂教学,实验课,自主学习
实验一 编译环境的使用
第
2
周
第二章程序设计初步
2.1 C程序的基本框架
5.3数组作为函数的参数
课堂教学,实验课
实验五数组(1)
第
8
周
第五章数组
5.4二维数组
5.5字符数组与字符串
5.6案例学习:计算课程平均成绩
课堂教学,实验课
实验五数组(2)
第
9
周
第六章指针
6.1指针和指针变量
6.2指针与数组
课堂教学,实验课
实验六指针(1)
第
10
周
第六章指针
6.3字符指针
6.4指针与函数
第
13
周
第八章自定义数据类型
8.1结构体
8.2案例学习:图书管理
课堂教学,实验课
实验八自定义数据类型
第
14
周
51电子日历C程序

#define SYS_CLOCK_EN 1#if SYS_CLOCK_EN#include "typedef.h"#include "reg52.h"#include "string.h"#include "stdlib.h"#include "Stdio.h"#define FOSC 22118400L#define MACHINE_NUM 12 /*根据需要调整,如:W777E58=4*/#define TICKS_PER_SEC 10 /* # of clock ticks to obtain 1 second */#define CLK_DATE_EN 1 /* Enable DATE (when 1) */#define ENTER_CRITICAL() EA=1#define EXIT_CRITICAL() EA=0#if CLK_DATE_ENtypedef struct clk_month{UCHAR MonthDays; /* Number of days in each month */char *MonthName; /* Name of the month */UCHAR MonthVal; /* Value used to compute day of the week */} CLK_MONTH;#endifstatic UCHAR ClkTickCtr; /* Counter used to keep track of system clock ticks */static UCHAR ClkHr;static UCHAR ClkMin;static UCHAR ClkSec; /* Counters for local TIME*/#if CLK_DATE_ENstatic UCHAR ClkDay; /* Counters for local DATE */static UCHAR ClkDOW; /* Day of week (0 is Sunday)*/static UCHAR ClkMonth;static UINT ClkYear;#endif/****************************************************************************** ***************************** FUNCTION PROTOTYPES******************************************************************************* ***************************/static BOOL ClkUpdateTime(void);#if CLK_DATE_ENstatic BOOL ClkIsLeapYear(UINT year);static void ClkUpdateDate(void);static void ClkUpdateDOW(void);#endifvoid Init_sys_timer(void);void Sys_clk_init(void);void Sys_clk_task(void);void Clk_format_time(UCHAR mode, char *s);void Clk_set_time(UCHAR hr, UCHAR min, UCHAR sec);int Cmp_now_time(UCHAR hr, UCHAR min, UCHAR sec);#if CLK_DATE_ENvoid Clk_format_date(UCHAR mode, char *s);void Clk_set_date(UCHAR month, UCHAR day, UINT year);void Clk_set_date_time(UCHAR month, UCHAR day, UINT year, UCHAR hr, UCHAR min, UCHAR sec);int Cmp_now_date_time(UCHAR month, UCHAR day, UINT year, UCHAR hr, UCHAR min, UCHAR sec);#endif/****************************************************************************** ***************************/#if CLK_DATE_ENstatic char code *ClkDOWTbl[] = { /* NAME FOR EACH DAY OF THE WEEK */"Sunday ","Monday ","Tuesday ","Wednesday ","Thursday ","Friday ","Saturday "};static CLK_MONTH code ClkMonthTbl[] = { /* MONTHS TABLE */{0, "", 0}, /* Invalid month */{31, "January ", 6}, /* January */{28, "February ", 2}, /* February (note leap years are handled by code) */{31, "March ", 2}, /* March */{30, "April ", 5}, /* April */{31, "May ", 0}, /* May */{30, "June ", 3}, /* June */{31, "July ", 5}, /* July */{31, "August ", 1}, /* August */{30, "September ", 4}, /* September */{31, "October ", 6}, /* October */{30, "November ", 2}, /* November */{31, "December ", 4} /* December */};#endif/******************************************************************************** *************************** TIME-OF-DAY CLOCK TASK** Description : This task is created by Sys_clk_init() and is responsible for updating the time and date.* Sys_clk_task() executes every second.* Arguments : None.* Returns : None.* Notes : CLK_DL Y_TICKS must be set to produce 1 second delays.******************************************************************************* ***************************/void Sys_clk_task (void){if(++ClkTickCtr==TICKS_PER_SEC){ClkTickCtr=0;if (ClkUpdateTime() == TRUE){#if CLK_DATE_ENClkUpdateDate(); /* And date if a new day (i.e. MM-DD-YY) */#endif}}}void Sys_tick_isr(void) interrupt 5 using 3{TF2=0;Sys_clk_task();}void Init_sys_timer(void){BYTE_WORD Init_value;Sys_clk_init();T2CON=0x00;Init_value.word=FOSC/(TICKS_PER_SEC*MACHINE_NUM);TH2=RCAP2H=-Init_value.bytes.high;TL2=RCAP2L=-Init_value.bytes.low;ET2=1;TR2=1;//TMOD&=0xF0; //使用定时器0,但在中断中需要重新赋初值,因而我更倾向用Timer2//TMOD|=0x01;// Init_value.word=FOSC/(TICKS_PER_SEC*MACHINE_NUM);//TH0=-Init_value.bytes.high;//TL0=-Init_value.bytes.low;//ET0=1;//TR0=1;}/******************************************************************************** *************************** TIME MODULE INITIALIZATION* TIME-OF-DAY CLOCK INITIALIZATION** Description : This function initializes the time module. The time of day clock task will be created* by this function.* Arguments : None* Returns : None.******************************************************************************* ***************************/void Sys_clk_init (void){ClkTickCtr = 0;Clk_set_time(11,32,0);#if CLK_DATE_ENClk_set_date(5,28,2002);#endif}/******************************************************************************** *************************** FORMAT CURRENT DATE INTO STRING** Description : Formats the current date into an ASCII string.* Arguments : mode is the format type:* 1 will format the time as "MM-DD-YY" (needs at least 9 characters)* 2 will format the time as "Day Month DD, YYYY" (needs at least30 characters)* 3 will format the time as "YYYY-MM-DD" (needs at least 11 characters)* s is a pointer to the destination string. The destination string must be large* enough to hold the formatted date.* contain* Returns : None.* Notes : - A 'switch' statement has been used to allow you to add your own date formats. For* example, you could display the date in French, Spanish, German etc. by assigning* numbers for those types of conversions.* - This function assumes that strcpy(), strcat() and itoa() are reentrant.******************************************************************************* ***************************/#if CLK_DATE_ENvoid Clk_format_date (UCHAR mode, char *s){UINT year;char str[5];switch (mode){case 1:strcpy(s, "MM-DD-YY"); /* Create the template for the selected format */s[0] = ClkMonth / 10 + '0'; /* Convert DATE to ASCII */s[1] = ClkMonth % 10 + '0';s[3] = ClkDay / 10 + '0';s[4] = ClkDay % 10 + '0';year = ClkYear % 100;s[6] = year / 10 + '0';s[7] = year % 10 + '0';break;case 2:strcpy(s, ClkDOWTbl[ClkDOW]); /* Get the day of the week */strcat(s, ClkMonthTbl[ClkMonth].MonthName); /* Get name of month */if (ClkDay < 10){str[0] = ClkDay + '0';str[1] = 0;}else{str[0] = ClkDay / 10 + '0';str[1] = ClkDay % 10 + '0';str[2] = 0;}strcat(s, str);strcat(s, ", ");sprintf(str,"%d",ClkYear);strcat(s, str);break;case 3:strcpy(s, "YYYY-MM-DD"); /* Create the template for the selected format */s[0] = year / 1000 + '0';year = year % 1000;s[1] = year / 100 + '0';year = year % 100;s[2] = year / 10 + '0';s[3] = year % 10 + '0';s[5] = ClkMonth / 10 + '0'; /* Convert DATE to ASCII */s[6] = ClkMonth % 10 + '0';s[8] = ClkDay / 10 + '0';s[9] = ClkDay % 10 + '0';break;default:strcpy(s, "?");break;}}#endif/******************************************************************************** *************************** FORMAT CURRENT TIME INTO STRING** Description : Formats the current time into an ASCII string.* Arguments : mode is the format type:* 1 will format the time as "HH:MM:SS" (24 Hour format)* (needs at least 9 characters)* 2 will format the time as "HH:MM:SS AM" (With AM/PM indication)* (needs at least 13 characters)* s is a pointer to the destination string. The destination string must be large* enough to hold the formatted time.* contain* Returns : None.* Notes : - A 'switch' statement has been used to allow you to add your own time formats. * - This function assumes that strcpy() is reentrant.******************************************************************************* ***************************/void Clk_format_time (UCHAR mode, char *s){UCHAR hr;switch (mode){case 1:strcpy(s, "HH:MM:SS"); /* Create the template for the selected format */s[0] = ClkHr / 10 + '0'; /* Convert TIME to ASCII */s[1] = ClkHr % 10 + '0';s[3] = ClkMin / 10 + '0';s[4] = ClkMin % 10 + '0';s[6] = ClkSec / 10 + '0';s[7] = ClkSec % 10 + '0';break;case 2:strcpy(s, "HH:MM:SS AM"); /* Create the template for the selected format */s[9] = (ClkHr >= 12) ? 'P' : 'A'; /* Set AM or PM indicator */if (ClkHr > 12){ /* Adjust time to be displayed */hr = ClkHr - 12;}else{hr = ClkHr;}s[0] = hr / 10 + '0'; /* Convert TIME to ASCII */s[1] = hr % 10 + '0';s[3] = ClkMin / 10 + '0';s[4] = ClkMin % 10 + '0';s[6] = ClkSec / 10 + '0';s[7] = ClkSec % 10 + '0';break;default:strcpy(s, "?");break;}}/******************************************************************************** *************************** UPDATE THE TIME** Description : This function is called to update the time (i.e. hours, minutes and seconds)* Arguments : None.* Returns : TRUE if we have completed one day.* FALSE otherwise* Notes : This function updates ClkSec, ClkMin and ClkHr.******************************************************************************* ***************************/static BOOL ClkUpdateTime (void){BOOL newday;newday = FALSE; /* Assume that we haven't completed one whole day yet */if (ClkSec >= 59){ /* See if we have completed one minute yet */ClkSec = 0; /* Yes, clear seconds */if (ClkMin >= 59){ /* See if we have completed one hour yet */ClkMin = 0; /* Yes, clear minutes */if (ClkHr >= 23){ /* See if we have completed one day yet */ClkHr = 0; /* Yes, clear hours ... */newday = TRUE; /* ... change flag to indicate we have a new day */}else{ClkHr++; /* No, increment hours */}}else{ClkMin++; /* No, increment minutes */}}else{ClkSec++; /* No, increment seconds */}return (newday);}/******************************************************************************** *************************** SET TIME ONL Y** Description : Set the time-of-day clock* Arguments : hr is the desired hour (0..23)* min is the desired minutes (0..59)* sec is the desired seconds (0..59)* Returns : None.* Notes : It is assumed that you are specifying a correct time (i.e. there is no range checking* done by this function).******************************************************************************* ***************************/void Clk_set_time (UCHAR hr, UCHAR min, UCHAR sec){ENTER_CRITICAL(); /* Gain exclusive access to time-of-day clock */ClkHr = hr;ClkMin = min;ClkSec = sec;EXIT_CRITICAL(); /* Release access to time-of-day clock */}/******************************************************************************** *************************** DETERMINE IF WE HA VE A LEAP YEAR** Description : This function determines whether the 'year' passed as an argument is a leap year.* Arguments : year is the year to check for leap year.* Returns : TRUE if 'year' is a leap year.* FALSE if 'year' is NOT a leap year.******************************************************************************* ***************************/#if CLK_DATE_ENstatic BOOL ClkIsLeapYear(UINT year){if (!(year % 4) && (year % 100) || !(year % 400)){return TRUE;}else{return (FALSE);}}#endif/******************************************************************************** *************************** SET DA TE ONL Y** Description : Set the date of the time-of-day clock* Arguments : month is the desired month (1..12)* day is the desired day (1..31)* year is the desired year (CLK_TS_BASE_YEAR .. CLK_TS_BASE_YEAR+63)* Returns : None.* Notes : It is assumed that you are specifying a correct date (i.e. there is no range checking* done by this function).******************************************************************************* ***************************/#if CLK_DATE_ENvoid Clk_set_date (UCHAR month, UCHAR day, UINT year){ENTER_CRITICAL();ClkMonth = month;ClkDay = day;ClkYear = year;ClkUpdateDOW();EXIT_CRITICAL();}#endif/******************************************************************************** *************************** SET DATE AND TIME** Description : Set the date and time of the time-of-day clock* Arguments : month is the desired month (1..12)* day is the desired day (1..31)* year is the desired year (2xxx)* hr is the desired hour (0..23)* min is the desired minutes (0..59)* sec is the desired seconds (0..59)* Returns : None.* Notes : It is assumed that you are specifying a correct date and time (i.e. there is no range* checking done by this function).******************************************************************************* ***************************/#if CLK_DATE_ENvoid Clk_set_date_time (UCHAR month, UCHAR day, UINT year, UCHAR hr, UCHAR min,UCHAR sec){ENTER_CRITICAL(); /* Gain exclusive access to time-of-day clock */ClkMonth = month;ClkDay = day;ClkYear = year;ClkHr = hr;ClkMin = min;ClkSec = sec;ClkUpdateDOW(); /* Compute the day of the week (i.e. Sunday ...) */EXIT_CRITICAL(); /* Release access to time-of-day clock */}#endif/******************************************************************************** *************************** UPDATE THE DATE** Description : This function is called to update the date (i.e. month, day and year)* Arguments : None.* Returns : None.* Notes : This function updates ClkDay, ClkMonth, ClkYear and ClkDOW.******************************************************************************* ***************************/#if CLK_DATE_ENstatic void ClkUpdateDate (void){BOOL newmonth;newmonth = TRUE;if (ClkDay >= ClkMonthTbl[ClkMonth].MonthDays) { /* Last day of the month? */if (ClkMonth == 2) { /* Is this February? */if (ClkIsLeapYear(ClkYear) == TRUE) { /* Yes, Is this a leap year? */if (ClkDay >= 29) { /* Yes, Last day in february? */ClkDay = 1; /* Yes, Set to 1st day in March */} else {ClkDay++;newmonth = FALSE;}} else {ClkDay = 1;}} else {ClkDay = 1;}} else {ClkDay++;newmonth = FALSE;}if (newmonth == TRUE) { /* See if we have completed a month */if (ClkMonth >= 12) { /* Yes, Is this december ? */ClkMonth = 1; /* Yes, set month to january... */ClkYear++; /* ...we have a new year! */} else {ClkMonth++; /* No, increment the month */}}ClkUpdateDOW(); /* Compute the day of the week (i.e. Sunday ...) */}#endif/******************************************************************************** *************************** COMPUTE DAY-OF-WEEK** Description : This function computes the day of the week (0 == Sunday) based on the current month,* day and year.* Arguments : None.* Returns : None.* Notes : - This function updates ClkDOW.* - This function is called by ClkUpdateDate().**********************************************************************************************************/#if CLK_DATE_ENstatic void ClkUpdateDOW (void){UINT dow;dow = ClkDay + ClkMonthTbl[ClkMonth].MonthVal;if (ClkMonth < 3){if (ClkIsLeapYear(ClkYear)){dow--;}}dow += ClkYear + (ClkYear / 4);dow += (ClkYear / 400) - (ClkYear / 100);dow %= 7;ClkDOW = dow;}#endifint Cmp_now_time(UCHAR hr, UCHAR min, UCHAR sec){if(ClkHr!=hr)return(hr-ClkHr);else if(ClkMin!= min)return(min-ClkMin);elsereturn(sec-ClkSec);}#if CLK_DATE_ENint Cmp_now_date_time(UCHAR month, UCHAR day, UINT year, UCHAR hr, UCHAR min, UCHAR sec){if(ClkYear!=year)return(year-ClkYear);else if(ClkMonth!=month)return(month-ClkMonth);else if(ClkDay!=day)return(day-ClkDay);else if(ClkHr!=hr)return(hr-ClkHr);else if(ClkMin!= min)return(min-ClkMin);elsereturn(sec-ClkSec); }#endif#endif。
(完整版)基于51单片机的万年历的设计

单片机课程实训SCM PRACTICAL TRAINING目录第一部分课程设计任务书 (1)一、课程设计题目 (1)二、课程设计时间 (1)三、实训提交方式 (1)四、设计要求 (1)第二部分课程设计报告 (2)一、单片机发展概况 (2)二、MCS-51单片机系统简介 (2)三、设计思想 (3)四、硬件电路设计 (3)1. 总体设计 (3)2. 晶振电路 (4)3. 复位电路 (4)4. DS1302时钟电路 (5)5. 温度采集系统电路 (5)6. 按键调整电路 (6)7. 闹钟提示电路 (6)五、软件设计框图 (7)六、程序源代码 (8)1. 主程序 (8)2. 温度控制程序 (11)3. 日历设置程序 (13)4. 时钟控制程序 (18)5. 显示设置程序 (20)七、结束语 (23)八、课程设计小组分工 (23)九、参考文献 (23)第一部分课程设计任务书一、课程设计题目用中小规模集成芯片设计制作万年历。
二、课程设计时间五天三、实训提交方式提交实训设计报告电子版与纸质版四、设计要求(1)显示年、月、日、时、分、秒和星期,并有相应的农历显示。
(2)可通过键盘自动调整时间。
(3)具有闹钟功能。
(4)能够显示环境温度,误差小于±1℃(5)计时精度:月误差小于20秒。
第二部分课程设计报告一、单片机发展概况单片机诞生于20世纪70年代末,它的发展史大致可分为三个阶段:第一阶段(1976-1978):初级单片机微处理阶段。
该时期的单片机具有 8 位CPU,并行 I/O 端口、8 位时序同步计数器,寻址范围 4KB,但是没有串行口。
第二阶段(1978-1982):高性能单片机微机处理阶段,该时期的单片机具有I/O 串行端口,有多级中断处理系统,15 位时序同步技术器,RAM、ROM 容量加大,寻址范围可达 64KB。
第三阶段(1982-至今)位单片机微处理改良型及 16 位单片机微处理阶段民用电子产品、计算机系统中的部件控制器、智能仪器仪表、工业测控、网络与通信的职能接口、军工领域、办公自动化、集散控制系统、并行多机处理系统和局域网络系统。
51单片机电子日历

51单片机电子日历(电子时钟)硬件实验箱是伟福LAB2000实验箱。
代码:/* 电子日历,有时间显示、闹铃、日期、秒表及键盘设置功能 */能键A: 设置位数字+1 闹钟模式下为闹钟开关秒表模式下为记时开关 */能键B: 设置位数字-1 闹钟模式下为闹钟开关 */能键C:设置模式及设置位选择秒表模式下为清零键 */ 能键D:在四种工作模式下切换设置闹钟开关 */dede/***************这里设置程序初始化时显示的时间****************/#define SET_HOUR 12 /*设置初始化小时*/#define SET_MINUTE 00 /*设置初始化分钟*/#define SET_SECOND 00 /*设置初始化秒数*/************************系统地址****************************/efine BASE_PORT 0x8000 /*选通基地址*/efine KEY_LINE BASE_PORT+1 /*键盘行线地址#define KEY_COLUMN BASE_PORT+2 /*键盘列线地址*/efine LED_SEG BASE_PORT+4 /*数码管段选地址*/efine LED_BIT BASE_PORT+2 /*数码管位选地址*/efine LED_ON(x) XBYTE[LED_BIT]=(0x01<<X)&NBSP; *6位led的位选通,带参数宏,参数为0~5*=""efine LED_OFF XBYTE[LED_SEG]=0x00 /*LED显示空*//**************在设置模式下对秒分时的宏定义*****************/#define SECOND 0 /*对应数码管右边两位*/#define MINUTE 1 /*对应数码管中间两位*/#define HOUR 2 /*对应数码管左边两位*//********************定义四种工作模式***********************/#define CLOCK clockstr /*时钟模式*/#define ALART alartstr /*闹钟模式*/#define DATE datestr /*日期模式*/#define TIMER timerstr /*秒表模式*//****************以下是所有子函数的声明*********************/void sys_init(void); /*系统的初始化程序*/void display(void); /*动态刷新一次数码管子程序*/void clockplus(void); /*时间加1S的子程序*/void update_clockstr(void); /*更新时间显示编码*/void update_alartstr(void); /*更新闹钟时间的显示编码*/void update_datestr(void); /*更新日期显示编码*/void update_timerstr(void); /*更新秒表时间的显示编码*/void deley(int); /*延时子程序*/void update_dispbuf(unsigned char *); /*更新显示缓冲区*/unsigned char getkeycode(void); /*获取键值子程序*/void keyprocess(unsigned char); /*键值处理子程序*/unsigned char getmonthdays(unsigned int,unsigned char);/*计算某月的天数子程序*//*功能键功能子函数*/void Akey(void); /*当前设置位+1 开关闹钟开关秒表*/void Ckey(void); /*设置位选择秒表清零*/void Dkey(void); /*切换四种工作模式*//**********************全局变量声明部分unsigned char led[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};/*从0~9的LED编码*/unsigned char ledchar[3]={0x5c,0x54,0x71};/*o n f*///unsigned char key[24]={ /* 键值代码数组对应键位:*/// 0x70,0x71,0x72,0x73,0x74,0x75, /* 7 8 9 A TRACE RESET*/// 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5, /* 4 5 6 B STEP MON */// 0xd0,0xd1,0xd2,0xd3,0xd4,0xd5, /* 1 2 3 C HERE LAST */// 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5}; /* 0 F E D EXEC NEXT */struct{ /*时间结构体变量*/unsigned char s;unsigned char m;unsigned char h;}clock={SET_SECOND,SET_MINUTE,SET_HOUR};struct{ /*闹铃时间结构体变量*/unsigned char m;unsigned char h;}alart={SET_MINUTE,SET_HOUR};struct{ /*日期结构体变量*/unsigned int year;unsigned char month;unsigned char day;}date={6,1,1};struct{ /*秒表时间结构体变量*/unsigned char ms;unsigned char s;unsigned char m;}timer={0,0,0};unsigned char dispbuf[6]; /*显示缓冲区数组*/unsigned char clockstr[6]; /*时间显示的数码管编码数组*/unsigned char alartstr[6]; /*闹钟显示的数码管编码数组*/unsigned char datestr[6]; /*日期显示的数码管编码数组*/unsigned char timerstr[6]; /*秒表显示的数码管编码数组*/unsigned int itime=0,idot; /*定时器0中断计数*/unsigned char itime1=0; /*定时器1中断计数*/sbit P3_1=P3^1; /*外接蜂鸣器的管脚*/bdata bit IsSet=0; /*设置模式标志位0:正常走时1:设置模式*/bdata bit Alart_EN=0; /*闹铃功能允许位0:禁止闹铃1:允许闹铃*/bdata bit IsBeep=0; /*响铃标志位0:未响铃1:正在响铃*/unsigned char SetSelect=0; /*在设置模式IsSet=1时,正在被设置的位,对应上面的宏*/unsigned char *CurrentMode; /*标志当前正设置的功能,如CurrentMode=CLOCK或CurrentMode=ALART等*/void timerplus(void);/**************************函数部分*************************/void main(void){sys_init();{XBYTE[KEY_COLUMN,0x00]; /*给键盘列线赋全零扫描码,判断是否有键按下 */while((XBYTE[KEY_LINE]&0x0f)==0x0f) /*检测是否有键按下,无则一直进行LED的刷新显示*/{if(Alart_EN&&(clock.h==alart.h)&&(clock.m==alart.m)) {IsBeep=1;}else{ IsBeep=0;P3_1=0;}display();}keyprocess(getkeycode()); /*有键按下时得到键值,并送入键值处理程序*/display(); /*可要可不要*/}}void sys_init(void){TMOD=0x22; /*定时器0和1都设置为工作方式2,基准定时250×2=500us=0.5ms*/TH0=6; /*定时器0中断服务用来产生1秒时钟定时及闹钟蜂鸣器蜂鸣脉冲*/TL0=6; /*定时器1中断服务留给秒表使用,产生1/100秒定时*/TH1=6;TL1=6;ET0=1;ET1=1;EA=1;TR0=1;update_clockstr(); /*初始化时钟显示编码数组*/update_alartstr(); /*初始化闹钟显示编码数组*/update_datestr(); /*初始化日期显示编码数组*/update_timerstr(); /*初始化秒表显示编码数组*/update_dispbuf(clockstr);/*初始化显示缓冲数组*/CurrentMode=CLOCK; /*默认的显示摸式为时钟*/P3_1=0; /*蜂鸣器接线引脚复位*/}void timer0(void) interrupt 1 using 1 /*定时器0中断服务器,用来产生1秒定时*/{itime++;if(itime==1000){if(IsSet) /*在设置模式下,对正在设置的位闪烁显示*/{dispbuf[SetSelect*2]=0; /*对正在设置的位所对应的显示缓冲区元素赋0,使LED灭*/ dispbuf[SetSelect*2+1]=0;}if(IsBeep) P3_1=!P3_1; /*闹钟模式时,产生峰鸣器响脉冲*/if(CurrentMode==CLOCK){dispbuf[2]=dispbuf[2]&0x7f;}}if(itime==2000) /*两千次计数为1S 2000×0.5ms=1s*/{itime=0; /*定时1s时间到,软计数清零*/clockplus(); /*时间结构体变量秒数加1 */update_clockstr(); /* 更新时间显示编码数组 */if(CurrentMode!=TIMER) update_dispbuf(CurrentMode); /* 用时间编码数组更新显示缓冲区 */ }}void timer1(void) interrupt 3 using 2 /*定时器1中断服务器,用来产生1/100秒定时*/{idot++;if(++itime1==20) /*20*0.5ms=10ms*/{itime1=0;timerplus();update_timerstr();if(CurrentMode==TIMER){update_dispbuf(timerstr);dispbuf[2]=dispbuf[2]&0x7f; /*关闭小数点的显示*/dispbuf[4]=dispbuf[4]&0x7f;if(idot<1000) /*闪烁显示小数点*/{dispbuf[2]=dispbuf[2]|0x80;dispbuf[4]=dispbuf[4]|0x80;}else{dispbuf[2]=dispbuf[2]&0x7f;dispbuf[4]=dispbuf[4]&0x7f;}}}if(idot==2000) idot=0;}/*功能模块子函数*/void clockplus(void) /*时间加1s判断分,时子函数*/{if(++clock.s==60) /*秒位判断*/{clock.s=0;if(++clock.m==60) /*分位判断*/{clock.m=0;if(++clock.h==24) /*时位判断*/{if(++date.day==(getmonthdays(date.year,date.month)+1)){date.day=1;if(++date.month==13) date.month=1;}}}}}void timerplus() /*秒表1/100秒位加1,判断秒、分子程序*/{if(++timer.ms==100){timer.ms=0;if(++timer.s==60){timer.s=0;if(++timer.m==60){timer.m=0;}}}}void update_clockstr(void) /*更新时钟显示代码数组clockstr*/{clockstr[0]=led[clock.s%10]; /*给元素0赋相应数码管显示编码,编码序号是秒数的个位*/clockstr[1]=led[(int)(clock.s/10)]; /*给元素1赋相应数码管显示编码,编码序号是秒数的十位*/ clockstr[2]=led[clock.m%10]; /*以下类推*/clockstr[3]=led[(int)(clock.m/10)];clockstr[4]=led[clock.h%10];clockstr[5]=led[(int)(clock.h/10)];}void update_alartstr(void) /*更新闹钟显示代码数组alartstr*/{ /*右边两位显示on:闹钟开启 of:闹钟关闭*/if(Alart_EN) alartstr[0]=ledchar[1];/*显示字母n*/else alartstr[0]=ledchar[2]; /*显示字母f*/alartstr[1]=ledchar[0]; /*显示字母o*/alartstr[2]=led[alart.m%10];alartstr[3]=led[(int)(alart.m/10)];alartstr[4]=led[alart.h%10];alartstr[5]=led[(int)(alart.h/10)];}void update_datestr(void) /*更新日期显示代码数组datestr*/{datestr[0]=led[date.day%10];datestr[1]=led[(int)(date.day/10)];datestr[3]=led[(int)(date.month/10)];datestr[4]=led[date.year%10];datestr[5]=led[(int)(date.year/10)];}void update_timerstr(void) /*更新秒表显示代码数组timerstr*/{timerstr[0]=led[timer.ms%10];timerstr[1]=led[(int)(timer.ms/10)];timerstr[2]=led[timer.s%10];timerstr[3]=led[(int)(timer.s/10)];timerstr[4]=led[timer.m%10];timerstr[5]=led[(int)(timer.m/10)];}void display(void) /*刷新显示六位LED一次*/{unsigned char i;for(i=0;i<6;i++){LED_ON(i); /*选通相应位*/XBYTE[LED_SEG]=dispbuf[i]; /*写显示段码*/deley(50); /*延时显示*/LED_OFF; /*写LED全灭段码*/}}void update_dispbuf(unsigned char *str) /*更新显示缓冲区子函数,参数为要用来更新缓冲区的源字符数组的首地址*/ {dispbuf[0]=str[0]; /*将要更新的源字符数组内容COPY至dispbuf数组,用作显示缓冲区*/dispbuf[1]=str[1];dispbuf[2]=str[2]|0x80; /*默认把时位和分位后面的小数点显示出来,根据需要再取舍*/dispbuf[3]=str[3];dispbuf[4]=str[4]|0x80;dispbuf[5]=str[5];}void deley(int i) /*延时子函数*/{while(i--);}unsigned char getkeycode(void) /*键盘扫描子程序,返回获得的键码*/{unsigned char keycode; /*键码变量,一开始存行码*/unsigned char scancode=0x20; /*列扫描码*/unsigned char icolumn=0; /*键的列号*/display(); /*用刷新数码管显示的时间去抖*/XBYTE[KEY_COLUMN]=0x00;keycode=XBYTE[KEY_LINE]&0x0f; /*从行端口读入四位行码*/while((scancode&0x3f)!=0) /*取scancode的低六位,只要没变为全0,则执行循环*/{if((XBYTE[KEY_LINE]&0x0f)==keycode) break; /*检测按键所在的列跳出循环*/scancode=scancode>>1; /*列扫描码右移一位*/icolumn++; /*列号加1*/}keycode=keycode<<4; /*把行码移到高四位*/keycode=keycode|icolumn; /*由行码和列码组成键码*///等待按键放开XBYTE[KEY_COLUMN]=0x00;while((XBYTE[KEY_LINE]&0x0f)!=0x0f) display();return keycode;}void keyprocess(unsigned char keycode) /*键值处理函数*/{switch (keycode){case 0x73: Akey();break;case 0xB3: Bkey();break;case 0xD3: Ckey();break;case 0xE3: Dkey();break;default: break;}update_dispbuf(CurrentMode);}unsigned char getmonthdays(unsigned int year,unsigned char month)/*得到某月的天数*/ {unsigned char days;switch (month){case 4:case 6:case 9:case 11:days=30;break;case 2: if(year%4==0) days=29;else days=28;break;default:days=31;break;}return days;}/*功能键子函数部分*/void Akey(void) /*对当前设置位进行加一操作,如果设置秒位,则给秒位清零*/if(CurrentMode==TIMER) /*秒表模式下启闭走时*/{ TR1=!TR1;return;}if(!IsSet) return; /*如果不是设置模式退出*/switch (SetSelect){case SECOND:if(CurrentMode==CLOCK){clock.s=0; /*如果当前被设置位是秒位,则清零秒位*/update_clockstr();}if(CurrentMode==ALART){Alart_EN=!Alart_EN;update_alartstr();}if(CurrentMode==DATE){if(++date.day==(getmonthdays(date.year,date.month)+1)) date.day=1; update_datestr();}if(CurrentMode==TIMER){TR1=!TR1;}break;case MINUTE:if(CurrentMode==CLOCK){if(++clock.m==60) clock.m=0; /*如果当前被设置分位,则分位加1*/update_clockstr();}if(CurrentMode==ALART){if(++alart.m==60) alart.m=0;update_alartstr();}if(CurrentMode==DATE){if(++date.month==13) date.month=1;update_datestr();}break;case HOUR: if(CurrentMode==CLOCK){if(++clock.h==24) clock.h=0; /*如果当前被设置时位,则时位加1*/update_clockstr();if(CurrentMode==ALART){if(++alart.h==24) alart.h=0;update_alartstr();}if(CurrentMode==DATE){if(++date.year==100) date.year=0;update_datestr();}break;default: break;}update_dispbuf(CurrentMode);}void Bkey(void) /*对当前设置位进行减一操作,如果设置秒分,则给秒位清零,类比Akey()函数*/{if(!IsSet) return;switch (SetSelect){case SECOND:if(CurrentMode==CLOCK){clock.s=0;update_clockstr();}if(CurrentMode==ALART){Alart_EN=!Alart_EN;update_alartstr();}if(CurrentMode==DATE){if(--date.day==0x00) date.day=getmonthdays(date.year,date.month); update_datestr();}break;case MINUTE:if(CurrentMode==CLOCK){if(--clock.m==0xff) clock.m=59;update_clockstr();}if(CurrentMode==ALART){if(--alart.m==0xff) alart.m=59;update_alartstr();}if(CurrentMode==DATE)if(--date.month==0x00) date.month=12;update_datestr();}break;case HOUR: if(CurrentMode==CLOCK){if(--clock.h==0xff) clock.h=23;update_clockstr();}if(CurrentMode==ALART){if(--alart.h==0xff) alart.h=23;update_alartstr();}if(CurrentMode==DATE){if(--date.year==0xffff) date.year=99;update_datestr();}break;default: break;}update_dispbuf(CurrentMode);}void Ckey(void) /*正常走时模式和设置模式的切换*/{if(CurrentMode==TIMER){TR1=0; /*初始化定时器1设置,停止秒表记时*/TH1=6;TL1=6;timer.ms=0; /*初始化秒表数组*/timer.s=0;timer.m=0;update_timerstr();}else{if(IsSet==0) /*在非秒表模式下,第一次按下C键进入设置模式,设置时位*/{IsSet=1; /*置位标志位,进入设置模式 */SetSelect=HOUR;return;} /*第二次按C键设置分位,第三次按键设置秒位,第四次按键完成退出设置*/if(SetSelect==0) /*按到第四次,即设置完秒位后,将标志位IsSet置0,完成设置*/ {IsSet=0; /*复位标志位,进入正常走时模式*/return;if(SetSelect>0) SetSelect--; /*设置位的标志变量SetSelect=0:时位 1:分位 2:秒位*/}}void Dkey(void) /*工作状态切换:时钟、闹钟、日期、秒表*/{if(CurrentMode==CLOCK) /*切换至闹钟,同时开关闹钟*/{ CurrentMode=ALART;Alart_EN=!Alart_EN;update_alartstr();return;}if(CurrentMode==ALART) /*切换至日期*/{ CurrentMode=DATE;return;}if(CurrentMode==DATE)/*切换至秒表,同时关闭设置模式*/{CurrentMode=TIMER;IsSet=0;return;}if(CurrentMode==TIMER) /*切换至时钟*/{CurrentMode=CLOCK;return;}}11。
51单片机课程设计——电子万年历

电子万年历的设计学院计算机与控制工程学院专业班级自动化学生姓名指导教师2010年6月25日引言随着社会、科技的发展,人类得知时间,从观太阳、摆钟到现在电子钟,不断研究、创新。
为了在观测时间的同时,能够了解其它与人类密切相关的信息,比如温度、星期、日期等,电子万年历诞生了,它集时间、日期、星期和温度功能于一身,具有读取方便、显示直观、功能多样、电路简洁等诸多优点,符合电子仪器仪表的发展趋势,具有广阔的市场前景。
二十一世纪的今天,最具代表性的计时产品就是电子万年历,它是近代世界钟表业界的第三次革命。
第一次是摆和摆轮游丝的发明,相对稳定的机械振荡频率源使钟表的走时差从分级缩小到秒级,代表性的产品就是带有摆或摆轮游丝的机械钟或表。
第二次革命是石英晶体振荡器的应用,发明了走时精度更高的石英电子钟表,使钟表的走时月差从分级缩小到秒级。
第三次革命就是单片机数码计时技术的应用(电子万年历),使计时产品的走时日差从分级缩小到1/600万秒,从原有传统指针计时的方式发展为人们日常更为熟悉的夜光数字显示方式,直观明了,并增加了全自动日期、星期、温度以及其他日常附属信息的显示功能,它更符合消费者的生活需求!因此,电子万年历的出现带来了钟表计时业界跨跃性的进步……我国生产的电子万年历有很多种,总体上来说以研究多功能电子万年历为主,使万年历除了原有的显示时间,日期等基本功能外,还具有闹铃,报警等功能。
商家生产的电子万年历更从质量,价格,实用上考虑,不断的改进电子万年历的设计,使其更加的具有市场。
本设计主要采用AT89C51单片机作为主控核心,由DS1302时钟芯片提供时钟、LED 动态扫描显示屏显示。
AT89C51单片机是由Atmel公司推出的,功耗小,电压可选用4~6V电压供电;DS1302时钟芯片是美国DALLAS公司推出的具有涓细电流充电功能的低功耗实时时钟芯片,它可以对年、月、日、星期、时、分、秒进行计时,还具有闰年补偿等多种功能,而且DS1302的使用寿命长,误差小;数字显示是采用的LED液晶显示屏来显示,可以同时显示年、月、日、星期、时、分、秒和温度等信息。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
uchar code table2[]="可调电子日历时钟";
uchar code table3[]="S*00: 00: 00**T*";
uchar code table4[]="日期: 11--01--20";
/******************************************************************/
hour=0; } write_sfm(1,hour); } /******************************************************************/ void t_day() { day++; if(day==31) {day=0;} write_nyr(7,day); } /******************************************************************/ void t_month() { month++; if(month==13) {month=0;} write_nyr(5,month); } /******************************************************************/ void t_year() { year++; if(year==100) {year=0;} write_nyr(3,year); } /******************************************************************/ void timergo() { if(tcount==20)
write_12864_dat(0x30+shi);//十进制码转换成十六进制码要加上 0x30
write_12864_dat(0x30+ge);
}
/******************************************************************/
void write_nyr(uchar add1,uchar date1)
#define uchar unsigned char
#define uint unsigned int
/******************************************************************/
uchar code table1[]="单片机内部定时器";
{
minute++;
if(minute==60)
{minute=0; }
write_sfm(3,minute);
}
/******************************************************************/
void t_hour() {
hour++; if(hour==24) {
{
uchar shi,ge;
shi=date1/10;
ge=date1%10;
write_12864_com(0x98+add1);
write_12864_dat(0x30+shi);//十进制码转换成十六进制码要加上 0x30
write_12864_dat(0x30+ge);
}
ห้องสมุดไป่ตู้
/******************************************************************/
/******************************************************************/
/*
头文件:LCD12864.H
*/
/******************************************************************/
/******************************************************************/
/*
头文件:TIMERGO.H
*/
/******************************************************************/
#define uchar unsigned char
#define uint unsigned int
/******************************************************************/
uchar second,tcount,minute,hour,day,month,year;
void delay_50us(uint t) {
uchar j; for(;t>0;t--) for(j=19;j>0;j--); } /******************************************************************/ void write_12864_com(uchar com) { rw=0; rs=0; delay_50us(1); P0=com; e=1; delay_50us(10); e=0; delay_50us(2); } /******************************************************************/ void write_12864_dat(uchar dat) {
}break;//1 调整分 case 0x7b:{
ET0=0; while((key=keyscan())!=0xbb) { if(key==0x7b)t_hour(); delay(100);
} ET0=1; } break;//2 调整时 case 0x77:{ ET0=0; while((key=keyscan())!=0xbb) {
void t_second()
{
second++;
if(second==60)
{second=0; }
write_sfm(5,second);
}
/******************************************************************/
void t_minute()
delay(100); } ET0=1; }break;//5 调整年 case 0xbb:{ ET0=1; }break;//6 调整完成后确定 } timergo(); } } /******************************************************************/ void timer0() interrupt 1 using 0 { tcount++; TH0=(65536-50000)/256; TL0=(65536-50000)%256; }
void delay(uint dly)
{
uchar i=0,j=0;
while(dly--)
{
for(i=0;i<10;i++)
for(j=0;j<60;j++);
}
}
/******************************************************************/
if(key==0x77)t_day(); delay(100); } ET0=1; }break;//3 调整日 case 0xbe:{ ET0=0; while((key=keyscan())!=0xbb) { key=keyscan(); if(key==0xbe)t_month(); delay(100); } ET0=1; }break;//4 调整月 case 0xbd:{ ET0=0; while((key=keyscan())!=0xbb) { key=keyscan(); if(key==0xbd)t_year();
void main()
{
uchar i,key;
init_12864();
write_12864_com(0x80);
for(i=0;i<16;i++)
{
write_12864_dat(table1[i]);
delay_50us(1);
}
write_12864_com(0x90); for(i=0;i<16;i++) {
/******************************************************************/
void write_sfm(uchar add,uchar date)
{
uchar shi,ge;
shi=date/10;
ge=date%10;
write_12864_com(0x88+add);
rw=0; rs=1; delay_50us(1); P0=dat;
e=1; delay_50us(10); e=0; delay_50us(2); } /******************************************************************/ void init_12864() { delay_1ms(100); write_12864_com(0x30); delay_50us(4); write_12864_com(0x30); delay_50us(4); write_12864_com(0x0c); delay_50us(4); write_12864_com(0x01); delay_50us(240); write_12864_com(0x06); delay_50us(10); }