基于单片机的万年历

更新时间:2024-04-02 12:24:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

单片机课程设计

题 目 基于单片机的万年历

目 录

1 绪论 .................................................................................. 1 1.1设计目的 .................................................................... 1 1.2 发展现状 ................................................................... 1 1.3 解决问题 ................................................................... 1 2基于单片机的万年历主要元器件介绍 .......................... 2 2.1本设计所需的主要元器件 ........................................ 2

2.2 STC89C52RC单片机 ................................................ 2 2.2.1单片机主要特性 ................................................................ 2 2.2.2单片机引脚说明 ................................................................ 4 2.3 DS1302时钟芯片 ...................................................... 4 2.4 LCD1602 .................................................................... 6 2.5独立按键 .................................................................... 7 3基于单片机的万年历的软件设计 .................................. 7 3.1 DS1302时钟芯片程序设计 ...................................... 8 4 总结 .................................................................................. 9 参考文献 ............................................................................. 11 附录1:总体电路原理图 ................................................. 12 附录2:总程序 ................................................................. 13 附录3:实物图 ................................................................. 25

1 绪论

1.1设计目的

培养和锻炼在学习完本课后综合运用所学理论知识,解决实际工程设计和应用问题的能力。通过课程设计,要求熟悉和掌握仿真系统的软件设计方法、设计步骤,以及硬件的设计方法、设计步骤,得到仿真系统应用方面的初步练习。

本设计主要是采用51单片机来实现。自己动手设计与制作可以对硬件的结构和功能有更深的认识,并与软件结合,以达到理论与实践更好的结合,进一步提高综合运用所学知识进行设计的能力。这是对自己大学四年的学习的检验,具有重要的意义。

1.2 发展现状

目前市场上的电子万年历并不是采用51单片机作为主控制器的,基于单片机的万年历一般是学生和单片机爱好者在进行设计,谈不上占有市场。也许就是这样,研究单片机万年历的人不在少数,并且都在努力。努力不是单方面的,单片机的功能也应该要提高,STC89C52单片机就是这样的例子,其功能虽然没有大幅度提高,但使用起来更方便了。我相信,在不久的将来肯定会有功能更强大成本更低的单片机出现,给我们的设计带来更多的便利。

1.3 解决问题

本课题主要通过单片机的功能和应用,利用Keil[1]编程软件和Proteus仿真软件进行设计,并制作实物。设计要达到预期的效果要解决以下问题:

1

(1)认真设计好万年历的逻辑原理图;

(2) 熟练使用C语言,运用Keil编程软件进行软件设计; (3) 在Proteus仿真平台上,对程序进行编译仿真; (4) 认真仔细地对万年历进行组装焊接;

2基于单片机的万年历主要元器件介绍

2.1本设计所需的主要元器件

(1)单片机:STC89C52RC; (2)时钟芯片:DS1302; (3)液晶:LCD1602; (4)按钮开关。

2.2 STC89C52RC单片机

本设计采用STC89C52RC单片机,8K字节可编程闪烁存储器。STC89系列单片机是MCS-51系列单片机的派生产品,它们在指令系统、硬件结构和片内资源上与标准8052单片机完全兼容。STC89系列是以8051为基核开发出的CMOS工艺单片机,DIP封装系列与8051为pin-to-pin(引脚对引脚)兼容。STC89系列单片机高速,低功耗,其程序写入时可通过串口采用STC-ISP.exe软件下载,不占用用户资源,学习单片机时较好的选择。

2.2.1单片机主要特性

(1) CPU:由运算和控制逻辑组成,同时还包括中断系统和部分外部特殊功能寄存器。中央处理器(CPU)是整个单片机的核心部件,是8位数据宽度的处理器,能处理8位二进制数据或代码,

2

CPU负责控制、指挥和调度整个单元系统协调的工作,完成运算和控制输入输出功能等操作。

(2) RAM:用于存放要读写的数据,如运算的中间结果、最终结果以及欲显示的数据。8051内部有128个8位用户数据存储单元和128个专用寄存器单元,它们是统一编址的,专用寄存器只能用于存放控制指令数据,用户只能访问,而不能用于存放用户数据,所以,用户能使用的RAM只有128个,可存放读写的数据,运算的中间结果或用户定义的字型表。

(3) ROM:8051共有4096个8位掩膜ROM,用于存放用户程序,原始数据或表格。

(4) I/O口:四组8位并行I/O口(P0、 P1、P2和P3),既可用作输入,也可用作输出。

(5) T/C定时/计数器:两个16位的可编程定时/计数器,既可以工作在定时模式,也可以工作在计数模式。

(6) 5个中断源的中断控制系统:8051具备较完善的中断功能,有两个外中断、两个定时/计数器中断和一个串行中断,可满足不同的控制要求,并具有2级的优先级别选择。

(7) 全双工串行口:一个全双工UART(通用异步接收发送器)的串行I/O口,用于实现单片机之间或单片机与微机之间的串行通信;

(8) 片内振荡器和时钟产生电路,石英晶体和微调电容需要外接。最高振荡频率取决于单片机型号及性能。

3

2.2.2单片机引脚说明

图2-1 STC89C52RC封装引脚图

STC89C52RC的引脚封装和8051的引脚封装是一样的,均采用40Pin封装的双列直插DIP结构。下图是它们的引脚配置,40个引脚中,Pin40为正电源,Pin20为地线;外置石英振荡器的时钟线Pin18和Pin19两根;4组8位共32个I/O口(P0、P1、P2和P3),中断口线与P3口线复用。本设计只是实现简单的读写功能,不需要用到I/O口的第二功能。单片机引脚封装如图2.1所示。

2.3 DS1302时钟芯片

市场上可以选择的时钟芯片很多,功能也不尽相同,价格各异。DS1302是美国DALLAS公司推出的一种串行接口实时时钟芯片。芯片内部具有可编程日历时钟和31个字节的静态RAM,它可以对年、月、日、星期、时、分、秒进行计时。DS1302引

4

脚封装如图2-2所示。

图2-2 DS1302封装引脚图

DS1302时钟芯片的引脚功能如下: (1) Pin1:Vcc2为主电源。

(2) Pin8:Vcc1为后备电源。在主电源关闭的情况下,也能保持时钟的连续运行。DS1302由Vcc1或Vcc2两者中的较大者供电。当Vcc2大于Vcc1+0.2V时,Vcc2给DS1302供电。当Vcc2小于Vcc1时,DS1302由Vcc1供电。

(3) Pin2、3:X1、X2是振荡源,外接32.768kHz晶振。 (4) Pin5:RST是复位/片选线,通过把RST输入驱动置高电平来启动所有的数据传送。RST输入有两种功能:首先,RST接通控制逻辑,允许地址/命令序列送入移位寄存器;其次,RST提供终止单字节或多字节数据的传送手段。当RST为高电平时,所有的数据传送被初始化,允许对DS1302进行操作。如果在传送过程中RST置为低电平,则会终止此次数据传送,I/O引脚变为高阻态。上电运行时,在Vcc>2.0V之前,RST必须保持低电平。

5

只有在SCLK为低电平时,才能将RST置为高电平。

(5) Pin6:I/O为串行数据输入输出端(双向),在控制指令字输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,数据输入从低位即位0开始。同样,在紧跟8位的控制指令字后的下一个SCLK脉冲的下降沿读出DS1302的数据,读出数据时从低位0位到高位7。

图2-3 DS1302

2.4 LCD1602

1602通过D0~D7的8位数据端传输数据和指令。显示模式设置(初始化)00111000[0x38]设置16×2显示,5×7点阵,8位数据接口;显示开关及光标设置:(初始化) 00001DCBD显示(1有效)、C光标显示(1有效)、B光标闪烁(1有效)。000001NS N=1(读或写一个字符后地址指针加1并且光标加1),N=0(读或写一个字符后地址指针减1并且光标减1),S=1且N=1(当写一个字符后,整屏显示左移),S=0当写一个字符后,整屏显示不移动。数据指针设置:数据首地址为80H,所以数据地址为80H+地址码(0-27H,40-67H)。其他设置:01H(显示清屏,数据指针=0,所有显示=0);02H(显示回车,数据指针=0)。

6

2.5独立按键

本设计采用的4个独立按键,分别是:“设置”、“确认”、“加”、“减”。判断“设置”键是否按下及第几次按下可以分别对日期、时间、星期选定,然后按“加”、“减”即可进行设置,“确认”键按下后,新数据即写入时钟芯片。图2-4 时间设置路。

图2-4 时间设置电路

3基于单片机的万年历的软件设计

本设计利用Keil(C51) 软件进行程序的编写。C语言是一种编译型程序设计语言,它兼顾了许多种高级语言的特点,并且具备汇编语言的功能,C 语言可以像汇编语言一样对位、字节和地址进行操作。目前,使用C语言进行程序设计已经成为软件开发的一个主流。C语言程序本身不依赖于机器硬件系统,基本上不作修改就可将程序从不同的单片机中移植过来。用C语言开发系统可以大大缩短开发周期,明显增强程序的可读性,便于改进、扩充和移植。而针对8051的C语言日趋成熟,成为了专业化的

7

实用高级语言。虽然汇编语言效率高,对硬件的可操控性更强,体积小,但是不易维护,可移植性差。本设计程序实现了阳历年、月、日、时间提醒等功能。图3-1是主程序流程图。

开始 LCD、DS1302相关变量初始化 调液晶显示程序 设置键是否按调用设置子程序 刷新 图3-1 主程序流程图

3.1 DS1302时钟芯片程序设计

在本设计中,要实现万年历的功能,DS1302时钟芯片是少不得的,虽然只用单片机也可以实现,但是将会造成时间误差较大,不好调节。用DS1302时钟芯片不仅可以大大的避免那样的问题,还可以减小程序的编写量。这个模块是本设计中是很重要的模块。如图3-2是DS1302时钟芯片工作的流程图。

8

开始 相关变量初始DS1302去保护 写DS1302地址 复位端产生 一个高电平 复位端产生 一个高电平 延时一段时间 将该地址数据读出 写DS1302地址 延时一段时间 向该地址写数据 地址增加 数据读完地址增加 数据写完否 显示数据 图3-2 DS1302时钟芯片工作的流程图

4 总结

本设计在进行Proteus软件仿真时,没有成功,因为Proteus软件的元件库里没有带中文字库的液晶,要想成功仿真,需要对程序进行大范围的修改,最终决定放弃Proteus软件仿真,直接采用硬件进行调试。

硬件的线路设计和元件组装都花了较长的时间,虽然以前也焊接过一些东西,但不能说那就是有经验。以前焊接的东西都是

9

有现成的电路板,只是把元件对应的组装起来就基本没问题了。在本设计中,并没有现成的电路板,而是用万能板自己搭线组装。在整个硬件焊接到一半时,才发现将液晶屏的引脚弄反了,只能进行修改。

在进行程序调试时,一些大问题比较容易找出并改正,而一些小的问题就比较麻烦,因此一定要注意细小的问题。 本设计总体最终实现了阳历及阴历的日期显示、时间、星期、温度的显示,独立按键调节日期、星期等功能。本设计整个过程还算顺利,没出现太大的问题。

10

参考文献

[1]郑郁正.单片机原理及应用.成都:四川大学出版社,2003.9. [2]王怀平,王仁波,胡开明.Proteus仿真设计基于单片机AT89C51的电子万年历[J].科技广场,2008,10:197-198.

[3]潘永雄,沙河.电子线路CAD实用教程(第三版).西安:西安电子科技大学出版社,

2007.7(2009.8重印).

[4]谭浩强.C程序设计(第三版).北京:清华大学出版社,2005(2007重印).

[5](日)晶体管技术编辑部编,杨洋等译,宗光华校.电子技术:原理·制作·实验.北京:科学出版社,2005.

[6]赵全利,肖兴达.单片机原理及应用教程(第二版).北京:机械工业出版社,2007.7.

[7]雷伏容,张小林,崔浩.51单片机常用模块设计查询手册.北京:清华大学出版社,2010.01.

[8]肖炎根,舒望.基于实时时钟芯片的电子万年历的设计[J].电子技术,2007,Z3:91-94.

[9]刘畅生,宣宗强,雷振亚等.传感器简明手册及应用电路——温度传感器分册(上册).西安:电子科技大学出版社,2005.11.

[10]李宏,张家田.液晶显示器件应用技术.北京:机械工业出版社,2004.2.

11

附录1:总体电路原理图

总体电路原理图

12

附录2:总程序

#include\

/*******************************************************************************

* 函 数 名 : Lcd1602_Delay1ms * 函数功能

: 延时函数,延时1ms

* 输 入 : c * 输 出 : 无

* 说 名 : 该函数是在12MHZ晶振下,12分频单片机的延时。 *******************************************************************************/

void Lcd1602_Delay1ms(uint c) //误差 0us {

uchar a,b; }

/*******************************************************************************

* 函 数 名 : LcdWriteCom * 函数功能

for (; c>0; c--) { }

for (b=199;b>0;b--) {

for(a=1;a>0;a--); }

: 向LCD写入一个字节的命令

13

* 输 入 : com * 输 出 : 无

*******************************************************************************/

#ifndef LCD1602_4PINS //当没有定义这个LCD1602_4PINS时 void LcdWriteCom(uchar com) { } #else

void LcdWriteCom(uchar com) {

LCD1602_DATAPINS = com;

//由于4位的接线是接到P0口的高四

LCD1602_E = 0; //使能清零 LCD1602_RS = 0; //选择写入命令 LCD1602_RW = 0; //选择写入

//写入命令

LCD1602_E = 1; //写入时序 Lcd1602_Delay1ms(5); //保持时间 LCD1602_E = 0;

LCD1602_E = 0; //使能

LCD1602_RS = 0; //选择发送命令 LCD1602_RW = 0; //选择写入

LCD1602_DATAPINS = com; //放入命令 Lcd1602_Delay1ms(1);

//等待数据稳定 //写入命令

位,所以传送高四位不用改

Lcd1602_Delay1ms(1); LCD1602_E = 1; //写入时序

14

// }

Lcd1602_Delay1ms(5); LCD1602_E = 0; Lcd1602_Delay1ms(1);

LCD1602_DATAPINS = com << 4; //发送低四位 Lcd1602_Delay1ms(1); LCD1602_E = 1; //写入时序 Lcd1602_Delay1ms(5); LCD1602_E = 0;

#endif

/*******************************************************************************

* 函 数 名 : LcdWriteData * 函数功能

: 向LCD写入一个字节的数据

* 输 入 : dat * 输 出 : 无

*******************************************************************************/

//写入数据

#ifndef LCD1602_4PINS void LcdWriteData(uchar dat) {

LCD1602_E = 0; //使能清零 LCD1602_RS = 1; //选择输入数据 LCD1602_RW = 0; //选择写入

LCD1602_DATAPINS = dat; //写入数据 Lcd1602_Delay1ms(1); LCD1602_E = 1; //写入时序

15

}

Lcd1602_Delay1ms(5); //保持时间 LCD1602_E = 0;

#else

void LcdWriteData(uchar dat) {

LCD1602_DATAPINS = dat; //由于4位的接线是接到P0口的高四位,LCD1602_E = 0; //使能清零 LCD1602_RS = 1; //选择写入数据 LCD1602_RW = 0; //选择写入

//写入数据

所以传送高四位不用改 } #endif

/*******************************************************************************

* 函 数 名 : LcdInit() * 函数功能

: 初始化LCD屏

16

Lcd1602_Delay1ms(1); LCD1602_E = 1; //写入时序 Lcd1602_Delay1ms(5); LCD1602_E = 0;

LCD1602_DATAPINS = dat << 4; //写入低四位 Lcd1602_Delay1ms(1); LCD1602_E = 1; //写入时序 Lcd1602_Delay1ms(5); LCD1602_E = 0;

* 输 入 : 无 * 输 出 : 无

*******************************************************************************/ #ifndef void LcdInit() { } #else void LcdInit() { } #endif

/******************************************************************************* * 实验名

: 定时器实验

LcdWriteCom(0x32); LcdWriteCom(0x28);

//将8位总线转为4位总线 //在四位线下的初始化

//LCD初始化子程序

LcdWriteCom(0x38); //开显示

LcdWriteCom(0x0c); //开显示不显示光标 LcdWriteCom(0x06); //写一个指针加1 LcdWriteCom(0x01); //清屏

LcdWriteCom(0x80); //设置数据指针起点

//LCD初始化子程序

LCD1602_4PINS

LcdWriteCom(0x0c); //开显示不显示光标 LcdWriteCom(0x06); //写一个指针加1 LcdWriteCom(0x01); //清屏

LcdWriteCom(0x80); //设置数据指针起点

* 使用的IO :

* 实验效果 :1602显示时钟,按K3进入时钟设置,按K1选择设置的时分秒,按K2选择

17

*选择设置加1。 *

注意

*******************************************************************************/ #include #include\sbit K1=P3^6; sbit K4=P3^4; sbit K3=P3^5; sbit K2=P3^3;

unsigned char Time; //用来计时间的值

void Delay1ms(unsigned int c); void TimerConfiguration(); void Int0Configuration();

unsigned char SetPlace;

/*******************************************************************************

* 函 数 名 : main * 函数功能

: 主函数

* 输 入 : 无 * 输 出 : 无

*******************************************************************************/ void main(void) {

unsigned char hour,minit,second;

18

unsigned int i; TimerConfiguration(); Int0Configuration(); LcdInit(); hour=12;

LcdWriteData('0'+hour/10); LcdWriteData('0'+hour); LcdWriteData('-');

LcdWriteData('0'+minit/10); LcdWriteData('0'+minit); LcdWriteData('-');

LcdWriteData('0'+second/10); LcdWriteData('0'+second); while(1) {

if(TR0==0) {

if(K1==0) {

Delay1ms(10);//消除抖动 if(K1==0) { }

while((i<50)&&(K1==0)) { }

19

//检测按键K2是否按下

SetPlace++; if(SetPlace>=3)

SetPlace=0;

//检测按键是否松开

Delay1ms(1); i++;

}

i=0;

//检测按键K3是否按下

if(K2==0) { Delay1ms(10);//消除抖动 if(K2==0) { if(SetPlace==0) { second++; if(second>=60)

second=0;

}

else if(SetPlace==1) { minit++; if(minit>=60)

minit=0; } else { hour++; if(hour>=24) hour=0; }

}

while((i<50)&&(K2==0)) { Delay1ms(1); i++;

}

20

//检测按键是否松开

}

}

i=0;

if(Time>=20) //一秒钟来到改变数值 { }

Time=0; second++; if(second==60) { }

second=0; minit++; if(minit==60) { }

minit=0; hour++; if(hour==24) { }

hour=0;

//--显示时钟--//

LcdWriteCom(0x80); LcdWriteData('0'+hour/10); LcdWriteData('0'+hour); LcdWriteCom(0x83); LcdWriteData('0'+minit/10); LcdWriteData('0'+minit); LcdWriteCom(0x86); LcdWriteData('0'+second/10); LcdWriteData('0'+second);

21

}

}

/*******************************************************************************

* 函 数 名 : Delay1ms() * 函数功能

: 延时1ms

* 输 入 : c * 输 出 : 无

*******************************************************************************/

void Delay1ms(unsigned int c) //误差 0us {

unsigned char a,b; }

/*******************************************************************************

* 函 数 名 : TimerConfiguration() * 函数功能

: 配置定时器值

for (; c>0; c--) { }

for(b=199;b>0;b--) { }

for(a=1;a>0;a--);

* 输 入 : 无

22

* 输 出 : 无

*******************************************************************************/

void TimerConfiguration() {

TMOD = 0x01; //选择工作方式1 TH0 = 0x3C; //设置初始值 TL0 = 0x0B0; EA = 1; ET0 = 1; TR0 = 1; }

/*******************************************************************************

* 函 数 名 : Timer0() * 函数功能

: 定时器0中断函数

//打开总中断

//打开定时器0中断 //启动定时器0

* 输 入 : 无 * 输 出 : 无

*******************************************************************************/

void Timer0() interrupt 1 { }

/*******************************************************************************

* 函 数 名 : Int0Configuration()

23

TH0 = 0x3C;

Time++;

//设置初始值

TL0 = 0x0B0;

本文来源:https://www.bwwdw.com/article/mphr.html

Top