我们不仅销售产品,我们还传播知识
商品分类

51单片机电子时钟课程设计报告

     录

第一部分  设计任务和要求

  1. 单片机课程设计内容…………………………………………………2
    1.   单片机课程设计要求…………………………………………………2
    1.   系统运行流程…………………………………………………………2

第二部分  设计方案

2.1  总体设计方案说明……………………………………………………2

2.2  系统方框图……………………………………………………………3

2.3  系统流程图……………………………………………………………3

第三部分  主要器材及基本简介

3.1  主要器材………………………………………………………………4

3.2  主要器材简介…………………………………………………………4

第四部分  系统硬件设计

4.1  最小系统………………………………………………………………6

4.2  LCD显示电路…………………………………………………………6

4.3  键盘输入电路…………………………………………………………7

4.4  蜂鸣器和LED灯电路…………………………………………………7

第五部分  仿真电路图与仿真结果………………………………………………8

第六部分 课程设计总结…………………………………………………………8

第七部分  参考文献………………………………………………………………9

附录A   实物图

附录B   系统源程序

第一部分  设计任务和要求

1.1  单片机课程设计内容

利用STC89C51单片机和LCD1602电子显示屏实现电子时钟,可由按键进行调时和12/24小时切换。

1.2  单片机课程设计要求

1.能实现年、月、日、星期、时、分、秒的显示;

2.能实现调时功能;

3.能实现12/24小时制切换;

4.能实现8:00—22:00整点报时功能。

1.3  系统运行流程

程序首先进行初始化,在主程序的循环程序中首先调用数据处理程序,然后调用显示程序,在判断是否有按键按下。若有按键按下则转到相应的功能程序执行,没有按键按下则调用时间程序。若没到则循环执行。计时中断服务程序完成秒的计时及向分钟、小时的进位和星期、年、月、日的进位。调时闪烁中断服务程序用于被调单元的闪烁显示。调时程序用于调整分钟、小时、星期、日、月、年,主要由主函数组成通过对相关子程序的调用,如图所示。实现了对时间的设置和修改、LCD显示数值等主要功能。相关的调整是靠对功能键的判断来实现的。

第二部分  设计方案

2.1  总体设计方案说明

1.程序设计及调试

根据单片机课程设计内容和要求,完成Protues仿真电路的设计和用Keil软件编写程序,并进行仿真模拟调试。

2.硬件焊接及调试

根据仿真电路图完成电路板的焊接,并进行软、硬件的调试,只到达到预期目的。

3.后期处理

对设计过程进行总结,完成设计报告。

2.2  单片机系统方框图

主流程图                         键盘扫描流程图

时钟流程图

第三部分  主要器件及简介

1. STC89C51单片机;

2.LCD1602液晶显示屏;

3.2  主要器件简介

1.STC89C51单片机简介

STC89C51是采用8051核的ISP(In System Programming)在系统可编程芯片,最高工作时钟频率为80MHz,片内含8K Bytes的可反复擦写1000次的Flash只读程序存储器,器件兼容标准MCS-51指令系统及80C51引脚结构,芯片内集成了通用8位中央处理器和ISP Flash存储单元,具有在系统可编程(ISP)特性,配合PC端的控制程序即可将用户的程序代码下载进单片机内部,省去了购买通用编程器,而且速度更快。

2.LCD1602液晶显示屏简介

LCD1602可以显示2行16个字符,有8位数据总线D0—D7,和RS、R/W、EN三个控制端口,工作电压为5V,并且带有字符对比度调节和背光。

LCD1602引脚说明如下表所示:

                  LCD液晶显示器各引脚功能及结构

编号符号引脚说明编号符号引脚说明
1VSS电源地9D2双向数据口
2VDD电源正极10D3双向数据口
3VL对比度调节11D4双向数据口
4RS数据/命令选择12D5双向数据口
5R/W读写/选择13D6双向数据口
6E模块使能端14D7双向数据口
7D0双向数据口15BLK背光源地
8D1双向数据口16BLA背光源正极

VDD:电源正极,4.5V—5.5V,通常使用5V电压;

VL:LCD对比度调节端,电压调节范围为0—5V。接正极时对比度最弱,接地电源时对比度最高,但对比度过高会产生“鬼影”,因此通常使用一个10K的电位器来调整对比度,或者直接串接一个电阻到地;

RS:MCU写入数据或者指令选择端。MCU要写入指令时,使RS为低电平;MCU要写入数据时,使RS为高电平;

R/W:读写控制端。R/W为高电平时,读取数据;R/W为低电平时,写入数据;

EN:LCD模块使能信号控制端。写数据时,需要下降沿触发模块。

D0—D7:8为数据总线,三态双向。如果MCU的I/O口资源紧张的话,该模块也可以只使用4位数据线D4—D7接口传送数据。

A:LED背光正极。需要背光时, A串接一个限流电阻接VDD, K接地。

K:LED背光地端。

第四部分  系统硬件设计

4.1  最小系统

4.2  LCD显示电路

LCD显示屏的D0到D7与单片机P0口相连,LCD显示屏EN口与单片机P3.4口相连,RS与P3.5相连。通过滑动变阻器改变LCD显示屏的显示对比度。

4.3  键盘输入电路

本次设计采用独立键盘,键盘按下时,相应的I/O口电平由高变低,一次检测按键是否被按下。4个独立按键与单片机P3.0—P3.3口相连。

4.3  蜂鸣器和LED灯电路

蜂鸣器的作用为准点报时产生报警声,LED在秒钟为偶数时或者功能键被按下时亮。蜂鸣器与单片机P2.2口相连,LED灯与单片机P2.3口相连。

第五部分  仿真电路图与仿真结果

第六部分  课程设计总结

本次单片机课程设计,在我和我的搭档陈雅琴默契配合,以及邹老师的指导和同学的帮助下顺利完成了。在设计过程中,从仿真电路的设计,源程序的书写和修改以及实物电路的焊接中都遇到了不少问题,但在我们的共同努力下解决了,并且从中学到了不少知识。我们在设计过程中还不断提出自己的疑点以及新的想法,联系实际应用,将课本上学习的东西运用到实际中,这些都令我们受益匪浅。

课程设计需要很大的耐心,尤其是遇到困难的时候,这也是对我们的考验。在设计过程中,我们遇到问题不是感到急躁,而是耐心地寻找解决的办法,与老师、同学进行交流讨论,寻求最佳的解决办法。

总之,在此次的课程设计中,我们不仅动手、动脑,也学会了不少东西,同时,谢谢对我们的设计带来建议、意见和帮助的老师和同学们!谢谢!

第七部分  参考文献

《单片机原理及应用(第二版)》      高等教育出版社

《新概念51单片机C语言教程》      电子工业出版社

附录A  实物图

附录B  系统源程序

#include<reg51.h>

#define uchar unsigned char

#define uint unsigned int

sbit lcdrs=P3^5;  //定义1602液晶RS端

sbit lcden=P3^4;//定义1602液晶LCDEN端

sbit s1=P3^0;   //定义按键–功能键

sbit s2=P3^1; //定义按键–增加键

sbit s3=P3^2; //定义按键–减小键

sbit s4=P3^3; //定义按键–闹钟键

sbit beep=P2^2; //定义蜂鸣器端

sbit led=P2^3;  //定义LED灯端

uchar count,s1num,s4num;

char year,month,day,week,miao,shi,fen,pshi;

uchar code table[]=” 20  –  –   “;//定义初始上电时液晶默认显示状态

void delay(uint z)  //延时函数

{

uint x,y;

for(x=z;x>0;x–)

for(y=110;y>0;y–);

}

void zhuanhuan()

{

if(shi==0)

    pshi=12;

if(shi<=12&&shi>=1)

    pshi=shi;

    if(shi>12)

    pshi=shi-12;    

}        

void di()//蜂鸣器发声函数

{

beep=0;

delay(300);

beep=1;

delay(300);

}

void write_com(uchar com)//液晶写命令函数

{

lcdrs=0;

lcden=0;

P0=com;

delay(5);

lcden=1;

delay(5);

lcden=0;

}

void write_date(uchar date)//液晶写数据函数

{

lcdrs=1;

lcden=0;

P0=date;

delay(5);

lcden=1;

delay(5);

lcden=0;

}

void _shi() //写”AM”、”PM”函数

{

   if(shi>=12)

   {

 write_com(0x80+0x40+1);//写出”PM”

 write_date(‘P’);

 write_date(‘M’);

   }

   else

   {

 write_com(0x80+0x40+1);//写出”AM”

 write_date(‘A’);

 write_date(‘M’);

   }

}

void write_ymd(uchar add1,uchar date1)//写年月日函数

{

uchar shi,ge;

shi=date1/10;//分解一个2位数的十位和个位

ge=date1%10;

write_com(0x80+add1);//设置显示位置

write_date(0x30+shi);//送去液晶显示十位

write_date(0x30+ge); //送去液晶显示个位

}

void write_sfm(uchar add,uchar date)//写时分秒函数

{

uchar shi,ge;

shi=date/10;//分解一个2位数的十位和个位

ge=date%10;

write_com(0x80+0x40+add);//设置显示位置

write_date(0x30+shi);//送去液晶显示十位

write_date(0x30+ge); //送去液晶显示个位

}

void write_week(char week)    //写液晶星期显示函数

{

write_com(0x80+12);

switch(week)

{

case 1: write_date(‘M’);delay(5);

write_date(‘O’);delay(5);

write_date(‘N’);

break;

case 2: write_date(‘T’);delay(5);

write_date(‘U’);delay(5);

write_date(‘E’);

break;

case 3: write_date(‘W’);delay(5);

write_date(‘E’);delay(5);

write_date(‘D’);

break;

case 4: write_date(‘T’);delay(5);

write_date(‘H’);delay(5);

write_date(‘U’);

break;

case 5: write_date(‘F’);delay(5);

write_date(‘R’);delay(5);

write_date(‘I’);

break;

case 6: write_date(‘S’);delay(5);

write_date(‘A’);delay(5);

write_date(‘T’);

break;

case 7: write_date(‘S’);delay(5);

write_date(‘U’);delay(5);

write_date(‘N’);

break;

}

}

void writeym()

{

   day=1;

   month++;

   if(month==13)

   {

 month=1;

 year++;

 if(year==100)

    year=0;

 write_ymd(3,year);//年若变化则重新写入

}

write_ymd(6,month);//月若变化则重新写入

}

void init()//初始化函数

{

    uchar num;

lcden=0;

year=13;//初始化种变量值

month=6;

day=21;

week=5;

shi=13;

fen=59;

miao=58;

count=0;

s1num=0;

s4num=0;

write_com(0x38);//初始化1602液晶

write_com(0x0c);

write_com(0x06);

write_com(0x01);

write_com(0x80);//设置显示初始坐标

for(num=0;num<15;num++)//显示年月日星期

{

write_date(table[num]);

delay(5);

}

delay(5);

write_com(0x80+0x40+6);//写出时间显示部分的两个”:”

write_date(‘:’);

delay(5);

write_com(0x80+0x40+9);

write_date(‘:’);

delay(5);

write_week(week);

write_ymd(3,year);//分别送去液晶显示

write_ymd(6,month);

write_ymd(9,day);

write_sfm(10,miao);//分别送去液晶显示

write_sfm(7,fen);

write_sfm(4,shi);

TMOD=0x01;//设置定时器0工作模式1

TH0=(65536-50000)/256;//定时器装初值

TL0=(65536-50000)%256;

EA=1; //开总中断

ET0=1; //开定时器0中断

TR0=1; //启动定时器0

}

void keyscan()//按键扫描函数

{

if(s1==0)

{

delay(5);

if(s1==0)//确认功能键被按下

{

    s1num++;//功能键按下次数记录

while(!s1);//释放确认

if(s1num==1)//第一次被按下时

{

    TR0=0;  //关闭定时器

write_com(0x80+3);//光标定位到年位置

write_com(0x0f); //光标开始闪烁

}

if(s1num==2)//第二次按下光标闪烁定位到月位置

{

write_com(0x80+6);

}

if(s1num==3)//第三次按下光标闪烁定位到日位置

{

write_com(0x80+9);

}

if(s1num==4)//第四次按下光标闪烁定位到星期位置

{

write_com(0x80+12);

}

if(s1num==7)//第七次被按下时光标定位到秒位置

{

write_com(0x80+0x40+10);

}

if(s1num==6)//第六次按下光标闪烁定位到分位置

{

write_com(0x80+0x40+7);

}

if(s1num==5)//第五次按下光标闪烁定位到时位置

{

write_com(0x80+0x40+4);

}

if(s1num==8)//第七次按下

{

s1num=0;//记录按键数清零

write_com(0x0c);//取消光标闪烁

TR0=1; //启动定时器使时钟开始走

}

}

}

if(s1num!=0)//只有功能键被按下后,增加和减小键才有效

{

if(s2==0)

{

delay(5);

if(s2==0)//增加键确认被按下

{

while(!s2);//按键释放

if(s1num==1)//若功能键第一次按下

{

year++; //则调整年加1

if(year==100)//若满100后将清零

year=0;

write_ymd(3,year);//每调节一次送液晶显示一下

write_com(0x80+3);//显示位置重新回到调节处

}

if(s1num==2)//若功能键第二次按下

{

month++;//则调整月加1

if(month==13)//若满12后将置一

month=1;

write_ymd(6,month);//每调节一次送液晶显示一下

write_com(0x80+6);//显示位置重新回到调节处

}

if(s1num==3)//若功能键第三次按下

{

day++;//则调整日加1

if(year%4==0&&month==2)

{

    if(day==30)//若满29后将置一

day=1;

 }

 if(year%4!=0&&month==2)

{

    if(day==29)//若满28后将置一

day=1;

 }

 if(month!=2&&month!=4&&month!=6&&month!=9&&month!=11)

 {

    if(day==32)//若满31后将置一

day=1;

 }

 if(month==4||month==6||month==9||month==11)

 {  

if(day==31)//若满30后将置一

day=1;

 }

write_ymd(9,day);;//每调节一次送液晶显示一下

write_com(0x80+9);//显示位置重新回到调节处

}

if(s1num==4)//若功能键第四次按下

{

week++;//则调整星期加1

if(week==8)//若满8后将置一

week=1;

write_week(week);//每调节一次送液晶显示一下

write_com(0x80+12);//显示位置重新回到调节处

}

if(s1num==7)//若功能键第七次按下

{

miao++; //则调整秒加1

if(miao==60)//若满60后将清零

miao=0;

write_sfm(10,miao);//每调节一次送液晶显示一下

write_com(0x80+0x40+10);//显示位置重新回到调节处

}

if(s1num==6)//若功能键第二次按下

{

fen++;//则调整分钟加1

if(fen==60)//若满60后将清零

fen=0;

write_sfm(7,fen);//每调节一次送液晶显示一下

write_com(0x80+0x40+7);//显示位置重新回到调节处

}

if(s1num==5)//若功能键第五次按下

{

shi++;

if(shi==24)//若满24后将清零

            {

   shi=0;

}

   if(s4num==0)

   {         

      write_sfm(4,shi);;//每调节一次送液晶显示一下

      write_com(0x80+0x40+4);//显示位置重新回到调节处

   }    

   if(s4num==1)

   {

      zhuanhuan();

      _shi();

      write_sfm(4,pshi);;//每调节一次送液晶显示一下

      write_com(0x80+0x40+4);//显示位置重新回到调节处

       }

       }

}

}

}

if(s3==0)

{

delay(5);

if(s3==0)//确认减小键被按下

{

while(!s3);//按键释放

if(s1num==1)//若功能键第一次按下

{

year–;//则调整秒减1

if(year==-1)//若减到负数则将其重新设置为99

year=99;

write_ymd(3,year);//每调节一次送液晶显示一下

write_com(0x80+3);//显示位置重新回到调节处

}

if(s1num==2)//若功能键第二次按下

{

month–;//则调整分钟减1

if(month==0)//若减到负数则将其重新设置为59

month=12;

write_ymd(6,month);//每调节一次送液晶显示一下

write_com(0x80+6);//显示位置重新回到调节处

}

if(s1num==3)//若功能键第二次按下

{

day–;//则调整日加1

if(year%4==0&&month==2)

{

    if(day==0)//若满29后将置一

day=29;

 }

 if(year%4!=0&&month==2)

{

    if(day==0)//若满28后将置一

day=28;

 }

 if(month!=2&&month!=4&&month!=6&&month!=9&&month!=11)

 {

    if(day==0)//若满31后将置一

day=31;

 }

 if(month==4||month==6||month==9||month==11)

 {  

if(day==0)//若满30后将置一

day=30;

 }

write_ymd(9,day);;//每调节一次送液晶显示一下

write_com(0x80+9);//显示位置重新回到调节处

}

if(s1num==4)//若功能键第二次按下

{

week–;//则调整小时减1

if(week==0)//若减到负数则将其重新设置为23

week=7;

write_week(week);//每调节一次送液晶显示一下

write_com(0x80+12);//显示位置重新回到调节处

}

if(s1num==7)//若功能键第一次按下

{

miao–;//则调整秒减1

if(miao==-1)//若减到负数则将其重新设置为59

miao=59;

write_sfm(10,miao);//每调节一次送液晶显示一下

write_com(0x80+0x40+10);//显示位置重新回到调节处

}

if(s1num==6)//若功能键第二次按下

{

fen–;//则调整分钟减1

if(fen==-1)//若减到负数则将其重新设置为59

fen=59;

write_sfm(7,fen);//每调节一次送液晶显示一下

write_com(0x80+0x40+7);//显示位置重新回到调节处

}

if(s1num==5)//若功能键第二次按下

{

shi–;

if(shi==-1)//若满24后将清零

   shi=23;

   if(s4num==0)

   {      

      write_sfm(4,shi);;//每调节一次送液晶显示一下

      write_com(0x80+0x40+4);//显示位置重新回到调节处       

   }

   if(s4num==1)

   {    

                      zhuanhuan();

      _shi();

      write_sfm(4,pshi);;//每调节一次送液晶显示一下

      write_com(0x80+0x40+4);//显示位置重新回到调节处

       }

     }

}

}

if(s1num==0)

{

  if(s4==0)

  {

delay(5);

if(s4==0)//确认功能键被按下

{

    s4num++;//功能键按下次数记录

while(!s4);//释放确认

if(s4num==1)//第一次被按下时

{

    zhuanhuan();

_shi();

write_sfm(4,pshi);

}

if(s4num==2)//第二次按下

{

s4num=0;//记录按键数清零

write_com(0x80+0x40+1);

write_date(‘ ‘);

write_date(‘ ‘);

write_sfm(4,shi);

}

}

      }

}    

}

void main()//主函数

{

init();//首先初始化各数据

while(1)//进入主程序大循环

{

keyscan();//不停的检测按键是否被按下

if(s1num!=0)

   led=0;

else    

   led=miao%2;

if((shi>7&&shi<23)&&(fen==0)&&(miao==0))

{

 di();  

 }

}

}

void timer0() interrupt 1//定时器0中断服务程序

{

TH0=(65536-50000)/256;//再次装定时器初值

TL0=(65536-50000)%256;

count++; //中断次数累加

if(count==20) //20次50毫秒为1秒

{

count=0;

miao++;

if(miao==60)//秒加到60则进位分钟

{

miao=0;//同时秒数清零

fen++;

if(fen==60)//分钟加到60则进位小时

{

fen=0;//同时分钟数清零

shi++;

if(shi==24)//小时加到24则小时清零

{

shi=0;

week++;

   if(week==8)

   {

       week=1;

   }

   write_week(week);//星期若变化则重新写入

day++;

   if(year%4==0&&month==2)//判断是否为闰年的2月

   {

      if(day==30)

  {

     writeym();    

  }

  write_ymd(9,day);//日若变化则重新写入

   }

   if(year%4!=0&&month==2)//判断是否为平年的2月

   {

      if(day==29)

  {

     writeym();    

  }

  write_ymd(9,day);//日若变化则重新写入

   }

   if(month!=2&&month!=4&&month!=6&&month!=9&&month!=11)

   {

      if(day==32)

  {

     writeym();    

  }

  write_ymd(9,day);//日若变化则重新写入

   }

   if(month==4||month==6||month==9||month==11)

   {

      if(day==31)

  {

     writeym();    

  }

  write_ymd(9,day);//日若变化则重新写入

   }

}

if(s4num==1)

  {

     zhuanhuan();

 _shi();  

     write_sfm(4,pshi);//12小时制小时若变化则重新写入

  }

else write_sfm(4,shi);//24小时制小时若变化则重新写入

}

write_sfm(7,fen);//分钟若变化则重新写入

}

write_sfm(10,miao);//秒若变化则重新写入

}

}

发表回复

登录后才能评论
微信群
微信群
联系我们

联系我们

微信:13823392571

在线咨询:点击这里给我发消息

工作时间:周一至周五,9:30-18:30,节假日休息

微信客服
微信客服
分享本页
返回顶部