LCD顯示時鐘,可斷電儲存,調整時間,調整鬧鐘
阿新 • • 發佈:2018-12-30
/*接線:
P2.2 ---> j42.b1(蜂鳴器)
P2.1 ---> iic.SDA
P2.0 ---> iic.SCL
P1 ---> j24(矩陣鍵盤)
矩陣鍵盤按鍵:+、-
問題:
1、對應修改位置閃爍時不能通過按鍵賦值
*/
#include<reg52.h>
#include<intrins.h>
void DelayUs2x(unsigned char t);
void DelayMs(unsigned char t);
unsigned char KeyScan(void);
unsigned char KeyPro(void);
void LCD_Write_Com(unsigned char com);
void LCD_Write_Data(unsigned char Data);
void LCD_Clear(void) ;
void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s);
void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data);
void LCD_Init(void);
void Start_I2c();
void Stop_I2c();
void Ack_I2c(void);
void NoAck_I2c(void);
void SendByte(unsigned char c);
unsigned char RcvByte();
bit ISendStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no);
bit IRcvStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no);
void time_to_str();//時間轉為字串
void str_to_time();//字串轉為時間
void clock();
unsigned char hour,min,sec;
unsigned char clock_h = 0,clock_m = 0;
unsigned char store[6];
unsigned char local = 0;
unsigned char revise_num;
sbit SPK=P2^2;
sbit SDA=P2^1; //模擬I2C資料傳送位SCL
sbit SCL=P2^0; //模擬I2C時鐘控制位SDA
sbit RS = P2^4; //定義埠
sbit RW = P2^5;
sbit EN = P2^6;
bit ack; //應答標誌位
#define _Nop() _nop_() //定義空指令
#define RS_CLR RS=0
#define RS_SET RS=1
#define RW_CLR RW=0
#define RW_SET RW=1
#define EN_CLR EN=0
#define EN_SET EN=1
#define DataPort P0
#define KeyPort P1
void main()
{
unsigned char i;
LCD_Init();
TMOD = 0x01;//初始化計數器
TH0 = 0x3c;//50ms
TL0 = 0xb0;
EA = 1;
ET0 = 1;
TR0 = 1;
/*hour = 23; //初始化時間設定
min = 59;
sec = 49;*/
IRcvStr(0xae,4,store,5); //呼叫儲存資料
str_to_time();
while(1)
{
LCD_Write_String(1,0,"time:");
LCD_Write_String(0,1,"clock:");
if(local != 1)
LCD_Write_Char(7,0,(hour/10)+ '0');
else
{
while(local == 1)
{
LCD_Write_Char(8,0,(hour%10)+ '0');
LCD_Write_Char(7,0,' ');
DelayMs(255);
LCD_Write_Char(7,0,(hour/10)+ '0');
DelayMs(255);
hour+=10;
if(hour >= 24 && hour <= 29)
hour-=20;
if(hour >=30)
hour -= 30;
}
//hour-=10;
}
if(local != 2)
LCD_Write_Char(8,0,(hour%10)+ '0');
else
{
while(local == 2)
{
LCD_Write_Char(7,0,(hour/10)+ '0');
LCD_Write_Char(8,0,' ');
DelayMs(255);
LCD_Write_Char(8,0,(hour%10)+ '0');
DelayMs(255);
hour++;
if(hour>=24)
hour-=24;
}
hour--;
}
LCD_Write_Char(9,0,':');
if(local != 3)
LCD_Write_Char(10,0,(min/10)+ '0');
else
{
while(local == 3)
{
LCD_Write_Char(11,0,(min%10)+ '0');
LCD_Write_Char(10,0,' ');
DelayMs(255);
LCD_Write_Char(10,0,(min/10)+ '0');
DelayMs(255);
min += 10;
if(min >= 60)
min -= 60;
}
//min-=10;
}
if(local != 4)
LCD_Write_Char(11,0,(min%10)+ '0');
else
{
while(local == 4)
{
LCD_Write_Char(10,0,(min/10)+ '0');
LCD_Write_Char(11,0,' ');
DelayMs(255);
LCD_Write_Char(11,0,(min%10)+ '0');
DelayMs(255);
min++;
if(min >= 60 )
min-=60;
}
min--;
}
LCD_Write_Char(12,0,':');
if(local != 5)
LCD_Write_Char(13,0,(sec/10)+ '0');
else
{
while(local == 5)
{
LCD_Write_Char(14,0,(sec%10)+ '0');
LCD_Write_Char(13,0,' ');
DelayMs(255);
LCD_Write_Char(13,0,(sec/10)+ '0');
DelayMs(255);
sec+=10;
if(sec >= 60)
sec-=60;
}
//sec-=10;
}
if(local != 6)
LCD_Write_Char(14,0,(sec%10)+ '0');
else
{
while(local == 6)
{
LCD_Write_Char(13,0,(sec/10)+ '0');
LCD_Write_Char(14,0,' ');
DelayMs(255);
LCD_Write_Char(14,0,(sec%10)+ '0');
DelayMs(255);
sec++;
if(sec >= 60)
sec-=60;
}
sec--;
}
if(local != 7)
LCD_Write_Char(7,1,(clock_h/10)+ '0');
else
{
while(local == 7)
{
LCD_Write_Char(8,1,(clock_h%10)+ '0');
LCD_Write_Char(7,1,' ');
DelayMs(255);
LCD_Write_Char(7,1,(clock_h/10)+ '0');
DelayMs(255);
clock_h+=10;
if(clock_h >= 24 && hour <= 29)
clock_h-=20;
if(clock_h >=30)
clock_h -= 30;
}
//clock_h-=10;
}
if(local != 8)
LCD_Write_Char(8,1,(clock_h%10)+ '0');
else
{
while(local == 8)
{
LCD_Write_Char(7,1,(clock_h/10)+ '0');
LCD_Write_Char(8,1,' ');
DelayMs(255);
LCD_Write_Char(8,1,(clock_h%10)+ '0');
DelayMs(255);
clock_h++;
if(clock_h>=24)
clock_h-=24;
}
clock_h--;
}
LCD_Write_Char(9,1,':');
if(local != 9)
LCD_Write_Char(10,1,(clock_m/10)+ '0');
else
{
while(local == 9)
{
LCD_Write_Char(11,1,(clock_m%10)+ '0');
LCD_Write_Char(10,1,' ');
DelayMs(255);
LCD_Write_Char(10,1,(clock_m/10)+ '0');
DelayMs(255);
clock_m += 10;
if(clock_m >= 60)
clock_m -= 60;
}
//clock_m-=10;
}
if(local != 10)
LCD_Write_Char(11,1,(clock_m%10)+ '0');
else
{
while(local == 10)
{
LCD_Write_Char(10,1,(clock_m/10)+ '0');
LCD_Write_Char(11,1,' ');
DelayMs(255);
LCD_Write_Char(11,1,(clock_m%10)+ '0');
DelayMs(255);
clock_m++;
if(clock_m >= 60 )
clock_m-=60;
}
clock_m--;
}
//LCD_Write_String(2,1,store);
time_to_str();
ISendStr(0xae,4,store,5); //寫入24c02
if(sec >= 60)
{
sec = 0;
min++;
}
if(min >= 60)
{
min = 0;
hour++;
for(i=0;i<200;i++)
{
DelayMs(1);
SPK=!SPK;
}
}
if(hour >= 24)
{
hour -= 24;
//min = 0;
//sec = 0;
}
clock();
}
}
void DelayUs2x(unsigned char t)
{
while(--t);
}
void DelayMs(unsigned char t)
{
while(t--)
{
//大致延時1mS
DelayUs2x(245);
DelayUs2x(245);
}
}
void time_to_str()//時間轉為字串
{
store[0] = hour;
store[1] = min;
store[2] = sec;
store[3] = clock_h;
store[4] = clock_m;
store[5] = '\0';
}
void str_to_time()//字串轉為時間
{
hour = store[0];
min = store[1];
sec = store[2];
clock_h = store[3];
clock_m = store[4];
}
/*------------------------------------------------
寫入命令函式
------------------------------------------------*/
void LCD_Write_Com(unsigned char com)
{
DelayMs(5);
RS_CLR;
RW_CLR;
EN_SET;
DataPort= com;
_nop_();
EN_CLR;
}
/*------------------------------------------------
寫入資料函式
------------------------------------------------*/
void LCD_Write_Data(unsigned char Data)
{
DelayMs(5);
RS_SET;
RW_CLR;
EN_SET;
DataPort= Data;
_nop_();
EN_CLR;
}
void LCD_Clear(void) //清屏
{
LCD_Write_Com(0x01);
DelayMs(5);
}
void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s) //寫入字串
{
if (y == 0)
{
LCD_Write_Com(0x80 + x);
}
else
{
LCD_Write_Com(0xC0 + x);
}
while (*s)
{
LCD_Write_Data( *s);
s ++;
}
}
void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data) //寫入字元
{
if (y == 0)
{
LCD_Write_Com(0x80 + x);
}
else
{
LCD_Write_Com(0xC0 + x);
}
LCD_Write_Data( Data);
}
void LCD_Init(void) //初始化
{
LCD_Write_Com(0x38); /*顯示模式設定*/
DelayMs(5);
LCD_Write_Com(0x38);
DelayMs(5);
LCD_Write_Com(0x38);
DelayMs(5);
LCD_Write_Com(0x38);
LCD_Write_Com(0x08); /*顯示關閉*/
LCD_Write_Com(0x01); /*顯示清屏*/
LCD_Write_Com(0x06); /*顯示游標移動設定*/
DelayMs(5);
LCD_Write_Com(0x0C); /*顯示開及游標設定*/
}
void Start_I2c() //啟動匯流排
{
SDA=1; //傳送起始條件的資料訊號
_Nop();
SCL=1;
_Nop(); //起始條件建立時間大於4.7us,延時
_Nop();
_Nop();
_Nop();
_Nop();
SDA=0; //傳送起始訊號
_Nop(); //起始條件鎖定時間大於4μ
_Nop();
_Nop();
_Nop();
_Nop();
SCL=0; //鉗住I2C匯流排,準備傳送或接收資料
_Nop();
_Nop();
}
/*------------------------------------------------
結束匯流排
------------------------------------------------*/
void Stop_I2c()
{
SDA=0; //傳送結束條件的資料訊號
_Nop(); //傳送結束條件的時鐘訊號
SCL=1; //結束條件建立時間大於4μ
_Nop();
_Nop();
_Nop();
_Nop();
_Nop();
SDA=1; //傳送I2C匯流排結束訊號
_Nop();
_Nop();
_Nop();
_Nop();
}
/*----------------------------------------------------------------
位元組資料傳送函式
函式原型: void SendByte(unsigned char c);
功能: 將資料c傳送出去,可以是地址,也可以是資料,發完後等待應答,並對
此狀態位進行操作.(不應答或非應答都使ack=0 假)
傳送資料正常,ack=1; ack=0表示被控器無應答或損壞。
------------------------------------------------------------------*/
void SendByte(unsigned char c)
{
unsigned char BitCnt;
for(BitCnt=0;BitCnt<8;BitCnt++) //要傳送的資料長度為8位
{
if((c<<BitCnt)&0x80)SDA=1; //判斷髮送位
else SDA=0;
_Nop();
SCL=1; //置時鐘線為高,通知被控器開始接收資料位
_Nop();
_Nop(); //保證時鐘高電平週期大於4μ
_Nop();
_Nop();
_Nop();
SCL=0;
}
_Nop();
_Nop();
SDA=1; //8位傳送完後釋放資料線,準備接收應答位
_Nop();
_Nop();
SCL=1;
_Nop();
_Nop();
_Nop();
if(SDA==1)ack=0;
else ack=1; //判斷是否接收到應答訊號
SCL=0;
_Nop();
_Nop();
}
/*----------------------------------------------------------------
位元組資料傳送函式
函式原型: unsigned char RcvByte();
功能: 用來接收從器件傳來的資料,並判斷匯流排錯誤(不發應答訊號),
發完後請用應答函式。
------------------------------------------------------------------*/
unsigned char RcvByte()
{
unsigned char retc;
unsigned char BitCnt;
retc=0;
SDA=1; //置資料線為輸入方式
for(BitCnt=0;BitCnt<8;BitCnt++)
{
_Nop();
SCL=0; //置時鐘線為低,準備接收資料位
_Nop();
_Nop(); //時鐘低電平週期大於4.7us
_Nop();
_Nop();
_Nop();
SCL=1; //置時鐘線為高使資料線上資料有效
_Nop();
_Nop();
retc=retc<<1;
if(SDA==1)retc=retc+1; //讀資料位,接收的資料位放入retc中
_Nop();
_Nop();
}
SCL=0;
_Nop();
_Nop();
return(retc);
}
/*----------------------------------------------------------------
應答子函式
原型: void Ack_I2c(void);
----------------------------------------------------------------*/
void Ack_I2c(void)
{
SDA=0;
_Nop();
_Nop();
_Nop();
SCL=1;
_Nop();
_Nop(); //時鐘低電平週期大於4μ
_Nop();
_Nop();
_Nop();
SCL=0; //清時鐘線,鉗住I2C匯流排以便繼續接收
_Nop();
_Nop();
}
/*----------------------------------------------------------------
非應答子函式
原型: void NoAck_I2c(void);
----------------------------------------------------------------*/
void NoAck_I2c(void)
{
SDA=1;
_Nop();
_Nop();
_Nop();
SCL=1;
_Nop();
_Nop(); //時鐘低電平週期大於4μ
_Nop();
_Nop();
_Nop();
SCL=0; //清時鐘線,鉗住I2C匯流排以便繼續接收
_Nop();
_Nop();
}
/*----------------------------------------------------------------
向有子地址器件傳送多位元組資料函式
函式原型: bit ISendStr(unsigned char sla,unsigned char suba,ucahr *s,unsigned char no);
功能: 從啟動匯流排到傳送地址,子地址,資料,結束匯流排的全過程,從器件
地址sla,子地址suba,傳送內容是s指向的內容,傳送no個位元組。
如果返回1表示操作成功,否則操作有誤。
注意: 使用前必須已結束匯流排。
----------------------------------------------------------------*/
bit ISendStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no)
{
unsigned char i;
Start_I2c(); //啟動匯流排
SendByte(sla); //傳送器件地址
if(ack==0)return(0);
SendByte(suba); //傳送器件子地址
if(ack==0)return(0);
for(i=0;i<no;i++)
{
SendByte(*s); //傳送資料
if(ack==0)return(0);
s++;
}
Stop_I2c(); //結束匯流排
return(1);
}
/*----------------------------------------------------------------
向有子地址器件讀取多位元組資料函式
函式原型: bit ISendStr(unsigned char sla,unsigned char suba,ucahr *s,unsigned char no);
功能: 從啟動匯流排到傳送地址,子地址,讀資料,結束匯流排的全過程,從器件
地址sla,子地址suba,讀出的內容放入s指向的儲存區,讀no個位元組。
如果返回1表示操作成功,否則操作有誤。
注意: 使用前必須已結束匯流排。
----------------------------------------------------------------*/
bit IRcvStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no)
{
unsigned char i;
Start_I2c(); //啟動匯流排
SendByte(sla); //傳送器件地址
if(ack==0)return(0);
SendByte(suba); //傳送器件子地址
if(ack==0)return(0);
Start_I2c();
SendByte(sla+1);
if(ack==0)return(0);
for(i=0;i<no-1;i++)
{
*s=RcvByte(); //傳送資料
Ack_I2c(); //傳送就答位
s++;
}
*s=RcvByte();
NoAck_I2c(); //傳送非應位
Stop_I2c(); //結束匯流排
return(1);
}
/*------------------------------------------------
按鍵掃描函式,返回掃描鍵值
------------------------------------------------*/
unsigned char KeyScan(void) //鍵盤掃描函式,使用行列逐級掃描法
{
unsigned char Val;
KeyPort=0xf0;//高四位置高,低四位拉低
if(KeyPort!=0xf0)//表示有按鍵按下
{
DelayMs(10); //去抖
if(KeyPort!=0xf0)
{ //表示有按鍵按下
KeyPort=0xfe; //檢測第一行
if(KeyPort!=0xfe)
{
Val=KeyPort&0xf0;
Val+=0x0e;
while(KeyPort!=0xfe);
DelayMs(10); //去抖
while(KeyPort!=0xfe);
return Val;
}
KeyPort=0xfd; //檢測第二行
if(KeyPort!=0xfd)
{
Val=KeyPort&0xf0;
Val+=0x0d;
while(KeyPort!=0xfd);
DelayMs(10); //去抖
while(KeyPort!=0xfd);
return Val;
}
KeyPort=0xfb; //檢測第三行
if(KeyPort!=0xfb)
{
Val=KeyPort&0xf0;
Val+=0x0b;
while(KeyPort!=0xfb);
DelayMs(10); //去抖
while(KeyPort!=0xfb);
return Val;
}
KeyPort=0xf7; //檢測第四行
if(KeyPort!=0xf7)
{
Val=KeyPort&0xf0;
Val+=0x07;
while(KeyPort!=0xf7);
DelayMs(10); //去抖
while(KeyPort!=0xf7);
return Val;
}
}
}
return 0xff;
}
/*------------------------------------------------
按鍵值處理函式,返回掃鍵值
------------------------------------------------*/
unsigned char KeyPro(void)
{
switch(KeyScan())
{
case 0x7e:return 1;break;// 按下相應的鍵顯示相對應的碼值
case 0x7d:return 4;break;
case 0x7b:return 7;break;
case 0x77:return 0;break;
case 0xbe:return 2;break;
case 0xbd:return 5;break;
case 0xbb:return 8;break;
case 0xb7:return '.';break;
case 0xde:return 3;break;
case 0xdd:return 6;break;
case 0xdb:return 9;break;
case 0xd7:return '=';break;
case 0xee:return '+';break;
case 0xed:return '-';break;
case 0xeb:return '*';break;
case 0xe7:return '/';break;
default:return 0xff;break;
}
}
void clock()
{
unsigned int i;
if(hour == clock_h && min == clock_m && sec <=3)
{
for(i=0;i<1000;i++)
{
DelayMs(1);
SPK=!SPK;
}
}
}
void ISR_T0(void) interrupt 1
{
unsigned char i,num;
TH0 = 0x3c; //50ms
TL0 = 0xb0;
num = KeyPro();
if(num == '+')
{
local++;
if(local == 11)
local = 0;
}
else if( num == '-')
{
local--;
if(local == 0xff)
local = 10;
}
if( local == 0 )
{
i++;
if(i == 20)
{
i = 0;
sec++;
SPK=!SPK;
}
}
}
P2.2 ---> j42.b1(蜂鳴器)
P2.1 ---> iic.SDA
P2.0 ---> iic.SCL
P1 ---> j24(矩陣鍵盤)
矩陣鍵盤按鍵:+、-
問題:
1、對應修改位置閃爍時不能通過按鍵賦值
*/
#include<reg52.h>
#include<intrins.h>
void DelayUs2x(unsigned char t);
void DelayMs(unsigned char t);
unsigned char KeyScan(void);
unsigned char KeyPro(void);
void LCD_Write_Com(unsigned char com);
void LCD_Write_Data(unsigned char Data);
void LCD_Clear(void) ;
void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s);
void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data);
void LCD_Init(void);
void Start_I2c();
void Stop_I2c();
void Ack_I2c(void);
void NoAck_I2c(void);
void SendByte(unsigned char c);
unsigned char RcvByte();
bit ISendStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no);
bit IRcvStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no);
void time_to_str();//時間轉為字串
void str_to_time();//字串轉為時間
void clock();
unsigned char hour,min,sec;
unsigned char clock_h = 0,clock_m = 0;
unsigned char store[6];
unsigned char local = 0;
unsigned char revise_num;
sbit SPK=P2^2;
sbit SDA=P2^1; //模擬I2C資料傳送位SCL
sbit SCL=P2^0; //模擬I2C時鐘控制位SDA
sbit RS = P2^4; //定義埠
sbit RW = P2^5;
sbit EN = P2^6;
bit ack; //應答標誌位
#define _Nop() _nop_() //定義空指令
#define RS_CLR RS=0
#define RS_SET RS=1
#define RW_CLR RW=0
#define RW_SET RW=1
#define EN_CLR EN=0
#define EN_SET EN=1
#define DataPort P0
#define KeyPort P1
void main()
{
unsigned char i;
LCD_Init();
TMOD = 0x01;//初始化計數器
TH0 = 0x3c;//50ms
TL0 = 0xb0;
EA = 1;
ET0 = 1;
TR0 = 1;
/*hour = 23; //初始化時間設定
min = 59;
sec = 49;*/
IRcvStr(0xae,4,store,5); //呼叫儲存資料
str_to_time();
while(1)
{
LCD_Write_String(1,0,"time:");
LCD_Write_String(0,1,"clock:");
if(local != 1)
LCD_Write_Char(7,0,(hour/10)+ '0');
else
{
while(local == 1)
{
LCD_Write_Char(8,0,(hour%10)+ '0');
LCD_Write_Char(7,0,' ');
DelayMs(255);
LCD_Write_Char(7,0,(hour/10)+ '0');
DelayMs(255);
hour+=10;
if(hour >= 24 && hour <= 29)
hour-=20;
if(hour >=30)
hour -= 30;
}
//hour-=10;
}
if(local != 2)
LCD_Write_Char(8,0,(hour%10)+ '0');
else
{
while(local == 2)
{
LCD_Write_Char(7,0,(hour/10)+ '0');
LCD_Write_Char(8,0,' ');
DelayMs(255);
LCD_Write_Char(8,0,(hour%10)+ '0');
DelayMs(255);
hour++;
if(hour>=24)
hour-=24;
}
hour--;
}
LCD_Write_Char(9,0,':');
if(local != 3)
LCD_Write_Char(10,0,(min/10)+ '0');
else
{
while(local == 3)
{
LCD_Write_Char(11,0,(min%10)+ '0');
LCD_Write_Char(10,0,' ');
DelayMs(255);
LCD_Write_Char(10,0,(min/10)+ '0');
DelayMs(255);
min += 10;
if(min >= 60)
min -= 60;
}
//min-=10;
}
if(local != 4)
LCD_Write_Char(11,0,(min%10)+ '0');
else
{
while(local == 4)
{
LCD_Write_Char(10,0,(min/10)+ '0');
LCD_Write_Char(11,0,' ');
DelayMs(255);
LCD_Write_Char(11,0,(min%10)+ '0');
DelayMs(255);
min++;
if(min >= 60 )
min-=60;
}
min--;
}
LCD_Write_Char(12,0,':');
if(local != 5)
LCD_Write_Char(13,0,(sec/10)+ '0');
else
{
while(local == 5)
{
LCD_Write_Char(14,0,(sec%10)+ '0');
LCD_Write_Char(13,0,' ');
DelayMs(255);
LCD_Write_Char(13,0,(sec/10)+ '0');
DelayMs(255);
sec+=10;
if(sec >= 60)
sec-=60;
}
//sec-=10;
}
if(local != 6)
LCD_Write_Char(14,0,(sec%10)+ '0');
else
{
while(local == 6)
{
LCD_Write_Char(13,0,(sec/10)+ '0');
LCD_Write_Char(14,0,' ');
DelayMs(255);
LCD_Write_Char(14,0,(sec%10)+ '0');
DelayMs(255);
sec++;
if(sec >= 60)
sec-=60;
}
sec--;
}
if(local != 7)
LCD_Write_Char(7,1,(clock_h/10)+ '0');
else
{
while(local == 7)
{
LCD_Write_Char(8,1,(clock_h%10)+ '0');
LCD_Write_Char(7,1,' ');
DelayMs(255);
LCD_Write_Char(7,1,(clock_h/10)+ '0');
DelayMs(255);
clock_h+=10;
if(clock_h >= 24 && hour <= 29)
clock_h-=20;
if(clock_h >=30)
clock_h -= 30;
}
//clock_h-=10;
}
if(local != 8)
LCD_Write_Char(8,1,(clock_h%10)+ '0');
else
{
while(local == 8)
{
LCD_Write_Char(7,1,(clock_h/10)+ '0');
LCD_Write_Char(8,1,' ');
DelayMs(255);
LCD_Write_Char(8,1,(clock_h%10)+ '0');
DelayMs(255);
clock_h++;
if(clock_h>=24)
clock_h-=24;
}
clock_h--;
}
LCD_Write_Char(9,1,':');
if(local != 9)
LCD_Write_Char(10,1,(clock_m/10)+ '0');
else
{
while(local == 9)
{
LCD_Write_Char(11,1,(clock_m%10)+ '0');
LCD_Write_Char(10,1,' ');
DelayMs(255);
LCD_Write_Char(10,1,(clock_m/10)+ '0');
DelayMs(255);
clock_m += 10;
if(clock_m >= 60)
clock_m -= 60;
}
//clock_m-=10;
}
if(local != 10)
LCD_Write_Char(11,1,(clock_m%10)+ '0');
else
{
while(local == 10)
{
LCD_Write_Char(10,1,(clock_m/10)+ '0');
LCD_Write_Char(11,1,' ');
DelayMs(255);
LCD_Write_Char(11,1,(clock_m%10)+ '0');
DelayMs(255);
clock_m++;
if(clock_m >= 60 )
clock_m-=60;
}
clock_m--;
}
//LCD_Write_String(2,1,store);
time_to_str();
ISendStr(0xae,4,store,5); //寫入24c02
if(sec >= 60)
{
sec = 0;
min++;
}
if(min >= 60)
{
min = 0;
hour++;
for(i=0;i<200;i++)
{
DelayMs(1);
SPK=!SPK;
}
}
if(hour >= 24)
{
hour -= 24;
//min = 0;
//sec = 0;
}
clock();
}
}
void DelayUs2x(unsigned char t)
{
while(--t);
}
void DelayMs(unsigned char t)
{
while(t--)
{
//大致延時1mS
DelayUs2x(245);
DelayUs2x(245);
}
}
void time_to_str()//時間轉為字串
{
store[0] = hour;
store[1] = min;
store[2] = sec;
store[3] = clock_h;
store[4] = clock_m;
store[5] = '\0';
}
void str_to_time()//字串轉為時間
{
hour = store[0];
min = store[1];
sec = store[2];
clock_h = store[3];
clock_m = store[4];
}
/*------------------------------------------------
寫入命令函式
------------------------------------------------*/
void LCD_Write_Com(unsigned char com)
{
DelayMs(5);
RS_CLR;
RW_CLR;
EN_SET;
DataPort= com;
_nop_();
EN_CLR;
}
/*------------------------------------------------
寫入資料函式
------------------------------------------------*/
void LCD_Write_Data(unsigned char Data)
{
DelayMs(5);
RS_SET;
RW_CLR;
EN_SET;
DataPort= Data;
_nop_();
EN_CLR;
}
void LCD_Clear(void) //清屏
{
LCD_Write_Com(0x01);
DelayMs(5);
}
void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s) //寫入字串
{
if (y == 0)
{
LCD_Write_Com(0x80 + x);
}
else
{
LCD_Write_Com(0xC0 + x);
}
while (*s)
{
LCD_Write_Data( *s);
s ++;
}
}
void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data) //寫入字元
{
if (y == 0)
{
LCD_Write_Com(0x80 + x);
}
else
{
LCD_Write_Com(0xC0 + x);
}
LCD_Write_Data( Data);
}
void LCD_Init(void) //初始化
{
LCD_Write_Com(0x38); /*顯示模式設定*/
DelayMs(5);
LCD_Write_Com(0x38);
DelayMs(5);
LCD_Write_Com(0x38);
DelayMs(5);
LCD_Write_Com(0x38);
LCD_Write_Com(0x08); /*顯示關閉*/
LCD_Write_Com(0x01); /*顯示清屏*/
LCD_Write_Com(0x06); /*顯示游標移動設定*/
DelayMs(5);
LCD_Write_Com(0x0C); /*顯示開及游標設定*/
}
void Start_I2c() //啟動匯流排
{
SDA=1; //傳送起始條件的資料訊號
_Nop();
SCL=1;
_Nop(); //起始條件建立時間大於4.7us,延時
_Nop();
_Nop();
_Nop();
_Nop();
SDA=0; //傳送起始訊號
_Nop(); //起始條件鎖定時間大於4μ
_Nop();
_Nop();
_Nop();
_Nop();
SCL=0; //鉗住I2C匯流排,準備傳送或接收資料
_Nop();
_Nop();
}
/*------------------------------------------------
結束匯流排
------------------------------------------------*/
void Stop_I2c()
{
SDA=0; //傳送結束條件的資料訊號
_Nop(); //傳送結束條件的時鐘訊號
SCL=1; //結束條件建立時間大於4μ
_Nop();
_Nop();
_Nop();
_Nop();
_Nop();
SDA=1; //傳送I2C匯流排結束訊號
_Nop();
_Nop();
_Nop();
_Nop();
}
/*----------------------------------------------------------------
位元組資料傳送函式
函式原型: void SendByte(unsigned char c);
功能: 將資料c傳送出去,可以是地址,也可以是資料,發完後等待應答,並對
此狀態位進行操作.(不應答或非應答都使ack=0 假)
傳送資料正常,ack=1; ack=0表示被控器無應答或損壞。
------------------------------------------------------------------*/
void SendByte(unsigned char c)
{
unsigned char BitCnt;
for(BitCnt=0;BitCnt<8;BitCnt++) //要傳送的資料長度為8位
{
if((c<<BitCnt)&0x80)SDA=1; //判斷髮送位
else SDA=0;
_Nop();
SCL=1; //置時鐘線為高,通知被控器開始接收資料位
_Nop();
_Nop(); //保證時鐘高電平週期大於4μ
_Nop();
_Nop();
_Nop();
SCL=0;
}
_Nop();
_Nop();
SDA=1; //8位傳送完後釋放資料線,準備接收應答位
_Nop();
_Nop();
SCL=1;
_Nop();
_Nop();
_Nop();
if(SDA==1)ack=0;
else ack=1; //判斷是否接收到應答訊號
SCL=0;
_Nop();
_Nop();
}
/*----------------------------------------------------------------
位元組資料傳送函式
函式原型: unsigned char RcvByte();
功能: 用來接收從器件傳來的資料,並判斷匯流排錯誤(不發應答訊號),
發完後請用應答函式。
------------------------------------------------------------------*/
unsigned char RcvByte()
{
unsigned char retc;
unsigned char BitCnt;
retc=0;
SDA=1; //置資料線為輸入方式
for(BitCnt=0;BitCnt<8;BitCnt++)
{
_Nop();
SCL=0; //置時鐘線為低,準備接收資料位
_Nop();
_Nop(); //時鐘低電平週期大於4.7us
_Nop();
_Nop();
_Nop();
SCL=1; //置時鐘線為高使資料線上資料有效
_Nop();
_Nop();
retc=retc<<1;
if(SDA==1)retc=retc+1; //讀資料位,接收的資料位放入retc中
_Nop();
_Nop();
}
SCL=0;
_Nop();
_Nop();
return(retc);
}
/*----------------------------------------------------------------
應答子函式
原型: void Ack_I2c(void);
----------------------------------------------------------------*/
void Ack_I2c(void)
{
SDA=0;
_Nop();
_Nop();
_Nop();
SCL=1;
_Nop();
_Nop(); //時鐘低電平週期大於4μ
_Nop();
_Nop();
_Nop();
SCL=0; //清時鐘線,鉗住I2C匯流排以便繼續接收
_Nop();
_Nop();
}
/*----------------------------------------------------------------
非應答子函式
原型: void NoAck_I2c(void);
----------------------------------------------------------------*/
void NoAck_I2c(void)
{
SDA=1;
_Nop();
_Nop();
_Nop();
SCL=1;
_Nop();
_Nop(); //時鐘低電平週期大於4μ
_Nop();
_Nop();
_Nop();
SCL=0; //清時鐘線,鉗住I2C匯流排以便繼續接收
_Nop();
_Nop();
}
/*----------------------------------------------------------------
向有子地址器件傳送多位元組資料函式
函式原型: bit ISendStr(unsigned char sla,unsigned char suba,ucahr *s,unsigned char no);
功能: 從啟動匯流排到傳送地址,子地址,資料,結束匯流排的全過程,從器件
地址sla,子地址suba,傳送內容是s指向的內容,傳送no個位元組。
如果返回1表示操作成功,否則操作有誤。
注意: 使用前必須已結束匯流排。
----------------------------------------------------------------*/
bit ISendStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no)
{
unsigned char i;
Start_I2c(); //啟動匯流排
SendByte(sla); //傳送器件地址
if(ack==0)return(0);
SendByte(suba); //傳送器件子地址
if(ack==0)return(0);
for(i=0;i<no;i++)
{
SendByte(*s); //傳送資料
if(ack==0)return(0);
s++;
}
Stop_I2c(); //結束匯流排
return(1);
}
/*----------------------------------------------------------------
向有子地址器件讀取多位元組資料函式
函式原型: bit ISendStr(unsigned char sla,unsigned char suba,ucahr *s,unsigned char no);
功能: 從啟動匯流排到傳送地址,子地址,讀資料,結束匯流排的全過程,從器件
地址sla,子地址suba,讀出的內容放入s指向的儲存區,讀no個位元組。
如果返回1表示操作成功,否則操作有誤。
注意: 使用前必須已結束匯流排。
----------------------------------------------------------------*/
bit IRcvStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no)
{
unsigned char i;
Start_I2c(); //啟動匯流排
SendByte(sla); //傳送器件地址
if(ack==0)return(0);
SendByte(suba); //傳送器件子地址
if(ack==0)return(0);
Start_I2c();
SendByte(sla+1);
if(ack==0)return(0);
for(i=0;i<no-1;i++)
{
*s=RcvByte(); //傳送資料
Ack_I2c(); //傳送就答位
s++;
}
*s=RcvByte();
NoAck_I2c(); //傳送非應位
Stop_I2c(); //結束匯流排
return(1);
}
/*------------------------------------------------
按鍵掃描函式,返回掃描鍵值
------------------------------------------------*/
unsigned char KeyScan(void) //鍵盤掃描函式,使用行列逐級掃描法
{
unsigned char Val;
KeyPort=0xf0;//高四位置高,低四位拉低
if(KeyPort!=0xf0)//表示有按鍵按下
{
DelayMs(10); //去抖
if(KeyPort!=0xf0)
{ //表示有按鍵按下
KeyPort=0xfe; //檢測第一行
if(KeyPort!=0xfe)
{
Val=KeyPort&0xf0;
Val+=0x0e;
while(KeyPort!=0xfe);
DelayMs(10); //去抖
while(KeyPort!=0xfe);
return Val;
}
KeyPort=0xfd; //檢測第二行
if(KeyPort!=0xfd)
{
Val=KeyPort&0xf0;
Val+=0x0d;
while(KeyPort!=0xfd);
DelayMs(10); //去抖
while(KeyPort!=0xfd);
return Val;
}
KeyPort=0xfb; //檢測第三行
if(KeyPort!=0xfb)
{
Val=KeyPort&0xf0;
Val+=0x0b;
while(KeyPort!=0xfb);
DelayMs(10); //去抖
while(KeyPort!=0xfb);
return Val;
}
KeyPort=0xf7; //檢測第四行
if(KeyPort!=0xf7)
{
Val=KeyPort&0xf0;
Val+=0x07;
while(KeyPort!=0xf7);
DelayMs(10); //去抖
while(KeyPort!=0xf7);
return Val;
}
}
}
return 0xff;
}
/*------------------------------------------------
按鍵值處理函式,返回掃鍵值
------------------------------------------------*/
unsigned char KeyPro(void)
{
switch(KeyScan())
{
case 0x7e:return 1;break;// 按下相應的鍵顯示相對應的碼值
case 0x7d:return 4;break;
case 0x7b:return 7;break;
case 0x77:return 0;break;
case 0xbe:return 2;break;
case 0xbd:return 5;break;
case 0xbb:return 8;break;
case 0xb7:return '.';break;
case 0xde:return 3;break;
case 0xdd:return 6;break;
case 0xdb:return 9;break;
case 0xd7:return '=';break;
case 0xee:return '+';break;
case 0xed:return '-';break;
case 0xeb:return '*';break;
case 0xe7:return '/';break;
default:return 0xff;break;
}
}
void clock()
{
unsigned int i;
if(hour == clock_h && min == clock_m && sec <=3)
{
for(i=0;i<1000;i++)
{
DelayMs(1);
SPK=!SPK;
}
}
}
void ISR_T0(void) interrupt 1
{
unsigned char i,num;
TH0 = 0x3c; //50ms
TL0 = 0xb0;
num = KeyPro();
if(num == '+')
{
local++;
if(local == 11)
local = 0;
}
else if( num == '-')
{
local--;
if(local == 0xff)
local = 10;
}
if( local == 0 )
{
i++;
if(i == 20)
{
i = 0;
sec++;
SPK=!SPK;
}
}
}