单片机简易电子钟设计c语言,基于51单片机的简易电子钟设计

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

3f829e29e76caa8c3b1f630a6b27d58d.gif

捕获.PNG (71.09 KB, 下载次数: 4)

2020-5-9 09:56 上传

C语言源程序如下:

#include

#include

//*****************************特殊功能寄存器声明********************

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

}

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值