STM32 NEC infrared remote control decoding

Infrared remote control coding format

The existing infrared remote control includes two methods: PWM (Pulse Width Modulation) and PPM (Pulse Position Modulation). The representatives of the two forms of codes are NEC and PHILIPS's RC-5, RC-6, and the future RC-7.
Features of NEC format:
1: Use 38 kHz carrier frequency
2: Pilot code interval is 9 ms + 4.5 ms
3: Use 16-bit customer code
4: Use 8-bit data code and 8-bit inverted data code
NEC protocol passes burst The time interval between to achieve signal modulation (English abbreviation PWM). Logic "0" is composed of 0.56ms 38KHZ carrier and 0.56ms no carrier interval; Logic "1" is composed of 0.56ms 38KHZ carrier and 1.68ms no carrier interval; the end bit is 0.56ms 38K carrier.
Insert picture description here
PPM (Pulse Position Modulation): "0" and "1" are represented by the position of the transmitted carrier. From transmitting carrier to non-transmitting carrier is "0", from not transmitting carrier to transmitting carrier is "1". The time for transmitting the carrier and not transmitting the carrier is the same, both are 0.68ms, that is, the time for each bit is fixed. RC5 coding is relatively simple: Insert picture description here
Insert picture description here
get a set of numbers: 110, 11010, 001101 According to the coding definition: the
first bit is the start bit S is usually logic 1, the
second bit is the field bit F is usually logic 1, in RC5 extended mode it Extend the last 6-digit command code to 7-digit code (high MSB), which can expand from 64 key values ​​to 128 key values.
The third bit is the control bit C, which flips every time a key is pressed, so that it can be distinguished whether a key has been pressed and not let go or if it is repeatedly pressed after letting go.
Then there are five system address bits: 11010=1A, and finally six command bits: 001101=0D.

Integrated infrared receiver

The infrared receiving circuit is usually integrated into one component by the manufacturer to become an integrated infrared receiving head. The internal circuit includes infrared monitoring diode, amplifier, limiter, band pass filter, integrating circuit, comparator, etc. The infrared monitoring diode detects the infrared signal, and then sends the signal to the amplifier and limiter. The limiter controls the pulse amplitude at a certain level, regardless of the distance between the infrared transmitter and the receiver. The AC signal enters the band-pass filter. The band-pass filter can pass the load wave of 30khz to 60khz, enter the comparator through the demodulation circuit and the integration circuit, and the comparator outputs high and low levels to restore the signal waveform at the transmitter. Note that the high and low levels of the output are inverted from the transmitting end. The purpose of this is to improve the sensitivity of the receiving.
There are many types of infrared receivers, and the pin definitions are different. Generally, there are three pins, including power supply pin, ground and signal output pin. The receiving head of the corresponding demodulation frequency should be selected according to the different modulating carrier of the transmitting end.
The gain of the internal amplifier of the infrared receiving head is very large and it is easy to cause interference. Therefore, a filter capacitor must be added to the power supply pin of the receiving head, generally above 22uf. Some manufacturers recommend connecting a 330 ohm resistor between the power supply pin and the power supply to further reduce power interference.

STM32 displays the numeric code pressed by the remote control

Insert picture description here
Connection of infrared receiver and STM32
Infrared receiver circuit principle diagram

Code piece

//红外遥控初始化
//设置IO以及定时器3的输入捕获
void Remote_Init(void)    			  
{
    
      

	RCC->APB1ENR|=1<<1;   	//TIM3 时钟使能 
	RCC->APB2ENR|=1<<3;    	//使能PORTB时钟 
	GPIOB->CRL&=0XFFFFFFF0;	//PB0 输入  
	GPIOB->CRL|=0X00000008;	//上拉输入     
	GPIOB->ODR|=1<<0;		//PB0 上拉
	
	TIM3->ARR=10000;  		//设定计数器自动重装值 最大10ms溢出  
	TIM3->PSC=71;  			//预分频器,1M的计数频率,1us加1.	
	TIM3->CCMR2|=1<<0;		//CC3S=01 	选择输入端 IC3映射到TI3上
 	TIM3->CCMR2|=3<<4;  	//IC3F=0011 配置输入滤波器 8个定时器时钟周期滤波
 	TIM3->CCMR2|=0<<2;  	//IC3PS=00 	配置输入分频,不分频 
	TIM3->CCER|=0<<9; 		//CC3P=0	上升沿捕获
	TIM3->CCER|=1<<8; 		//CC3E=1 	允许捕获计数器的值到捕获寄存器中
	TIM3->DIER|=1<<3;   	//允许CC3IE捕获中断				
	TIM3->DIER|=1<<0;   	//允许更新中断				
	TIM3->CR1|=0x01;    	//使能定时器3
  	MY_NVIC_Init(1,3,TIM3_IRQn,2);//抢占1,子优先级3,组2		
	
}

 
//遥控器接收状态
//[7]:收到了引导码标志
//[6]:得到了一个按键的所有信息
//[5]:保留	
//[4]:标记上升沿是否已经被捕获								   
//[3:0]:溢出计时器
u8 	RmtSta=0;	  	  
u16 Dval;		//下降沿时计数器的值
u32 RmtRec=0;	//红外接收到的数据	   		    
u8  RmtCnt=0;	//按键按下的次数	  
//定时器3中断服务程序	 
void TIM3_IRQHandler(void)
{
    
     	
    u16 tsr;
	tsr=TIM3->SR;
	
    if(tsr&0X01)//溢出
	{
    
    
		if(RmtSta&0x80)//上次有数据被接收到了
		{
    
    	
			RmtSta&=~0X10;						//取消上升沿已经被捕获标记
			if((RmtSta&0X0F)==0X00)RmtSta|=1<<6;//标记已经完成一次按键的键值信息采集
			if((RmtSta&0X0F)<14)RmtSta++;
			else
			{
    
    
				RmtSta&=~(1<<7);//清空引导标识
				RmtSta&=0XF0;	//清空计数器	
			}						 	   	
		}							    
	}
 	if(tsr&(1<<3))//CC3IE中断
	{
    
    	  
		if(RDATA)//上升沿捕获
		{
    
    			
			TIM3->CCER|=1<<9; 				//CC3P=1	设置为下降沿捕获
			TIM3->CNT=0;					//清空定时器值
			RmtSta|=0X10;					//标记上升沿已经被捕获		
		}else //下降沿捕获
		{
    
    			
			
			Dval=TIM3->CCR3;				//读取CCR3也可以清CC2IF标志位
  			TIM3->CCER&=~(1<<9);			//CC3P=0	设置为上升沿捕获
 			
			if(RmtSta&0X10)					//完成一次高电平捕获 
			{
    
    
 				if(RmtSta&0X80)//接收到了引导码
				{
    
    
					
					if(Dval>300&&Dval<800)			//560为标准值,560us
					{
    
    
						RmtRec<<=1;	//左移一位.
						RmtRec|=0;	//接收到0	   
					}else if(Dval>1400&&Dval<1800)	//1680为标准值,1680us
					{
    
    
						RmtRec<<=1;	//左移一位.
						RmtRec|=1;	//接收到1
					}else if(Dval>2200&&Dval<2600)	//得到按键键值增加的信息 2500为标准值2.5ms
					{
    
    
						RmtCnt++; 		//按键次数增加1次
						RmtSta&=0XF0;	//清空计时器		
					}
 				}else if(Dval>4200&&Dval<4700)		//4500为标准值4.5ms
				{
    
    
					RmtSta|=1<<7;	//标记成功接收到了引导码
					RmtCnt=0;		//清除按键次数计数器
				}						 
			}
			RmtSta&=~(1<<4);
		}				 		     	    					   
	}	
   TIM3->SR=0;//清除中断标志位     
}

//处理红外键盘
//返回值:
//	 0,没有任何按键按下
//其他,按下的按键键值.
u8 Remote_Scan(void)
{
    
            
	u8 sta=0;       
    u8 t1,t2;  
	if(RmtSta&(1<<6))//得到一个按键的所有信息了
	{
    
     
	    t1=RmtRec>>24;			//得到地址码
	    t2=(RmtRec>>16)&0xff;	//得到地址反码 
 	    if((t1==(u8)~t2)&&t1==REMOTE_ID)//检验遥控识别码(ID)及地址 
	    {
    
     
	        t1=RmtRec>>8;
	        t2=RmtRec; 	
	        if(t1==(u8)~t2)sta=t1;//键值正确	 
		}   
		if((sta==0)||((RmtSta&0X80)==0))//按键数据错误/遥控已经没有按下了
		{
    
    
		 	RmtSta&=~(1<<6);//清除接收到有效按键标识
			RmtCnt=0;		//清除按键次数计数器
		}
	}  
    return sta;
}
// 共阴数字数组
// 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F, .,全灭
u8 smg_num[]={
    
    0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xfe,0xf6,0xee,0x3e,0x9c,0x7a,0x9e,0x8e,0x01,0x00};
u8 key=0;  //按键值
u8 num=0x00;//数值
u8 num1=0x00;//数值
u8 smg_wei=6;//数码管位选
u8 smg_duan=0;//数码管段选
u8 smg_flag=0;//数码管显示标志 0:正常显示 1:不显示(消除鬼影)
u8 t=0;
 int main(void)
 {
    
     
	
	Stm32_Clock_Init(9);	//系统时钟设置
	uart_init(72,115200);	//串口初始化为115200
	delay_init(72);	   	 	//延时初始化 
	BEEP_Init();            //蜂鸣器初始化
	LED_Init();		  		//初始化与LED连接的硬件接口
    LED_SMG_Init();         //数码管初始化
    TIM4_Init(19,7199);     //数码管2ms定时显示
    Remote_Init();			//红外接收初始化		 
	while(1);
}

void TIM4_IRQHandler(void) //TIM4中断
{
    
    
	
	if(TIM4->SR&0X0001)//溢出中断
	{
    
    
        key = Remote_Scan();//获取红外遥控键值
		 if(key)
		 {
    
    
			switch(key)
			{
    
    
				case 104:num1=0x00; num = smg_num[1]; BEEP=0;break; //按键'1'
				case 152:num1=0x00;num=smg_num[2];BEEP=0;break;     //按键'2'	   
				case 176:num1=0x00;num=smg_num[3];BEEP=0;break;     //按键'3'	    
				case 48:num1=0x00;num=smg_num[4];BEEP=0;break;      //按键'4'		    
				case 24:num1=0x00;num=smg_num[5];BEEP=0;break;      //按键'5'		    
				case 122:num1=0x00;num=smg_num[6];BEEP=0;break;     //按键'6'		  
				case 16:num1=0x00;num=smg_num[7];BEEP=0;break;      //按键'7'			   					
				case 56:num1=0x00;num=smg_num[8];BEEP=0;break;      //按键'8'	 
				case 90:num1=0x00;num=smg_num[9];BEEP=0;break;      //按键'9'
				case 66:num1=0x00;num=smg_num[0];BEEP=0;break;      //按键'0'
				case 82:num1=0x00;num=smg_num[17];BEEP=0;break;     //按键'DELETE'
				case 162:num1=smg_num[1];num=smg_num[0];BEEP=0; break;//按键'POWER'    
				case 98:num1=smg_num[1];num=smg_num[1];BEEP=0;  break;//按键'UP'
				case 226:num1=smg_num[1];num=smg_num[2];BEEP=0; break;//按键'ALIENTEK'
				case 34:num1=smg_num[1];num=smg_num[3];BEEP=0;  break;//按键'LEFT'
				case 2:num1=smg_num[1];num=smg_num[4];BEEP=0;   break;//按键'PLAY'
				case 194:num1=smg_num[1];num=smg_num[5];BEEP=0; break;//按键'RIGHT'
				case 224:num1=smg_num[1];num=smg_num[6];BEEP=0; break;//按键'VOL-'
				case 168:num1=smg_num[1];num=smg_num[7];BEEP=0; break;//按键'DOWN'
				case 144:num1=smg_num[1];num=smg_num[8];BEEP=0; break;//按键'VOL+'
			}
		 }else
		 {
    
    
			BEEP=1;
		 }
		 if(smg_wei==6)//数码管位
		 {
    
    
			 smg_duan = num1;
		 }
		 else if(smg_wei==7)//数码管位
		 {
    
    
			 smg_duan = num;
		 }
		 if(smg_flag) LED_Write_Data(0x00,smg_wei);//消除鬼影(段码不显示)
		 else 	  LED_Write_Data(smg_duan,smg_wei);//正常显示 
		 LED_Refresh();//数码管数据更新
		 smg_flag=!smg_flag;
		 if(smg_flag==0)//正常显示才更新位码
		 {
    
    
			 smg_wei++;
		     if(smg_wei==8) smg_wei=6;
		 }
		 t++;
		 if(t==250)//LED0每500MS闪烁
		 {
    
    
			t=0;
			LED0=!LED0;
		 } 
	}
	TIM4->SR&=~(1<<0);//清除中断标志位 
		
}

to sum up

Through this experiment, understand the basic principles of NEC infrared remote control decoding. The key codes of the infrared remote control are fixed, and the key codes of different remote controls may be different. The infrared remote control can also use the infrared transmitting tube to build the transmitting circuit by itself, the single-chip computer program is encoded, and the infrared receiving head decodes according to the encoding rules.

Guess you like

Origin blog.csdn.net/qq_42250136/article/details/114268829