分享一個紅外遙控風扇和開關的PCB制作,還有程序控制
Altium Designer畫的PCB圖如下:(51hei附件中可下載工程文件)
單片機源程序如下:
- /******************************************************************
- /* STC89C52單片機 *
- /* 11.0592M晶振 *
- /*程序用了外部中斷0接收紅外信號,IO口為P32 *
- /*遙控OK鍵為關閉,在定時設置狀態時為確認 *
- /*遙控上、下鍵為檔位加、減,在設置定時狀態時為定時時間加、減, *
- /*遙控V-鍵為進入設置定時模式 *
- /*右鍵為睡眠模式的開啟與關閉,睡眠模式指定時時間到后自動切為1檔 *
- /*遙控返回鍵為1檔,遙控主頁鍵為2檔,遙控菜單鍵為3檔, *
- /*定時設置狀態時,第二個數碼管為小寫H,設置完成后為大寫H. *
- /*最多定時8小時,99分鐘內顯示分鐘倒計時 *
- /******************************************************************/
- #include <reg52.h>
- #include <intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- #define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};
- #define const_key_time1 20 //按鍵去抖延時的時間
- #define const_1s 440 //大概1秒鐘所需要的中斷數
- void delay_long(unsigned int uiDelaylong);
- void delay(uchar x); //x*0.14MS
- void delay1(int ms);
- void T0_time(); //定時器0中斷函數
- void key_service(); //按鍵服務的應用程序
- void key_scan(); //按鍵掃描函數,放在定時中斷里
- void key_service1(); //關閉的應用程序
- void initial_myself(); //初始化單片機
- void initial_peripheral();//初始化外圍
- void LCD_XSservice(); //數碼管顯示程序
- void display_drive(); //數碼管字模驅動函數
- sfr ISP_CONTR=0xe7; //軟復位地址
- sbit IRIN = P3^2; //紅外接收器數據線,外部中斷0
- sbit K1 = P2^0; //按鍵1
- sbit K2 = P2^1; //按鍵2
- sbit K3 = P2^2; //按鍵3
- //風量1檔最小,3檔最大
- sbit SC1 = P2^3; //1檔輸出,控制PNP三極管,三極管再控制BT136雙向可控硅
- sbit SC2 = P2^4; //2檔輸出,控制PNP三極管,三極管再控制BT136雙向可控硅
- sbit SC3 = P2^5; //3檔輸出,控制PNP三極管,三極管再控制BT136雙向可控硅
- sbit LED1 = P1^0; //檔位指示小燈1
- sbit LED2 = P1^1; //檔位指示小燈2
- sbit LED3 = P1^2; //檔位指示小燈3
- sbit LED4 = P1^3; //睡眠模式指示小燈
- sbit LCD1 = P2^6; //接PNP三極管控制定時顯示數碼管1的陽極(顯示數碼管為共陽管)
- sbit LCD2 = P2^7; //接PNP三極管控制定時顯示數碼管2的陽極(顯示數碼管為共陽管)
- //定時顯示數碼管的八個陰極接P0
- uchar IRCOM[7]; //定義紅外接收數組
- uchar code Tab0[]= //定義數碼管數組,沒有小數點
- {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x89
- };//0,1,2,3,4,5,6,7,8,9,h
- uint code Dingshi0[]= //定義定時數組
- {0,60,120,180,240,300,360,420,480
- };
- unsigned char ly_dis1;//定義顯示緩沖區
- unsigned char ly_dis2;//定義顯示緩沖區
- unsigned char ucKeySec=0; //被觸發的按鍵編號
- unsigned int uiKeyTimeCnt1=0; //按鍵1去抖延時計數器
- unsigned char ucKeyLock1=0; //按鍵1觸發后自鎖的變量標志
- unsigned int uiKeyTimeCnt2=0; //按鍵2去抖延時計數器
- unsigned char ucKeyLock2=0; //按鍵2觸發后自鎖的變量標志
- unsigned int uiKeyTimeCnt3=0; //按鍵3去抖延時計數器
- unsigned char ucKeyLock3=0; //按鍵3觸發后自鎖的變量標志
- unsigned char anjiank=0; //有按鍵被觸發
- unsigned char hw_anjiank=0; //紅外按鍵被觸發
- unsigned char LCDSec=0; //定時設置狀態
- unsigned char LCDszxs=0; //數碼管定時的變量
- unsigned int DSSJ=0; //定時的時間
- unsigned char DSBZ=0; //定時標志
- unsigned char iii=0; //動態數碼管定時顯示變量
- unsigned char posit=0;//動態數碼管掃描步驟
- unsigned int uiTimeCnt=0; //倒計時的時間計數器
- unsigned int js1m=0;//計時秒
- unsigned char Guanbi=0; //關閉標志
- unsigned char SMMS=0; //睡眠模式標志
- unsigned char SMMSJK=0; //睡眠模式監控
- /*******************************************************************/
- main()
- {
- initial_myself(); //初始化
- delay_long(100);
- initial_peripheral();//初始化外圍
-
- while(1)
- {
- key_service1(); //關閉的應用程序
- key_service();//按鍵服務的應用程序
- LCD_XSservice(); //數碼管顯示程序
- }
- }
- //end main
- /**********************************************************/
- void LCD_XSservice() //數碼管顯示程序
- {
- if (DSBZ==1)
- {
- if (DSSJ>60)
- {
- if (DSSJ>99) {iii=2;}
- if (DSSJ>120) {iii=3;}
- if (DSSJ>180) {iii=4;}
- if (DSSJ>240) {iii=5;}
- if (DSSJ>300) {iii=6;}
- if (DSSJ>360) {iii=7;}
- if (DSSJ>420) {iii=8;}
- ly_dis1=iii;//P0口驅動數碼管2到8的定時顯示
- ly_dis2=10; //顯示個位值
- }
-
- if (DSSJ<=99)
- {
- if (DSSJ>0)
- {
- ly_dis1=DSSJ/10; //顯示十位值
- ly_dis2=DSSJ%10; //顯示個位值
- }
- }
- if (DSSJ==0)
- {
-
- if (SMMS==1)
- {
- LCD1=1;
- LCD2=1;
- DSBZ=0;
- LED4=1;
- SMMSJK=0;
- hw_anjiank=1; //表明由紅外按鍵觸發
- ucKeySec=1;//觸發1檔按鍵
- }
- if (SMMS==0)
- {
- if (DSBZ==1)
- {
- ISP_CONTR=0x20; //關閉所有,所有變量清零,軟復位
- }
- }
-
- }
- }
- }
- /**********************************************************/
- void key_scan()//按鍵掃描函數,放在定時中斷里
- {
- if (LCDSec!=1)
- {
- if(K1==1)//IO口是高電平,說明按鍵1一直沒有按下,這時要及時清零一些標志位
- {
- ucKeyLock1=0; //按鍵自鎖標志清零
- uiKeyTimeCnt1=0;//按鍵去抖延時計數器清零
- }
- else if(ucKeyLock1==0)//有按鍵按下,且是第一次按下
- {
- uiKeyTimeCnt1++; //累計定時中斷次數
- if(uiKeyTimeCnt1>const_key_time1)
- {
- uiKeyTimeCnt1=0;
- ucKeyLock1=1; //自鎖按鍵置位,避免一直觸發
- hw_anjiank=0; //表明解除由紅外按鍵觸發
- anjiank=1; //表明由按鍵觸發
- ucKeySec=1; //觸發1檔按鍵
- }
- }
-
- if(K2==1)//IO口是高電平,說明按鍵2一直沒有按下,這時要及時清零一些標志位
- {
- ucKeyLock2=0; //按鍵自鎖標志清零
- uiKeyTimeCnt2=0;//按鍵去抖延時計數器清零
- }
- else if(ucKeyLock2==0)//有按鍵按下,且是第一次按下
- {
- uiKeyTimeCnt2++; //累計定時中斷次數
- if(uiKeyTimeCnt2>const_key_time1)
- {
- uiKeyTimeCnt2=0;
- ucKeyLock2=1; //自鎖按鍵置位,避免一直觸發
- hw_anjiank=0; //表明解除由紅外按鍵觸發
- anjiank=1; //表明由按鍵觸發
- ucKeySec=2; //觸發2檔按鍵
- }
- }
-
- if(K3==1)//IO口是高電平,說明按鍵3一直沒有按下,這時要及時清零一些標志位
- {
- ucKeyLock3=0; //按鍵自鎖標志清零
- uiKeyTimeCnt3=0;//按鍵去抖延時計數器清零
- }
- else if(ucKeyLock3==0)//有按鍵按下,且是第一次按下
- {
- uiKeyTimeCnt3++; //累計定時中斷次數
- if(uiKeyTimeCnt3>const_key_time1)
- {
- uiKeyTimeCnt3=0;
- ucKeyLock3=1; //自鎖按鍵置位,避免一直觸發
- hw_anjiank=0; //表明解除由紅外按鍵觸發
- anjiank=1; //表明由按鍵觸發
- ucKeySec=3; //觸發3檔按鍵
- }
- }
- }
- }
- /**********************************************************/
- void key_service1() //關閉的應用程序
- {
- if(anjiank==1) //判斷按鍵是否有按下,如果按鍵觸發,但三個按鍵都為高電平,那么表示按了按鍵關按鍵
- {
- if(K1&K2&K3==1)
- {
- ISP_CONTR=0x20; //關閉所有,所有變量清零,軟復位
- }
- }
-
- if(hw_anjiank==1)//判斷紅外關按鍵是否按下
- {
- if(Guanbi==1) //關閉標志
- {
- //關閉所有,所有變量清零,軟位
- initial_myself(); //初始化
- delay_long(100);
- initial_peripheral();//初始化外圍
- Guanbi=0; //關閉標志清零
-
- }
- }
-
-
- }
- /**********************************************************/
- void key_service() //按鍵服務的應用程序
- {
- switch(ucKeySec) //按鍵的切換
- {
-
- case 1: //按鍵1--1檔
- LED1 = 1;
- LED2 = 1;
- LED3 = 1;
- LED1 = 0;
- SC2 = 1;
- SC3 = 1;
- delay(300);
- if (SC2&SC3)
- {
- SC1 = 0;
- }
- ucKeySec=0; //響應按鍵服務處理程序后,按鍵編號清零,避免一直觸發
- break;
- case 2: //按鍵2--2檔
- LED1 = 1;
- LED2 = 1;
- LED3 = 1;
- LED1 = 0;
- LED2 = 0;
- SC1 = 1;
- SC3 = 1;
- delay(300);
- if (SC1&SC3)
- {
- SC2 = 0;
- }
- ucKeySec=0; //響應按鍵服務處理程序后,按鍵編號清零,避免一直觸發
- break;
- case 3: //按鍵3--3檔
- LED1 = 1;
- LED2 = 1;
- LED3 = 1;
- LED1 = 0;
- LED2 = 0;
- LED3 = 0;
- SC1 = 1;
- SC2 = 1;
- delay(300);
- if (SC1&SC2)
- {
- SC3 = 0;
- }
- ucKeySec=0; //響應按鍵服務處理程序后,按鍵編號清零,避免一直觸發
- break;
- case 4: //OK按鍵短按
-
- ucKeySec=0; //響應按鍵服務處理程序后,按鍵編號清零,避免一直觸發
- break;
-
- }
- }
- /**********************************************************/
- void IR_IN() interrupt 0 //using 0 接收紅外信號
- {
- unsigned char j,k,N=0;
- EX0 = 0;
- delay(15);
- if (IRIN==1)
- { EX0 =1;
- return;
- }
- //確認IR信號出現
- while (!IRIN) //等IR變為高電平,跳過9ms的前導低電平信號。
- {delay(1);}
- for (j=0;j<4;j++) //收集四組數據
- {
- for (k=0;k<8;k++) //每組數據有8位
- {
- while (IRIN) //等 IR 變為低電平,跳過4.5ms的前導高電平信號。
- {delay(1);}
- while (!IRIN) //等 IR 變為高電平
- {delay(1);}
- while (IRIN) //計算IR高電平時長
- {
- delay(1);
- N++;
- if (N>=30)
- { EX0=1;
- return;} //0.14ms計數過長自動離開。
- } //高電平計數完畢
- IRCOM[j]=IRCOM[j] >> 1; //數據最高位補“0”
- if (N>=8) {IRCOM[j] = IRCOM[j] | 0x80;} //數據最高位補“1”
- N=0;
-
- }//end for k
- }//end for j
-
-
-
- if (IRCOM[2]!=~IRCOM[3])
- { EX0=1;
- return; }
-
- if (LCDSec!=1)
- {
- if (IRCOM[2]==0xC5)//返回鍵 這一步就是判斷,如果對應按鍵,則執行下面動作!
- {
- anjiank=0; //表明解除由按鍵觸發
- hw_anjiank=1; //表明由紅外按鍵觸發
- ucKeySec=1;//觸發1檔按鍵
-
- }
- if (IRCOM[2]==0x88)// 主頁鍵 這一步就是判斷,如果對應按鍵,則執行下面動作!
- {
- anjiank=0; //表明解除由按鍵觸發
- hw_anjiank=1; //表明由紅外按鍵觸發
- ucKeySec=2;//觸發2檔按鍵
-
- }
- if (IRCOM[2]==0x82)//菜單鍵 這一步就是判斷,如果對應按鍵,則執行下面動作!
- {
- anjiank=0; //表明解除由按鍵觸發
- hw_anjiank=1; //表明由紅外按鍵觸發
- ucKeySec=3;//觸發3檔按鍵
-
- }
- }
- if (IRCOM[2]==0xCA)//上鍵,這一步就是判斷,如果對應按鍵,則執行下面動作!
- {
- if (LCDSec==1)//如果在時間設置狀態,就是設置時間的加
- {
- LCDszxs++;
- if (LCDszxs>8)
- {
- LCDszxs=0;
- }
- }
- else //除了時間設置狀態,為風量檔位加
- {
- if (SC1&SC2&SC3)
- {
- ucKeySec=1;
- }
- if (SC1==0)
- {
- ucKeySec=2;
- }
- if (SC2==0)
- {
- ucKeySec=3;
- }
- anjiank=0; //表明解除由按鍵觸發
- hw_anjiank=1; //表明由紅外按鍵觸發
- }
- }
- if (IRCOM[2]==0xD2)//下鍵,這一步就是判斷,如果對應按鍵,則執行下面動作!
- {
- if (LCDSec==1)//如果在時間設置狀態,就是設置時間的減
- {
- if (LCDszxs>0)
- {
- LCDszxs--;
- }
- if (LCDszxs==0)
- {
- LCDszxs=8;
- }
- }
- else //除了時間設置狀態,為風量檔位減
- {
- if (SC1==0)
- {
- Guanbi=1; //關閉標志打開
- }
- if (SC2==0)
- {
- ucKeySec=1;
- }
- if (SC3==0)
- {
- ucKeySec=2;
- }
- anjiank=0; //表明解除由按鍵觸發
- hw_anjiank=1; //表明由紅外按鍵觸發
- }
- }
-
- if (IRCOM[2]==0x81)// V-鍵 這一步就是判斷,如果對應按鍵,則執行下面動作!定時設置
- {
- if ((SC1&SC2&SC3)==0)
- {
- LCDSec=1; //定時設置狀態,數碼管閃動
- LCDszxs=0; //數碼管定時的變量
- LCD1=0;
- LCD2=0;
- }
- }
-
- if (IRCOM[2]==0xce)//OK鍵 這一步就是判斷,如果對應按鍵,則執行下面動作!確認并退出定時設置
- {
- if (LCDSec==1)
- {
- if (LCDszxs>0)
- {
- DSSJ=Dingshi0[LCDszxs];
- DSBZ=1;
- LCDSec=0;
- SMMSJK=0;
- }
- else
- {
- LCD1=0;
- LCD2=0;
- LCDSec=0;
- }
- }
- else
- {
- initial_myself(); //初始化
- delay_long(100);
- initial_peripheral();//初始化外圍
- Guanbi=0; //關閉標志清零
- }
- }
-
- if (IRCOM[2]==0xC1)//右鍵,這一步就是判斷,如果對應按鍵,則執行下面動作!
- {
- if ((SC1&SC2&SC3)==0)
- {
- if (LCDSec==0)
- {
- LED4=!LED4; //LED4取反
-
- if (LED4==0)
- {
- SMMS=1;
- if (DSBZ==0)
- {
- if(SMMSJK==0)
- {
- LCD1=0;
- LCD2=0;
- LCDszxs=3;
- DSSJ=Dingshi0[LCDszxs];
- DSBZ=1;
- SMMSJK=1;
- }
- }
- }
- if (LED4==1)
- {
- SMMS=0;
-
- if (DSBZ==1)
- {
- if(SMMSJK==1)
- {
- LCD1=1;
- LCD2=1;
- DSBZ=0;
- LCDszxs=0;
- DSSJ=Dingshi0[LCDszxs];
- SMMSJK=0;
- }
- }
- }
- }
- }
- }
-
-
- EX0 = 1;
- }
- /**********************************************************/
- void display_drive() //數碼管字模驅動函數
- {
- if (DSBZ|LCDSec)
- {
- switch(posit)
- {
- case 1:
- LCD1=0;
- LCD2=1;
- if (LCDSec==1)
- {
- P0=Tab0[LCDszxs];//P0口驅動數碼管0到8的定時顯示
- }
- else
- {
- P0=Tab0[ly_dis1];//P0口驅動數碼管1到8的定時顯示
- }
- break;
- case 2:
- LCD1=1;
- LCD2=0;
- if (LCDSec==1)
- {
- P0=0X8b;//顯示H
- }
- else
- {
- P0=Tab0[ly_dis2];//P0口驅動數碼管1到8的定時顯示
- }
- break;
- }
- posit++;
- if(posit>2)
- {
- posit=1;
- }
- }
- else
- {
- LCD1=1;
- LCD2=1;
- }
- }
- /**********************************************************/
- void T0_time() interrupt 1 //定時器0函數
- {
- TF0=0; //清除中斷標志
- TR0=0; //關中斷
- key_scan(); //按鍵掃描函數
-
- if(DSBZ==1) //啟動定時倒計時計數器
- {
- uiTimeCnt++;
- if(uiTimeCnt>=const_1s) //1秒時間到
- {
- js1m++;
- if (js1m==210)
- {
- if(DSSJ!=0) //防止倒計時到0秒
- {
- DSSJ--; //倒計時值減1
- }
- js1m=0;
- }
-
- uiTimeCnt=0; //計時器清零,準備重新開始
- }
- }
- display_drive(); //數碼管字模驅動函數
- TH0=0xfe; //重裝初始值(65535-500)=635035=0xfe0b
- TL0=0x0b;
- TR0=1; //開中斷
- }
- /*******************************************************/
- void initial_myself() //初始化單片機
- {
-
-
- //I/O口初始化
- IRIN=1; //紅外接收器數據線,外部中斷0
- K1 = 1; //按鍵1
- K2 = 1; //按鍵2
- K3 = 1; //按鍵3
- SC1 = 1; //1檔輸出
- SC2 = 1; //2檔輸出
- SC3 = 1; //3檔輸出
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
51hei附件下載:
程序+PCB文件.7z
(1.45 MB, 下載次數: 92)
2022-4-30 16:27 上傳
點擊文件名下載附件
|