#include<reg51.h>
#include "Clock.h"
#include "OrphanKey.h"
#include "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賦值,以確定T0和T1的工作方式。
TH0=T_High_50ms;// 計算初值,并將其寫入TH0、TL0或TH1、TL1。
TL0=T_Low_50ms;
EA =1;//開啟中斷總允許
ET0 =1;
IT0 =1; //開啟定時器0,1中斷允許
TR0=1; // 使TR0或TR1置位,啟動定時/計數器定時或計數
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;// 計算初值,并將其寫入TH0、TL0或TH1、TL1。
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++;
}
//=========中斷函數區結束============================================
|