STM32 NEC infrared remote control decoding

Infrared remote control coding format

The existing infrared remote control includes two modes: PWM (pulse width modulation) and PPM (pulse position modulation). The representatives of the two forms of coding are RC-5 and RC-6 of NEC and PHILIPS and RC-7 in the future.
Features of NEC format:
1: Use 38 kHz carrier frequency
2: The boot code interval is 9 ms + 4.5 ms
3: Use 16 digit customer code
4: Use 8-bit data code and 8-bit inverted data code
NEC protocol realizes signal modulation through the time interval between pulse trains (PWM in English). Logic "0" is composed of 0.56ms 38KHZ carrier and 0.56ms carrier free interval; Logic "1" is composed of 38KHZ carrier of 0.56ms and carrier free interval of 1.68ms; The end bit is a 38K carrier of 0.56ms.

PPM (pulse position modulation): represent "0" and "1" with the position of the transmitting carrier. From transmit carrier to non transmit carrier is "0", from never transmit carrier to transmit carrier is "1". The transmission time of each carrier is not the same as 680.0 Ms. RC5 coding is relatively simple:

Get a set of numbers: 11010001101 according to the code definition:
The first bit is the start bit S, which is usually logical 1
The second bit is field bit F, which is usually logic 1. In RC5 expansion mode, it expands the last 6-bit command code to 7-bit code (high MSB), so that it can expand from 64 key values to 128 key values.
The third bit is the control bit C, which flips after each key is pressed, so as to distinguish whether a key is pressed all the time or repeatedly after it is released.
Followed by five system address bits: 11010=1A, and finally six command bits: 001101=0D.

Integrated infrared receiver

Infrared receiving circuit is usually integrated into one component by manufacturers to become an integrated infrared receiving head. The internal circuit includes infrared monitoring diode, amplifier, pair limiter, band-pass filter, integral circuit, comparator, etc. The infrared monitoring diode monitors the infrared signal, and then sends the signal to the amplifier and limiter, which 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 through the load wave of 30khz to 60khz and enter the comparator through the demodulation circuit and integration circuit. The comparator outputs high and low levels to restore the signal waveform at the transmitting end. Note that the high and low levels of the output and the transmitter are reversed, so as to improve the sensitivity of the receiver.
There are many kinds of infrared receiving heads, and the pin definitions are also different. Generally, there are three pins, including power supply pin, grounding pin and signal output pin. The receiver with corresponding demodulation frequency shall be selected according to the different modulation carriers at the transmitting end.
The gain of the internal amplifier of the infrared receiving head is very large, which is easy to cause interference. Therefore, a filter capacitor must be added to the power supply pin of the receiving head, which is generally more than 22uf. Some manufacturers suggest connecting 330 ohm resistance between the power supply pin and the power supply to further reduce the power interference.

STM32 displays the digital code pressed by the remote control



Code slice

//Infrared remote control initialization
//Set IO and input capture of timer 3
void Remote_Init(void)    			  
{  

	RCC->APB1ENR|=1<<1;   	//TIM3 clock enable 
	RCC->APB2ENR|=1<<3;    	//Enable PORTB clock 
	GPIOB->CRL&=0XFFFFFFF0;	//PB0 input  
	GPIOB->CRL|=0X00000008;	//Pull up input     
	GPIOB->ODR|=1<<0;		//PB0 pull-up
	
	TIM3->ARR=10000;  		//Set the maximum 10ms overflow of the counter automatic reload value  
	TIM3->PSC=71;  			//Prescaler, 1M counting frequency, 1us plus 1	
	TIM3->CCMR2|=1<<0;		//CC3S=01  	 Select input IC3 to map to TI3
 	TIM3->CCMR2|=3<<4;  	//IC3F=0011 configure input filter, 8 timer clock cycle filtering
 	TIM3->CCMR2|=0<<2;  	//IC3PS=00  	 Configure input frequency division without frequency division 
	TIM3->CCER|=0<<9; 		//CC3P=0 	 Rising edge capture
	TIM3->CCER|=1<<8; 		//CC3E=1  	 Allows the value of the capture counter to be added to the capture register
	TIM3->DIER|=1<<3;   	//Allow CC3IE to capture interrupts				
	TIM3->DIER|=1<<0;   	//Allow update interruption				
	TIM3->CR1|=0x01;    	//Enable timer 3
  	MY_NVIC_Init(1,3,TIM3_IRQn,2);//Preemption 1, sub priority 3, group 2		
	
}

 
//Remote control receiving status
//[7] : received boot code flag
//[6] : get all the information of a key
//[5] : reserved	
//[4] : mark whether the rising edge has been captured								   
//[3:0]: overflow timer
u8 	RmtSta=0;	  	  
u16 Dval;		//Counter value at falling edge
u32 RmtRec=0;	//Infrared received data	   		    
u8  RmtCnt=0;	//Number of key presses	  
//Timer 3 interrupt service program	 
void TIM3_IRQHandler(void)
{ 	
    u16 tsr;
	tsr=TIM3->SR;
	
    if(tsr&0X01)//overflow
	{
		if(RmtSta&0x80)//Data was received last time
		{	
			RmtSta&=~0X10;						//Cancel the mark that the rising edge has been captured
			if((RmtSta&0X0F)==0X00)RmtSta|=1<<6;//Mark that the key value information collection of one key has been completed
			if((RmtSta&0X0F)<14)RmtSta++;
			else
			{
				RmtSta&=~(1<<7);//Clear the boot flag
				RmtSta&=0XF0;	//Clear counter	
			}						 	   	
		}							    
	}
 	if(tsr&(1<<3))//CC3IE interrupt
	{	  
		if(RDATA)//Rising edge capture
		{			
			TIM3->CCER|=1<<9; 				//CC3P=1 	 Set to falling edge capture
			TIM3->CNT=0;					//Clear timer value
			RmtSta|=0X10;					//The rising edge of the marker has been captured		
		}else //Falling edge capture
		{			
			
			Dval=TIM3->CCR3;				//Reading CCR3 can also clear the CC2IF flag bit
  			TIM3->CCER&=~(1<<9);			//CC3P=0 	 Set to rising edge capture
 			
			if(RmtSta&0X10)					//Complete a high level acquisition 
			{
 				if(RmtSta&0X80)//Received boot code
				{
					
					if(Dval>300&&Dval<800)			//560 is the standard value, 560us
					{
						RmtRec<<=1;	//Move left one bit
						RmtRec|=0;	//Received 0	   
					}else if(Dval>1400&&Dval<1800)	//1680 is the standard value, 1680us
					{
						RmtRec<<=1;	//Move left one bit
						RmtRec|=1;	//Received 1
					}else if(Dval>2200&&Dval<2600)	//Get the information about the increase of key value 2500, which is the standard value of 2.5ms
					{
						RmtCnt++; 		//Increase the number of keys by 1 time
						RmtSta&=0XF0;	//Clear timer		
					}
 				}else if(Dval>4200&&Dval<4700)		//4500 is the standard value of 4.5ms
				{
					RmtSta|=1<<7;	//Flag successfully received boot code
					RmtCnt=0;		//Clear key count
				}						 
			}
			RmtSta&=~(1<<4);
		}				 		     	    					   
	}	
   TIM3->SR=0;//Clear interrupt flag bit     
}

//Processing infrared keyboard
//Return value:
//	 0, no key pressed
//Other, press the key value
u8 Remote_Scan(void)
{        
	u8 sta=0;       
    u8 t1,t2;  
	if(RmtSta&(1<<6))//Got all the information about a key
	{ 
	    t1=RmtRec>>24;			//Get the address code
	    t2=(RmtRec>>16)&0xff;	//Get the address inverse code 
 	    if((t1==(u8)~t2)&&t1==REMOTE_ID)//Verify the remote control identification code (ID) and address 
	    { 
	        t1=RmtRec>>8;
	        t2=RmtRec; 	
	        if(t1==(u8)~t2)sta=t1;//The key value is correct	 
		}   
		if((sta==0)||((RmtSta&0X80)==0))//Key data error / remote control has not been pressed
		{
		 	RmtSta&=~(1<<6);//Clear received valid key identification
			RmtCnt=0;		//Clear key count
		}
	}  
    return sta;
}
// Common negative number array
// 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F, ., Total extinction
u8 smg_num[]={0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xfe,0xf6,0xee,0x3e,0x9c,0x7a,0x9e,0x8e,0x01,0x00};
u8 key=0;  //Key value
u8 num=0x00;//numerical value
u8 num1=0x00;//numerical value
u8 smg_wei=6;//Nixie tube position selection
u8 smg_duan=0;//Nixie tube segment selection
u8 smg_flag=0;//Nixie tube display flag 0: normal display 1: not display (eliminate ghosts)
u8 t=0;
 int main(void)
 { 
	
	Stm32_Clock_Init(9);	//System clock setting
	uart_init(72,115200);	//The serial port is initialized to 115200
	delay_init(72);	   	 	//Delay initialization 
	BEEP_Init();            //Buzzer initialization
	LED_Init();		  		//Initialize the hardware interface to the LED
    LED_SMG_Init();         //Nixie tube initialization
    TIM4_Init(19,7199);     //Nixie tube 2ms timing display
    Remote_Init();			//Infrared receiving initialization		 
	while(1);
}

void TIM4_IRQHandler(void) //TIM4 interrupt
{
	
	if(TIM4->SR&0X0001)//Overflow interrupt
	{
        key = Remote_Scan();//Get infrared remote control key value
		 if(key)
		 {
			switch(key)
			{
				case 104:num1=0x00; num = smg_num[1]; BEEP=0;break; //Key '1'
				case 152:num1=0x00;num=smg_num[2];BEEP=0;break;     //Key '2'	   
				case 176:num1=0x00;num=smg_num[3];BEEP=0;break;     //Key '3'	    
				case 48:num1=0x00;num=smg_num[4];BEEP=0;break;      //Key '4'		    
				case 24:num1=0x00;num=smg_num[5];BEEP=0;break;      //Key '5'		    
				case 122:num1=0x00;num=smg_num[6];BEEP=0;break;     //Key '6'		  
				case 16:num1=0x00;num=smg_num[7];BEEP=0;break;      //Key '7'			   					
				case 56:num1=0x00;num=smg_num[8];BEEP=0;break;      //Key '8'	 
				case 90:num1=0x00;num=smg_num[9];BEEP=0;break;      //Key '9'
				case 66:num1=0x00;num=smg_num[0];BEEP=0;break;      //Key '0'
				case 82:num1=0x00;num=smg_num[17];BEEP=0;break;     //Key 'DELETE'
				case 162:num1=smg_num[1];num=smg_num[0];BEEP=0; break;//Key 'POWER'    
				case 98:num1=smg_num[1];num=smg_num[1];BEEP=0;  break;//Key 'UP'
				case 226:num1=smg_num[1];num=smg_num[2];BEEP=0; break;//Key 'ALIENTEK'
				case 34:num1=smg_num[1];num=smg_num[3];BEEP=0;  break;//Key 'LEFT'
				case 2:num1=smg_num[1];num=smg_num[4];BEEP=0;   break;//Key 'PLAY'
				case 194:num1=smg_num[1];num=smg_num[5];BEEP=0; break;//Key 'RIGHT'
				case 224:num1=smg_num[1];num=smg_num[6];BEEP=0; break;//Key 'VOL -'
				case 168:num1=smg_num[1];num=smg_num[7];BEEP=0; break;//Key 'DOWN'
				case 144:num1=smg_num[1];num=smg_num[8];BEEP=0; break;//Key 'VOL +'
			}
		 }else
		 {
			BEEP=1;
		 }
		 if(smg_wei==6)//Digital tube position
		 {
			 smg_duan = num1;
		 }
		 else if(smg_wei==7)//Digital tube position
		 {
			 smg_duan = num;
		 }
		 if(smg_flag) LED_Write_Data(0x00,smg_wei);//Eliminate ghosts (segment code is not displayed)
		 else 	  LED_Write_Data(smg_duan,smg_wei);//Normal display 
		 LED_Refresh();//Nixie tube data update
		 smg_flag=!smg_flag;
		 if(smg_flag==0)//The bit code is updated only when it is displayed normally
		 {
			 smg_wei++;
		     if(smg_wei==8) smg_wei=6;
		 }
		 t++;
		 if(t==250)//LED0 flashes every 500MS
		 {
			t=0;
			LED0=!LED0;
		 } 
	}
	TIM4->SR&=~(1<<0);//Clear interrupt flag bit 
		
}

summary

Through this experiment, we understand the basic principle of NEC infrared remote control decoding. The key codes of infrared remote control are fixed. The key codes of different remote controls may be different. The infrared remote controller can also use the infrared transmitting tube to build its own transmitting circuit, the MCU program is encoded, and the infrared receiving head decodes according to the coding rules.

Posted by Coronach on Thu, 14 Apr 2022 05:25:50 +0930