(14) Infrared remote control

Infrared remote control is a device that uses infrared light to communicate. The modulated signal is sent out by the infrared LED, and the demodulated output is performed by a dedicated infrared receiver.

Communication method: simplex, asynchronous

Infrared LED wavelength: 940nm

Communication protocol standard: NEC standard

Please add a picture description

Idle state: the infrared LED is off, and the receiving head outputs a high level

Sending low level: the infrared LED flashes at a frequency of 38KHz, and the receiving head outputs low level

Sending high level: the infrared LED is off, and the receiving head outputs high level

NEC code:

Please add a picture description

Please add a picture description

STC89C52 has 4 external interrupts

There are two ways to trigger the external interrupt of STC89C52:

  • Falling edge trigger
  • Low level trigger

Low-level trigger means that after the interrupt is enabled, as long as the signal of the interrupt pin is low, the interrupt will be triggered. When using it, please note that if the low level is kept, it will cause multiple trigger interrupts. (keep pressing the button)

The falling edge trigger means that after the interrupt is enabled, as long as the signal of the interrupt pin has a falling edge, the interrupt will be triggered. When using it, please note that if the signal jitters, it will cause multiple trigger interrupts. (one click action)

interrupt number:

Please add a picture description

External Interrupt Register

Please add a picture description

Please add a picture description

// 配置外部中断
void Int0_Init(){
    
    
	IT0 = 1; // 配置外部中断的触发模式:1下降沿触发,0低电平触发
	IE0 = 0; // 中断位清零
	EX0 = 1; // 外部中断打开
	EA = 1; // 总中断开启
	PX0 = 1; // 优先级(高)保证能及时响应
}
#include <REGX52.H>
#include "Timer0.h"
#include "Int0.h"

unsigned int IR_Time; // 计时
unsigned char IR_State; // 红外解码状态

// 出错可能是0x01默认是int型,写成0x01LL就不会错了
unsigned char IR_Data[4]; // 数据区(4个字节)
unsigned char IR_pData; // 数据区下标

unsigned char IR_DataFlag; // 标识是否接受完数据
unsigned char IR_RepeatFlag; // 接收Repeat时的标识
unsigned char IR_Address; // 数据接收完后保存地址数据
unsigned char IR_Command; // 保存命令码数据


void IR_Init(){
    
    
	Timer0_Init_Counter();
	Int0_Init();
}

unsigned char IR_GetDataFlag(){
    
    
	if(IR_DataFlag){
    
    
		IR_DataFlag = 0;
		return 1;
	}
	return 0;
}

unsigned char IR_GetRepeatFlag(){
    
    
	if(IR_RepeatFlag){
    
    
		IR_RepeatFlag = 0;
		return 1;
	}
	return 0;
}

unsigned char IR_GetAddress(){
    
    
	return IR_Address;
}

unsigned char IR_GetCommand(){
    
    
	return IR_Command;
}

void Int0_Routine() interrupt 0{
    
     // 外部中断函数
	
	switch(IR_State){
    
    
		case 0:{
    
     // 空闲状态
			// P2_0 = 0;
			Timer0_SetCounter(0);
			Timer0_CounterRun(1); // 开始程序计时
			IR_State = 1;
			break;
		}
		case 1:{
    
     // 接收Start/Repeat状态
			IR_Time = Timer0_GetCounter(); // 获取计时结果
			Timer0_SetCounter(0); // 重置计时器
			if(IR_Time>12442-500 && IR_Time<12442+500){
    
     // 红外发送Start,范围误差
				//P2_1 = 0;
				IR_State = 2;
			}else if(IR_Time>10368-500 && IR_Time<10368+500){
    
     // 红外发送Repeat,范围误差
				IR_RepeatFlag = 1; // 标识接收到Repeat
				Timer0_CounterRun(0); // 停止计时
				IR_State = 0; // 回到空闲状态
			}
			break;
		}
		case 2:{
    
     // 接收0/1状态
			IR_Time = Timer0_GetCounter(); // 获取计时结果
			Timer0_SetCounter(0); // 重置计时器
			if(IR_Time>1032-500 && IR_Time<1032+500){
    
     // 红外发送数据0
				IR_Data[IR_pData/8] &= ~(0x01 << (IR_pData % 8));
                /*
                这一句有点复杂
                IR_Data一共能存四个字节,分别是地址码、地址反码、命令码、命令反码
                每个字节8位,要存入0就用:&=1101 1111,但是按位移会把位置0,所以使用:&=~(0010 0000)
                IR_pData是从0增加到32的,(IR_pData % 8)使得按位移时不超过字节
                IR_pData/8使得IR_pData每增加8次就换到下一个字节,4(个字节)*8(位)=32
                */
				IR_pData++;
			}else if(IR_Time>2074-500 && IR_Time<2074+500){
    
     // 红外发送数据1
				IR_Data[IR_pData/8] |= (0x01 << (IR_pData % 8));
				IR_pData++;
			}else{
    
    
				IR_pData = 0;
				IR_State = 1;
			}
			
			if(IR_pData >= 32){
    
     // 接收了32位数据
				IR_pData = 0;
				if((IR_Data[0] == ~IR_Data[1]) && (IR_Data[2] == ~IR_Data[3])){
    
     // 校验反码
					
					IR_Address = IR_Data[0];
					IR_Command = IR_Data[2];
					IR_DataFlag = 1;
				}
				Timer0_CounterRun(0);
				IR_State = 0;
			}
			break;
		}
		default:
			break;
	}
}

Guess you like

Origin blog.csdn.net/Falling_Asteroid/article/details/130737398