实验7 利用51单片机的定时器设计一个时钟

1.利用实验板和配件,设计一个时钟,时间显示在LCD1602上,并按秒更新,能够在实验板上设计3个按键调整时,分,秒。其功能为:功能选择键,数值增大和数值减小键。利用板上AT24C02设计实现断电保护显示数据的功能。

=============Clock.h=============

#ifndef __CLOCK_H__

#define __CLOCK_H__

 

 

//========全局变量区============================================

unsignedchar T_High_50ms=(65536-45872)/256;

unsignedint T_Low_50ms=(65536-45872)%256;

unsignedchar Count,Count_T1,Count_1s;//Count用来记录每50ms的计数,Count_T1用来记

 

//========全局变量区结束============================================

#endif

 

=============I2C.H=============

#ifndef __I2C_H__

#define __I2C_H__

#include<reg51.h>

sbit sda=P2^0;                        

sbit scl=P2^1;

//========函数区============================================

void nop();

void initI2C();

externvoid I2C_start();  //开始信号

externvoid I2C_stop();   //停止

externvoid I2C_respons();  //应答

externvoid I2C_write_byte(unsignedchar date);

externunsignedchar I2C_read_byte();

externvoid I2C_write_address(unsignedchar address,unsignedchar date);

externunsignedchar I2C_read_address(unsignedchar address);

//========函数区结束============================================

#endif

 

=============OrphanKey.h=============

#ifndef __ORPHANKEY_H__

#define __ORPHANKEY_H__

 

sbit FUNCTION_KEY=P3^2;//功能键 --按下暂停,再按开始

sbit Key_ADD=P3^3;//1

sbit KEY_MINUS=P3^4;//1

const bit PRESSED=0;//按下

bit SUSPEND=0;//0的时候运行,1的时候暂停

 

#endif

 

=============I2C.C=============

#include "head/I2C.h"

//=========全局变量区============================================

 

#define uchar unsigned char

#define uint unsigned int

 

  bit I2C_write=0;           //24C02的标志;

 

 unsignedchar sec,tcnt;

 

//=========全局变量区结束============================================

void nop()

{;;}

 

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

    I2C的初始化

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

void initI2C(){

    sda=1;

    nop();

    scl=1;

    nop();

 

}

void I2C_start()  //开始信号

{  

    sda=1;

    nop();

    scl=1;

    nop();

    sda=0;

    nop();

}

void I2C_stop()   //停止

{

    sda=0;

    nop();

    scl=1;

    nop();

    sda=1;

    nop();

}

void I2C_respons()  //应答

{

    uchar i;

    scl=1;

    nop();

    while((sda==1)&&(i<250))i++;

    scl=0;

    nop();

}

 

void I2C_write_byte(uchar date)

{

    uchar i,temp;

    temp=date;

    for(i=0;i<8;i++)

    {

       temp=temp<<1;

       scl=0;

        nop();

       sda=CY;

       nop();

       scl=1;

       nop();

    }

    scl=0;

    nop();

    sda=1;

    nop();

}

uchar I2C_read_byte()

{

    uchar i,k;

    scl=0;

    nop();

    sda=1;

    nop();

    for(i=0;i<8;i++)

    {

       scl=1;

       nop();

       k=(k<<1)|sda;

       scl=0;

       nop();

    }

    return k;

}

void I2C_write_address(uchar address,uchar date)

{

    I2C_start();

    I2C_write_byte(0xa0);

    I2C_respons();

    I2C_write_byte(address);

    I2C_respons();

    I2C_write_byte(date);

    I2C_respons();

    I2C_stop();

}

uchar I2C_read_address(uchar address)

{

    uchar date;

    I2C_start();

    I2C_write_byte(0xa0);

    I2C_respons();

    I2C_write_byte(address);

    I2C_respons();

    I2C_start();

    I2C_write_byte(0xa1);

    I2C_respons();

    date=I2C_read_byte();

    I2C_stop();

    return date;

}

 

=============lab8_1.c=================

#include<reg51.h>

#include "head/Clock.h"

#include "head/OrphanKey.h"

#include "head/I2C.H"

/*

1.利用实验板和配件,设计一个时钟,时间显示在LCD1602上,并按秒更新,能够在实验板上设计3个按键调整时,分,秒。其功能为:功能选择键,数值增大和数值减小键。利用板上AT24C02设计实现断电保护显示数据的功能。

*/

 

/*

步骤:

1、设计一个中断,用来计时

2、设计一个字符生成函数,用来生成所需的时间

3、独立按键监测功能,用来监测按下了什么键

4、一个外部中断

5、一个断点保护的功能,其实就是通过I2C写入,读取数值

*/

 

//=========全局变量区============================================

#define uchar unsigned char

#define uint unsigned int

uchar code table[]="12:23:12";

uchar code table1[]="I am a boy!";

sbit lcden=P2^7;  //液晶使能端

sbit lcdrs=P2^6;  //数据或命令控制(0代表命令,1代表数据)  

sbit LCDWR=P2^5;  //读写控制(0代表写,1代表读)

uchar num;

uchar FIRST_LINE=0x80;

uchar SECOND_LINE=0xc0;

uchar Current_Time[9];

uchar Hour,Minute,Second=0;//时、分、秒

sbit beer = P1 ^4;      //蜂鸣器

// sbit led1=P1^3;

 

//=========全局变量区结束============================================

 

 

//=========函数区============================================

 

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

    延时函数

    参数说明:

    z代表要延时z ms

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

void delay(uint z)

{

    uint x,y;

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

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

}

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

    写命令或数据

    参数说明:

    isRs=1代表写数据,isRs=0代表写命令

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

void write(uchar mdata, uchar isRs)

{

    lcdrs=isRs;

    P0=mdata;

    delay(5);

    lcden=1;

    delay(5);

    lcden=0;

}

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

    写命令

    参数说明:

    data代表要写的命令

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

void write_command(uchar com)

{

    write(com,0);

}

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

    写数据

    参数说明:

    data代表要写的数据

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

void write_data(uchar mdata)

{

    write(mdata,1);

}

 

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

    初始化时钟

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

void InitTime(){

    //

    Current_Time[0]=Hour/10+'0';

    Current_Time[1]=Hour%10+'0';

    Current_Time[2]=':';

    Current_Time[3]=Minute/10+'0';

    Current_Time[4]=Minute%10+'0';

    Current_Time[5]=':';

    Current_Time[6]=Second/10+'0';

    Current_Time[7]=Second%10+'0';

    Current_Time[8]='\0';

}

 

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

    保存时钟的值

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

void KeepClockValue(){

    I2C_write_address(2,Second); 

    delay(10); 

    I2C_write_address(3,Minute);     

    delay(10);

    I2C_write_address(4,Hour);   

}

 

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

    改变时间

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

void changeTime()

{

    //

    if(Second>=60){

       Second=0;

       Minute++;

    }else{

       ++Second;

    }

 

    if(Minute==60){

       Hour++;

       Minute=0;

    }

    if(Hour==24){

       Second=0;

       Minute=0;

       Hour=0;

    }

    KeepClockValue();

}

/**

    初始化

**/

void InitClockInterrupt(){//初始化中断

 

    TMOD=0x11;        // TMOD赋值,以确定T0T1的工作方式。

    TH0=T_High_50ms;// 计算初值,并将其写入TH0TL0TH1TL1

    TL0=T_Low_50ms;

    EA =1;//开启中断总允许

    ET0 =1;  

    IT0 =1;   //开启定时器0,1中断允许

    TR0=1;     // 使TR0TR1置位,启动定时/计数器定时或计数

    Count=Count_T1=Count_1s=0;//计数

}

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

    初始化按钮中断

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

void initButtonInterupt(){

    IT0 =0;

    //EA = 1;     //开启中断总允许

    EX0 =1;   //外部中断0允许位

}

 

 

void init()

{

 

    InitTime();

    lcden=0;

    LCDWR=0;

    write_command(0x38);//设置16X2显示,5X7点阵,8位数据接口

    write_command(0x0c);//设置开显示,不显示光标

    write_command(0x06);//写一个字符后地址指针加1

    write_command(0x01);//显示清零,数据指针清零

}

void WriteStringToLCD(uchar *dat)

{

    while(*dat!='\0')

    {  

       write_data(*dat);

       dat++;

       delay(5);

    }

}

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

    LCD整体左移动

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

void LCD_MoveToLeft(){

    int num;

    for(num=0;num<16;num++)

    {

           write_command(0x18);

           delay(200);

    }

}

 

 

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

    LCD打印字符串

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

void PrintToLCD(){

   

    //write_command(FIRST_LINE);

    //WriteStringToLCD(table);

    write_command(SECOND_LINE);

    WriteStringToLCD(Current_Time);

 

}

 

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

    是否加1

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

void IsAdd(){

    if(PRESSED==Key_ADD){       //当加1按键按下

       delay(10);        //去抖动

       if(PRESSED==Key_ADD){    //当加1按键按下

           changeTime();

           InitTime();

           PrintToLCD();

           while(!Key_ADD);

       }

    }

}

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

    是否减1

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

void IsMinus(){

    if(PRESSED==KEY_MINUS){     //当减1按键按下

       delay(10);        //去抖动

       if(PRESSED==KEY_MINUS){  //当减1按键按下

           if(Second>0){    //防止按下减1按钮的时候,被减成负数

              Second--;

              InitTime();

              PrintToLCD();

              while(!KEY_MINUS);

           }

       }

    }

}

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

    是否运行

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

void IsRun(){

    if(PRESSED==FUNCTION_KEY){      //当减1按键按下

       delay(10);        //去抖动

          

       if(PRESSED==FUNCTION_KEY){  //当减1按键按下

           SUSPEND=~SUSPEND;

           // led1=SUSPEND;

       while(!KEY_MINUS);

        }

    }

}

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

    是否暂停

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

void IsSuspend(){

    IsRun();

    IsMinus();        //监测是否需要减1

    IsAdd();          //监测是否需要加1     

}

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

    重新计数

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

void ReCount(){

    Count=0;  //开始下一轮1s的计时

    TH0=T_High_50ms;// 计算初值,并将其写入TH0TL0TH1TL1

    TL0=T_Low_50ms;

}

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

    初始化时钟的值

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

void initClockValue(){

    Second=I2C_read_address(2);    //读出保存的数据赋于Second

 

    Minute=I2C_read_address(3);

    Hour=I2C_read_address(4);

}

void main()

{

    init();

    InitClockInterrupt();

    initButtonInterupt();

    initClockValue();

    if(Second>100)        //防止首次读取出错误数据

       Second=0;

 

    while(1){

    IsSuspend();

    if(Count>=20&&(!SUSPEND)){//定时器0 1s时间到

           ReCount();

           changeTime();

           InitTime();

           PrintToLCD();

       }

    }

 

}

//=========函数区结束============================================

 

//=========中断函数区============================================

 

/**

    初始化按钮外部中断

**/

void intButton() interrupt 0//外部中断0

{

 

}

 

/**

    用定时0实现8个发光二极管以1s间隔闪烁

**/

void int0() interrupt 1//定时/计数器T0中断

{

    Count++;

}

 

 

//=========中断函数区结束============================================

posted @ 2013-07-05 22:20  陈哈哈  阅读(4376)  评论(0编辑  收藏  举报