生活随笔
收集整理的這篇文章主要介紹了
红外数据的基本原理和处理机制
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
紅外數(shù)據(jù)的處理主要分為對(duì)應(yīng)的接收和發(fā)送處理。 數(shù)據(jù)要基于38K的載波進(jìn)行數(shù)據(jù)的發(fā)送。
紅外常用的協(xié)議有NEC和RC-5。 NEC: 起始碼:9ms低電平 + 4.5ms高電平 邏輯0: 560us + 560us 邏輯1: 560us + 1680us 重復(fù)碼 : 9ms低電平 + 2.5ms高電平
RC-5: 邏輯0: 889us低電平+889高電平 邏輯1: 889us高電平+889低電平 起始位(Start Bit):1bit,固定為邏輯"1". 驗(yàn)證位(Field Bit):1bit, (1)“1”: RC-5(原始RC5協(xié)議), (2) “0”: RC-5X(擴(kuò)展RC5協(xié)議)。 控制位(TR Bit):1bit,當(dāng)遙控器按鍵松開到再次按下時(shí),這位會(huì)反轉(zhuǎn)(0→1, 1→0),通過這種方式,接收器可以辨別按鍵是否一直按下或者是重復(fù)按鍵。 地址位(Address):5bit,表示所要控制的設(shè)備類型,最高有效位首先發(fā)送。 命令位(Command)6bit,表示按鍵的值,最高有效位首先發(fā)送。 (1)若FieldBit = 1,CMD范圍:0x0~0x3F; (2)若FieldBit = 0,CMD范圍:0x40~0x7F。
不過現(xiàn)在市面的空調(diào),電視等基本都是采用NEC的數(shù)據(jù)格式,再結(jié)合自己的數(shù)據(jù)分包形成協(xié)議發(fā)送。
美的的空調(diào)數(shù)據(jù)協(xié)議: 數(shù)據(jù)格式:引導(dǎo)碼+48位數(shù)據(jù)+分隔碼+48位數(shù)據(jù) LAA’BB’CC’ S LAA’BB’CC’) L為引導(dǎo)碼; ABC為實(shí)際數(shù)據(jù),A’為A的反碼,B’為B的反碼,C’為C的反碼; S為分隔碼; L引導(dǎo)碼:4.5ms低電平+4.5ms高電平 數(shù)據(jù)A:A為識(shí)別碼 數(shù)據(jù)B和C就是對(duì)應(yīng)的空調(diào)數(shù)據(jù)。 分隔碼:540us低電平+5.2ms高電平。
格力的空調(diào)數(shù)據(jù)協(xié)議格式: 起始碼(s)+35位數(shù)據(jù)碼+連接碼(c)+32位數(shù)據(jù)碼 起始碼:9000us低電平+4500us高電平 連接碼:600us低電平+20000us高電平 邏輯0: 600us低電平 + 600us高電平 邏輯1: 600us低電平 + 1600us高電平 這樣會(huì)產(chǎn)生一個(gè)問題就是每個(gè)廠商他們使用的不統(tǒng)一,這樣會(huì)導(dǎo)致我們無(wú)法通過統(tǒng)一的標(biāo)準(zhǔn)格式去處理數(shù)據(jù)。這樣想到唯一的處理方式就是將對(duì)應(yīng)的高低電平直接記錄用以表示整個(gè)數(shù)據(jù)協(xié)議格式。
每個(gè)位的低電平和高電平分別用兩個(gè)字節(jié)數(shù)據(jù)存儲(chǔ),比如格力的:起始碼4個(gè)字節(jié)數(shù)據(jù),35位數(shù)據(jù)碼140個(gè)字節(jié),連接碼4個(gè)字節(jié),32位數(shù)據(jù)碼128個(gè)字節(jié),一共276個(gè)字節(jié)可以記錄完整數(shù)據(jù)。
紅外數(shù)據(jù)接收處理:NEC格式
1、將定時(shí)器通道配置為上升沿捕獲,當(dāng)捕獲到一個(gè)上升沿時(shí),計(jì)數(shù)器等清0,接著將捕獲極性改為下降沿捕獲。當(dāng)?shù)诙尾东@中斷時(shí),捕獲到下降沿,并記錄此時(shí)時(shí)間,這個(gè)時(shí)間就是整個(gè)高電平的時(shí)間。 2、根據(jù)NEC編碼規(guī)則判斷該次時(shí)長(zhǎng)代表的是0還是1。1.68 ms 高電平為1,0.56 ms 高電平為0,2.25ms高電平為重復(fù)碼。 3、如何判斷數(shù)據(jù)收完了?重復(fù)碼有沒有,或者說(shuō)重復(fù)碼又什么時(shí)候收完?可以在初始化定時(shí),設(shè)置定時(shí)器10ms溢出中斷一次,根據(jù)NEC協(xié)議可以知道,因?yàn)槊看紊仙夭东@時(shí)都會(huì)計(jì)數(shù)器等清0,那么收完整個(gè)數(shù)據(jù)都不會(huì)溢出中斷一次,所以當(dāng)溢出中斷一次就代表數(shù)據(jù)收完了。 4、判斷重復(fù)碼什么時(shí)候收完?因?yàn)閿?shù)據(jù)碼和重復(fù)碼中間有段空閑,而 10ms溢出中斷一次,測(cè)試空閑時(shí)長(zhǎng)應(yīng)該是30ms左右,那么只需要設(shè)置溢出中斷標(biāo)志,每次觸發(fā)都加1,在上升沿捕獲時(shí)清0,那么如果溢出中斷標(biāo)志>3,就代表40ms內(nèi)沒收到過高電平了,那么就說(shuō)明數(shù)據(jù)接收完了,且沒有重復(fù)碼的產(chǎn)生。根據(jù)NEC重復(fù)碼的協(xié)議,我們10ms溢出中斷一次,為了接收全部的重復(fù)碼則判斷當(dāng)收到重復(fù)碼時(shí),如果溢出中斷標(biāo)志>9時(shí),就代表重復(fù)碼收完。
void Tim_Init(void) ? ??? ??? ??? ? ?
{?? ??? ?GPIO_InitTypeDef ?GPIO_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;TIM_TimeBaseInitTypeDef ?TIM_TimeBaseStructure;TIM_ICInitTypeDef ?TIM1_ICInitStructure;RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//使能GPIOA時(shí)鐘RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);//TIM1時(shí)鐘使能?//GPIOA8 ?復(fù)用功能,上拉GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//復(fù)用功能GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽輸出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHzGPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIO_PinAFConfig(GPIOA,GPIO_PinSource8,GPIO_AF_TIM1); //GPIOA8復(fù)用為TIM1TIM_TimeBaseStructure.TIM_Prescaler=167; ?預(yù)分頻器,1M的計(jì)數(shù)頻率,1us加1.?? ?TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上計(jì)數(shù)模式TIM_TimeBaseStructure.TIM_Period=10000; ? //設(shè)定計(jì)數(shù)器自動(dòng)重裝值 最大10ms溢出 ?TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;?TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStructure);?//初始化TIM2輸入捕獲參數(shù)TIM1_ICInitStructure.TIM_Channel = TIM_Channel_1; //CC1S=01 ?? ?選擇輸入端 IC1映射到TI1上TIM1_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;?? ?//上升沿捕獲TIM1_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到TI1上TIM1_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;?? ? //配置輸入分頻,不分頻?TIM1_ICInitStructure.TIM_ICFilter = 0x03;//IC1F=0003 8個(gè)定時(shí)器時(shí)鐘周期濾波TIM_ICInit(TIM1, &TIM1_ICInitStructure);//初始化定時(shí)器2輸入捕獲通道TIM_ITConfig(TIM1,TIM_IT_Update|TIM_IT_CC1,ENABLE);//允許更新中斷 ,允許CC1IE捕獲中斷?? ?TIM_Cmd(TIM1,ENABLE ); ?? ? ?? ?//使能定時(shí)器1NVIC_InitStructure.NVIC_IRQChannel = TIM1_CC_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;//搶占優(yōu)先級(jí)1NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;?? ??? ?//子優(yōu)先級(jí)3NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;?? ??? ??? ?//IRQ通道使能NVIC_Init(&NVIC_InitStructure);?? ?//初始化NVIC寄存器NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_TIM10_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;//搶占優(yōu)先級(jí)3NVIC_InitStructure.NVIC_IRQChannelSubPriority =2;?? ??? ?//子優(yōu)先級(jí)2NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;?? ??? ??? ?//IRQ通道使能NVIC_Init(&NVIC_InitStructure);?? ?//初始化NVIC寄存器
}//遙控器接收狀態(tài)
//[7]:收到了引導(dǎo)碼標(biāo)志
//[6]:得到了一個(gè)按鍵的所有信息
//[5]:保留?? ?
//[4]:標(biāo)記上升沿是否已經(jīng)被捕獲?? ??? ??? ??? ??? ??? ??? ??? ? ??
//[3:0]:溢出計(jì)時(shí)器
u8 ?? ?RmtSta=0;?? ? ??? ? ?
u16 Dval;?? ??? ?//下降沿時(shí)計(jì)數(shù)器的值
u32 RmtRec=0;?? ?//紅外接收到的數(shù)據(jù)?? ? ? ?? ??? ? ? ?
u8 ?RmtCnt=0;?? ?//按鍵按下的次數(shù)?? ??
//定時(shí)器1溢出中斷
void TIM1_UP_TIM10_IRQHandler(void)
{if(TIM_GetITStatus(TIM1,TIM_IT_Update)==SET) //溢出中斷{if(RmtSta&0x80)//上次有數(shù)據(jù)被接收到了{(lán)?? ?RmtSta&=~0X10;?? ??? ??? ??? ??? ??? ?//取消上升沿已經(jīng)被捕獲標(biāo)記if((RmtSta&0X0F)==0X00)RmtSta|=1<<6;//標(biāo)記已經(jīng)完成一次按鍵的鍵值信息采集if((RmtSta&0X0F)<14)RmtSta++;else{RmtSta&=~(1<<7);//清空引導(dǎo)標(biāo)識(shí)RmtSta&=0XF0;?? ?//清空計(jì)數(shù)器?? ?}?? ??? ??? ??? ??? ??? ? ?? ? ? ?? ?}?? ??? ??? ??? ??? ??? ??? ? ? ?}TIM_ClearITPendingBit(TIM1,TIM_IT_Update); ?//清除中斷標(biāo)志位?
}?
//定時(shí)器1輸入捕獲中斷服務(wù)程序?? ??
void TIM1_CC_IRQHandler(void)
{ ?? ??? ? ? ??? ??if(TIM_GetITStatus(TIM1,TIM_IT_CC1)==SET) //處理捕獲(CC1IE)中斷{?? ? ?if(RDATA)//上升沿捕獲{TIM_OC1PolarityConfig(TIM1,TIM_ICPolarity_Falling);?? ??? ?//CC1P=1 設(shè)置為下降沿捕獲TIM_SetCounter(TIM1,0);?? ? ? ?? ?//清空定時(shí)器值RmtSta|=0X10;?? ??? ??? ??? ??? ?//標(biāo)記上升沿已經(jīng)被捕獲}else //下降沿捕獲{Dval=TIM_GetCapture1(TIM1);//讀取CCR1也可以清CC1IF標(biāo)志位TIM_OC1PolarityConfig(TIM1,TIM_ICPolarity_Rising); //CC1P=0?? ?設(shè)置為上升沿捕獲if(RmtSta&0X10)?? ??? ??? ??? ??? ?//完成一次高電平捕獲?{if(RmtSta&0X80)//接收到了引導(dǎo)碼{if(Dval>300&&Dval<800)?? ??? ??? ?//560為標(biāo)準(zhǔn)值,560us{RmtRec<<=1;?? ?//左移一位.RmtRec|=0;?? ?//接收到0?? ? ??}else if(Dval>1400&&Dval<1800)?? ?//1680為標(biāo)準(zhǔn)值,1680us{RmtRec<<=1;?? ?//左移一位.RmtRec|=1;?? ?//接收到1}else if(Dval>2200&&Dval<2600)?? ?//得到按鍵鍵值增加的信息 2500為標(biāo)準(zhǔn)值2.5ms{RmtCnt++; ?? ??? ?//按鍵次數(shù)增加1次RmtSta&=0XF0;?? ?//清空計(jì)時(shí)器?? ??? ?}}else if(Dval>4200&&Dval<4700)?? ??? ?//4500為標(biāo)準(zhǔn)值4.5ms{RmtSta|=1<<7;?? ?//標(biāo)記成功接收到了引導(dǎo)碼RmtCnt=0;?? ??? ?//清除按鍵次數(shù)計(jì)數(shù)器}?? ??? ??? ??? ??? ??? ??}RmtSta&=~(1<<4);}?? ??? ??? ??? ? ?? ??? ? ? ? ?? ? ? ??? ??? ??? ??? ??? ? ??}TIM_ClearITPendingBit(TIM1,TIM_IT_CC1); ?//清除中斷標(biāo)志位?
}
//處理紅外鍵盤
//返回值:
//?? ? 0,沒有任何按鍵按下
//其他,按下的按鍵鍵值.
u8 Jx_IrDataHandle(void)
{ ? ? ? ?u8 sta=0; ? ? ??u8 t1,t2; ?if(RmtSta&(1<<6))//得到一個(gè)按鍵的所有信息了{(lán)?t1=RmtRec>>24;?? ??? ??? ?//得到地址碼t2=(RmtRec>>16)&0xff;?? ?//得到地址反碼?if((t1==(u8)~t2)&&t1==REMOTE_ID)//檢驗(yàn)遙控識(shí)別碼(ID)及地址?{?t1=RmtRec>>8;t2=RmtRec; ?? ?if(t1==(u8)~t2)sta=t1;//鍵值正確?? ??} ??if((sta==0)||((RmtSta&0X80)==0))//按鍵數(shù)據(jù)錯(cuò)誤/遙控已經(jīng)沒有按下了{(lán)RmtSta&=~(1<<6);//清除接收到有效按鍵標(biāo)識(shí)RmtCnt=0;?? ??? ?//清除按鍵次數(shù)計(jì)數(shù)器}} ?return sta;
}
紅外發(fā)送處理: 根據(jù)我們上面接收到的紅外數(shù)據(jù),然后通過對(duì)應(yīng)的PWM波設(shè)置對(duì)應(yīng)高低電平的占空比,然后在38K的載波進(jìn)行數(shù)據(jù)發(fā)送就可形成紅外數(shù)據(jù)。
總結(jié)
以上是生活随笔 為你收集整理的红外数据的基本原理和处理机制 的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔 推薦給好友。