找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 12008|回复: 0
打印 上一主题 下一主题
收起左侧

单片机时钟程序实验报告

[复制链接]
跳转到指定楼层
楼主
ID:143490 发表于 2016-10-19 21:45 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式










单片机原理与应用


课程名称:    单片机原理与应用               
设计题目:    LCD电子钟                 
院    系:    电子信息工程学院                             
班    级:    自动化0706                    
设 计 者:    全宏宇                     
指导教师:                                 




一,设计目标
LCD显示电子钟的基本功能
1,实现时钟功能;
2,实现闹铃功能;
3,实现秒表功能;
4,具有一定的计时精度。
LCD显示电子钟的基本要求
1,掌握单片机开发编程设计的基本流程;
2,了解Keil及Proteus软件的基本使用;
3,了解LCD的基本使用;
4,学习单片机硬件制作。

二,具体实现
1,软件平台
1)Keil编程
Keil 的开发工具的使用的基本过程:
○1创建 C 或汇编语言的源程序;
○2编译或汇编源文件;
○3纠正源文件中的错误;
○4从编译器和汇编器连接目标文件;
○5测试连接的应用程序。
2)Proteus仿真
  Proteus软件不仅具有其它EDA工具软件的仿真功能,还能仿真单片机及外围器件。它是目前最好的仿真单片机及外围器件的工具。在编译方面,它也支持IAR,Keil,PLAB等多种编译器。

2,硬件开发平台
JD51开发板的基本资料
○1 LED 电路,8 只独立LED 发光管,可做指示或各种闪烁效果用。
○2 数码管电路,4只共阳一体8 段数码显示管,可实现各种数据显示,如计数、时钟等。
○3蜂鸣器电路,可用于设计各种提示音、演奏音乐等。
○4键盘电路,学习按键控制相关编程。
○5 LCD 显示电路,编程控制LCD 显示。
○6串口电路,学习编程实现JD51 和PC 或其他符合该通信协议的电路之间的通信。
○7红外电路,通过选配的红外遥控器,学习红外解码并可实现红外遥控JD51。
○8 温度模块电路,采用一线式温度传感器实现温度的采集并可显示在数码管或者LCD 上,通过温度数据处理便可实现温度控制器功能。
○9除了以上提到的可编程电路本学习板还有一些常用的不可编程电路,包括电源电路、复位电路、晶振电路等。

    本次LCD电子钟实验用到其中的蜂鸣器,按键,LCD显示接口。
3,总体设计
1)        基本资源的使用
本次实验采用了89C52型单片机,1602LCD液晶显示屏,蜂鸣器。为了实现时钟,定时,闹钟,秒表的功能,用到了单片机的外部中断,计时器中断,及
I/O端口.
资源        功能
外部中断        外部中断INT1            模式选择(时钟,调时,秒表,闹钟)
        外部中断INT0            秒表的暂停,清零
定时器        定时器T0            秒表,时钟定时基准
        定时器T1            音乐闹铃的音符产生
I/O端口        P1,P2            LCD接口,蜂鸣器

2)软件仿真
(1)程序设计的一些关键问题(具体参照后面的程序清单)
 ○1建立Keil工程时,注意对程序编译环境进行设置;
 设置内容包括器件,频率,产生hex文件等。

  ○2LCD管脚及控制字;
LCD管脚的定义


 控制字

1602液晶模块的读写操作,屏幕和光标的操作都是通过指令编程来实现的。
指令1:清显示,指令码01H,光标复位到地址00H位置
指令2:光标复位,光标返回到地址00H
指令3:光标和显示位置设置I/D,光标移动方向,高电平右移,低电平左移,S:屏幕上所有文字是否左移或右移,高电平表示有效,低电平表示无效。
指令4:显示开关控制。D:控制整体的显示开与关,高电平表示开显示,低电平表示关显示。C:控制光标的开与关,高电平表示有光标,低电平表示无光标 B:控制光标是否闪烁,高电平闪烁,低电平不闪烁。
指令5:光标或显示移位 S/C :高电平时显示移动的文字,低电平时移动光标
指令6:功能设置命令 DL:高电平时为4位总线,低电平时为8位总线 N:低电平时为单行显示,高电平时为双行显示,F:低电平时显示5X7的点阵字符,高电平时显示5X10的显示字符。
指令7:字符发生器RAM地址设置。
指令8:DDRAM地址设置。
指令9:读忙信号和光标地址 BF:忙标志位,高电平表示忙,此时模块不能接收命令或数据,如果为低电平表示不忙。
  ○3LCD实现滚动显示;
 方法一:采用LCD1602控制命令,显示后画面移动一个字符;
 方法二:循环使用显示不同位置,形成滚动效果。
○5秒表
主要是产生计时基准0.01秒,有了基准之后需要解决的问题是如何实现有效的暂停,清零(达到精准动作),采用中断是很不错的结果。
 ○6闹铃
 主要是如何实现闹铃关闭的逻辑,if(f&&g)语句可以实现这一动作。
 ○7提高计时精度
  本程序除了调时模式外,其他模式的时候时钟都在跑动,提高了因模式转换而导致的时间精度降低。
(2)Proteus仿真
在Proteus中画出如下电路图,添加hex文件,进行虚拟仿真。

2)        开发板运行调试
  在JD51板上烧制程序,根据实际的效果,对中断的反应时间,显示效果做出了调整,整体效果不错,只是音乐的效果不佳,主要是由于如果将蜂鸣器换成扬声器效果会好些,还可以在程序中增加节拍来增加音乐效果。
4,硬件制作
根据仿真电路图购买元件进行焊接,下载程序效果后,液晶显示器显示乱码,检查电路后已无连接错误,但功能依然没有实现,相关检查在进行中。

三,设计体会
 本次课程设计系统地学习了单片编程开发及实际电路的制作。学习了Keil的C语言编程的基本知识,Proteus仿真软件的模拟仿真,JD51开发实验板的使用,本次课设,时间了较多的其他案例,比较全面的掌握了单片机的运营,包括编程,电路,LCD器件等,在知识上有了很多的长进。
 本次课程设计还有很多其他收获,锻炼了自学的能力,特别是动手实践方面的东西,让我深深感受到理论与实际的差距,实际当中会有一些小的问题,这些问题是意想不到的,需要去思考,去解决,这是很锻炼人的。







四,程序
#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define ulong unsigned long
#define uint  unsigned int
uchar idata     welcome[16]={"    clock       "};                //定义第一行显示数组
uchar idata   lwelcome[16]={"      clock     "};                //定义第一行显示数组
uchar idata   llwelcome[16]={"        clock   "};                //定义第一行显示数组
uchar idata  lllwelcome[16]={"          clock "};                //定义第一行显示数组

uchar  idata  sslcdtimer[16]={"    00:00:00    "};
uchar  idata tsslcdtimer[16]={"    00:00:00    "};
uchar  idata   lcdtimer[16]={"    00:00:00    "};                //定义第二行显示数组
uchar  idata  mlcdtimer[16]={"    00:  :      "};                //定义第二行显示数组
uchar  idata   hlcdtimer[16]={"      :00:      "};                //定义第二行显示数组
uchar  idata  setlcdtimer[16]={"    00:01:00    "};
uchar timecount;
uchar temps;

bit timeflag;
bit sstimeflag;
sbit ring=P2^0;//蜂鸣闹铃

sbit e=P2^7;//LCD显示器E                               
sbit rw=P2^6;//LCD显示器RW
sbit rs=P2^5;//LCD显示器RS
sbit P10=P1^0; //测试用闪灯

sbit Key=P3^2;//秒表暂停,清零
sbit Key0=P3^3;//调时,设定闹钟时间,秒表选择
sbit Key1=P3^4;//调时,设定闹钟时间改变


uchar th1_f; //在中断中装载的T0的值高8位
uchar tl1_f; //在中断中装载的T0的值低8位
uint m=0;
uint n=0;
ulong i;
uint f=0,g=1;  
uint j,k;
uchar code freq[3][14]=
{
{0xF2,0x42,
0xF3,0xC1,
0xF5,0x17,
0xF5,0xB6,
0xF6,0xD0,
0xF7,0xD1,
0xF8,0xB6},
{0xF9,0x21,
0xF9,0xE0,
0xFA,0x8B,
0xFA,0xD7,
0xFB,0x68,
0xFB,0xE8,
0xFC,0x5B },
{0xFC,0x8D,
0xFC,0xEE,
0xFD,0x44,
0xFD,0x6D,
0xFD,0xB4,
0xFD,0xF4,
0xFE,0x2D},
};         //音乐频率表,低音,中音,高音,系统振荡频率11.0592MHz

uint code song1[]={26,25,23,25,31,26,25,26,23,25,26,25,23,22,21,16,25,23,22,22,23,23,23,26,23,22,21,25,23,22,21,16,21,15,26,25,23,25,31,26,25,26,23,25,26,25,23,22,21,16,25,23,22,22,23,23,23,26,23,22,21,25,23,22,21,16,21,15};
//编制音乐


//**************************************************
//软件延时函数(系统晶振为11.0592MHz),延时时间约为40μs
//入口条件:无符号整型变量del1,最终的延时时间为(del1*40)μs
//**************************************************
void delay(uint del1)
{
        uchar del2;
        for(;del1>0;del1--)
                for(del2=10;del2>0;del2--);
}
//**************************************************
//液晶显示器判忙函数
//**************************************************
void busy()
{
        uchar temp;
        temp=0x00;
        rs=0;
        rw=1;
        while((temp&0x80)==0x80)
        {
                P0=0xff;
                e=1;
                temp=P0;
                e=0;
        }
}
//**************************************************
//向液晶显示器写命令函数
//**************************************************
void WR_Com(uchar temp)
{
        busy();
        rs=0;
        rw=0;
        P0=temp;
        e=1;
        e=0;
}
//**************************************************
//向液晶显示器写数据函数
//**************************************************
void WR_Data(uchar num)
{
        busy();
        rs=1;
        rw=0;
        P0=num;
        e=1;
        e=0;
}
//**************************************************
//向液晶显示器写入显示数据函数
//入口条件:液晶显示器行首地址(指示第一行还是第二行)和待显示数组的首地址
//**************************************************
//void disp_lcdchar(uchar addr,uchar temp1)
//{
//    WR_Com(addr);
//        delay(100);
//        WR_Data(temp1);
//}
       

void disp_lcd(uchar addr,uchar *temp1)
{
        uchar i;
        WR_Com(addr);
        delay(100);
        for(i=0;i<16;i++)
        {
                WR_Data(temp1[i]);
                delay(100);
        }
}       
//**************************************************
//液晶显示器初始化函数
//**************************************************
void lcd_ini()
{
        char i;
        for(i=3;i>0;i--)
        {
                P0=0x30;
                rs=0;
                rw=0;
                e=1;
                e=0;
                delay(100);
        }
        P0=0x38;
        rs=0;
        rw=0;
        e=1;
        e=0;
        delay(100);
}
//**************************************************
//液晶显示器复位函数
//**************************************************
void lcd_Reset()
{
        WR_Com(0x01);
        delay(100);
        WR_Com(0x06);
        delay(100);
        WR_Com(0x0c);
        delay(100);
}

//**************************************************
//外部中断函数,秒表暂停,清零
//**************************************************
void modess() interrupt 0 using 0  
{       
    delay(10000);                                                                                                       
        n++;
        if(n==3)
        n=0;
}

//**************************************************
//外部中断函数,模式选择
//**************************************************
void modepp() interrupt 2  using 1
{                                                                                                               
        delay(30000);
        m++;
        if(m==6)
        n=0;
        if(m==7)
        m=0;
}


//**************************************************
//定时/计数器中断函数,1S及0.01S
//**************************************************
void timer0() interrupt 1  using 2
{
        TH0=0xdc;
        TL0=0x23;
        sstimeflag=1;
        if(--timecount==0)
        {
                timecount=100;
                timeflag=1;
        }
}
//**************************************************
//定时/计数器中断函数,装入音乐频率计数初值
//**************************************************
void timer1() interrupt 3  using 3
{
  TL1=tl1_f;TH0=th1_f; //调入预定时值
  ring=!ring; //取反音乐输出IO
}                        

                                                                                                                                                                                                                  
//**************************************************
//主函数
//**************************************************
void main()
{
    P10=1;
        lcd_ini();
        lcd_Reset();
/*        for(i=0;i<10;i++)
        {                                                                                        
          temps=welcome[i];
          disp_lcdchar(0x80+1,temps); //LCD 单字符从左到右显示
          delay(10000);
         }*/
        disp_lcd(0x80,welcome);
    delay(10000);
        disp_lcd(0x80,lwelcome);
    delay(10000);
        disp_lcd(0x80,llwelcome);
    delay(10000);
        disp_lcd(0x80,lllwelcome);
        delay(10000);
        disp_lcd(0x80,llwelcome);
        delay(10000);
        disp_lcd(0x80,lwelcome);
        delay(10000);
        disp_lcd(0x80,welcome);        //LCD滚动显示
        delay(10000);
        disp_lcd(0xc0,lcdtimer);
        P10=0;
        TMOD=0x11;
        TH0=0xdc;
        TL0=0x23;
        TR0=1;
    IE=0x86;
        timeflag=0;         //1秒计时标志
        sstimeflag=0; //0.01秒计时标志
        timecount=100;
        while(1)
        {
         while(m==6)//秒表
         {
            IE=0x87;
            if(n==0) //秒表跑动
                {
             if(sstimeflag==1)
             {
              sstimeflag=0;
              sslcdtimer[11]+=1;
                  if(sslcdtimer[11]>=0x3a)
                  {
                     sslcdtimer[11]=0x30;
                            sslcdtimer[10]+=1;
                          if(sslcdtimer[10]>=0x3a)
                          {
                           sslcdtimer[10]=0x30;
                           sslcdtimer[8]+=1;
                             if(sslcdtimer[8]>=0x3a)
                             {
                               sslcdtimer[8]=0x30;
                                   sslcdtimer[7]+=1;
                                   if(sslcdtimer[7]>=0x36)
                                      {
                                          sslcdtimer[7]=0x30;
                                          }
                          }
               }
            }
                         disp_lcd(0xc0,sslcdtimer);
          }
                  if(n==1)//秒表暂停
                  {
                   disp_lcd(0xc0,sslcdtimer);
                  }

                  if(n>=2)//秒表清零
                 {
                   disp_lcd(0xc0,tsslcdtimer);
                   for(i=0;i<16;i++)
                   sslcdtimer[i]=tsslcdtimer[i];
                 }
          }
   }
            while(m==0||m>=3) //时钟程序,只要不是调时,就一直运行
           {
              IE=0x86;
                    if(timeflag==1)
                  {
                        timeflag=0;
                        lcdtimer[11]+=1;
                        if(lcdtimer[11]>=0x3a)
                        {
                                lcdtimer[11]=0x30;
                                lcdtimer[10]+=1;
                                if(lcdtimer[10]>=0x36)
                                {
                                        lcdtimer[10]=0x30;
                                        lcdtimer[8]+=1;
                                        if(lcdtimer[8]>=0x3a)
                                        {
                                                lcdtimer[8]=0x30;
                                                lcdtimer[7]+=1;
                                                  if(lcdtimer[7]>=0x36)
                                                {
                                                        lcdtimer[7]=0x30;
                                                        lcdtimer[5]+=1;
                                                   if(lcdtimer[5]>=0x3a)
                                                      {
                                                       lcdtimer[5]=0x30;
                                                           lcdtimer[4]+=1;
                                                            if(lcdtimer[4]>=0x33&&lcdtimer[5]>=0x35)
                                                        {
                                                         lcdtimer[5]=0x30;
                                                         lcdtimer[4]=0x30;
                                }
                                                }
                                                  }
                                        }
                                }
                    }
           }
                                           if(m==0)
                                    {
                                                     disp_lcd(0xc0,lcdtimer);
                                                                          if(!Key1)//关掉闹钟
                                                                          {
                                                                            g=0;
                                                                                }
                                                                          if(lcdtimer[8]==setlcdtimer[8]&&lcdtimer[7]==setlcdtimer[7]&&lcdtimer[5]==setlcdtimer[5]&&lcdtimer[4]==setlcdtimer[4])
                                                                                     f=1;  //开启闹钟 ,播放音乐
                                                  if(f&&g)
                                                {
                                                            /*ring=1;
                                                            delay(10000);         
                                                                                            ring=0;
                                                                                             f=0; */
                                                        IE=0x8e;
                                                                                            j=song1[i]/10-1;
                                                    k=2*(song1[i]%10-1);
                                                th1_f=freq[j][k]; //取出对应的定时值送给T0
                                                tl1_f=freq[j][++k];
                                                TR1=1;
                                                                                                for(n=0;n<50000;n++); //音符间延时
                                                                                            i++;
                                                                                                TR1=0;
                                                                                                f=0;
                                                }
                                       }
        }
      while(m==1)          //调时分
        {
           if(!Key1)
           {
               delay(10000);
               timeflag=0;
               lcdtimer[8]+=1;
                          if(lcdtimer[8]>=0x3a)
                        {
                                lcdtimer[8]=0x30;
                                lcdtimer[7]+=1;
                                if(lcdtimer[7]>=0x36)
                                {
                                  lcdtimer[7]=0x30;
                                }
                        }
           }
                   disp_lcd(0xc0,lcdtimer);
                delay(8000);
                mlcdtimer[11]=lcdtimer[11];
                mlcdtimer[10]=lcdtimer[10];
                mlcdtimer[5]=lcdtimer[5];
                mlcdtimer[4]=lcdtimer[4];
                disp_lcd(0xc0,mlcdtimer);
    }

          while(m==2)  //调时时
         {
           if(!Key1)
           {
              delay(10000);
                  lcdtimer[5]+=1;
                   if(lcdtimer[5]>=0x3a)
                        {
                                lcdtimer[5]=0x30;
                                lcdtimer[4]+=1;       
                        }
                  if(lcdtimer[4]==0x32&&lcdtimer[5]>=0x34)
                           {
                                   lcdtimer[5]=0x30;
                                   lcdtimer[4]=0x30;                         
                           }
       }
                disp_lcd(0xc0,lcdtimer);
                delay(8000);
            hlcdtimer[11]=lcdtimer[11];
                hlcdtimer[10]=lcdtimer[10];
                hlcdtimer[8]=lcdtimer[8];
                hlcdtimer[7]=lcdtimer[7];
                disp_lcd(0xc0,hlcdtimer);
      }
                 while(m==3)//显示闹铃时间
         {
           if(!Key1)
           {
              delay(10000);                 
       }
            disp_lcd(0xc0,setlcdtimer);
      }
                      while(m==4) //调闹铃分
        {
           if(!Key1)   
           {
               delay(10000);
               setlcdtimer[8]+=1;
                          if(setlcdtimer[8]>=0x3a)
                        {
                                setlcdtimer[8]=0x30;
                                setlcdtimer[7]+=1;
                                if(setlcdtimer[7]>=0x36)
                                {
                                  setlcdtimer[7]=0x30;
                                }
                        }
           }
                   disp_lcd(0xc0,setlcdtimer);
                delay(8000);
                mlcdtimer[11]=setlcdtimer[11];
                mlcdtimer[10]=setlcdtimer[10];
                mlcdtimer[5]=setlcdtimer[5];
                mlcdtimer[4]=setlcdtimer[4];
                disp_lcd(0xc0,mlcdtimer);
    }
          while(m==5)//调闹铃时
         {
           if(!Key1)
           {
              delay(10000);
                  setlcdtimer[5]+=1;
                   if(setlcdtimer[5]>=0x3a)
                        {
                                setlcdtimer[5]=0x30;
                                setlcdtimer[4]+=1;       
                        }
                  if(setlcdtimer[4]==0x32&&setlcdtimer[5]>=0x34)
                           {
                                   setlcdtimer[5]=0x30;
                                   setlcdtimer[4]=0x30;                         
                           }
       }
                disp_lcd(0xc0,setlcdtimer);
                delay(8000);
            hlcdtimer[11]=setlcdtimer[11];
                hlcdtimer[10]=setlcdtimer[10];
                hlcdtimer[8]=setlcdtimer[8];
                hlcdtimer[7]=setlcdtimer[7];
                disp_lcd(0xc0,hlcdtimer);
      }
  }
}       


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表