實驗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++;

}

 

 

//=========中斷函數區結束============================================


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM