C源程序,
main.rar
(3.36 KB, 下載次數: 49)
2020-4-9 08:56 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
- #include <reg52.H>
- //--------數碼管段選定義--------
- #define LEDPORT P0
- #define uchar unsigned char
- #define uint unsigned int
- //--------數碼管位選定義--------
- sbit D1=P2^0;
- sbit D2=P2^1;
- sbit D3=P2^2;
- sbit D4=P2^3;
- sbit D5=P2^4;
- sbit D6=P2^5;
- //--------DS1302接口定義--------
- sbit CLK =P3^7;
- sbit IO =P3^6;
- sbit RST =P3^1;
- //--------狀態標記--------
- sbit LED1=P2^6;
- sbit LED2=P2^7;
- sbit ACC0=ACC^0;
- sbit ACC7=ACC^7;
- unsigned char hour,min,sec; //小時、分鐘、秒
- bit rev_start,rev_stop; //GPS接收開始、結束標志位
- unsigned char code tab[ ]={
- 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,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;
- /******************************************************************************************
- *函數名稱:Timer_Init
- *功能描述:定時器初始化
- ******************************************************************************************/
- 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);
- }
- //--------DS1302初始化--------
- 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 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 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]˙ //最高位"0",消隱字符
- 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];
- D5=0;
- D1=D2=D3=D4=D6=1;
- break;
- case 5:
- LEDPORT=tab [c%16];
- D6=0;
- D1=D3=D4=D5=D2=1;
- break;
- }
- i++;
- if(i==6)i=0;
- }
- /******************************************************************************************
- *函數名稱:main
- *功能描述:主函數
- ******************************************************************************************/
- 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
- {
- LED1=1;
- 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=0x7f;
- 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;
- }
- }
- /******************************************************************************************
- *函數名稱:timer0
- *功能描述:紅外解碼計算脈沖寬度
- ******************************************************************************************/
- 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;
- if (ch == 'R') //如果收到字符'
- ,便開始接收
- {
- rev_start = 1;
- rev_stop = 0; //接收停止標志
- }
- if (rev_start == 1) //標志位為1,開始接收
- {
- buf[num++] = ch; //字符存到數組中
- if (ch == '.') //如果接收到換行
- {
- buf[num] = '\n';
- rev_start = 0;
- rev_stop = 1; //接收停止標志
- num = 0;
- }
- }
- }
- RI = 0; //RI清0,重新接收
- ES = 1; //串口1中斷允許
- }
- /******************************************************************************************
- *函數名稱:Timer2
- *功能描述:定時刷新顯示
- ******************************************************************************************/
- void Timer2() interrupt 5 //2mS //用于刷新數碼管的顯示
- {
- TF2=0; //定時器2必須由軟件對溢出標志位清零,硬件不能清零,這里與定時器0和定時器1不同!!!
- switch(set)
- {
- case 0:
- Display(hour,min,sec);
- LED1=0;
- LED2=0;
- break;
- case 1:
- Display(hour,0xaa,0xaa);
- LED1=0;
- LED2=1;
- break;
- case 2:
- Display(0xaa, min,0xaa);
- break;
- case 3:
- Display(0xaa, 0xaa,sec);
- LED1=1;
- LED2=0;
- break;
- }
- cnt++;
- }
復制代碼
|