ImageVerifierCode 换一换
格式:DOCX , 页数:14 ,大小:163.98KB ,
资源ID:29886102      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/29886102.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(51单片机万年历课程设计报告.docx)为本站会员(b****8)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

51单片机万年历课程设计报告.docx

1、51单片机万年历课程设计报告一、设计任务:1、设计任务:设计并制作一个数字钟。2、设计要求: 显示年月日时分秒及星期信息具有可调整日期和时间功能增加闰年计算功能显示部分由LCD1602完成二、方案论证:1.显示部分:显示部分是本次设计的重要部分,一般有以下两种方案:方案一:采用LED显示,分静态显示和动态显示。对于静态显示方式,所需的译码驱动装置很多,引线多而复杂,且可靠性也较低。而对于动态显示方式,虽可以避免静态显示的问题,但设计上如果处理不当,易造成亮度低,有闪烁等问题。方案二:采用LCD显示。LCD液晶显示具有丰富多样性、灵活性、电路简单、易于控制而且功耗小等优点,对于信息量多的系统,是

2、比较适合的。鉴于上述原因,我们采用方案二。2.数字时钟:数字时钟是本设计的核心的部分。根据需要可采用以下两种方案实现:方案一:方案完全用软件实现数字时钟。原理为:在单片机内部存储器设三个字节分别存放时钟的时、分、秒信息。利用定时器与软件结合实现1秒定时中断,每产生一次中断,存储器内相应的秒值加1;若秒值达到60,则将其清零,并将相应的分字节值加1;若分值达到60,则清零分字节,并将时字节值加1;若时值达到24,则将时字节清零。该方案具有硬件电路简单的特点,但当单片机不上电,程序将不执行。而且由于每次执行程序时,定时器都要重新赋初值,所以该时钟精度不高。方案二:方案采用Dallas公司的专用时钟

3、芯片DS1302。该芯片内部采用石英晶体振荡器,其芯片精度不大于10ms/年,且具有完备的时钟闹钟功能,因此,可直接对其以用于显示或设置,使得软件编程相对简单。为保证时钟在电网电压不足或突然掉电等突发情况下仍能正常工作,芯片内部包含锂电池。当电网电压不足或突然掉电时,可使系统自动转换到内部锂电池供电系统。而且即使系统不上电,程序不执行时,锂电池也能保证芯片的正常运行,以备随时提供正确的时间。基于时钟芯片的上述优点,本设计采用方案二完成数字时钟的功能。三、总体方案:本设计采用STC89C52RC单片机作为本系统的控制模块。单片机可把由DS1302、LCD液晶显示模块中的数据利用软件来进行处理,从

4、而把数据传输到显示模块,实现日历和修改的显示。以LCD液晶显示器为显示模块,把单片机传来的数据显示出来,并且显示多样化。在显示电路中,主要靠按键来实现日期的修改和选择。四、系统硬件设计:1. STC89C52RC单片机最小系统:最小系统包括晶体振荡电路、复位开关和电源部分。图1为STC89C52RC单片机的最小系统。图1单片机最小系统2.时钟模块:时钟模块采用DS1302芯片,DS1302是DALLAS公司推出的涓流充电时钟芯片内含有一个实时时钟/日历和31字节静态RAM通过简单的串行接口与单片机进行通信实时时钟/日历电路提供秒分时日日期月年的信息每月的天数和闰年的天数可自动调整时钟操作可通过

5、AM/PM指示决定采用24或12小时格式DS1302与单片机之间能简单地采用同步串行的方式进行通信仅需用到三个口线:RST复位、I/O数据线、SCLK串行时钟。时钟/RAM的读/写数据以一个字节或多达31个字节的字符组方式通信。DS1302工作时功耗很低,保持数据和时钟信息时功率小于1mW,其接线电路如图2所示:图2时钟模块3. LCD液晶显示模块:LCD液晶显示模块采用LCD1602型号,具有很低的功耗,正常工作时电流仅2.0mA/5.0V。通过编程实现自动关闭屏幕能够更有效的降低功耗。LCD1602分两行显示,每行可显示多达16个字符。LCD1602液晶模块内部的字符发生存储器(CGROM

6、)已经存储了160个不同的点阵字符图形,通过内部指令可实现对其显示多样的控制,并且还能利用空余的空间自定义字符。其接线如图3所示:图3LCD液晶显示五、整体电路:1.电路如下图:图4 整体电路2.Altium Designer布线图图5 Altium Designer布线图3.手动布线PCB图图6PCB图六、数字时钟使用说明:1) 调整时间设定:在时间显示界面中按K1键后,进入时间调整,选择需要修改的或设定的时间。按K2键对应内容加1, K3键减1,K4键确定时间设定并退出设置。2) 调整屏幕显示/背光亮度:调整左上方的蓝色变阻器可调整LCD显示灰度LCD背光亮度。3) 复位键(K5):按下该

7、键系统复位,系统从头开始执行程序。如遇故障可按下该键进行系统复位。复位不会造成时间、生日和闹铃等信息的丢失。七、心得体会:1.将理论教学与实践相结合,使我对于单片机的实际应用有了较深刻的认识。 2.让我熟悉电子系统设计的全过程,提高了我对设计课题的分析能力、编程能力及解决实际问题的综合能力。3.对于Protues软件有了更加深入的了解,仿真这方面有很大的缺点,程序时序不对软件直接忽略了,因此在这方面花了好多时间进行调试。同时在与老师和同学的交流过程中,互动学习,将知识融会贯通。通过自己的努力,做出了一个万年历,对以后的学习是一个莫大的鼓舞,激起了我的学习兴趣和开发创新思维。八、程序及解释:#i

8、nclude #include #include #define uint unsigned int#define uchar unsigned charunsigned char code displaywelcome= Welcome To My Lcd Timer;/欢迎界面unsigned char code displaywish=通信102闭光俭; /欢迎界面sbit IO= P23; /DS1302数据线sbit SCLK = P24; /DS130时钟线sbit RST = P25; /DS1302复位线sbit RS = P20; /LCD数据/命令选择端sbit RW =

9、P21; /LCD读/写控制sbit EN = P22; /LCD使能端sbit K1=P34; /选择sbit K2=P35; /加sbit K3=P36; /减sbit K4=P37; /确定uchar tCount=0;uchar MonthsDays=0,31,0,31,30,31,30,31,31,30,31,30,31;uchar *WEEK=SUN,MON,TUS,WEN,THU,FRI,SAT;uchar LCD_DSY_BUFFER1=DATE 00-00-00 ; /显示格式uchar LCD_DSY_BUFFER2=TIME 00:00:00 ;uchar DateTim

10、e7; /所读取的日期时间char Adjust_Index=-1; /当前调节的时间对象:,分,是,日,月,年(1,2,3,4,6)uchar Change_Flag= -MHDM-Y; /(分,时,日,月,年)(不调节秒与周)void DelayMS(uint ms) /延时程序 uchar i; while(ms-)for(i=0;i120;i+);void Write_A_Byte_TO_DS1302(uchar x) /向DS1302写入一字节 uchar i; SCLK=0; for(i=0;i=1; / 右移 uchar Get_A_Byte_FROM_DS1302() /从DS

11、1302读取一字节 uchar i,b=0x00; for(i=0;i8;i+) b |= _crol_(uchar)IO,i); SCLK=1;SCLK=0; /每一个高脉冲读取一位数据 return b/16*10+b%16; /返回BCD码uchar Read_Data(uchar addr) /从DS1302指定位置读数据 uchar dat; RST = 0;SCLK=0;RST=1; /RST高电平时读/写 Write_A_Byte_TO_DS1302(addr); /先写入地址 dat = Get_A_Byte_FROM_DS1302(); SCLK=1;RST=0; retur

12、n dat;void Write_DS1302(uchar addr,uchar dat) /向DS1302某地址写入数据 RST=0;SCLK=0;RST=1; Write_A_Byte_TO_DS1302(addr); Write_A_Byte_TO_DS1302(dat); SCLK=1;RST=0; /高脉冲写入数据void SET_DS1302() /设置时间 uchar i; /写控制字,取消写保护 Write_DS1302(0x8E,0x00); /分时日月年依次写入 for(i=1;i7;i+) Write_DS1302(0x80+2*i,(DateTimei/104)|(Da

13、teTimei%10); /分的起始地址(0x82),后面依次是时,日,月,周,年,写入地址每次递增2 Write_DS1302(0x8E,0x80); /加保护void GetTime()/读取当前日期时间 uchar i; for(i=0;i7;i+) DateTimei=Read_Data(0X81+2*i);uchar Read_LCD_State()/读LCD状态 uchar state; RS=0;RW=1;EN=1; /输出:D0D7=状态字 DelayMS(1); state=P0; /从P0口读LCD状态 EN = 0;DelayMS(1); return state;voi

14、d LCD_Busy_Wait() / 忙等待 while(Read_LCD_State()&0x80)=0x80); DelayMS(5); void Write_LCD_Data(uchar dat) /向LCD写数据 LCD_Busy_Wait(); RS=1;EN=0;RW=0; /写数据,EN为高脉冲, P0=dat;EN=1;DelayMS(1);EN=0; void Write_LCD_Command(uchar cmd) /写LCD指令 LCD_Busy_Wait(); RS=0;EN=0; RW=0; /写指令,EN高脉冲,输出:D0D7=数据 P0=cmd;EN=1;Del

15、ayMS(1);EN=0; void Init_LCD() /LCD初始化 Write_LCD_Command(0x38); /设置16*2显示,5*7点阵,8位数据接口 DelayMS(1); Write_LCD_Command(0x01); /显示清零,数据指针清零 DelayMS(1); Write_LCD_Command(0x06); /写一个字符后地址指针自动加1 DelayMS(1); Write_LCD_Command(0x0c); /设置开显示,不显示光标 DelayMS(1); void Set_LCD_POS(uchar p) /设置液晶显示位置 Write_LCD_Com

16、mand(p|0x80);/相当于在0x80基础上加入位置量 void displaystar(void) /显示欢迎界面 unsigned char i,j; Set_LCD_POS(0x0f); while(displaywelcomei!=0) Write_LCD_Data(displaywelcomei); i+; DelayMS(1); i=0; Set_LCD_POS(0x4f); while(displaywishi!=0) Write_LCD_Data(displaywishi); i+; DelayMS(1); j=40; while(j-) Write_LCD_Comman

17、d(0x18);/循环左移 DelayMS(200);Write_LCD_Command(0x01); DelayMS(1);void Display_LCD_String(uchar p,uchar *s) /-在LCD上显示字符串-/ uchar i; Set_LCD_POS(p); for(i=0;i16;i+) Write_LCD_Data(si); /在固定位置显示时间日期 DelayMS(1);void Format_DateTime(uchar d,uchar *a) /日期与时间值转换为数字字符 a0=d/10+0; a1=d%10+0;uchar isLeapYear(uin

18、t y) /判断是否为闰年 return (y%4=0&y%100!=0)|(y%400=0);/求自2000.1.1开始的任何一天是星期几/函数没有通过,求出总天数后再求星期几/因为求总天数可能会超出uint的范围void RefreshWeekDay() uint i,d,w=5; /已知1999.12.31是周五 for(i=2000;i2000+DateTime6;i+) d=isLeapYear(i)?366:365; w=(w+d)%7; d=0; for(i=1;iDateTime4;i+) d+=MonthsDaysi; d+=DateTime3;/保存星期,06表示星期日,星

19、期一,二,.,六,为了与DS1302的星期格式匹配,返回值需要加1 DateTime5=(w+d)%7+1;void DateTime_Adjust(char x) /年月日时分+/- switch(Adjust_Index) case 6: /年00-99 if(x=1&DateTime60) DateTime6-; MonthsDays2=isLeapYear(2000+DateTime6)?29:28; /获取2月天数 /如果年份变化后当前月份的天数大于上限则设为上限/ if(DateTime3MonthsDaysDateTime4) DateTime3=MonthsDaysDateTi

20、me4; RefreshWeekDay(); /刷新星期 break; case 4: /月01-12 if(x=1&DateTime412) DateTime4=0; if(x=-1&DateTime41) DateTime4-; if(DateTime4MonthsDaysDateTime4) DateTime3=MonthsDaysDateTime4; RefreshWeekDay(); break; case 3: /日00-28、29、30、31,调节之前首先根据年份得出该年中断二月天数 MonthsDays2=isLeapYear(2000+DateTime6)?29:28; /根

21、据当前月份决定调节日期的上限 if(x=1&DateTime30) DateTime3-; RefreshWeekDay(); break; case 2: /时 if(x=1&DateTime20) DateTime2-; break; case 1: /分 if(x=1&DateTime10) DateTime1-; break;void T0_INT() interrupt 1 /定时器0每秒刷新LCD显示 TH0=-50000/256; TL0=-50000%256; if(+tCount !=2) return; tCount=0; /按指定格式生成待显示的日期时间串/ Format

22、_DateTime(DateTime6,LCD_DSY_BUFFER1+5); Format_DateTime(DateTime4,LCD_DSY_BUFFER1+8); Format_DateTime(DateTime3,LCD_DSY_BUFFER1+11); strcpy(LCD_DSY_BUFFER1+13,WEEKDateTime5-1); /星期 Format_DateTime(DateTime2,LCD_DSY_BUFFER2+5); /时分秒 Format_DateTime(DateTime1,LCD_DSY_BUFFER2+8); Format_DateTime(DateTi

23、me0,LCD_DSY_BUFFER2+11); Display_LCD_String(0x00,LCD_DSY_BUFFER1); /显示年月日,星期,时分秒 Display_LCD_String(0x40,LCD_DSY_BUFFER2);void EX_INT0() interrupt 0 /键盘中断(INT0) if(K1=0) /选择调整对象(Y M D H M) DelayMS(10); if(K1=0) while(K1=0); if(Adjust_Index=-1|Adjust_Index=1) Adjust_Index=7; Adjust_Index-; if(Adjust_

24、Index=5) Adjust_Index=4; LCD_DSY_BUFFER213=; LCD_DSY_BUFFER214=Change_FlagAdjust_Index; /显示调节对象 LCD_DSY_BUFFER215=; else if(K2=0) /加 while(K2=0); DelayMS(10); if(K2=0) DateTime_Adjust(1); else if(K3=0) /减 DelayMS(10);/while(K3=0); if(K3=0) DateTime_Adjust(-1); else if(K4=0) /确定 while(K4=0); DelayMS(

25、10); if(K4=0) SET_DS1302(); /将调整后的时间写入DS1302 LCD_DSY_BUFFER213= ; LCD_DSY_BUFFER214= ; LCD_DSY_BUFFER215= ; Adjust_Index=-1;void main() Init_LCD(); /液晶初始化 displaystar( ); IE=0x83; /允许INT0,T0中断,EA=1,ET0=1,EX0=1 IP=0x01; /设置外部中断0为高级中断 IT0=0x01; /外部中断0为电平触发,低电平有效 TMOD=0x01; /设置定时器T0工作方式为方式1, TH0=-50000/256; /装入初始值,定时1秒 TL0=-50000%256; TR0=1; /启动定时器 GetTime(); while(1)if(Adjust_Index=-1) GetTime(); /如果未执行调整操作则正常读取当前时间

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1