单片机电子万年历课程设计
基于单片机的万年历设计

基于单片机的万年历设计一、系统总体设计基于单片机的万年历系统主要由单片机控制模块、时钟模块、显示模块、按键模块和电源模块等组成。
单片机控制模块是整个系统的核心,负责处理和协调各个模块之间的数据传输和控制信号。
通常选用具有较高性能和稳定性的单片机,如 STC89C52 等。
时钟模块用于提供准确的时间信息,常见的有 DS1302 等芯片,能够实现年、月、日、时、分、秒的精确计时。
显示模块用于将时间等信息直观地展示给用户,可采用液晶显示屏(LCD)或数码管。
LCD 显示效果清晰、美观,但成本相对较高;数码管则价格低廉,显示简单明了。
按键模块用于用户对万年历进行设置和操作,如调整时间、设置闹钟等。
电源模块为整个系统提供稳定的电源供应,保证系统的正常运行。
二、硬件设计1、单片机最小系统单片机最小系统包括单片机芯片、晶振电路和复位电路。
晶振电路为单片机提供时钟信号,保证其正常工作;复位电路则用于在系统出现异常时将单片机恢复到初始状态。
2、时钟模块电路DS1302 时钟芯片通过串行方式与单片机进行通信,其引脚连接到单片机的相应 I/O 口。
通过对 DS1302 进行读写操作,可以获取和设置时间信息。
3、显示模块电路若采用 LCD1602 液晶显示屏,其数据线和控制线与单片机的 I/O 口相连。
通过编程控制单片机向 LCD 发送指令和数据,实现时间等信息的显示。
4、按键模块电路通常使用独立按键,将按键的一端接地,另一端连接到单片机的I/O 口,并通过上拉电阻保证在按键未按下时引脚处于高电平。
当按键按下时,引脚电平被拉低,单片机通过检测引脚电平的变化来判断按键的操作。
三、软件设计软件设计主要包括主程序、时钟模块驱动程序、显示模块驱动程序和按键处理程序等。
主程序负责初始化各个模块,并进行循环检测和处理。
在循环中,不断读取时钟模块的时间数据,然后通过显示模块进行显示,并检测按键是否有操作。
时钟模块驱动程序根据 DS1302 的通信协议,实现对时钟芯片的读写操作,从而获取和设置时间。
万年历单片机课程设计

万年历单片机课程设计一、课程目标知识目标:1. 学生能理解单片机的基本原理,掌握其功能和应用。
2. 学生能掌握万年历的运行机制,理解日期、时间计算的方法。
3. 学生能了解并运用编程语言(如C语言)进行单片机程序设计。
技能目标:1. 学生能运用所学知识,设计并实现一个具有日期和时间显示功能的万年历单片机系统。
2. 学生能够通过实践操作,掌握使用开发工具和调试技巧,提高问题解决能力。
情感态度价值观目标:1. 学生培养对单片机技术及编程的兴趣,激发创新意识和探索精神。
2. 学生通过团队协作,培养沟通、合作能力,提高集体荣誉感。
3. 学生在学习过程中,认识到科技发展对社会的重要性,增强社会责任感。
课程性质:本课程为实践性较强的课程,结合理论知识与实践操作,让学生在动手实践中掌握单片机技术。
学生特点:学生具备一定的电子技术基础,对编程有一定了解,好奇心强,喜欢动手实践。
教学要求:教师需结合学生特点,采用任务驱动、案例教学等方法,引导学生主动探究,确保课程目标的实现。
在教学过程中,注重培养学生的实践能力和创新能力。
通过对课程目标的分解和教学评估,确保学生达到预期学习成果。
二、教学内容1. 单片机基础知识:介绍单片机的组成、工作原理及功能特点,结合教材第二章内容,使学生建立单片机的基本概念。
2. 编程语言基础:回顾C语言编程基础,强调其在单片机编程中的应用,参考教材第四章进行教学。
3. 万年历原理:讲解日期和时间的计算方法,分析万年历的运行机制,结合教材第三章内容进行教学。
4. 单片机程序设计:教授如何使用C语言编写单片机程序,实现万年历功能,参考教材第五章内容。
5. 硬件电路设计:介绍万年历单片机系统的硬件组成,分析电路原理,结合教材第六章进行教学。
6. 实践操作:指导学生使用开发工具进行程序编写、调试和烧录,完成万年历单片机系统的搭建和测试。
7. 教学进度安排:- 第1周:单片机基础知识学习;- 第2周:编程语言基础复习;- 第3-4周:万年历原理讲解和单片机程序设计;- 第5周:硬件电路设计;- 第6周:实践操作,完成万年历单片机系统设计;- 第7周:总结与展示,进行教学评估。
单片机课设 电子万年历

《单片机原理及应用》课程设计题目:万年历设计姓名:学号:系别:专业:年级:2008起讫日期:2010.11.22 ~2010.12.3指导教师:职称:目录1.设计概述 (1)2.硬件电路图 (3)3.软件设计 (5)3.1流程图 (5)3.2程序 (7)4. 结论4.1测试结果 (12)4.2遇到问题 (12)5.3如何解决 (12)5.参考文献 (13)附录:电路图 (15)组员分工 (14)1、设计概述单片机就是微控制器,是面向应用对象设计、突出控制功能的芯片。
单片机接上晶振、复位电路和相应的接口电路,装载软件后就可以构成单片机应用系统。
将它嵌入到形形色色的应用系统中,就构成了众多产品、设备的智能化核心。
本设计就是应用单片机强大的控制功能制作而成的电子万年历,该电子万年历包括三大功能:实时显示年、月、日、时、分、秒、周期。
本设计采用的是AT89S52单片机,该单片机采用的MCU51内核,因此具有很好的兼容性,内部带有8KB的ROM,能够存储大量的程序。
计时芯片采用DALLAS公司的涓细充电时钟芯片DS1302,该芯片通过简单的串行通信与单片机进行通信,时钟/日历电路能够实时提供年、月、日、时分、秒信息。
显示器件采用通用型1602液晶,可显示32个字符,如果使用数码管来做显示器件需消耗大量的系统资源,因此采用低功耗的1602液晶,该液晶显示方便,功能强大,完全能满足数字万年历的显示要求。
综上各方案所述,对此次作品的方案选定: 采用AT89S52作为主控制系统; DS1302提供时钟;LCD液晶显示屏作为显示。
通过此次设计能够更加牢固的掌握单片机的应用技术,增强动手能力、硬件设计能力以及软件设计能力。
2、硬件电路图1.时钟芯片2.LCD1602液晶显示屏3.单片机芯片C523、软件设计3.1流程图主程序流程图3.2程序#include <REG51.H>#include <intrins.h>//#include "LCD1602.h"//#include "DS1302.h"#define uint unsigned int#define uchar unsigned charsbit DS1302_CLK = P1^7; //实时时钟时钟线引脚sbit DS1302_IO = P1^6; //实时时钟数据线引脚sbit DS1302_RST = P1^5; //实时时钟复位线引脚sbit ACC0 = ACC^0;sbit ACC7 = ACC^7;charhide_sec,hide_min,hide_hour,hide_day,hide_week,hide_month,hide_year; //秒,分,时到日,月,年位闪的计数sbit Set = P2^0; //模式切换键sbit Up = P2^1; //加法按钮sbit Down = P2^2; //减法按钮sbit out = P2^3; //立刻跳出调整模式按钮char done,count,temp,flag,up_flag,down_flag;uchar TempBuffer[5],week_value[2];void show_time(); //液晶显示程序/***********1602液晶显示部分子程序****************///PortDefinitions********************************************************** sbit LcdRs = P2^5;sbit LcdRw = P2^6;sbit LcdEn = P2^7;sfr DBPort = 0x80; //P0=0x80,P1=0x90,P2=0xA0,P3=0xB0.数据端口//内部等待函数//******************************************************************* *******unsigned char LCD_Wait(void){LcdRs=0;LcdRw=1; _nop_();LcdEn=1; _nop_(); LcdEn=0;return DBPort;}//向LCD写入命令或数据//************************************************************#define LCD_COMMAND 0 // Command#define LCD_DATA 1 // Data#define LCD_CLEAR_SCREEN 0x01 // 清屏#define LCD_HOMING 0x02 // 光标返回原点void LCD_Write(bit style, unsigned char input){LcdEn=0;LcdRs=style;LcdRw=0; _nop_();DBPort=input;_nop_();//注意顺序LcdEn=1; _nop_();//注意顺序LcdEn=0; _nop_();LCD_Wait();}//设置显示模式************************************************************#define LCD_SHOW 0x04 //显示开#define LCD_HIDE 0x00 //显示关#define LCD_CURSOR 0x02 //显示光标#define LCD_NO_CURSOR 0x00 //无光标#define LCD_FLASH 0x01 //光标闪动#define LCD_NO_FLASH 0x00 //光标不闪动void LCD_SetDisplay(unsigned char DisplayMode){LCD_Write(LCD_COMMAND, 0x08|DisplayMode); }//设置输入模式************************************************************#define LCD_AC_UP 0x02#define LCD_AC_DOWN 0x00 // default#define LCD_MOVE 0x01 // 画面可平移#define LCD_NO_MOVE 0x00 //defaultvoid LCD_SetInput(unsigned char InputMode){LCD_Write(LCD_COMMAND, 0x04|InputMode);}//初始化LCD************************************************************void LCD_Initial(){LcdEn=0;LCD_Write(LCD_COMMAND,0x38); //8位数据端口,2行显示,5*7点阵LCD_Write(LCD_COMMAND,0x38);LCD_SetDisplay(LCD_SHOW|LCD_NO_CURSOR); //开启显示, 无光标LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN); //清屏LCD_SetInput(LCD_AC_UP|LCD_NO_MOVE); //AC递增, 画面不动}//液晶字符输入的位置************************void GotoXY(unsigned char x, unsigned char y){if(y==0)LCD_Write(LCD_COMMAND,0x80|x);if(y==1)LCD_Write(LCD_COMMAND,0x80|(x-0x40));}//将字符输出到液晶显示void Print(unsigned char *str){while(*str!='\0'){LCD_Write(LCD_DATA,*str);str++;}}/***********DS1302时钟部分子程序******************/typedef struct __SYSTEMTIME__{unsigned char Second;unsigned char Minute;unsigned char Hour;unsigned char Week;unsigned char Day;unsigned char Month;unsigned char Year;unsigned char DateString[11];unsigned char TimeString[9];}SYSTEMTIME; //定义的时间类型SYSTEMTIME CurrentTime;#define AM(X) X#define PM(X) (X+12) // 转成24小时制#define DS1302_SECOND 0x80 //时钟芯片的寄存器位置,存放时间#define DS1302_MINUTE 0x82#define DS1302_HOUR 0x84#define DS1302_WEEK 0x8A#define DS1302_DAY 0x86#define DS1302_MONTH 0x88#define DS1302_YEAR 0x8Cvoid DS1302InputByte(unsigned char d) //实时时钟写入一字节(内部函数) { unsigned char i;ACC = d; for(i=8; i>0; i--){DS1302_IO = ACC0; //相当于汇编中的 RRCDS1302_CLK = 1; DS1302_CLK = 0; ACC = ACC >> 1; } }unsigned char DS1302OutputByte(void) //实时时钟读取一字节(内部函数) { unsigned char i; for(i=8; i>0; i--){ ACC = ACC >>1; //相当于汇编中的 RRCACC7 = DS1302_IO; DS1302_CLK = 1;DS1302_CLK = 0; }return(ACC); }void Write1302(unsigned char ucAddr, unsigned char ucDa) //ucAddr: DS1302地址, ucData: 要写的数据{ DS1302_RST = 0;DS1302_CLK = 0;DS1302_RST = 1;DS1302InputByte(ucAddr); // 地址,命令DS1302InputByte(ucDa); // 写1Byte数据DS1302_CLK = 1;DS1302_RST = 0;} unsigned char Read1302(unsigned char ucAddr) //读取DS1302某地址的数据{ unsigned char ucData;DS1302_RST = 0;DS1302_CLK = 0;DS1302_RST = 1;DS1302InputByte(ucAddr|0x01); // 地址,命令ucData = DS1302OutputByte(); // 读1Byte数据DS1302_CLK = 1;DS1302_RST = 0;return(ucData);}void DS1302_GetTime(SYSTEMTIME *Time) //获取时钟芯片的时钟数据到自定义的结构型数组{unsigned char ReadValue;ReadValue = Read1302(DS1302_SECOND);Time->Second = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_MINUTE);Time->Minute = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_HOUR);Time->Hour = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_DAY);Time->Day = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_WEEK);Time->Week = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_MONTH);Time->Month = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_YEAR);Time->Year = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); } void DateToStr(SYSTEMTIME *Time) //将时间年,月,日,星期数据转换成液晶显示字符串,放到数组里DateString[]{ if(hide_year<2) //这里的if,else语句都是判断位闪烁,<2显示数据,>2就不显示,输出字符串为 2007/07/22{ Time->DateString[0] = '2';Time->DateString[1] = '0';Time->DateString[2] = Time->Year/10 + '0';Time->DateString[3] = Time->Year%10 + '0';}else{ Time->DateString[0] = ' '; Time->DateString[1] = ' ';Time->DateString[2] = ' '; Time->DateString[3] = ' ';}Time->DateString[4] = '/';if(hide_month<2){Time->DateString[5] = Time->Month/10 + '0';Time->DateString[6] = Time->Month%10 + '0';}else{ Time->DateString[5] = ' '; Time->DateString[6] = ' ';}Time->DateString[7] = '/';if(hide_day<2){Time->DateString[8] = Time->Day/10 + '0';Time->DateString[9] = Time->Day%10 + '0';}else{Time->DateString[8] = ' ';Time->DateString[9] = ' '; } if(hide_week<2){week_value[0] = Time->Week%10 + '0'; } //星期的数据另外放到week_value[]数组里,跟年,月,日的分开存放,因为等一下要在最后显示} else { week_value[0] = ' ';}week_value[1] = '\0';Time->DateString[10] = '\0'; //字符串末尾加 '\0' ,判断结束字符}void TimeToStr(SYSTEMTIME *Time) //将时,分,秒数据转换成液晶显示字符放到数组 TimeString[];{ if(hide_hour<2){ Time->TimeString[0] = Time->Hour/10 + '0';Time->TimeString[1] = Time->Hour%10 + '0';}else{ Time->TimeString[0] = ' ';Time->TimeString[1] = ' ';}Time->TimeString[2] = ':';if(hide_min<2){ Time->TimeString[3] = Time->Minute/10 + '0';Time->TimeString[4] = Time->Minute%10 + '0';}else {Time->TimeString[3] = ' ';Time->TimeString[4] = ' '; }Time->TimeString[5] = ':';if(hide_sec<2){Time->TimeString[6] = Time->Second/10 + '0';Time->TimeString[7] = Time->Second%10 + '0';}else{Time->TimeString[6] = ' ';Time->TimeString[7] = ' '; } Time->DateString[8] = '\0';}void Initial_DS1302(void) //时钟芯片初始化{ unsigned char Second=Read1302(DS1302_SECOND);if(Second&0x80) //判断时钟芯片是否关闭{Write1302(0x8e,0x00); //写入允许Write1302(0x8c,0x07); //以下写入初始化时间日期:07/07/25.星期: 3.时间: 23:59:55Write1302(0x88,0x07);Write1302(0x86,0x25);Write1302(0x8a,0x07);Write1302(0x84,0x23);Write1302(0x82,0x59);Write1302(0x80,0x55);Write1302(0x8e,0x80); //禁止写入}}void Delay1ms(unsigned int count){unsigned int i,j;for(i=0;i<count;i++)for(j=0;j<120;j++);}/*延时子程序*/void mdelay(uint delay){ uint i;for(;delay>0;delay--){for(i=0;i<62;i++) //1ms延时. {;}}}void outkey() //跳出调整模式,返回默认显示{ uchar Second;if(out==0) { mdelay(8); count=0;hide_sec=0,hide_min=0,hide_hour=0,hide_day=0,hide_week=0,hide_mon th=0,hide_year=0;Second=Read1302(DS1302_SECOND);Write1302(0x8e,0x00); //写入允许Write1302(0x80,Second&0x7f);Write1302(0x8E,0x80); //禁止写入done=0; while(out==0); }}///////////////////////////////////////////////////////////////////// //////////void Upkey()//升序按键{ Up=1;if(Up==0){mdelay(8);switch(count){case 1:temp=Read1302(DS1302_SECOND); //读取秒数temp=temp+1; //秒数加1up_flag=1; //数据调整后更新标志if((temp&0x7f)>0x59) //超过59秒,清零temp=0; break;case 2:temp=Read1302(DS1302_MINUTE); //读取分数temp=temp+1; //分数加1up_flag=1;if(temp>0x59) //超过59分,清零temp=0;break;case 3:temp=Read1302(DS1302_HOUR); //读取小时数temp=temp+1; //小时数加1up_flag=1;if(temp>0x23) //超过23小时,清零temp=0; break;case 4:temp=Read1302(DS1302_WEEK); //读取星期数temp=temp+1; //星期数加1up_flag=1;if(temp>0x7)temp=1;break;case 5:temp=Read1302(DS1302_DAY); //读取日数temp=temp+1; //日数加1up_flag=1;if(temp>0x31)temp=1;break;case 6:temp=Read1302(DS1302_MONTH); //读取月数temp=temp+1; //月数加1up_flag=1;if(temp>0x12)temp=1;break;case 7:temp=Read1302(DS1302_YEAR); //读取年数temp=temp+1; //年数加1up_flag=1;if(temp>0x85)temp=0;break;default:break;}while(Up==0); }}///////////////////////////////////////////////////////////////////// //////////void Downkey()//降序按键{ Down=1;if(Down==0){ mdelay(8);switch(count){case 1:temp=Read1302(DS1302_SECOND); //读取秒数temp=temp-1; //秒数减1down_flag=1; //数据调整后更新标志if(temp==0x7f) //小于0秒,返回59秒temp=0x59;break;case 2:temp=Read1302(DS1302_MINUTE); //读取分数temp=temp-1; //分数减1down_flag=1;if(temp==-1)temp=0x59; //小于0秒,返回59秒break;case 3:temp=Read1302(DS1302_HOUR); //读取小时数temp=temp-1; //小时数减1down_flag=1;if(temp==-1)temp=0x23;break;case 4:temp=Read1302(DS1302_WEEK); //读取星期数temp=temp-1; //星期数减1down_flag=1;if(temp==0)temp=0x7;;break;case 5:temp=Read1302(DS1302_DAY); //读取日数temp=temp-1; //日数减1down_flag=1;if(temp==0)temp=31;break;case 6:temp=Read1302(DS1302_MONTH); //读取月数temp=temp-1; //月数减1down_flag=1;if(temp==0)temp=12;break;case 7:temp=Read1302(DS1302_YEAR); //读取年数temp=temp-1; //年数减1down_flag=1;if(temp==-1)temp=0x85;break;default:break;}while(Down==0); }}void Setkey()//模式选择按键{Set=1;if(Set==0){ mdelay(8); count=count+1; //Setkey按一次,count就加1 done=1; //进入调整模式while(Set==0); }}void keydone()//按键功能执行{ uchar Second;if(flag==0) //关闭时钟,停止计时{ Write1302(0x8e,0x00); //写入允许temp=Read1302(0x80);Write1302(0x80,temp|0x80);Write1302(0x8e,0x80); //禁止写入flag=1; }Setkey(); //扫描模式切换按键 switch(count){case 1:do //count=1,调整秒{ outkey(); //扫描跳出按钮Upkey(); //扫描加按钮Downkey(); //扫描减按钮if(up_flag==1||down_flag==1) //数据更新,重新写入新的数据{Write1302(0x8e,0x00); //写入允许Write1302(0x80,temp|0x80); //写入新的秒数Write1302(0x8e,0x80); //禁止写入up_flag=0;down_flag=0; }hide_sec++; //位闪计数if(hide_sec>3)hide_sec=0;show_time(); //液晶显示数据}while(count==2);break;case 2:do //count=2,调整分{ hide_sec=0;outkey();Upkey();Downkey();if(temp>0x60)temp=0;if(up_flag==1||down_flag==1){ Write1302(0x8e,0x00); //写入允许Write1302(0x82,temp); //写入新的分数Write1302(0x8e,0x80); //禁止写入up_flag=0;down_flag=0; }hide_min++;if(hide_min>3)hide_min=0;show_time();}while(count==3);break;case 3:do //count=3,调整小时{ hide_min=0;outkey();Upkey();Downkey();if(up_flag==1||down_flag==1){ Write1302(0x8e,0x00); //写入允许Write1302(0x84,temp); //写入新的小时数Write1302(0x8e,0x80); //禁止写入up_flag=0;down_flag=0; }hide_hour++;if(hide_hour>3)hide_hour=0;show_time();}while(count==4);break;case 4:do //count=4,调整星期{ hide_hour=0;outkey();Upkey();Downkey();if(up_flag==1||down_flag==1){ Write1302(0x8e,0x00); //写入允许Write1302(0x8a,temp); //写入新的星期数Write1302(0x8e,0x80); //禁止写入up_flag=0;down_flag=0;}hide_week++;if(hide_week>3)hide_week=0;show_time();}while(count==5);break;case 5:do //count=5,调整日{hide_week=0;outkey();Upkey();Downkey();if(up_flag==1||down_flag==1){Write1302(0x8e,0x00); //写入允许Write1302(0x86,temp); //写入新的日数Write1302(0x8e,0x80); //禁止写入up_flag=0;down_flag=0; }hide_day++;if(hide_day>3)hide_day=0;show_time();}while(count==6);break;case 6:do //count=6,调整月{ hide_day=0;outkey();Upkey();Downkey();if(up_flag==1||down_flag==1){ Write1302(0x8e,0x00); //写入允许Write1302(0x88,temp); //写入新的月数Write1302(0x8e,0x80); //禁止写入up_flag=0;down_flag=0; }hide_month++;if(hide_month>3)hide_month=0;show_time();}while(count==7);break;case 7:do //count=7,调整年{ hide_month=0;outkey();Upkey();Downkey();if(up_flag==1||down_flag==1){ Write1302(0x8e,0x00); //写入允许Write1302(0x8c,temp); //写入新的年数Write1302(0x8e,0x80); //禁止写入up_flag=0;down_flag=0; }hide_year++;if(hide_year>3)hide_year=0;show_time();}while(count==8);break;case 8: count=0;hide_year=0; //count8, 跳出调整模式,返回默认显示状态Second=Read1302(DS1302_SECOND);Write1302(0x8e,0x00); //写入允许Write1302(0x80,Second&0x7f);Write1302(0x8E,0x80); //禁止写入done=0;break; //count=7,开启中断,标志位置0并退出default:break; }}void show_time() //液晶显示程序{ DS1302_GetTime(&CurrentTime); //获取时钟芯片的时间数据TimeToStr(&CurrentTime); //时间数据转换液晶字符DateToStr(&CurrentTime); //日期数据转换液晶字符GotoXY(0,1);Print(CurrentTime.TimeString); //显示时间GotoXY(0,0);Print(CurrentTime.DateString); //显示日期GotoXY(15,0);Print(week_value); //显示星期GotoXY(11,0);Print("Week"); //在液晶上显示字母 weekDelay1ms(400); //扫描延时}void main(){ flag=1; //时钟停止标志LCD_Initial(); //液晶初始化Initial_DS1302(); //时钟芯片初始化up_flag=0;down_flag=0;done=0; //进入默认液晶显示while(1){ while(done==1) keydone(); //进入调整模式while(done==0){ show_time(); //液晶显示数据flag=0; Setkey(); //扫描各功能键}}}4、结论4.1测试结果经过多次的反复测试与分析,可以对电路的原理及功能更加熟悉,同时提高了设计能力与及对电路的分析能力。
单片机课程设计报告电子万年历

单片机课程设计报告电子万年历单片机课程设计报告:电子万年历一、设计简介在本次单片机课程设计中,我们选择了电子万年历作为设计主题。
电子万年历是一种结合了数字电路、单片机技术和实时时钟(RTC)技术的电子产品,它具有显示年份、月份、星期、日、时、分、秒的功能,还可以根据用户的需求进行定时、闹钟、报时等功能。
二、硬件设计我们采用了基于8051内核的单片机作为主控芯片。
该单片机具有丰富的I/O 端口,适于实现各种复杂的输入输出操作。
此外,它还内置了定时器和中断控制器,可以很方便地实现实时时钟功能。
1.显示模块:为了方便用户查看时间信息,我们选用了LCD显示屏作为显示设备。
LCD屏具有功耗低、体积小、显示内容丰富等优点。
2.实时时钟(RTC)模块:我们采用了常用的DS1302芯片作为实时时钟模块。
该芯片可以提供秒、分、时、日、星期、月、年的信息,而且还有可编程的报警功能。
3.按键模块:为了实现人机交互,我们设计了一组按键。
用户可以通过按键来调整时间、设置闹钟等。
4.电源模块:为了保证系统的稳定工作,我们采用了稳定的5V直流电源。
三、软件设计我们采用了C语言编写程序。
程序主要由以下几个部分组成:1.主程序:主程序主要负责读取RTC模块的时间信息,并控制LCD显示屏显示时间。
同时,主程序还要检测按键输入,根据用户的需求进行相应的操作。
2.RTC驱动程序:为了正确地读取和设置DS1302芯片的时间信息,我们编写了相应的驱动程序。
驱动程序包括初始化和读写寄存器两部分。
3.按键处理程序:按键处理程序用于检测按键输入,并根据按键值执行相应的操作。
比如,用户可以通过按键来增加或减少时间,设置闹钟等。
4.LCD显示程序:LCD显示程序用于控制LCD显示屏的显示内容。
在本设计中,我们使用了点阵字符库,将时间信息以字符的形式显示在LCD屏上。
四、测试与验证为了确保我们的电子万年历设计正确无误,我们进行了以下的测试和验证:1.硬件测试:首先,我们对硬件电路进行了测试,确保每个模块都能正常工作。
基于51单片机的万年历设计

基于51单片机的万年历设计一、系统设计方案本万年历系统主要由 51 单片机、时钟芯片、液晶显示屏、按键等部分组成。
51 单片机作为核心控制器,负责整个系统的运行和数据处理。
时钟芯片用于提供精确的时间信息,液晶显示屏用于显示万年历的相关内容,按键则用于设置时间和功能切换。
二、硬件设计1、单片机选型选用常见的 51 单片机,如 STC89C52 单片机,它具有性能稳定、价格低廉、易于编程等优点。
2、时钟芯片选择 DS1302 时钟芯片,该芯片能够提供高精度的实时时钟,具有闰年补偿功能,并且可以通过串行接口与单片机进行通信。
3、液晶显示屏采用 1602 液晶显示屏,能够清晰地显示字符和数字,满足万年历的显示需求。
4、按键电路设计四个按键,分别用于时间设置、功能切换、加和减操作。
三、软件设计1、主程序流程系统上电后,首先进行初始化操作,包括单片机端口初始化、时钟芯片初始化、液晶显示屏初始化等。
然后读取时钟芯片中的时间数据,并在液晶显示屏上显示出来。
接着进入循环,不断检测按键状态,根据按键操作执行相应的功能,如时间设置、功能切换等。
2、时钟芯片驱动程序通过单片机的串行接口向 DS1302 发送命令和数据,实现对时钟芯片的读写操作,获取准确的时间信息。
3、液晶显示屏驱动程序编写相应的函数,实现对1602 液晶显示屏的字符和数字显示控制。
4、按键处理程序采用扫描方式检测按键状态,当检测到按键按下时,执行相应的按键处理函数,实现时间设置和功能切换等操作。
四、时间设置功能通过按键操作进入时间设置模式,可以分别设置年、月、日、时、分、秒等信息。
在设置过程中,液晶显示屏会显示当前设置的项目和数值,并通过加、减按键进行调整。
设置完成后,将新的时间数据保存到时钟芯片中。
五、显示功能万年历的显示内容包括年、月、日、星期、时、分、秒等信息。
通过合理的排版和显示控制,使这些信息在液晶显示屏上清晰、直观地呈现给用户。
六、系统调试在完成硬件和软件设计后,需要对系统进行调试。
单片机电子万年历课程设计

单片机课程设计姓名:吕长明学号:04040804021专业班级:机电四班一、单片机原理及应用简介随着国内超大规模集成电路的出现,微处理器及其外围芯片有了迅速的发展。
集成技术的最新发展之一是将CPU和外围芯片,如程序存储器、数据存储器、并行、串行I/O口、定时/计数器、中断控制器及其他控制部件集成在一个芯片之中,制成单片计算机(Single-Chip Microcomputer)。
而近年来推出的一些高档单片机还包括有许多特殊功能单元,如A/D、D/A转换器、调制解调器、通信控制器、锁相环、DMA、浮点运算单元等。
因此,只要外加一些扩展电路及必要的通道接口就可以构成各种计算机应用系统,如工业控制系统、数据采集系统、自动测试系统、万年历电子表等。
二、系统硬件设计8052 是标准的40引脚双列直插式集成电路芯片,引脚分布请参照----单片机引脚图图1:图1 8052引脚P0.0~P0.7 P0口8位双向口线(在引脚的39~32号端子)。
P1.0~P1.7 P1口8位双向口线(在引脚的1~8号端子)。
P2.0~P2.7 P2口8位双向口线(在引脚的21~28号端子)。
P3.0~P3.7 P2口8位双向口线(在引脚的10~17号端子)。
8052芯片管脚说明:VCC:供电电压。
GND:接地。
P0口:P0口为一个8位漏级开路双向I/O口,每脚可吸收8TTL 门电流。
当P1口的管脚第一次写1时,被定义为高阻输入。
P0能够用于外部程序数据存储器,它可以被定义为数据/地址的第八位。
在FIASH编程时,P0 口作为原码输入口,当FIASH进行校验时,P0输出原码,此时P0外部必须被拉高。
P1口:P1口是一个内部提供上拉电阻的8位双向I/O口,P1口缓冲器能接收输出4TTL门电流。
P1口管脚写入1后,被内部上拉为高,可用作输入,P1口被外部下拉为低电平时,将输出电流,这是由于内部上拉的缘故。
在FLASH编程和校验时,P1口作为第八位地址接收。
单片机课程设计(论文)电子万年历的设计

目录1设计要求 (2)2方案论证与对比 (2)液晶显示器控制方式选择 (2)2.2并行接口动态显示电路选择 (2)2.3LCD液晶显示器的接口方法选择 (3)液晶显示器限流电阻选择 (4)3系统硬件电路的设计 (5)主控模块AT89C52 (5)3.2显示模块电路设计 (6)4系统软件设计 (7)4.1系统软件概述 (7)4.2主要子程序设计 (8)4.2.1 时钟中断服务子程序设计 (8)时间调整子程序设计 (9)4.2.3 判断闰年子程序设计 (9)4.2.4 精度分析分析与计算 (10)4.2.5 第一次初值的设置 (10)4.2.6 重载初值的方法 (10)5系统仿真与测试 (11)5.1系统仿真 (11)功能测试 (11)6总结 (12)参考文献 (13)1设计要求本课题以AT89C52单片机为核心,设计并制作出智能LCD电子钟,具有以下基本功能:能进行时间、年份、日期、星期显示;能区分是否闰年;能检测室温并显示。
扩展功能部分可以通过控制按键使时间暂停、可以调整校正时间并通过按键切换轮流显示时间、年份、日期、星期。
2方案论证与对比2.1液晶显示器控制方式选择采用LCD液晶显示,具有超精致影像画质、十足平面显示、节省空间、节省能源等优点,但按控制方式不同,LCD可分为被动矩阵式LCD及主动矩阵式LCD两种。
可根据不同需要采用不同的方式。
方案一被动矩阵式LCD被动矩阵式LCD在亮度及可视角方面受到较大的限制,反应速度也较慢。
由于画面质量方面的问题,使得这种显示设备不利于发展为桌面型显示器,但成本低廉。
方案二主动矩阵式LCD目前应用比较广泛的主动矩阵式LCD,也称TFT-LCD(Thin Film Transistor-LCD,薄膜晶体管LCD)。
TFT液晶显示器是在画面中的每个像素内建晶体管,可使亮度更明亮、色彩更丰富及更宽广的可视面积。
与CRT显示器相比,LCD显示器的平面显示技术体现为较少的零件、占据较少的桌面及耗电量较小,但CRT技术较为稳定成熟。
单片机课程设计电子万年历设计

单片机课程设计电子万年历设计(总17页)--本页仅作为文档封面,使用时请直接删除即可----内页可以根据需求调整合适字体及大小--摘要随着科技的快速发展,时间的流逝,至从观太阳、摆钟到现在电子钟,人类不断研究,不断创新纪录。
美国DALLAS公司推出的具有涓细电流充电能的低功耗实时时钟电路DS1302。
它可以对年、月、日、周日、时、分、秒进行计时,还具有闰年补偿等多种功能,而且DS1302的使用寿命长,误差小。
对于数字电子万年历采用直观的数字显示,可以同时显示年、月、日、周日、时、分、秒和温度等信息,还具有时间校准等功能。
该电路采用AT89S52单片机作为核心,功耗小,能在3V的低压工作,电压可选用3~5V电压供电。
综上所述此万年历具有读取方便、显示直观、功能多样、电路简洁、成本低廉等诸多优点,符合电子仪器仪表的发展趋势,具有广阔的市场前景。
本设计是基于51系列的单片机进行的电子万年历设计,可以显示年月日时分秒及周信息,具有可调整日期和时间功能。
在设计的同时对单片机的理论基础和外围扩展知识进行了比较全面准备。
在硬件与软件设计时,没有良好的基础知识和实践经验会受到很大限制,每项功能实现时需要那种硬件,程序该如何编写,算法如何实现等,没有一定的基础就不可能很好的实现。
具体实现功能:(1)显示年月日时分秒及星期信息(2)具有可调整日期和时间功能(3)与即时时间同步目录1方案论证 (3)单片机芯片的选择方案和论证 (3)显示模块选择方案和论证 (3)时钟芯片的选择方案和论证.....................................错误!未定义书签。
电路设计最终方案决定 (4)2系统的硬件设计与实现 (5)电路设计框图 (5)系统硬件概述 (5)主要单元电路的设计 (5)单片机主控制模块的设计 (5)时钟电路模块的设计 (6)电路原理及说明 (7)显示模块的设计 (8)3系统的软件设计 (9)程序流程框图 (9)4测试与结果分析 (11)硬件测试....................................................错误!未定义书签。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
课程设计报告课程名称:单片机课程设计设计题目:单片机电子万年历课程设计院系:电气学院设计时间:2012-6-22目录摘要一、单片机原理及应用简介 (2)二、系统硬件设计 (2)2.1引脚功能及管脚电压 (2)2.1.1 P0 口 (3)2.1.2 P1 口 (3)2.1.3 P2 口 (4)2.1.4 P3 口 (4)2.1.5 RST (4)2.1.6 ALE/PROG (4)2.1.7 PSEN (5)2.1.8 EA/VPP (5)2.1.9 XTAL1 (5)2.2.0 XTAL2 (5)三、系统总体方案 (5)3.1.1微处理器 (5)3.1.2显示电路 (6)四、硬件电路的总体框图设计 (8)五、硬件电路原理图设计 (8)六、主程序流程图设计 (10)七、仿真过程 (11)八、仿真结果 (11)附一源程序代码 (13)附二参考文献 (36)摘要单片机应用技术飞速发展,纵观我们现在生活的各个领域,从导弹的导航装置,到飞机上各种仪表的控制,从计算机的网络通讯与数据传输,到工业自动化过程的实时控制和数据处理,以及我们生活中广泛使用的各种智能IC卡、电子宠物等,这些都离不开单片机。
单片机是集CPU ,RAM ,ROM ,定时,计数和多种接口于一体的微控制器。
它体积小,成本低,功能强,广泛应用于智能产业和工业自动化上。
而51系列单片机是各单片机中最为典型和最有代表性的一种。
这次毕业设计通过对它的学习,应用,从而达到学习、设计、开发软、硬的能力。
本文通过对一个基于单片机的能实现万年历功能电子时钟的设计,从而达到学习、了解单片机相关指令在各方面的应用。
系统由主控制器AT89C52、显示电路、按键电路、和复位电路等部分构成,能实现时钟日历显示的功能,能进行时、分、秒的显示。
关键词: 单片机, 万年历一、单片机原理及应用简介随着国内超大规模集成电路的出现,微处理器及其外围芯片有了迅速的发展。
集成技术的最新发展之一是将CPU和外围芯片,如程序存储器、数据存储器、并行、串行I/O口、定时/计数器、中断控制器及其他控制部件集成在一个芯片之中,制成单片计算机(Single-Chip Microcomputer)。
而近年来推出的一些高档单片机还包括有许多特殊功能单元,如A/D、D/A转换器、调制解调器、通信控制器、锁相环、DMA、浮点运算单元等。
因此,只要外加一些扩展电路及必要的通道接口就可以构成各种计算机应用系统,如工业控制系统、数据采集系统、自动测试系统、万年历电子表等。
二、系统硬件设计2.1引脚功能及管脚电压AT89C52为8 位通用微处理器,采用工业标AT89C52引脚图准的C51内核,在内部功能及管脚排布上与通用的8xc52 相同,其主要用于会2.1.3 P2 口P2 是一个带有内部上拉电阻的8 位双向I/O 口,P2 的输出缓冲级可驱动(吸收或输出电流)4 个TTL 逻辑门电路。
对端口P2 写“1”,通过内部的上拉电阻把端口拉到高电平,此时可作输入口,作输入口使用时,因为内部存在上拉电阻,某个引脚被外部信号拉低时会输出一个电流(IIL)。
在访问外部程序存储器或16 位地址的外部数据存储器(例如执行MOVX @DPTR 指令)时,P2 口送出高8 位地址数据。
在访问8 位地址的外部数据存储器(如执行MOVX @RI 指令)时,P2 口输出P2 锁存器的内容。
Flash 编程或校验时,P2亦接收高位地址和一些控制信号。
2.1.4 P3 口P3 口是一组带有内部上拉电阻的8 位双向I/O 口。
P3 口输出缓冲级可驱动(吸收或输出电流)4 个TTL 逻辑门电路。
对P3 口写入“1”时,它们被内部上拉电阻拉高并可作为输入端口。
此时,被外部拉低的P3 口将用上拉电阻输出电流(IIL)。
P3 口除了作为一般的I/O 口线外,更重要的用途是它的第二功能P3 口还接收一些用于Flash 闪速存储器编程和程序校验的控制信号。
2.1.5 RST复位输入。
当振荡器工作时,RST引脚出现两个机器周期以上高电平将使单片机复位。
2.1.6 ALE/PROG当访问外部程序存储器或数据存储器时,ALE(地址锁存允许)输出脉冲用于锁存地址的低8 位字节。
一般情况下,ALE 仍以时钟振荡频率的1/6 输出固定的脉冲信号,因此它可对外输出时钟或用于定时目的。
要注意的是:每当访问外部数据存储器时将跳过一个ALE 脉冲。
对Flash 存储器编程期间,该引脚还用于输入编程脉冲(PROG)。
如有必要,可通过对特殊功能寄存器(SFR)区中的8EH 单元的D0 位置位,可禁止ALE 操作。
该位置位后,只有一条MOVX 和MOVC指令才能将ALE 激活。
此外,该引脚会被微弱拉高,单片机执行外部程序时,应设置ALE 禁止位无效。
2.1.7 PSEN程序储存允许(PSEN)输出是外部程序存储器的读选通信号,当AT89C52 由外部程序存储器取指令(或数据)时,每个机器周期两次PSEN 有效,即输出两个脉冲。
在此期间,当访问外部数据存储器,将跳过两次PSEN信号。
2.1.8 EA/VPP外部访问允许。
欲使CPU 仅访问外部程序存储器(地址为0000H—FFFFH),EA 端必须保持低电平(接地)。
需注意的是:如果加密位LB1 被编程,复位时内部会锁存EA端状态。
如EA端为高电平(接Vcc端),CPU 则执行内部程序存储器中的指令。
Flash 存储器编程时,该引脚加上+12V 的编程允许电源Vpp,当然这必须是该器件是使用12V 编程电压Vpp。
2.1.9 XTAL1振荡器反相放大器的及内部时钟发生器的输入端。
2.2.0 XTAL2振荡器反相放大器的输出端。
三、系统总体方案我选用的是单片机(AT89C52)来实现电子万年历的功能。
共具备两个功能:(1)显示年月日及分秒信息(2)具有可调整日期和时间功能。
该电子万年历能够成功实现时钟运行,调整功能,且精确度经调试一天的误差在2S内。
3.1.1微处理器在设计过程中我使用12MHZ晶振与单片机AT89C52相连接,通过软件编程的方法实现了以24小时为一个周期同时显示小时,分钟和秒的要求,该定时闹钟设有九个按键,使之具备了校时、定时功能。
利用单片机定时器及计数器产生定时效果通过编程形成数字钟效果,再利用数码管动态扫描显示单片机内部处理的数据。
同时通过端口读入当前外部控制状态来改变程序的不同状态,实现不同功能。
在PROTEUS软件环境下的AT89C52芯片如图4所示:图4 PROTEUS软件环境下的AT89C52芯片3.1.2显示电路就时钟而言,通常可采用液晶显示或数码管显示。
由于一般的段式液晶屏,需要专门的驱动电路,而且液晶显示作为一种被动显示,可视性相对较差;对于具有驱动电路和微处理器接口的液晶显示模块(字符或点阵),一般多采用并行接口,对微处理器的接口要求较高,占用资源多。
另外,AT89C52本身无专门的液晶驱动接口,因此,本设计采用点阵式数码管显示,点阵式数码管是由八行八列的发光二极管组成,对于显示文字比较适合。
初始化时,由软件编写的指令就集中在显示功能的设置上。
LCD3 AMPIRE 128×64的指令可带一个、两个参数,或无参数。
若指令中含有参数,则每条指令执行时均须先送入参数,再送入指令代码。
由于状态位作用不一样,因此执行不同指令必须检测不同状态位。
液晶显示模块LCD3 AMPIRE 128×64如图5所示:图5 显示电路AMPIRE 128×643按键电路由于我设计的是电子万年历,需要实现多种功能的显示,并要能够切换显示和调节年月日,因此,在设计过程中按键的设计就显得尤为重要。
在设计过程中我一共采用了3个按键,尽量在小的空间里实现最多的功能。
按键电路如图6所示:图6 按键电路四、硬件电路的总体框图设计该设计的硬件电路的总体框图如图7所示:图7 总体框图五、硬件电路原理图设计该万年历是以单片机AT89C52为核心来完成的。
在硬件电路中采用P1口作为6位液晶显示电路的驱动接口,这是由于P1口输出驱动电路工作处于开漏状态,它的驱动能力强,故只需外接上拉电阻便可以把LED数码管点亮。
因为共阴的LED数码管它的驱动电流是分开的,在单片机进行动态扫描的时候不会影响彼此的电流,故该电路中的8位LED数码管均用共阳阴极的数码管。
电路原理图如图8所示:六、主程序流程图设计图9 主程序流程图基本显示模块设计的重点是由显示代码取得相应的段码、显示段码数据的串行发送,程序流程如图1-11所示。
其中时个位的段码必须加上小数点,即带小数点显示时个位,目的是以小数点符代替时间分割符“-”。
软件秒脉冲发生器其实质是利用了定时器0的定时溢出中断,将它设定为100ms溢出中断,则10次中断的时间正好为1s。
将时间参数设计为100ms的原因有两个:1)根据系统时钟主频为6M的特点,16位定时器最大定时时间为65536×2M(M为机器周期,这里是2μS),即131ms,取整数100便于计次数;2)如取的太短,如10ms,则定时器频繁中断,干扰系统正常运行效果。
有了秒脉冲发生器,10次中断为1s,秒指示灯闪亮1次,秒变量单元加1,60后分变量单元加1,如果为60分则时变量单元加1。
任何一个变量的变化,则显示刷新一次(更新)。
上述思想的实现均集成在定时器0的中断子程序中。
该设计显示模块流程图如图10所示:图10 基本显示模块的程序流程图七、仿真过程1、仿真:打开WAVE6000,输入所编写的源程序并对程序进行编译,在软件的帮助下检查其中的错误并进行反复修改,知道编译正确后运行,确保没有错误以后对正确的源程序进行保存,保存时给其命名,以便将来载入程序时容易找到。
2、打开PROTEUS软件,并出画单片机电子万年历具体运行电路图。
3、检查所画电路运行图,确保没有错误以后,在PROTEUS下对原理图进行加载WAVE6000下的源程序。
4、加载完成后,单击电路图框下的开始按钮,进行仿真,观察LED数码管现实情况,此时LED数码管开始显示数字。
调节开关进行时间的调节。
当秒的显示间隔快与或慢与实际间隔时,调节石英晶体震荡器的频率参数,从而使秒的间隔达到标准。
然后检查电路其它问题,并对其的各参数进行调整,使之正确。
八、仿真结果通过在WAVE6000下对源程序的编译,改正了其中的很多错误,然后运行,保证源程序的正确性。
然后按原理图选择正确合理的电器元件,画出正确的电路图,加载源程序运行,顺利实现了单片机数字电子钟的“小时”、“分钟”、“秒”的显示。
该电子万年历的显示效果及电子万年历时间和日期的运行效果如图12所示:图12 电子万年历的运行效果九、课程设计体会通过这一周的课程设计,我学到了不少的知识。