紅外遙控
紅外遙控簡介
紅外遙控是一種無線、非接觸控制技術,具有抗干擾能力強,信息傳輸可靠,功耗低,成本低,易實現(xiàn)等顯著優(yōu)點,被諸多電子設備特別是家用電器廣泛采用,并越來越多的應用到計算機系統(tǒng)中。
由于紅外線遙控不具有像無線電遙控那樣穿過障礙物去控制被控對象的能力,所以,在設計紅外線遙控器時,不必要像無線電遙控器那樣,每套(發(fā)射器和接收器)要有不同的遙控頻率或編碼(否則,就會隔墻控制或干擾鄰居的家用電器),所以同類產品的紅外線遙控器,可以有相同的遙控頻率或編碼,而不會出現(xiàn)遙控信號“串門”的情況。這對于大批量生產以及在家用電器上普及紅外線遙控提供了極大的方面。由于紅外線為不可見光,因此對環(huán)境影響很小,再由紅外光波動波長遠小于無線電波的波長,所以紅外線遙控不會影響其他家用電器,也不會影響臨近的無線電設備。
紅外遙控的編碼目前廣泛使用的是:NEC Protocol 的 PWM(脈沖寬度調制)和 Philips RC-5 Protocol的 PPM(脈沖位置調制)。我使用的的遙控器使用的是NEC 協(xié)議,其特征如下:
8位地址和8位指令長度; 地址和命令2次傳輸(確保可靠性); PWM脈沖位置調制,以發(fā)射紅外載波的占空比代表“ 0”和“ 1”; 載波頻率為38Khz; 位時間為1.125ms或2.25ms;
NEC 碼的位定義:一個脈沖對應560us的連續(xù)載波,一個邏輯 1 傳輸需要2.25ms(560us 脈沖+1680us 低電平),一個邏輯0的傳輸需要 1.125ms(560us 脈沖+560us 低電平)。而遙控接收頭在收到脈沖的時候為低電平,在沒有脈沖的時候為高電平,這樣,我們在接收頭端收到的信號為:邏輯1應該是560us低+1680us高,邏輯0應該是560us低+560us高。
NEC 遙控指令的數(shù)據格式為:同步碼頭、地址碼、地址反碼、控制碼、控制反碼。同步碼由一個9ms的低電平和一個4.5ms的高電平組成,地址碼、地址反碼、控制碼、控制反碼均是8位數(shù)據格式。按照低位在前,高位在后的順序發(fā)送。采用反碼是為了增加傳輸?shù)目煽啃裕捎糜谛r灒?/p>
1. ENC 協(xié)議的時序圖

ENC特點如下:
1),協(xié)議規(guī)定低位首先發(fā)送。一串信息首先發(fā)送9ms的AGC(自動增益控制)的高脈沖,接著發(fā)送4.5ms的起始低電平,接下來是發(fā)送四個字節(jié)的地址碼和命令碼,這四個字節(jié)分別為:地址碼;地址碼反碼;命令碼;命令碼反碼。
2),如果你一直按那個按鍵,一串信息也只能發(fā)送一次,一直按著,發(fā)送的則是以110ms為周期的重復碼。
3),接收到的信號是跟發(fā)送信號正好反向的。
2.重復碼的格式

重復碼的格式是由9ms的AGC高電平和4.5ms的低電平及一個560us的高電平組成。
3.邏輯“1”的表示

邏輯1的是由560us的高電平和1.69ms的低電平組成的脈沖表示。
4.邏輯“0”的表示

邏輯0的是有560us的高電平和565us的低電平組成的脈沖表示。
5.ENC的解碼過程
一般ENC的解碼過程為:
1),產生下降沿,進入外部中斷15的中斷函數(shù),延時一下之后檢測IO口是否還是低電平,是就等待9ms的低電平過去。
2),等待完9ms低電平過去,再去等待4.5ms的高電平過去。
3),接著開始接收傳送的4組數(shù)據
①先等待560us的低電平過去
②檢測高電平的持續(xù)時間,如果超過1.12ms那么是高電平(高電平的的持續(xù)時間為1.69ms,低電平的持續(xù)時間為565us。
4),檢測接收到的數(shù)據和數(shù)據的反碼進行比較,是否等到的數(shù)據是一樣的。

6,下面直接寫驅動程序
#include <linux/init.h>
#include <linux/module.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/ktime.h>
#include <mach/gpio.h>
#define IRDA_GPIO EXYNOS4_GPX3(2)
int flag = 0; // 表示數(shù)據幀的開始
int num = 0; // 表示數(shù)據幀里的第幾位數(shù)據
static long long prev = 0; // 64bit,記錄上次的時間
unsigned int times[40]; // 記錄每位數(shù)據的時間
irqreturn_t
infrared_irq_handler(int irqno, void *dev_id)
{
long long now = ktime_to_us(ktime_get());
unsigned int offset;
int i, j, tmp;
if(!flag){ // 數(shù)據開始
flag = 1;
prev = now;
return IRQ_HANDLED;
}
offset = now - prev;
prev = now;
if((offset > 13000) && (offset < 14000)){ // 判斷是否收到引導碼
num = 0;
return IRQ_HANDLED;
}
if(num < 32)
times[num++] = offset;
if(num >= 32){
for(i = 0; i < 4; i++){ // 一共4個字節(jié)
tmp = 0;
for(j = 0; j < 8; j++){
if(times[i * 8 + j] > 2000) // 如果數(shù)據位的信號周期大于20ms,則是二進制數(shù)據1
tmp |= 1 << j;
}
printk("%02x ", tmp);
}
printk("\n");
flag = 0;
}
return IRQ_HANDLED;
}
static void __exit
infrared_drv_exit(void)
{
free_irq(gpio_to_irq(IRDA_GPIO), NULL);
}
static int __init
infrared_drv_init(void)
{
int ret = -1;
ret = request_irq(gpio_to_irq(IRDA_GPIO), infrared_irq_handler, IRQF_TRIGGER_FALLING, "infrared", NULL);
if(ret < 0){
printk("request irq failed !\n");
return ret;
}
return 0;
}
module_init(infrared_drv_init);
module_exit(infrared_drv_exit);
MODULE_LICENSE("GPL");
還有對應的Makefile:
#指定內核源碼路徑
KERNEL_DIR = /home/george/1702/exynos/linux-3.5
#指定當前路徑
CUR_DIR = $(shell pwd)
#MYAPP = dht11_app
MODULE = IRDA_for_irq
all:
make -C $(KERNEL_DIR) M=$(CUR_DIR) modules
# arm-none-linux-gnueabi-gcc -o $(MYAPP) $(MYAPP).c
clean:
make -C $(KERNEL_DIR) M=$(CUR_DIR) clean
$(RM) $(MYAPP)
install:
cp -raf *.ko $(MYAPP) /home/george/1702/exynos/filesystem/1702
#指定編譯當前目錄下那個源文件
obj-m = $(MODULE).o
編譯生成.ko文件之后,裝載,然后進行實物測試,驗證效果圖如下:

