標題: 基于51單片機的簡易電子鐘設計 [打印本頁]
作者: 夢幻承影 時間: 2020-5-9 09:57
標題: 基于51單片機的簡易電子鐘設計
單片機實現電子鐘主要有兩種方案。一種是利用單片機內部的定時/計數器產生標準秒信號,并根據時間系統的進位原則進行加1調整。另一種方法是為單片機配置一片可獨立走時的實時鐘(RTC)芯片,單片機通過串行信號線與該芯片進行通信,讀取或設置其當前時間。第一種方案結構簡單、成本低,精度可滿足多數場合的需要,因此,本設計采用第一種方案。
捕獲.PNG (71.09 KB, 下載次數: 29)
下載附件
2020-5-9 09:56 上傳
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);
}
| 歡迎光臨 (http://m.raoushi.com/bbs/) |
Powered by Discuz! X3.1 |