找回密码
 立即注册

QQ登录

只需一步,快速开始

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

基于51单片机的简易电子钟设计

[复制链接]
跳转到指定楼层
楼主
单片机实现电子钟主要有两种方案。一种是利用单片机内部的定时/计数器产生标准秒信号,并根据时间系统的进位原则进行加1调整。另一种方法是为单片机配置一片可独立走时的实时钟(RTC)芯片,单片机通过串行信号线与该芯片进行通信,读取或设置其当前时间。第一种方案结构简单、成本低,精度可满足多数场合的需要,因此,本设计采用第一种方案。

C语言源程序如下:
#include <reg51.h>
#include <string.h>
//*****************************特殊功能寄存器声明********************
sfr P4SW = 0xBB;
sfr P4 = 0xC0;
//*******************************数据类型定义************************
typedef unsigned char uint8;
typedef unsigned int uint16;
typedef struct
{
        char Hour;
        char Minute;
        char Second;
} tsRTClock;
//**********************************口线声明*************************
#define LCD1602_DATA P0
sbit LCD1602_RS=P4^6;
sbit LCD1602_EN=P4^5;
sbit LCD1602_BL=P1^5;
sbit KX0           =P3^2;
sbit KX1           =P3^4;
sbit KX2           =P3^5;
sbit KX3           =P3^7;
sbit BUZZ=P1^0;
//******************************全局变量声明*************************
tsRTClock RTClock;
uint8 Timer50ms=0;
//******************************函数原型声明*************************
void SystemInit();
void LCD1602BLCtrl(uint8 OnOff);
void LCD1602CmdWrite(uint8 cmdByte);
void LCD1602DataWrite(uint8 DataByte);
void LCD1602Init();
void LCD1602ClrScr();
void LCD1602DispChar(uint8 Row, uint8 Col, char Char);
void LCD1602DispStr(uint8 Row, uint8 Col, char *Str);
void RTClockInit();
void RTClockAdj();
void RTClockDisp();
uint8 key();
void Delay(uint16 ms);
void AA();
void ZD (void);
//*******************************中断服务函数************************
void T0ISR(void) interrupt 1
{
        TH0=(65536-45*1024)>>8; //设置50ms定时初值(对应晶振11.0592MHz)
        TL0=(65536-45*1024)&0xFF;
        if(++Timer50ms<20 ) return;
        Timer50ms=0; //已满1s,Timer50ms清0
        RTClockAdj(); //时间调整
}
//*********************************主函数****************************
void main()
{
        SystemInit(); //系统初始化
        RTClockInit(); //时钟初始化
        LCD1602ClrScr();
        LCD1602DispStr(0, 0, "What time is it ?"); //首行显示提示信息
        while(1)
        {
                Delay(100);
                key();
                ZD ();
                RTClockDisp(); //显示当前时间
        }
}
//******************************系统初始化函数***********************
void SystemInit()
{
        P4SW |= 0x70; //将P44-P46设为I/O口
        TMOD=0x01; //T0用作定时器(方式1)
        TH0=(65536-45*1024)>>8; //设置50ms定时初值(对应晶振11.0592MHz)
        TL0=(65536-45*1024)&0xFF;
        TR0=1; //启动T0
        ET0=1; //允许T0中断
        EA=1;
        LCD1602BLCtrl(0); //背光点亮
        LCD1602Init(); //LCD1602初始化
}
//****************************LCD1602背光控制函数********************
void LCD1602BLCtrl(uint8 OnOff) //0:背光点亮,1:背光熄灭
{
    LCD1602_BL=OnOff;
}
//*****************************LCD1602写命令函数*********************
void LCD1602CmdWrite(uint8 cmdByte)
{
uint16 i;
        for(i=100;i;i--); //适当延时(取代忙状态检测)
        LCD1602_RS=0 ;
        LCD1602_EN=1;
        LCD1602_DATA=cmdByte; //发送命令字节
        LCD1602_EN=0;
}
//*****************************LCD1602写数据函数*********************
void LCD1602DataWrite(uint8 DataByte)
{
        uint16 i;
        for(i=100;i;i--); //适当延时(取代忙状态检测)
        LCD1602_RS=1;
        LCD1602_EN=1;
        LCD1602_DATA=DataByte; //发送数据字节
        LCD1602_EN=0;
}
//*****************************LCD1602初始化函数*********************
void LCD1602Init()
{
        LCD1602_EN=0;
        LCD1602CmdWrite(0x38); //8位总线方式,两行显示,5*7点阵
        LCD1602CmdWrite(0x0C); //LCD显示开,无光标
        LCD1602CmdWrite(0x06); //写入一个数据字节后地址计数器自动加1
}
//******************************LCD1602清屏函数**********************
void LCD1602ClrScr()
{
        LCD1602CmdWrite(0x01); //发送清屏命令
        Delay(8);
}
//****************************LCD1602字符显示函数********************
void LCD1602DispChar(uint8 Row, uint8 Col, char Char)
{
        if(Row)
        Col |= 0x40; //显示第二行时DDRAM地址从40H开始
        Col |= 0x80; //拼为DDRAM地址设置命令
        LCD1602CmdWrite(Col); //发送DDRAM地址
        LCD1602DataWrite(Char); //发送ASCII码
}
//***************************LCD1602字符串显示函数*******************
void LCD1602DispStr(uint8 Row, uint8 Col, char *Str)
{
        if(Row)
        Col |= 0x40; //显示第二行时DDRAM地址从40H开始
        Col |= 0x80; //拼为DDRAM地址设置命令
        LCD1602CmdWrite(Col); //发送DDRAM地址
        while(*Str )
        LCD1602DataWrite(*Str++); //连续发送每个字符的ASCII码
}
//******************************电子钟初始化函数*********************
void RTClockInit()
{
        RTClock.Hour=23;
        RTClock.Minute=59;
        RTClock.Second=50;
}
//*****************************电子钟时间调整函数********************
void RTClockAdj()
{
        if(++RTClock.Second<60 ) return;
        RTClock.Second=0;
        if(++RTClock.Minute<60 ) return;
        RTClock.Minute=0;
        if(++RTClock.Hour<24 ) return;
        RTClock.Hour=0;
}
//*****************************电子钟显示更新函数********************
void RTClockDisp()
{
        if(RTClock.Hour>=10)
        LCD1602DispChar(1,4,0x30+RTClock.Hour/10); //显示Hour的十位
        else
        LCD1602DispChar(1,4,' ');                  //Hour的十位为0则隐去
        LCD1602DispChar(1,5,0x30+RTClock.Hour%10); //显示Hour的个位
        LCD1602DispChar(1,6,':');
        LCD1602DispChar(1,7,0x30+RTClock.Minute/10); //显示Minute的十位
        LCD1602DispChar(1,8,0x30+RTClock.Minute%10); //显示Minute的个位
        LCD1602DispChar(1,9,':');
        LCD1602DispChar(1,10,0x30+RTClock.Second/10); //显示Second的十位
        LCD1602DispChar(1,11,0x30+RTClock.Second%10); //显示Second的个位
}
uint8 key()
{
        if(KX0==0)
        {
                Delay(2);
                if(KX0==0)
                {
                        EA=0;
                        TH0=0;
                        TL0=0;
                        RTClock.Hour++;
                        RTClock.Second=0;
                        if(RTClock.Hour>=24)
                                RTClock.Hour=0;
                        while(!KX0);
                }
                EA=1;
                return RTClock.Hour;
        }
        if(KX1==0)
        {
                Delay(2);
                if(KX1==0)
                {
                        EA=0;
                        TH0=0;
                        TL0=0;
                        RTClock.Hour--;
                        RTClock.Second=0;
                        if(RTClock.Hour<0)
                                RTClock.Hour=23;
                        while(!KX1);
                }
                EA=1;
                return RTClock.Hour;
        }
        if(KX2==0)
        {
                Delay(2);
                if(KX2==0)
                {
                        EA=0;
                        TH0=0;
                        TL0=0;
                        RTClock.Minute++;
                        RTClock.Second=0;
                        if(RTClock.Minute>=60)
                                RTClock.Minute=0;
                        while(!KX2);
                }
                EA=1;
                return RTClock.Minute;
        }
        if(KX3==0)
        {
                Delay(2);
                if(KX3==0)
                {
                        EA=0;
                        TH0=0;
                        TL0=0;
                        RTClock.Minute--;
                        RTClock.Second=0;
                        if(RTClock.Minute<0)
                                RTClock.Minute=59;
                        while(!KX3);
                }
                EA=1;
                return RTClock.Hour;
        }
}               
void AA()
{   int i=0;
          for(i=0;i<=RTClock.Hour;i++)
                {
                    BUZZ=0;
            Delay(100);
                    BUZZ=1;
                }
}
void ZD (void)
{
        if(RTClock.Second==0&&RTClock.Minute==0)
        {
                 {
                        AA();
                 }
        }
}
//******************************软件延时函数*************************
void Delay(uint16 ms)
{
        uint16 i;
        do{
        for(i=700;i;i--); //以1ms为延时单位
        } while(--ms);
}

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

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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