• 方案介紹
    • 一、前言
    • 二、代碼實現(xiàn)
  • 附件下載
  • 相關推薦
申請入駐 產(chǎn)業(yè)圖譜

定時器+外部中斷實現(xiàn)NEC紅外線協(xié)議解碼

4小時前
59
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論

更多詳細資料請聯(lián)系.docx

共1個文件

一、前言

1.1 功能介紹

隨著科技的進步和人們生活水平的提高,紅外遙控器已經(jīng)成為了日常生活中不可或缺的電子設備之一,廣泛應用于電視、空調(diào)、音響等多種家電產(chǎn)品中。 傳統(tǒng)的紅外遙控器通常只能實現(xiàn)預設的有限功能,無法滿足用戶對設備更加智能化、個性化的控制需求。

STC90C51作為一款功能強大的8位微控制器,具備高性能、低功耗和豐富的I/O端口資源,非常適合用于實現(xiàn)紅外遙控信號的解碼和控制。本項目利用STC90C51微控制器,結合定時器和外部中斷機制,實現(xiàn)NEC紅外線協(xié)議的解碼,從而實現(xiàn)對紅外遙控器的控制功能。

NEC紅外線協(xié)議是一種常見的紅外遙控通信協(xié)議,具有傳輸速度快、編碼簡單、可靠性高等特點。通過解碼NEC紅外線協(xié)議,可以獲取遙控器發(fā)送的按鍵信息,進而實現(xiàn)對設備的遠程控制。在本項目中,我們將利用STC90C51的定時器功能,設置合適的定時參數(shù),以檢測紅外信號的脈沖寬度和間隔。同時,利用外部中斷機制,實時監(jiān)測紅外接收管的狀態(tài)變化,捕捉紅外信號的起始和結束時刻。

通過解碼NEC紅外線協(xié)議,我們可以獲取遙控器發(fā)送的按鍵編碼,并將其轉(zhuǎn)換為對應的控制指令。在本項目中,我們將以開關控制為例,實現(xiàn)對目標設備的遠程控制。具體而言,當遙控器發(fā)送“開”或“關”的按鍵編碼時,STC90C51將解碼該編碼,并發(fā)送相應的控制指令給目標設備,以實現(xiàn)設備的開關控制。

本項目的開發(fā)背景不僅體現(xiàn)了現(xiàn)代家居和電子設備對遠程控制技術的需求,也展示了STC90C51微控制器在嵌入式系統(tǒng)設計和開發(fā)中的強大功能。通過實現(xiàn)NEC紅外線協(xié)議的解碼和控制,本項目將為用戶帶來更加便捷、智能的遠程控制體驗,推動智能家居物聯(lián)網(wǎng)技術的發(fā)展。

image-20240612131713957

image-20240612131727095

image-20240612131746139

image-20240612131757396

1.2 NEC協(xié)議介紹

NEC協(xié)議是一種紅外線通信協(xié)議,廣泛應用于家電遙控器和其他紅外線設備之間的通信。該協(xié)議具有簡單、易于實現(xiàn)和廣泛兼容的特點,使得不同品牌和型號的紅外設備能夠互相通信和控制。

NEC協(xié)議的工作原理基于38kHz的紅外線載波頻率,通過發(fā)送特定格式的數(shù)據(jù)包來傳輸信息。每個數(shù)據(jù)包由連續(xù)的脈沖和間隔組成,其中脈沖表示邏輯1,間隔表示邏輯0。數(shù)據(jù)包的結構包括同步碼(Sync Header)、地址碼、地址碼的反碼、命令碼以及命令碼的反碼。

同步碼是數(shù)據(jù)包開始的標識,通常是一個持續(xù)約9ms的高電平脈沖(Mark),用于同步接收器和發(fā)送器之間的通信。地址碼和命令碼是每個按鍵特定的標識,用于識別按下的是哪個按鍵。地址碼和地址碼的反碼用于驗證遙控器發(fā)送的數(shù)據(jù)是否正確,而命令碼和命令碼的反碼則用于執(zhí)行相應的操作。

在NEC協(xié)議中,數(shù)據(jù)以二進制格式進行傳輸,確保了信息的準確性和高效性。此外,NEC協(xié)議還定義了一個重復碼,當用戶長按遙控器上的某個按鍵時,遙控器會發(fā)送該按鍵的重復碼,以避免連續(xù)發(fā)送相同的命令。

NEC協(xié)議是一種基于紅外線通信的協(xié)議,通過發(fā)送特定格式的數(shù)據(jù)包來實現(xiàn)不同設備之間的通信和控制。它具有簡單、易于實現(xiàn)和廣泛兼容的特點,被廣泛應用于家電遙控器等紅外設備中。

二、代碼實現(xiàn)

2.1 main.c

#include <reg51.h>
#include "delay.h"
#include "key.h"
#include "type.h"
#include "led.h"
#include "uart.h"
#include "timer.h"
#include "exti.h"
#include "infrared.h"
int main()
{
    UART_Init();        //初始化串口波特率為4800
    Infrared_Init();    //初始化紅外功能
    while(1)
    {
        if(Infrared_RX_Flag)          //接收到紅外數(shù)據(jù)
        {
            Infrared_RX_Flag=0;     //清楚標志
            printf("user1:%d,user2:%drn",(int)Infrared_RX_Buff[0],(int)((u8)(~Infrared_RX_Buff[1])));
			printf("key1:%d,key2:%drn",(int)Infrared_RX_Buff[2],(int)((u8)(~Infrared_RX_Buff[3])));
        } 
    }
}

2.2 INFRARED.c

#include "Infrared.h"
u8 Infrared_RX_Flag=0; //紅外接收標志,收到一幀正確數(shù)據(jù)后置1
u8 Infrared_RX_Buff[4];//紅外代碼接收緩沖區(qū)

/*
函數(shù)功能: 開始紅外線解碼之前的相關初始化
實驗板的晶振頻率是12MHZ
51單片機標準架構下一個機器周期是12個時鐘周期,如果晶振頻率是12MHZ,那一個機器周期的時間就是12/12微秒。
也就是說定時器的計數(shù)器+1的時間就是12/12=1us。
*/
void Infrared_Init(void)
{	
	Infrared_GPIO=1;//紅外接收引腳默認保持高電平輸出
	TMOD&=0xF0; //清除配置  
	TMOD|=0x01; //配置定時器0,工作在16位計數(shù)模式
	TR0=0;      //停止定時器0計數(shù)
	ET0=0; 	    //禁止定時器0中斷
	IT0=1;      //開啟外部中斷0,下降沿觸發(fā)
	EX0=1;      //允許外部中斷0中斷
}

/*
函數(shù)功能: 檢測高電平持續(xù)的時間
*/
u16 Infrared_GetTimeH(void)
{
	TH0=0; //定時器0重裝值為0
	TL0=0; //定時器0重裝值為0
	TR0=1; //啟動定時器0開始計數(shù)
	while(Infrared_GPIO)//等待高電平結束
	{
		if(TH0>0x40)//防止超時   
		{
			break;
		}
	}
	TR0=0;//停止定時器0計數(shù)
	return TH0<<8|TL0;//T0計數(shù)值合成為16位整數(shù)返回
}

/*
檢測低電平持續(xù)的時間
*/
u16 Infrared_GetTimeL(void)
{
	TH0=0;//定時器0的高8位重裝值
	TL0=0;//定時器0的低8位重裝值  
	TR0=1;//開啟定時器0
	while(Infrared_GPIO==0)//等待低電平結束
	{
		if(TH0>0x40)//防止超時   
		{
			break;
		}
	}
	TR0=0;//停止定時器0計數(shù)
	return TH0<<8|TL0;//T0計數(shù)值合成為16位整數(shù)返回
}

/*
外部中斷0中斷服務函數(shù)
*/
void EXTI0_IRQHandler() interrupt 0
{
	u8 i, j;
	u16 time;
	u8 byte;
	time=Infrared_GetTimeL();   //獲取出現(xiàn)低電平的時間
	if((time<7800)||(time>9300))//判斷低電平時間是否符合9ms范圍
	{                           //超過此范圍則說明為誤碼,直接退出
		IE0=0;                  //清除外部中斷0中斷標志
		return;	
	}
	time=Infrared_GetTimeH();   //獲取出現(xiàn)高電平的時間
	if((time<3500)||(time>4700))//高電平是否符合4.5ms范圍
	{                           //超過此范圍則說明為誤碼,直接退出
		IE0=0; 				    //清除外部中斷0中斷標志
		return;
	}
	//接收32位數(shù)據(jù)位
	for(i=0;i<4;i++)
	{
		for(j=0;j<8;j++)
		{
			time=Infrared_GetTimeL();   //獲取低電平持續(xù)時間,標準的間隔時間為560us范圍		    				
			if((time<300)||(time>700))  //判斷范圍是否合理
			{
				IE0=0;//清除外部中斷0中斷標志
				return;
			}
            //1和0是靠高電平持續(xù)的長短來區(qū)分的
			time=Infrared_GetTimeH();  //獲取高電平持續(xù)時間
			if(time>300&&time<700)    //0的標準時間為560us
			{
				byte>>=1;
			}
            else if(time>1400&&time<1800) //1的標準時間是1680us
			{
				byte>>=1;
				byte|=0x80;
			}
			else //不在上面的判斷范圍內(nèi)說明是錯誤碼,直接退出
			{
				IE0=0;//清除外部中斷0中標
				return;
			}
		}
		Infrared_RX_Buff[i]=byte;//接收完一個字節(jié)后保存到緩沖區(qū)
	}
	Infrared_RX_Flag=1;//接收完畢后設置標志
	IE0=0;//退出前清除外部中斷0中斷標志
}

2.3 INFRARED.h

#ifndef _INFRAREAD_H
#define _INFRAREAD_H
#include <reg51.h>
#include "type.h"
sbit Infrared_GPIO=P3^2;//紅外接收引腳--外部中斷0
void Infrared_Init();//紅外線接收初始化
u16 Time_H();//檢測高電平
u16 Time_L();//檢測低電平
extern u8 Infrared_RX_Flag; //紅外接收標志,收到一幀正確數(shù)據(jù)后置1
extern u8 Infrared_RX_Buff[4];   //紅外代碼接收緩沖區(qū)
#endif

  • 更多詳細資料請聯(lián)系.docx
    下載

相關推薦