资源描述
。
目录
1、设计目的 2
2、系统方案设计 2
2.1 设计任务及要求 2
2.1.1 设计任务 2
2.1.2 设计要求 2
2.2 方案设计 3
2.2.1 设计原理 3
2.2.2 模块分析 3
2.2.3总原理图以及主程序流程图 8
2.2.4 proteus仿真结果 9
2.2.5实验结果 9
3、设计总计 10
4、参考文献 11
附录:源程序 11
1、设计目的
单片机项目设计是以课题或设计方式开展的一门课程,具有较强的综合性、实践性,是工科、工程类院校或职业类院校电类专业在校生的必修课,是将单片机原理与应用课程的理论知识转变为应用技术的重要教学环节。这一环节不但能加深对单片机原理的理解,而且还能培养学生的实践动手能力,开发学生的分析、解决问题的能力。单片机项目设计环节的训练能够让学生知道单片机工程项目的制作过程,使学生尽早了解单片机系统的开发流程。
掌握单片机系统的开发应用,巩固和加深已学过的知识,提高动手能力及解决实际问题的能力,同时培养团队合作精神。将自己学到的知识更好地运用于实际当中。
2、系统方案设计
2.1 设计任务及要求
2.1.1 设计任务
(1)根据技术要求和现有开发环境,制作智能电子钟(LCD);
(2)设计系统实现方案;
(3)设计并绘制电路原理图;
(4)画出功能模块的程序流程图;
(5)使用汇编语言(或C语言)编写实现程序
(6)结合硬件调试、修改并完善程序;
(7)编写课程设计报告。
2.1.2 设计要求
(1) 计时:秒、分、时、天、周、月、年。
(2) 闰年自动判别。
(3)自定任意时刻自动开/关屏。
(4) 计时精度:误差≤1秒/月(具有微调设置)。
(5) 键盘采用动态扫描方式查询。所有的查询、设置功能均由功能键K1、K2完成。
(6)选作内容:编写上位机程序,通过串口发送指令来调整时钟。
2.2 方案设计
2.2.1 设计原理
此设计原理框图如图2-1所示,此电路包括以下四个部分:单片机,键盘,DS1302时钟采集模块及LCD1602液晶显示屏。经过编译程序仿真后,89C51的4K空间不够用,就选用更大空间的89C52单片机了。本设计用的元器件如列表2-1所示
DS1302时钟
采集模块
89C52CPU
控制模块
按键处理模块
LCD显示模块
图2-1
2.2.2 模块分析
1.DS1302时钟采集模块
(1)DS1302电路图
(2)DS1302芯片分析
DS1302是DALLAS公司推出的涓流充电时钟芯片。内含有一个实时时钟/日历和31字节静态RAM通过简单的串行接口与单片机进行通信实时时钟/日历电路提供秒分时日日期月年的信息每月的天数和闰年的天数可自动调整时钟操作。
DS1302芯片广脚介绍:X1、X2为32.768KHz晶振管脚。GND 为地。RST复位脚。I/O数据输入/输出引脚。SCLK串行时钟。Vcc1,Vcc2电源供电管脚。与单片机连接的信号线为:
DS1302_SCLK 接P1^6 ; 实时时钟时钟线引脚
DS1302_IO 接P1^7; 实时时钟数据线引脚
DS1302_RST 接P1^5; 实时时钟复位线引脚
特别注意DS1302芯片在读取或写入数据时,都是一位一位传送的,并且每传送一位,SCLK信号线要有一个负跳变。数据时通过IO进行传送的。
(3)数据处理流程图
是否调用时间获取子程序
否
是
调用Read1302函数,读取各个时间参数。
对各个时间参数数据进行转换,转换成十进制数,并赋给Time指针中。
调用年份转换成可供lcd显示的字段子程序。
时间转换成可供lcd显示的字段子程序。
结束
2. LCD1602液晶显示模块
(1)LCD1602模块电路图
(2)LCD1602芯片以及连线分析
液晶显示器是一种功耗极低的被动式显示器件,1602广脚介绍:D0—D7数据传送引脚,VSS为接地线,VDD为电源线,VEE为 LCD驱动电压调节,由此可以调节显示亮度。RS为寄存器选择信号,高电平选择数据寄存器,低电平选择指令寄存器。RW为读写控制信号,高电平读,低电平写。EN使能信号,读状态下高电平有效,写状态下下降沿有效。
RS连接P2^0; 寄存器选择信号
RW连接P2^1; 读写控制信号线
EN连接P2^2; 使能信号线
写指令0x38,显示模式设置
(3)LCD初始化程序流程图:
写指令,显示光标
写指令,光标移动
清屏
3.按键模块
(1)按键模块电路图
其中按键key1为选择键,按键key2为加1键,按键key3为减1键。与单片机连线如下:
Key1连接P3^0;
Key2连接P3^1;
Key3连接P3^2;
(2)按键扫描流程图
Key1键是否按下
将key1按键次数存放于变量key1n中
1n=1
?
1n=5
?
1n=4
?
1n=3
?
1n=2
?
否 否 否 否
是 是 是 是
是
1n=7?
1n=6?
否
否
是 是
移动光标
3.加减键处理子程序流程图
判断是否为修改模式
否
判断是否为加1键
是
转减1键程序
否
是
判断key2=3
判断key2=2?
判断key2=1?
否 否
是 是 是
修改day值
修改mon值
修改year值
判断key2=4?
判断key2=6?
判断key2=5?
否 否
是
修改分值
修改day值
修改week值
是 是
判断key2=7?
修改秒值
是
减1子程序与加1子程序区别只在于修改数值处理不一样,其他都一样。
2.2.3总原理图以及主程序流程图
1.总原理图
2.主程序流程图
初始化lcd
初始化内部定时器
初始化DS1302
从DS1302读取日期和时间
移动光标并显示日期
移动光标并显示时间
重复进行按键扫描
2.2.4 proteus仿真结果
2.2.5实验结果
1、在该电子钟的设计中修改定时或调整时间时采用了闪烁,在编程上,首先进行了初始化定义了程序的入口地址以及中断的入口地址,在主程序的开始定义了一组固定单元用来存储计数的秒,分,时以及定时时间的序号等。其次,时,分,秒显示用了软件译码(查表)的方式,再用了一段固定的程序段进行进制转化。最后,用查询方式对按键进行判断,若有键按下,则进行软件延时消抖,避免了抖动引起的干扰,执行相应的定时,选时或调时程序段。对当前时间或定时时间修改后又返回到最初的显示程序段,如此循环下去。
2、在硬件上,选用DS1302,LCD1602相结合,首先DS1302内含有一个实时时钟/日历和31字节静态RAM通过简单的串行接口与单片机进行通信实时时钟/日历电路提供秒分时日日期月年的信息每月的天数和闰年的天数可自动调整时钟操作,这样读取数据简单。其次,选用LCD1602进行显示时,数据位串行输入,接口连线少,低功耗,显示清晰。并且本实验的电子钟即要实现时间的现实,还要实现日期的现实,所以若是运用数码管进行显示的话,就算运用动态显示,所占用的IO口多,并且所需的数码管个数多,硬件复杂。
3、proteus是一个非常好用的仿真软件,其具有强大的电路原理图绘制功能,且可以实现模拟电路仿真、数字电路仿真、单片机及其外围电路组成的系统仿真、键盘、LCD系统仿真等多种功能;和keil联合使用时可以检测所编写的程序的正确与否。将keil和proteus联合起来使用是实现电子设计制作的初步阶段,可避免在实际的硬件操作中因为电路原理图或向单片机烧录的程序有误而造成的难以修改的为题。
3、设计总计
通过本次智能电子时钟的课程设计,我学习将理论和实践相结合,初步掌握综合运用所学知识分析和设计一般数字系统的基本方法,增强动手解决实际问题的能力。通过这次设计,我学会了了初步设计电路的整体思想。学会了怎样查找资料,设计电路。熟悉了绘制电路原理图和电路的调试整个过程,是所学的知识应用到实践,进一步所学的知识。
本次实验也使我认识到了自身的许多缺点和不足,因为自身水平有限,要自己编写C程序很难,但在此实验中,最大的收获莫过于看懂别人的程序,分析之后,自己拼凑编写以实现不同的功能。使我明白现实生活中电子钟的工作原理,锻炼了查找资料的能力。
通过这次课程设计,让我体会到今天认真的进行课程设计,学会脚踏实地迈开这一步,就是为明天能稳健地在社会大潮中奔跑打下坚实的基础。通过这次智能电子时钟设计,人在多方面都有所提高。通过这次智能电子时钟设计,综合运用本专业所学课程的理论和生产实际知识进行智能电子时钟设计工作的实际训练从而培养和提高学生独立工作能力,巩固与扩充了课程所学的内容,智能电子时钟设计的方法和步骤,握智能电子时钟设计的工艺方案,解了智能电子时钟的基本结构,悉了规范和标准,时各科相关的课程都有了全面的复习,立思考的能力也有了提高。
整个设计过程让我收获很多,前所学过的理论知识又再次重现在我们的脑海中,经过了自己的亲手实践使我们更好的理解和掌握了那些知识。同时,经过这短短几天的课程设计也使我提高了自己与其他同学交流沟通的能力。这次课程设计也使我明白了“实践是检验真理的唯一标准”,要想更好的掌握以前学过的知识除了定期的“温故知新”外,还需要进行一些实验和实践。使我们的理论和实践能力同步提高,这次课程设计也使我深刻的认识到了团队合作的重要性。
4、参考文献
[1] 张毅刚.单片机原理及应用[J].高等教育出版社,2009.2
[2].孙育才,王荣兴,孙华芳,新型AT89S52系列单片机及其应用. 北京:清华大学出版社,2005.1.1
[3].朱清慧,张凤蕊,王志奎,Proteus教程—电子线路设计、制版与仿真,北京:清华大学出版社,2008.9.1
[4].侯玉宝,陈忠平,李成群等,基于Proteus 的51系列单片机设计与仿真,北京:电子工业出版社,2008.9.1
[5].彭小军.用单片机实现电子时钟[J].新余高专学报,2004,9(2):54-57.
[6].徐宏亮,艾学忠等.实现多功能电子时钟设计[J].吉林化工学院学报,2001,5(1):26-29.
[7].朱路,朱清慧,连续补充充电实时时钟芯片DS1302及其应用,河南:南阳理工出版社,2006
[8].杨将军,李华军,刘东骏,单片机程序设计及应用,北京:电子工业出版社,2006.3
附录:源程序
#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
#define yh 0x80 //第一行的初始位置
#define er 0x80+0x40 //第二行初始位置
#define true(x) x = 1
#define fals(x) x = 0
sbit du = P2^6;
sbit we = P2^7;
sbit wr = P2^1;
sbit rs = P2^0;
sbit en = P2^2;
sbit SCLK = P1^6;
sbit IO = P1^7;
sbit RST = P1^5;
sbit ACC0 = ACC^0;
sbit ACC7 = ACC^7;
sbit key1 = P3^0;
sbit key2 = P3^1;
sbit key3 = P3^2;
uchar code tab1[]={"20 - - "};
uchar code tab2[]={" : : "};
uchar a,sec,hour,min,day,mon,year,week,flag,temp,key1n=0;
void delay(uchar xms) //延时函数
{
uchar y;
while(xms--)
for(y = 0;y < 110;y ++);
}
/******************液晶写入************************/
void write_1602com(uchar com)
//给液晶1602写入命令函数
{
fals(rs); //置为写入命令
P0 = com; //送入数据
delay(1);
true(en); //拉高使能端
delay(1);
fals(en); //完成高脉冲
}
void write_1602dat(uchar dat)
//向液晶1602中写入数据
{
true(rs); //置为写入数据
P0 = dat; //送入数据
delay(1);
true(en);
delay(1);
fals(en);
}
/********************ds1302****************************/
void writeds1302_1byte(uchar dat) //向ds1302中写入1个字节数据
{
ACC = dat;
true(RST);
for(a = 8;a > 0;a --)
{
IO = ACC0;
fals(SCLK);
true(SCLK);
ACC = ACC >> 1;
}
}
uchar readds1302_1byte()
//读出ds1302的一个数据
{
true(RST);
for(a = 8;a > 0;a --)
{
ACC7 = IO;
true(SCLK);
fals(SCLK);
ACC = ACC >> 1;
}
return(ACC);
}
void write_ds1302(uchar add,uchar dat)
//向ds1302中写入数据
{
fals(RST);
fals(SCLK);
true(RST);
writeds1302_1byte(add);
//给ds1302输入寻址指令
writeds1302_1byte(dat);
//ds1302寻到上面地址后写入相应数据
true(SCLK);
fals(RST);
}
uchar read_ds1302(uchar add) //读出相应地址上的数据
{
uchar temp;
fals(RST );
fals(SCLK);
true(RST );
writeds1302_1byte(add );
//给ds1302输入寻址指令
temp=readds1302_1byte();
//找到相应地址后,读出其数据
true(SCLK);
fals(RST );
return temp;
}
uchar BCD_Decimal(uchar bcd)
//将相应的BCD码转换为10进制(各个位上不会出现大于9的数)
{
uchar Decimal;
Decimal = bcd >> 4 ;
return(Decimal = Decimal * 10 + (bcd &= 0x0F));
}
void write_1602sfm(uchar add,uchar dat)
//写时分秒
{
uchar gw,sw;
gw = dat % 10;
sw = dat / 10;
write_1602com(er + add);
write_1602dat(0x30 + sw );
write_1602dat(0x30 + gw );
}
void write_1602nyr(uchar add,uchar dat)
{
uchar gw,sw;
gw = dat % 10;
sw = dat / 10;
write_1602com(yh + add);
//给液晶1602写入一个地址
write_1602dat(0x30 + sw );
write_1602dat(0x30 + gw );
//给那个地址上写入一个2位数
}
void write_1602week(uchar week)
//写星期函数
{
write_1602com(yh + 0x0d);
//要写星期的地址
switch(week)
{
case 1: write_1602dat('M');
write_1602dat('O');
write_1602dat('N');
break;
case 2: write_1602dat('T');
write_1602dat('U');
write_1602dat('E');
break;
case 3: write_1602dat('W');
write_1602dat('E');
write_1602dat('D');
break;
case 4: write_1602dat('T');
write_1602dat('H');
write_1602dat('U');
break;
case 5: write_1602dat('F');
write_1602dat('R');
write_1602dat('I');
break;
case 6: write_1602dat('S');
write_1602dat('T');
write_1602dat('A');
break;
case 7: write_1602dat('S');
write_1602dat('U');
write_1602dat('N');
break;
}
}
void deal_3day()
{
if(mon==1||mon==3||mon==5||mon==7||mon==8||mon==10||mon==12)
day=32;
else if(mon==4||mon==6||mon==9||mon==11)
day=31;
else if(mon==2&&(year%4==0&&year%100!=0||year%400==0))
day=30;
else
day=29;
}
void keyscan()
{
if(key1 == 0) //key1为功能键
{
delay(5);
if(key1 == 0)
{
while( !key1);
delay(10);
while( !key1);
//松手检测
key1n ++;
if(key1n == 9)
key1n = 1;
switch(key1n)
{
case 1: fals(TR0); //关闭定时器
write_1602com(er+0x0b); //写入光标位置
write_1602com(0x0f ); //设置光标为闪烁
write_ds1302(0x8e,0x00);
write_1602com(yh + 0x05); //nian
write_ds1302(0x8e,0x80);
break;
case 2: write_1602com(yh + 0x08); //月
break;
case 3: write_1602com(yh + 0x0b); //日
break;
case 4: write_1602com(yh + 0x0f); //星期
break;
case 5: write_1602com(er + 5); //时
break;
case 6: write_1602com(er+8); //分
break;
case 7: write_1602com(er+0x0b); //因为设置液晶的模式是写入数据后,指针自动加一,在这里是写回原来的位置
break;
case 8: write_1602com(0x0c ); //设置光标不闪烁
true(TR0); //打开定时器
temp = (sec)/10*16 + (sec)%10;
write_ds1302(0x8e,0x00);
write_ds1302(0x80,0x00|temp); //秒
write_ds1302(0x8e,0x80);
key1n=0;
break;
}
}
}
if(key1n != 0) //当key1按下以下。再按以下键才有效
{
if(key2 == 0) //上调键
{
delay(5);
if(key2 == 0)
{
while( !key2);
delay(10);
while( !key2);
switch(key1n)
{
case 1: year ++;
if(year == 100)
year = 0;
write_1602nyr(4,year);
temp = (year)/10*16 + (year)%10;
write_ds1302(0x8e,0x00);
write_ds1302(0x8c,temp);
write_ds1302(0x8e,0x80);
write_1602com(yh + 5);
break;
case 2: mon++;
if(mon == 13)
mon = 1;
write_1602nyr(7,mon);
temp = (mon)/10*16 + (mon)%10;
write_ds1302(0x8e,0x00);
write_ds1302(0x88,temp);
write_ds1302(0x8e,0x80);
write_1602com(yh + 8);
break;
case 3: day ++;
if(mon==1||mon==3||mon==5||mon==7||mon==8||mon==10||mon==12)
{ if(day == 32)
day = 1;
}
else if(mon==4||mon==6||mon==9||mon==11)
{
if(day == 31)
day = 1; }
else if(mon==2&&(year%4==0&&year%100!=0||year%400==0))
{
if(day == 30)
day = 1;
}
else
{
if(day == 29)
day = 1;
}
if(day == 32)
day = 1;
write_1602nyr(10,day);
temp = (day)/10*16 + (day)%10;
write_ds1302(0x8e,0x00);
write_ds1302(0x86,temp);
write_ds1302(0x8e,0x80);
write_1602com(yh + 11);
break;
case 4: week ++;
if(week == 8)
week = 1;
write_1602week(week);
write_ds1302(0x8e,0x00);
write_ds1302(0x8a,week);
write_ds1302(0x8e,0x80);
write_1602com(yh + 0x0f);
break;
case 5: hour ++;
if(hour ==24)
hour = 0;
write_1602sfm(4,hour);
temp = (hour)/10*16 + (hour)%10;
write_ds1302(0x8e,0x00);
write_ds1302(0x84,temp);
write_ds1302(0x8e,0x80);
write_1602com(er + 5);
break;
case 6: min ++;
if(min == 60)
min = 0;
write_1602sfm(0x07,min);
temp = (min)/10*16 + (min)%10;
write_ds1302(0x8e,0x00);
write_ds1302(0x82,temp);
write_ds1302(0x8e,0x80);
write_1602com(er + 8);
break;
case 7: sec ++;
if(sec == 60)
sec = 0;
write_1602sfm(0x0a,sec); //写入新的秒数
temp = (sec)/10*16 + (sec)%10;
write_ds1302(0x8e,0x00);
write_ds1302(0x80,0x80|temp);
write_ds1302(0x8e,0x80);
write_1602com(er+0x0b); //因为设置液晶的模式是写入数据后,指针自动加一,在这里是写回原来的位置
break;
}
}
}
if(key3 == 0)
{
delay(5);
if(key3 == 0)
{
while( !key3);
delay(10);
while( !key3);
switch(key1n)
{
case 1: year --;
if(year ==-1)
year = 99;
write_1602nyr(4,year);
temp = (year)/10*16 + (year)%10;
write_ds1302(0x8e,0x00);
write_ds1302(0x8c,temp);
write_ds1302(0x8e,0x80);
write_1602com(yh + 5);
break;
case 2: mon --;
if(mon == 0)
mon = 12;
write_1602nyr(7,mon);
temp = (mon)/10*16 + (mon)%10;
write_ds1302(0x8e,0x00);
write_ds1302(0x88,temp);
write_ds1302(0x8e,0x80);
write_1602com(yh + 8);
break;
case 3: day --;
if(day == 0)
deal_3day();
day = 31;
write_1602nyr(10,day);
temp = (day)/10*16 + (day)%10;
write_ds1302(0x8e,0x00);
write_ds1302(0x86,temp);
write_ds1302(0x8e,0x80);
write_1602com(yh + 11);
break;
case 4: week --;
if(week ==0 )
week = 7;
write_1602week(week);
write_ds1302(0x8e,0x00);
write_ds1302(0x8a,week);
write_ds1302(0x8e,0x80);
write_1602com(yh + 0x0f);
break;
case 5: hour --;
if(hour == -1)
hour = 23;
write_1602sfm(4,hour);
temp = (hour)/10*16 + (hour)%10;
write_ds1302(0x8e,0x00);
write_ds1302(0x84,temp);
write_ds1302(0x8e,0x80);
write_1602com(er + 5);
break;
case 6: min --;
if(min == -1)
min = 59;
write_1602sfm(7,min);
temp = (min)/10*16 + (min)%10;
write_ds130
展开阅读全文