• 实验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]='';

    }

     

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

        保存时钟的值

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

    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!='')

        {  

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

    }

     

     

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

  • 相关阅读:
    俄罗斯的 HTTPS 证书问题
    11. 第十篇 网络组件flanneld安装及使用
    8.第七篇 验证kubeapiserver及kubeconfig配置详解
    4.第三篇 PKI基础概念、cfssl工具介绍及kubernetes中证书
    不要舔 Switch 游戏卡,单性生殖,永久夏令时
    catalina.out日志割接
    15. 第十四篇 安装CoreDNS
    6.第五篇 安装keepalived与Nginx
    5.第四篇 Etcd存储组件高可用部署
    DirectPV文章内容有待进一步实践完善
  • 原文地址:https://www.cnblogs.com/kissazi2/p/3174473.html
Copyright © 2020-2023  润新知