[注]:
一眨眼,大學接近尾聲,具有找工作需要,所以把大學做的電子設計“劣作”放上來。希望考研失意,還能趕上“好工作”的春招班車。如果大伙有什么工作推薦也可以聯系我哦,因為一年考研少接觸了這方面,所以難免有些生疏。但請相信我!給我機會我會很認真學的!
郵箱:lydmom@163.com
轉載請注明出處呀!
基於51單片機的紅外遙控課程設計
目錄
第一章 設計簡介... 3
第二章 系統方案... 3
一、設計方案對比... 3
二、方案設計... 4
第三章 硬件設計... 5
一、紅外遙控器... 5
二、紅外接收模塊部分... 7
第四章 軟件設計... 8
一、紅外遙控器軟件設計... 8
二、紅外接收模塊軟件設計... 11
三、程序代碼... 11
第五章 測試及分析... 11
第六章 結論... 11
第七章 參考文獻... 12
附錄一(程序代碼):... 13
第一章 設計簡介
本設計分為紅外遙控器與紅外接收模塊兩部分。紅外遙控器包括矩陣鍵盤、增強型51單片機(STC11L04E)、紅外發射電路組成。單片機掃描矩陣鍵盤后,將按鍵狀態進行信源編碼與信道編碼,載波(38k脈沖)后由紅外發射器發射。紅外接收模塊部分由傳統51單片機、數碼管、一體化紅外接收頭組成。一體化紅外接收頭將信號進行限幅放大、帶通濾波、解調、積分、整形后輸出解調信號至單片機,並由單片機輸出解調信號。
第二章 系統方案
一、設計方案對比
紅外遙控器部分
2.1.1 主控芯片
方案一:HT6222
方案二:STC11L04E
分析 :傳統紅外遙控器芯片HT6222具有性價比高、功能強大、穩定可靠、使用簡單等特點,但該芯片難以零購。STC11L04E為增強型51單片機,控制靈活(載波頻率可調、通信協議可變更、用戶碼可變換)、價格較HT6222稍貴。STC11L04E最大的特別是低功耗,功作電壓低3.3V,易於應用於移動設備。
結論 :由於STC11L04E單片機的靈活性以及學習性(可增強我們對一個完整通信系統的理解)。因此我們采用方案二。
2.1.2 矩陣鍵盤
方案一:3*6*2.5 貼片輕觸開關
方案二:6*6*6 直插輕觸開關
分析 :3*6*2.5貼片輕觸開關雖然體積小巧、美觀,但與6*6*6直插輕觸開關對比,在制板布線上較繁鎖。
結論 :綜上,我們采用6*6*6直插輕觸開關,使得整體布線簡單,可布單面版,簡化制板流程。
2.1.3電源模塊
方案一:鈕扣電池CR2032
方案二:可充電鋰電池18650
分析 : 可充電鋰電池18650容量大,節能環保(可多次利用),但體積大。鈕扣電池CR2032價格低廉、替換容易、體積輕巧。
結論 :基於紅外遙控器的便攜性考慮,我們采用方案一。
2.1.4 紅外發射管
方案一:3mm 紅外發射管
方案二:5mm 紅外發射管
分析 :方案一與方案二的區別在於直徑越大發射管發射距離更遠、信號穩定。
結論 :鑒於發射距離,我們采用5mm 紅外發射管。
紅外接收模塊部分
2.1.5電源電路
方案一:線性電源AMS1117。AMS1117系列。
方案二:開關電源LM2576。
分析 :AMS1117系列含有可調(ADJ)與固定輸出兩種。AMS1117具有性價比高、體積小、外部電路簡單、輸出電流大(800mA)、最大輸入電壓達16V等特點。其固定輸出AMS1117-5.0甚至可以在僅加一個SS14二極管的情況下穩定工作,但為了增強其穩定性,我們在其輸出輸入端各加一個10uF電解電容。LM2576系列開關,穩壓集成電路是線性三端穩壓器件的替代品,它具有可靠的工作性能,較高的工作效率,和較強的輸出電流驅動能力,從而可為單片機的穩定可靠工作提供強有力的保證。
結論 :雖然LM2576性能極佳,但在本系統對於體積、外部電路、性價比的要求上進行衡量。我決定采用AMS1117-5.0作為供電系統。
二、方案設計
(圖2.2.a紅外遙控器部分)
(圖2.2.b紅外接收模塊部分)
第三章 硬件設計
一、紅外遙控器
單片機由CR2032鈕扣電池供電。STC11L04E對矩陣鍵盤進行按鍵掃描,並將按鍵狀態進行信源編碼、信道編碼,載波后由紅外發射管向外發射信號。
(圖3.1.a )
二、紅外接收模塊部分
單片機電源由AMS1117-5.0芯片供電。STC89C52將一體化紅外接收器傳來的信號進行解調,並輸出顯示至數碼管。
(圖3.1.a )
第四章 軟件設計
一、紅外遙控器軟件設計
(圖4.1.a 主函數)
(圖4.1.b 發送一串數據)
(圖4.1.c 定時器0中斷)
(圖4.1.d 發送一字節)
二、紅外接收模塊軟件設計
(略)
三、程序代碼
(見附錄一)
第五章 測試及分析
測試量 |
參數 |
傳輸距離 |
|
誤碼率 |
|
第六章 結論
一、電子技術
- 增強型51單片機如STC11、12、15系列單片機的實際運行速度為傳統51單片機的8~12倍。在將程序從傳統51單片機移植至增強型51單片機時,時序上只需將延時常數乘以8~12倍,調試可得最佳延時常數。
- 按鍵掃描程序應添加延時函數以消除按鍵抖動。
- 常見紅外遙控器使的協議有:ITT protocol、NEC protocol、Nokia NRC17 protocol、Sharp protocol等。
- 由於共射放大電路輸出的波形與輸入信號波形相反、一體化紅外接收頭輸出信號波形與輸入波形又相反,故由單片機調制后輸出的波形信號應與紅外接收頭輸出信號波形相同,即采用負脈沖載波。
- 不同延時函數的延時效果不一樣,有些延時函數的延時時長與形參成正比,有些呈對數關系。
- 單片機時鍾頻率與晶振頻率、諧振電容、晶振引腳長度有關。12M的晶振可選22~30pF的電容,30M的晶振可選30~33pF電容,24M的晶振可選20~22pF的電容。
- 畫PCB的時候要選合適的封裝。不應0603封裝的電容誤選1206的封裝。
- 調試程序時序可以借助示波器、軟件的Debug功能。
- 在這次合作設計中,加強了我們團隊配合能力。
- 培養了我們膽大,心細,謹慎的工作作風。
- 養成了敢於發現問題,解決問題的習慣
- 在調試過程中,要多利用萬用表、示波器等電子儀器。
二、心得體會
第七章 參考文獻
[1] 《HT6122.pdf》 NEC著
[2] 《全面了解紅外遙控》 San Bergmans著
[3] 《STC11L04E.pdf》 宏晶科技著
[4] 《例說51單片機(C語言版)(第3版)》 張義和著
[5] 《模擬電子技術基礎(第四版)》 華成英.童詩白著
[6] 《Altium Designer原理圖與PCB設計》 穆秀春著
[7] 《通信原理》 樊昌信著
[8] 《通信原理》 周烔槃著
附錄一(程序代碼):
紅外遙控器程序
/*----------------------Item Description----------------------------------- - Project Name : IR_Remote/基於單片機的紅外遙控課程設計 - Files : - Description : 本設計基於單片機的紅外遙控,具有穩定可靠、指令、 地址可自定義、控制距離遠等特點。 - IDE : Keil uVision4 - Author : Mason 別名:小菜 - Email Address : 1609099954@qq.com - Create Date : 2013/6/7 - Performance : Finished - ------------------------------------------- - Revision History - No. Date Revised by Item Description - -------------------------------------------------------------------------*/ /*----------------------------Head---------------------------------------*/ #include <reg52.H> #include "keyboard3_3.H" #include "IR_Tran.H" /*----------------------------Grobal Variable----------------------------*/ char cmd=0,lastcmd=0,ctemp; /*----------------------------Code---------------------------------------*/ void main() { IRtimer_Init(); while(1) { ctemp = scankeyboard3_3(); if(ctemp!=NULL) cmd = ctemp;
if(cmd != lastcmd){ IR_send(cmd); lastcmd = cmd; } } } |
/*----Head Description---- - File Name : IR_Tran.H - Author : Mason 別名:小菜 - Create Date : 2013/6/7 - ------------------------------------------- - Revision History - No. Date Revised by Item Description - -------------------------------------------------------------------------*/ #ifndef _IR_TRAN_H_ #define _IR_TRAN_H_
#include "MICRO.H"
void IRtimer_Init(void); // 定時器初使化 void IR_Pulse(void); // 頻率為精准38k方波(截波) void IR_send(char cmd); // 發送指令
#endif |
/*----File Description---- - File Name : IR_Tran.c - Functions : void IRtimer_Init(void);void IR_Pulse(void); void timer0() interrupt 1 void IR_send(char cmd); - Description : 紅外遙控的驅動程序,調節IR_Pulse函數中的dt可將 程序從傳統51單片機移殖至增強型(1T)51單片機。 更改iraddr的值可以改變遙控器的地址。 本設計的晶振采用12M,但實際中只有11.89M,因此為了 使遙控器反應更准確,需根據實際振盪頻率調節 void IR_Pulse(void)的延時環節,最終使用頻率計測試. - Author : Mason 別名:小菜 - Create Date : 2013/6/7 - Performance : Finished - Global Variable : None - File static Variable : None - ------------------------------------------- - Revision History - No. Date Revised by Item Description - -------------------------------------------------------------------------*/ /*----------------------------Head---------------------------------------*/ #include <reg52.H> #include "MICRO.H" #include "intrins.H" /*----------------------------Micro--------------------------------------*/ // 由於晶振有誤差,以下測量值是用示波器調試出來的,晶振此時頻率11.89M #define TH0_0P ((65536-544)/256) // 560us #define TL0_0P ((65535-544)%256) #define TH0_0 ((65536-515)/256) // 560us #define TL0_0 ((65536-515)%256) #define TH0_1 ((65536-1650)/256) // 1690us #define TL0_1 ((65535-1650)%256)
sbit IR_OP = P3^7; /*----------------------------Grobal Variable----------------------------*/ bit timer_f = 1; // 定時器計時狀態位 char const iraddr = 0xff; // 遙控器本機地址 char temp; // 程序引用的臨時變量 /*----------------------------Code---------------------------------------*/ void IRtimer_Init(void) // 定時器初使化 { TMOD = 0x01; // 16 bit timer EA = 1; ET0 = 1; }
void IR_Pulse(void) // 頻率為精准38k方波(截波) { // 需根據實際原器件而定。 unsigned char dt ; // 本設計實際晶振頻率為11.89M IR_OP = 0; // 增強型單片機請將延時環節的 for(dt = 71;dt>0;dt--); // 延時系數"dt = 7"改為"dt = _nop_(); // 71" IR_OP = 1; // 由於發射管采用共射放大電路, } // 故載波為下降沿脈沖。
void timer0() interrupt 1 // 定時器中斷 { timer_f = 0; } void IR_Send_Byte(char ca) // cmd or addr { for(temp = 0x01;temp != 0x00;temp <<= 1) { TR0 = 0; TH0 = TH0_0P; // 560us高電平 TL0 = TL0_0P; timer_f = 1; TR0 = 1; while(timer_f) IR_Pulse();
if((temp&ca) == 0){ TH0 = TH0_0; // 560us低電平 TL0 = TL0_0; }else{ TH0 = TH0_1; // 1690us低電平 TL0 = TL0_1; } timer_f = 1; while(timer_f); } }
void IR_send(char cmd) // 發送指令 { TH0 = (65536-9000)/256; // 9ms前導高電平 TL0 = (65535-9000)%256; TR0 = 1; timer_f = 1; while(timer_f) IR_Pulse(); // 載波 TH0 = (65536-4500)/256; // 4.5ms前導低電平 TL0 = (65535-4500)%256; timer_f = 1; while(timer_f); // 延時
// 發送地址原碼 IR_Send_Byte(iraddr);
// 發送地址反碼 IR_Send_Byte(~iraddr);
// 發送操作原碼 IR_Send_Byte(cmd);
// 發送操作反碼 IR_Send_Byte(~cmd);
TR0 = 0; // 560us后導脈沖序列 TH0 = TH0_0P; TL0 = TL0_0P; timer_f = 1; TR0 = 1; while(timer_f) IR_Pulse();
TR0 = 0; } |
/*----Head Description---- - File Name : keyboard3_4.h - Author : Mason 別名:小菜 - Create Date : 2013/6/7 - ------------------------------------------- - Revision History - No. Date Revised by Item Description - -------------------------------------------------------------------------*/ #ifndef __KEYBOARD3_3_H__ #define __KEYBOARD3_3_H__
/*********************************************************** *scankeyboard3*4:return 0_12 by every touch, else return 16* ***********************************************************/
#define NULL -1 extern char scankeyboard3_3(void);
#endif |
/*----File Description---- - File Name : keyboard3_3.c - Functions : - Description : None
- Author : Mason 別名:小菜 - Create Date : 2013/6/7 - Performance : Finished - Global Variable : None - File static Variable : None - ------------------------------------------- - Revision History - No. Date Revised by Item Description - -------------------------------------------------------------------------*/ /*----------------------------Head---------------------------------------*/ #include "keyboard3_3.h" #include <keyboard3_3.h> #include <reg52.h>
/*----------------------------Micro--------------------------------------*/ /********************************************************* *keyboard3*3:return 0-12 by every touch, else return null* *********************************************************/ #define KEYB P1 char scannum[3]={0xfe,0xfd,0xfb};
/*----------------------------Code---------------------------------------*/ /*Oscillator frequence choose 11.0592MHz ,the debouncert is 600 Oscillator frequence choose 12MHz,the debouncert is 700*/ void debouncer() { unsigned int debouncert; for(debouncert=328;debouncert>0;debouncert--); } char scankeyboard3_3(void) { char column,row; for(row = 0;row < 3;row++) { KEYB = scannum[row]; debouncer(); column = (~KEYB)&0x0f; if(column != 0){ switch(column) { case 0x20:{column = 0; break;} case 0x40:{column = 1; break;} case 0x80:{column = 2; break;} } while((~KEYB&0x0e)!=0); // 去除長按 debouncer(); return (row*3+column); } } return NULL; } |
/*----Head Description---- - File Name : MICRO_H - Author : Mason 別名:小菜 - Create Date : 2013/3/5 - ------------------------------------------- - Revision History - No. Date Revised by Item Description - -------------------------------------------------------------------------*/
#ifndef _MICRO_H_ #define _MICRO_H_
//#include <STC12C5A.H> #include <reg52.H>
//MICRO typedef unsigned int uint16; typedef int WORD; typedef long int DWORD; typedef unsigned char uchar; typedef char BYTE;
// ADC 啟動轉換 #define EN_ADC0 0xf8 // 選擇 P1.n ADC引腳,並使能 ADC_START. #define EN_ADC1 0xf9 #define EN_ADC2 0xfa #define EN_ADC5 0xfd #define EN_ADC6 0xfe #define EN_ADC7 0xff
#endif |
紅外接收模塊程序
/*----------------------Item Description----------------------------------- - Project Name : IR_Receiver - Files : - Description : None
- IDE : Keil uVision4 - Author : Mason 別名:小菜 - Email Address : 1609099954@qq.com - Create Date : 2013/6/10 - Performance : Finished - ------------------------------------------- - Revision History - No. Date Revised by Item Description - -------------------------------------------------------------------------*/ /*----------------------------Head---------------------------------------*/ #include <reg52.H> #include "NixieTube.H" #include "MICRO.H" #include "IR.H" /*----------------------------Grobal Variable----------------------------*/ extern uchar IR_value[6];
/*----------------------------Code---------------------------------------*/ void main() { IR_init();
while(1); } |
/*----Head Description---- - File Name : IR.H - Author : Mason 別名:小菜 - Create Date : 2013/4/22 - ------------------------------------------- - Revision History - No. Date Revised by Item Description - -------------------------------------------------------------------------*/ /* 對應按鍵編碼 - 45 46 47 - 44 40 43 - 07 15 09 - 16 19 0D - 0C 18 5E - 08 1C 5A - 42 52 4A -------------*/
#ifndef _IR_H_ #define _IR_H_
#define uchar unsigned char #define uint unsigned int
sbit IRIN = P3^2; // 紅外傳感器引腳
void IR_init(void); void IR_Delay(uchar t1); // 0.15ms
#endif |
/*----File Description---- - File Name : IR.c (infrared remoted control) - Functions : 該文件用於處理紅外傳感器信號。適用於傳統51單片機 增強型51單片機需適當調速延時函數。晶振頻率為12M。 占用外部中斷0;不需定時器中斷。只需調用IR_init(void); 便可從全局變量IR_value[4]/IR_value[5]分別讀取紅外用 戶碼(0x00)與操作碼。 - Description : 對應按鍵編碼: - 45 46 47 - 44 40 43 - 07 15 09 - 16 19 0D - 0C 18 5E - 08 1C 5A - 42 52 4A - Author : Mason 別名:小菜 - Create Date : 2013/4/22 - Performance : Finished - Global Variable : uchar IR_value[6]; - File static Variable : None - ------------------------------------------- - Revision History - No. Date Revised by Item Description - -------------------------------------------------------------------------*/ #include <reg52.H> #include "NixieTube.H" #include "IR.H"
uchar IR_value[6]; uint t = 0;
void IR_init(void) { IE |= 0x81; // EA = 1;EX0 =1;ET0=1; TCON |= 0x01; // IT0 = 1;下降沿觸發 IRIN = 1; // 將引腳拉高 }
/*----Function Description---- - Function Name : void IR_Delay(uchar t1) - Description : 線性延時子函數 延時 t1*0.15ms - Return Code : None - Parameters/Arguments : None - Global Variable : None - static Variable : None -------------------------------------------------------------------------*/ void IR_Delay(uchar t1) // t1*0.15ms { uchar t2; while(t1--) for(t2=0;t2<13;t2++); }
/*----Function Description---- - Function Name : void IR_Get(void) - Description : 外部中斷讀到紅外前導信號后調用。將4個字節的用 戶碼與操作碼放於IR_value[0:3]中。 - Return Code : IR_value[0:3] - Parameters/Arguments : None - Global Variable : IR_value[0:3] - static Variable : None -------------------------------------------------------------------------*/ void IR_Get(void) { uchar i,j,k=0; IR_Delay(5); // 稍做延時,去除干擾,增強型單片機將5改為10 if(IRIN == 1) return; // 檢測低電平是否有效 while(!IRIN); // 去除9ms前導低電平 while(IRIN) ; // 去除4.5ms前導高電平 for(i=0;i<4;i++) // 4個字節數據 { for(j=0;j<8;j++) // 8個位 { //while(IRIN) IR_Delay(1); while(!IRIN); // 去除560us while(IRIN) // 軟件計時 { IR_Delay(1);// 將 1 改為 9 可移殖至12M 1T 單片機 k++; // 如STC 12C5A60S2 if(k>=30) {k=0; return;} // 時間過長自動返回 } IR_value[i] = IR_value[i] >> 1; if(k>=8) // k值可以有誤差,但 k*軟件計時(ms)>=0.56ms IR_value[i] = IR_value[i] | 0x80; k=0; // 清零 } } }
/*----Function Description---- - Function Name : 外部中斷0 服務子程序 - Description : 用於檢測紅外前導電平信號,調用IR_Get(); 驗證數據有效性,並將最終用戶碼與操作碼分別存放於 IR_value[4:5]中。 - Return Code : IR_value[4:5] - Parameters/Arguments : None - Global Variable : IR_value[4:5] - static Variable : None -------------------------------------------------------------------------*/ void IR_ISR(void) interrupt 0 { EX0 = 0; // 關閉 外部中斷0 IR_value[0] = IR_value[1] = IR_value[2] = IR_value[3] = 0 ; IR_Get(); // 讀IR if(IR_value[0]==~IR_value[1] && IR_value[2]==~IR_value[3]){ IR_value[5] = IR_value[2]; // 保存指令 IR_value[4] = IR_value[0]; // 有效性驗證,保存用戶碼 } Dis_Tube(IR_value[5]%16);
IE0 = 0; // 清空中斷標志,防止在數據處理過程中產生中斷請求 EX0 = 1; // 打開 外部中斷0,准備接收下一條指令 } |
/*----Head Description---- - File Name : NixieTube.H - Author : Mason 別名:小菜 - Create Date : 2013/4/19 - ------------------------------------------- - Revision History - No. Date Revised by Item Description - -------------------------------------------------------------------------*/ #ifndef _NIXIETUBE_H_ #define _NIXIETUBE_H_
#include "MICRO.H" void Dis_Tube(uchar dat);
#endif |
/*----File Description---- - File Name : Nixietube.c - Functions : 數碼管驅動程序 - Description : None
- Author : Mason 別名:小菜 - Create Date : 2013/4/19 - Performance : Finished - Global Variable : smg_table[18] - File static Variable : None - ------------------------------------------- - Revision History - No. Date Revised by Item Description - 1 6/11 mason none add -------------------------------------------------------------------------*/ /*----------------------------Head---------------------------------------*/ #include <reg52.h> #include "NixieTube.H" #include "MICRO.H" /*------------------------------Code Variable----------------------------*/ //共陰 char code smg_table[16]={0x03,0x9f,0x25,0x0d,0x99,0x49,0x41,0x1f,0x01,0x19, 0x11,0xc1,0xe5,0x85,0x61,0x71}; /*----------------------------Code---------------------------------------*/
void Dis_Tube(uchar dat) { P2 = smg_table[dat]; } |