1. 程式人生 > >即插即用的PC紅外遙控接收器

即插即用的PC紅外遙控接收器

文章原標題《基於V-USB製作的電腦紅外遙控接收器》 已刊登在《無線電》雜誌2014年12期      點此購買淘寶套件

基於V-USB製作的電腦紅外遙控接收器

文 任鵬


當我們使用電腦觀看電影、聽歌,或是將播放視訊的畫面投射到電視機上時,總是希望可以像遙控電視機那樣遙控電腦,方便地實現上一曲、下一曲、音量增減等必要功能。網上已有一些常見的方案為電腦增加紅外遙控功能,硬體上不外乎使用到了串列埠,而且需要安裝一款軟體用於記憶紅外編碼,並賦予該編碼確定的功能。筆者製作的這款,無需安裝驅動程式,也不需要上位機軟體,真正做到了即插即用。同時,硬體結構簡單,成本極低,很適合自制(如圖1

)。

 

紅外遙控接收器

 

生活中,可能大多數朋友使用的鍵盤是標準鍵盤,不過,市場上還有一種帶多媒體按鍵的鍵盤,有音量控制、曲目控制、睡眠,甚至一鍵開啟主頁、計算器等功能。這一特點給了筆者啟發,我們完全可以製作一款紅外遙控接收器,對於使用者而言,它接收紅外編碼指令,而對於電腦而言,電腦會認為它是一款只擁有多媒體按鍵的特殊鍵盤,通過它完成了紅外解碼並轉換為鍵碼的過程。如此一來,我們就擺脫了對上位機軟體的依賴,更方便廣大電腦使用者的使用。

 

有了思路,接下來就是劃定方案。首先,製作一款鍵盤,USB介面是必不可少的。實現下位機和上位機通過

USB交換資料的方案很多,但是考慮到成本、體積、下位機程式設計的難易,甚至是相關晶片的購買是否方便,筆者認為多年前出現的V-USB方案比較符合要求。V-USB是一套用於在AVR微控制器上實現低速USB裝置的軟體包,AVR家族的絕大多數型號均可使用而無需內建硬體USB控制器,USB通訊完全靠軟體模擬時序完成,受此制約,CPU佔用率較高。在V-USB的官網,提供了一款使用8引腳微控制器ATtiny 45製作的範例,其小巧的封裝很符合本次製作的要求,但是ATtiny 45並不容易購得,且零售價較高。

 

深圳綠智微電子2012年推出了相容AVR指令的LGT8F0XA

系列微控制器,隨後進一步優化了核心,並擴充了產品線。其中,LGT8F08ASOP8L封裝非常符合本設計要求,體積小,且售價低廉(零售價約為1.35元),由於其相容AVR指令,使得移植V-USB成為可能。根據晶片手冊的描述,基於MVR8X核心的LGT微控制器有若干指令的執行速度比AVR快,則V-USB的底層彙編部分程式碼需要進行調整,以滿足時序。令人欣喜的是,在綠智微電子的官方網站上,已經提供了移植好的模板程式碼包。該模板僅提供對12MHz和16MHz系統時鐘的支援。

 

硬體確定後,緊接著就是微控制器程式的編寫。開啟從綠智微電子官網下載的模板壓縮包,將其中的VUSB-Sample資料夾解壓到某一位置,然後開啟該資料夾,將除source資料夾和Makefile檔案之外的全部刪掉,後面的工作我們都在這個基礎上展開。source資料夾中,usbdrv資料夾內是移植好的V-USB程式包,Smpl_USBLED.c是官方提供的示例檔案。V-USB為適應不同型號AVR微控制器的暫存器差別,大量使用了巨集定義,我們需要根據硬體的具體情況對V-USB進行配置。開啟usbdrv資料夾裡的usbconfig.h檔案,根據註釋可以很快清楚每項巨集定義的用途,這其中,我們修改的重點是外部中斷的入口。按照V-USB的要求,USB+USB-兩根訊號線需要和同一組的不同IO相連,同時,佔用一個外部中斷,預設情況下,V-USB使用的是外部中斷0,但是,本著節約IO的原則,以及根據LGT8F08A-SOP8L封裝的特點,我們選擇使用外部中斷2,同時USB+USB-分別連線到PA6PA3,滿足前述要求(如圖2)。在usbconfig.h檔案的末端,就是用來修改中斷入口的。我們將其修改為如下程式碼:


#define USB_INTR_CFG            EICRA //EICRA –外部引腳中斷控制暫存器
#define USB_INTR_CFG_SET        ((1 << ISC20) | (1 << ISC21))
#define USB_INTR_CFG_CLR        0
#define USB_INTR_ENABLE         EIMSK //EIMSK –外部引腳中斷遮蔽暫存器
#define USB_INTR_ENABLE_BIT     INT2
#define USB_INTR_PENDING        EIFR  //EIFR –外部引腳中斷標誌暫存器
#define USB_INTR_PENDING_BIT    INTF2 //外部引腳 2 中斷標誌位
#define USB_INTR_VECTOR         INT2_vect


 

 

原理圖

 

其它配置塊,如“Hardware Config”和“Optional Hardware Config”等,只需根據電路實際進行修改即可。“Optional Hardware Config”下的“USB_CFG_PULLUP_IOPORTNAME”和“USB_CFG_PULLUP_BIT”是用來配置USB- 線上的上拉電阻連線的IO的,用以將USB裝置配置為低速裝置。原本這是個可選項,1.5k 的上拉電阻完全可以直接接到3.3V電平上,但是這裡有個特殊情況,LGT8F08A-SOP8L封裝的IO高電平比供電電平低了約0.6V,這是因為,這款晶片的VCC實際上是RESET,在晶片內部,RESET通過一個二極體連線到真正的VCC(如圖3)。為了匹配USB電平標準,我們使用一個穩壓二極體來產生3.9V的供電電壓,同時佔用一個IO完成上拉操作。“Device Description”下的“USB_CFG_VENDOR_ID”和“USB_CFG_DEVICE_ID”分別為VIDPID的配置巨集,原則上,這裡的值需要向USB組織付費申請,作為實驗,筆者均使用0x8888進行代替。至於“USB_CFG_VENDOR_NAME”和“USB_CFG_DEVICE_NAME”則可根據自己的需要修改。

 

圖3 SOP8L封裝內部結構

 

配置完畢後,我們來建立主程式。開啟source資料夾下的Smpl_USBLED.c,將原來的main函式替換為如下程式碼:


int main(void)
{
	uchar i;

	hardwareInit();

	wdt_enable(WDTO_1S);    // enable 1s watchdog timer

	usbInit();

	usbDeviceDisconnect(); 	// enforce re-enumeration

	i = 0;
	while (--i)             // fake USB disconnect for > 250 ms
	{
		wdt_reset();
		_delay_ms(1);
	}

	usbDeviceConnect();

	sei(); 					// Enable interrupts after re-enumeration

	while (1)
	{
		wdt_reset(); 		// keep the watchdog happy
		usbPoll();
		if (IR_Press && usbInterruptIsReady())
		{ /* we can send another report */
			IR_Press = 0;
			buildReport();
			usbSetInterrupt(reportBuffer, sizeof(reportBuffer));
			IR_PressRelease = 1;
		}
		if (IR_PressRelease && usbInterruptIsReady())
		{ /* we can send another report */
			IR_PressRelease = 0;
			buildReport();
			usbSetInterrupt(reportBuffer, sizeof(reportBuffer));
		}
	}
	return 0;
}


其中,hardwareInit() 函式用於初始化相關暫存器,首先是禁能SWD功能。SWDLGT微控制器的模擬除錯介面,上電預設開啟,並佔用PC6PA6引腳,根據資料手冊描述,軟體必須在 個時鐘週期內將期望的數值兩次寫入SWDD 位,所以程式中需要連續兩次執行MCUCR = 1 << SWDD; 語句。緊接著是將系統的時鐘源切換到外部晶振,雖然晶片自帶16MHz 的內部RC振盪器,但其精度不滿足USB通訊要求,故外接精度較高的無源晶振。最後是初始化定時器0中斷,這將用於紅外解碼。在主函式的while死迴圈中,usbPoll(); 用於USB事務輪詢,下面的兩個if語句用於判斷按鍵是否按下或釋放,並建立相應的資料包上傳給電腦。事實上,這裡不像機械按鍵那樣存在一直按下的行為,所以在傳送按鍵按下的資料包後,立即傳送按鍵釋放的資料包。

 

前面說到,定時器0中斷將用於紅外解碼,整個紅外解碼的方式採用了狀態機的程式設計思想。筆者使用的是市面上常見的採用NEC協議的遙控器,NEC協議(如圖4)根據脈衝時間長短編碼,每個脈衝為560us長的38KHz載波(21個載波週期),邏輯“1”脈衝時間為2.25ms,邏輯“0”脈衝時間為1.12ms(如圖5)。定時器0100us 中斷一次,每次中斷都檢測紅外接收器的DAT腳是否發生了電平翻轉,並記錄該時長,以此判斷相應的邏輯位或是超時。由於V-USB已經佔用了較高的CPU使用率,所以紅外解碼必須採用佔CPU時間少的方式,狀態機解碼比其它方式更滿足這個要求。同時,由於定時器0的中斷優先順序比外部中斷2的優先順序低,不必擔心USB響應錯誤或超時。讀者在購買紅外遙控器的時候,應當向賣家索要該遙控器的鍵碼錶和使用者碼(如圖7),特別指出的是,筆者將“EQ”按鍵定義為了“靜音”鍵,“CH-”和“CH+”分別定義為了“睡眠”和“關機”,數字鍵和“CH”鍵沒有用到。對於無法獲知鍵碼編碼的情況,需要自行測試獲取。在附件當中,筆者提供了一份用於獲取鍵碼的測試程式碼,結果通過串列埠輸出到電腦。如想利用其他協議的遙控器,則需對解碼部分進行修改。電路中的R4C4不可省去,以免干擾過大而無法工作。

 

圖4 NEC幀格式

 

 

圖5 邏輯1和邏輯0

 

 

邏輯分析儀捕獲的紅外一體化接收頭輸出波形(與發射波形反相)

 

 

遙控器外形及鍵碼,第一個使用者碼為00,第二個為FF

 

為了讓電腦認為這是一款USB鍵盤,必須將其描述為HID(人體工程學裝置),usbHidReportDescriptor[USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH]陣列中,正是相應的HID報告描述符,在該描述符中,按順序規定了8個按鍵,這8個按鍵共佔用一個位元組,其中的每一bit用於描述按鍵的按下(1)和釋放(0)。關於HID報告描述符的具體含義,筆者在原始碼中進行了詳細註釋,更為全面的介紹,可以參考網上的一篇技術博文(http://blog.csdn.net/cazicaquw/article/details/6724951)。如果讀者朋友希望自定義其它功能,只需按規則改動這裡即可,相關的描述符可以通過HID報告描述符生成工具(http://www.usb.org/developers/hidpage/dt2_4.zip)查閱,同時注意修改usbconfig.h檔案當中USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH這個巨集的值。

 

原始碼整理好後,就可以進行編譯了。V-USB推薦使用GCC進行編譯,本文也不例外。開啟VUSB-Sample資料夾下的Makefile檔案,可以看到,“## General Flags”下的“MCU”被配置為“atmega164p”,也就是說,在開發LGT8F08A時,只需將其看作ATmega164p即可。“## Include Directories”下,“INCLUDES”需要根據你的實際的安裝目錄進行配置。修改完畢後,進入命令列操作介面,鍵入“make”並回車,便會完成編譯並生成HEX檔案。為了方便,筆者將一些常用操作整理成了一個批處理檔案,每次編譯僅需雙擊這個批處理檔案即可。此外,對於習慣使用類似Keil 這種IDE軟體的人來說,上面的這些操作,無論是編輯還是編譯,都顯得十分不便,筆者推薦大家可以試試TKStudio這款國產的IDE軟體,無論是51AVR,還是ARM,都可輕鬆應對。更多詳情,請參考TKStudio的官方網站

 

最後一步,就是把HEX檔案燒錄到微控制器裡。筆者使用的是LGT微控制器專用ISP下載器(如圖8),這款下載器可以自制,相關的原理圖以及韌體均可在綠智微電子官網下載,也可直接購買成品。如果讀者手裡有現成的用於AVR微控制器的USBASP下載器,也可將其改制,用於LGT微控制器的下載,甚至,普通的51微控制器開發板也可以改製為下載器,具體的說明詳見附件,這裡不再贅述。

 

8 LGT_ISP下載器

 

 

圖9 確保HID服務處於執行態

 

到這裡,我們預期的目標算是基本達成了,有條件的朋友還可以找一個合適的外殼或是使用熱縮管進行防塵防靜電保護。有些使用精簡版或是GHOST版系統的使用者需要注意,如無法自動安裝驅動,可能是缺少系統元件,按照電腦的提示從網上下載即可,另外,需要確保Human Interface Device Access服務處於“正在執行”狀態(如圖9),可以通過手動輸入命令來設定,點選“開始”→“執行”,輸入“sc start hidserv”並回車,需要設定為開機自啟動的,在“執行”中輸入“sc config hidserv start= auto”並回車(注意“auto”前有一空格)。對於有興趣繼續研究的朋友來說,這個小製作還可以變成USB介面的溫度計,只需將紅外接收頭替換成DS18B20即可,又或是變成USB介面的顯示器、I2C讀寫器、一鍵輸入密碼登入器等等,可擴充套件性很強,同時又能熟悉USB通訊的各個環節,對於開發其它USB裝置很有幫助。


資料包下載地址:http://www.hobbypress.cn/bencandy.php?fid-194-id-8220-page-1.htm