啥也別嘮了,給你看一下最簡單的六位時鐘的一部分程序
#include <reg52.H> //為了布線方便用到了P4口,故包含了STC專用的頭文件,可以在STC-ISP軟件中下載
#define LEDPORT P0
#define uchar unsigned char
#define uint unsigned int
sbit D1=P3^3;
sbit D2=P3^4;
sbit D3=P3^5;
sbit D4=P3^6;
sbit D5=P3^7;
sbit D6=P4^0;
sbit LED1=P2^5;
sbit LED2=P2^6;
sbit CLK =P2^1;
sbit IO =P2^2;
sbit RST =P2^3;
sbit ACC0=ACC^0;
sbit ACC7=ACC^7;
unsigned char hour,min,sec; //小時、分鐘、秒
bit rev_start,rev_stop; //GPS接收開始、結束標志位
unsigned char code tab[ ]={0xA0,0xBE,0x64,0x2C,0x3A,0x29,0x21,0xBC,0x20,0x28,0xFF};//0-9,滅
unsigned char buf[10]; //GPS數據接收緩沖
unsigned char irtime;//紅外用全局變量,用于計算2個下降沿之間的時間
bit decode_ok,irok;
static unsigned char ircode[4];
unsigned char irdata[33];
uchar set,temp,dot;
bit flag,test;
uint cnt;
void Timer_Init()
{
TMOD=0x22;
TH0=0x00; //重載值
TL0=0x00; //初始化值
ET0=1; //開中斷
TR0=1;
IT0 = 1; //指定外部中斷0下降沿觸發,INT0 (P3.2)
EX0 = 1; //使能外部中斷
TL2 = 0xCD; //設置定時初值
TH2 = 0xF8; //設置定時初值
RCAP2L = 0xCD; //設置定時重載值
RCAP2H = 0xF8; //設置定時重載值
ET2=1;
TR2=1;
TH1 = 0xFD; //9600波特率的初值
TL1 = TH1; //9600波特率的初值
TR1 = 1;
SCON = 0x50; //使用串行工作方式1,10位異步收發8位數據,波特率可變(由T1的溢出率控制)
// ES = 1;
EA=1;
}
void inputbyte(unsigned char ucDa)
{
unsigned char i;
ACC = ucDa;
for(i=8; i>0; i--)
{
IO = ACC0; //相當于匯編中的 RRC
CLK = 1;
CLK = 0;
ACC = ACC >> 1;
}
}
unsigned char outputbyte(void)
{
unsigned char i;
for(i=8; i>0; i--)
{
ACC = ACC >>1; //相當于匯編中的 RRC
ACC7 = IO;
CLK = 1;
CLK = 0;
}
return(ACC);
}
void write(unsigned char ucAddr, unsigned char ucDa)
{
RST = 0;
CLK = 0;
RST = 1;
inputbyte(ucAddr); //地址,命令
inputbyte(ucDa); //寫1Byte數據
CLK = 1;
RST =0;
}
unsigned char read(unsigned char ucAddr)
{
unsigned char ucDa;
RST = 0;
CLK = 0;
RST = 1;
inputbyte(ucAddr); //地址,命令
ucDa = outputbyte(); //讀1Byte數據
CLK = 1;
RST =0;
return(ucDa);
}
void DS1302_init()
{
if(read(0xc1)!=0x82) //如果1302掉電,寫入下面的初始值
{
write(0x8e,0x00);//關閉寫保護
write(0x80,0x22); //設置秒
write(0x82,0x22);//設置分鐘
write(0x84,0x22); // 小時
write(0x90,0xa5);//涓流充電
write(0xc0,0x82);//掉電標志位
}
}
void decode(void)//紅外碼值處理函數
{
unsigned char i, j, k;
unsigned char cord,value;
k=1;
for(i=0;i<4;i++) //處理4個字節
{
for ( j=1; j<=8; j++) //處理1個字節8位
{
cord=irdata[k];
if(cord>7)//大于某值為1,這個和晶振有絕對關系,這里使用12M計算,此值可以有一定誤差
{
value=value|0x80;
}
else
{
value=value;
}
if(j<8)
{
value=value>>1;
}
k++;
}
ircode[i]=value;
value=0;
}
if(ircode[2]==~ircode[3])
decode_ok=1;//解碼完畢后標志位置1
}
void Display(unsigned char a,b,c) //數碼管顯示
{
static unsigned char i;
LEDPORT=0xff;
switch (i)
{
case 0: if(a/16) LEDPORT=tab[a/16]˙ else LEDPORT=tab[10]˙D1=0;D2=D3=D4=D5=D6=1; break;
case 1: LEDPORT=tab [a%16]; D2=0;D1=D3=D4=D5=D6=1; break;
case 2: LEDPORT=tab [b/16]; D3=0;D1=D2=D4=D5=D6=1; break;
case 3: LEDPORT=tab [b%16]; D4=0;D1=D2=D3=D5=D6=1; break;
case 4: LEDPORT=tab [c/16]; D6=0;D1=D2=D3=D4=D5=1; break;
case 5: LEDPORT=tab [c%16]; D5=0;D1=D3=D4=D6=D2=1; break;
}
i++;
if(i==6)i=0;
}
void ir_work()
{
if(ircode[2]==0x1e)
test=!test;
if(ircode[2]==0x05)
{
set++;
if(set==4)
set=0;
}
if(set==1)
{
if(ircode[2]==0x02|ircode[2]==0x06) //hour
{
temp=(read(0x85)/16)*10+read(0x85)%16;
temp++;if(temp==24)temp=0;
write(0x84,(temp/10)*16+temp%10);
}
if(ircode[2]==0x08|ircode[2]==0x04)
{
temp=(read(0x85)/16)*10+read(0x85)%16;
temp--;if(temp==-1)temp=23;
write(0x84,(temp/10)*16+temp%10);
}
}
if(set==2) //min
{
if(ircode[2]==0x02|ircode[2]==0x06)
{
temp=(read(0x83)/16)*10+read(0x83)%16;
temp++;if(temp==60)temp=0;
write(0x82,(temp/10)*16+temp%10);
}
if(ircode[2]==0x08|ircode[2]==0x04)
{
temp=(read(0x83)/16)*10+read(0x83)%16;
temp--;if(temp==-1)temp=59;
write(0x82,(temp/10)*16+temp%10);
}
}
if(set==3) //sec
{
if(ircode[2]==0x02|ircode[2]==0x06)
{
temp=(read(0x81)/16)*10+read(0x81)%16;
temp++;if(temp==60)temp=0;
write(0x80,(temp/10)*16+temp%10);
}
if(ircode[2]==0x08|ircode[2]==0x04)
{
temp=(read(0x81)/16)*10+read(0x81)%16;
temp--;if(temp==-1)temp=59;
write(0x80,(temp/10)*16+temp%10);
}
}
decode_ok=0;
}
void main()
{
Timer_Init();
DS1302_init();
dot=0xff;
flag=1;
while(1)
{
hour= read(0x85);
min = read(0x83);
sec = read(0x81);
/* if((hour==0x08)&&(min==0x00) ) //可以設置為每天的某個時間打開GPS對一下時間再關掉,這里設置的是8:00
ES=1;
else
ES=0;*/
if(flag==1&&cnt>500) //上電稍做延時再打開串口,防止數碼管顯示出錯
{
flag=0;
cnt=0;
ES=1;
}
if((rev_stop==1)&&(buf[1]=='M')&&(buf[2]=='C')&&(buf[3]==','))//如果接收到GPRMC 就把GPS接收到的時間寫入DS1302
{
ES=0;
hour= (buf [4]-0x30)* 16+ buf[5] -0x30;
min= (buf [6]-0x30)* 16+ buf[7]-0x30;
sec= (buf[8]-0x30)* 16+ buf[9]-0x30;
hour= hour / 16 * 10 + hour % 16;
hour= (hour+8) % 24; //UTC Time換算成北京時間
hour=hour/10*16+hour%10;
write(0x84,hour);
write(0x82,min);
write(0x80,sec);
ES=1;
rev_stop=0;
}
if( sec== (buf[8]-0x30)* 16+ buf[9]-0x30) //用左上角的小點顯示有無GPS信號
dot=0xdf;
else
dot=0xff;
if(irok) //如果接收到正確的紅外信號后進行紅外處理
{
decode();
irok=0;
}
if(decode_ok) //如果解碼正確就進入調時程序
{
ir_work();
}
if(test) //需要時可以遙控關閉屏幕
{
ET2=0;
P0=0xff;
LED1=LED2=1;
}
else
{
ET2=1;
}
}
}
void int0 (void) interrupt 0 //外部中斷0服務函數 用于紅外解碼
{
static unsigned char i; //接收紅外信號處理
static bit startflag; //是否開始處理標志位
if(startflag)
{
if(irtime<63&&irtime>=33)//引導碼 TC9012的頭碼,9ms+4.5ms
i=0;
irdata[i]=irtime;//存儲每個電平的持續時間,用于以后判斷是0還是1
irtime=0;
i++;
if(i==33)
{
irok=1;
i=0;
}
}
else
{
irtime=0;
startflag=1;
}
}
void timer0 (void) interrupt 1 //定時器0中斷服務函數 ,紅外解碼
{
irtime++; //計算2個下降沿之間的時間
}
void Uart_Receive(void) interrupt 4 //串口中斷,用于GPS數據接收
{
unsigned char ch,num;
ES = 0;
if (RI) //如果接收完成則進入
{
ch = SBUF;
|