GPIO analog timing control peripheral 4 - infrared emission tube

foreword

The previous article introduced the use of GPIO analog timing to realize the function of the I2C protocol. This article continues to use the GPIO analog method to implement a module commonly used in daily life - the drive of the infrared emission tube. Infrared is widely used in home appliances, air conditioners, TV, projection, etc. are all realized by infrared remote control.

Infrared Emitter Introduction

The actual infrared emitting tube is the device in the red box on the left in the figure below, and the infrared receiving tube is on the right.
insert image description here
After you get the infrared emission tube, the first reaction may be that this thing looks exactly the same as the LED light. In fact, not only the appearance is the same, but also the working principle is the same, that is, the level is given by a certain rule, click " Turn on" and turn off the infrared emitting tube to generate infrared light signals. After the infrared light signal is processed by the receiving tube, a corresponding electrical signal will be generated, and then the user can receive and process the electrical signal to control different peripherals. It's just that the wavelength of the infrared emission tube exceeds the band visible to our naked eyes, which we can't usually observe. As shown in the figure below: the wavelength band of light visible to our naked eyes is 380nm----760nm, and the wavelength of this infrared emission tube is 940nm.
insert image description here
insert image description here
Of course, if you really want to see the lighting effect, you can also turn off the surrounding lights, find a darker environment, and use the phone camera to see the red light.
insert image description here

NEC agreement

As mentioned above, the infrared transmitting tube uses a special way to send data. The specific sending format needs to refer to the chip manual of the infrared receiving tube and the specific communication protocol used. Here, the receiving tube uses HS0038, and the communication protocol is NEC.

HS0038

Let’s take a look at how the HS0038 manual describes it. As shown in the figure below, we can know that when the received input infrared light is a PWM waveform with a frequency of 38khz, a duty cycle of 50%, and a duration of 500us-700us , the output of HS0038 will generate a low level, and when the input infrared light is not a signal of this specification, HS0038 will output a high level.
insert image description here
Let’s analyze the actual waveform:
as shown in the figure below: D1 is the optical signal emitted by the infrared transmitting tube, and D0 is the output signal generated by the infrared receiving tube according to the input signal. It can be seen that when the waveform of D1 becomes PWM, D0 outputs low level, and when D1 output is not PWM, D0 output is high level.
insert image description here

Logical "1" and logical "0" of NEC

Why the output of HS0038 that I have been talking about above is high and low level instead of logic 0 and logic 1?
I still remember that when driving WS2812B and DHT11 before, their logic 0 and logic 1 did not simply correspond to high and low levels. The same is true here. Logic 0 and logic 1 in the NEC protocol are not simple high and low levels, but have The combination of high and low levels in different time periods, among which:
logic "0" is composed of 560us low level plus 560us high level,
logic "1" is composed of 560us low level plus 1690us high level ,
Combined with the diagram of the logic analyzer below, you can understand it. Pay attention to the green decoding at the bottom. The first low level and the first high level form the first logic 0, and the second low
level The level and the second high level form a logic 0,
and the third low level and the third high level form a logic 1,
insert image description here
because most of the equipment in the infrared transmission project supports NEC Format, so we also need to adjust the timing of the NEC code at the transmitter end. When outputting logic 1, we need to use the first half of the timing in the figure below, and when outputting logic "0", we need to use it. The timing sequence of the second half of the figure below:
Link to the original text - http://t.csdn.cn/LoC2r
insert image description here
The dynamic process of the entire data transmission can be seen in the following animation:
the single-chip microcomputer controls the switching tube according to the logic "0" and logic "1" Timing is used to control the lighting and closing of the infrared emitting tube, and the infrared receiving tube will output the corresponding high and low level information after receiving the signal of the infrared emitting tube, and it is enough to use the MCU to capture and process this part of the signal.
insert image description here

NEC data frame format

After clarifying the logic "0" and logic "1" of the NEC protocol, you need to know the specific format of the data frame. In order to further improve the stability of the data, the NEC code also has a lot to do with the data frame during transmission. High requirements, the specific frame format is as follows:
insert image description here
It should be noted that the previous data communication is high-order first, high-order first, and the NEC here is low-order first, low-order first.

Synchronous terminal (boot code/start code), address code (remote control ID), address inverse code, control code (key value), control inverse code.
Synchronization code, address code (remote control ID), address inversion code, control code (key value), control inversion code
Synchronization code consists of a 9ms low level and a 4.5ms high level
. If synchronization is received, it means that there is infrared data Come in

Synchronization code + 8-bit address code + 8-bit address code inverse code + 8-bit control code + 8-bit control code inverse code
Infrared receiving data is 32 bits each time

Actual data:

frame header address code Inverse address code Order Inverse command
9ms low level + 4.5ms high level 8 bits 8 bits 8 bits 8 bits
9ms low level + 4.5ms high level 1011 0111 0100 1000 0110 0110 1001 1001

insert image description here
In addition, there is a data frame format that is sent continuously, so I won’t introduce it here. If you need it, you can study it yourself.

programming ideas

After figuring out the communication process between the infrared transmitter tube and the receiver tube and the format of its data frame, you can start programming. This article first solves the code of the infrared transmitter tube, and the use of the receiver tube is left to the next article to introduce GPIO multiplexing Let's talk about the function.

1. GPIO pins

First step, without further ado, just look at the schematic diagram and find that the GPIO is PB7. According to the previous analysis, when sending infrared light, it is necessary to send a frequency of 38khz, a duty cycle of 50%, and a duration of 560us. PWM, to make the infrared receiving tube output low level. Generally speaking, the best solution is to use the timer to generate PWM to achieve low level. When the time is up, pull the GPIO port low and not output PWM to achieve this
. Selecting PB7 pin can be used as channel 2 of timer 4, but there is a problem, in the actual use process, timer 4 has other uses; so there is no way, only GPIO analog method can be used to realize infrared Now that the function of the launch tube is over, it is necessary to simulate a PWM waveform here, of course, it is realized by using the push-pull mode with the delay.
insert image description here
For the PWM implementation scheme, here are a few links for Daji for your reference.
STM32 NEC infrared remote control decoding-
infrared receiving and sending based on STM32f103c8t6
In addition, there are several well-written blogs for everyone to post here.
STM32 entry development: making infrared remote control (smart home-universal remote control)
insert image description here
GPIO initialization code:

/************************************************
函数功能:红外发送控制码
函数名:Infrared_Send_Init
函数形参:None
函数返回值:
备注:  PB7
**************************************************/
void Infrared_Send_Init(void)
{
    
    
	GPIO_InitTypeDef GPIO_InitStruct;                       // 定义一个GPIO_InitTypeDef类型的变量
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);   // 允许GPIOB时钟
	
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7;                  // GPIO_Pin_7
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;           // 通用推挽输出
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;          // 50MHz速度
	GPIO_Init(GPIOB, &GPIO_InitStruct);
	
	GPIO_ResetBits(GPIOB, GPIO_Pin_7);                      //PB7拉低
}

After finding the implementation plan, it’s time to implement it. For this kind of communication method with more complex data frames, remember to write from bottom to top when simulating its timing. First fix each part, and then splice them together to form a whole sequence.
The entire data frame is nothing more than the following content,
1. Synchronization header, 2. Logic "0" and logic "1"; and logic 0 and logic 1 can be further subdivided into low level and high level, that is, a PWM, one non-PWM. Then implement them one by one.

2. Analog sync head

Since the synchronous head of the receiving tube is a low level of 9ms plus a high level of 4.5ms, according to the conversion method, it can be known that the synchronous head of the transmitting tube is 9ms of 38khz, 50% duty cycle PWM plus 4.5ms low level.
insert image description here
For 38khz PWM, the duration of a pulse is 1/38 000=26.3us;
the duty cycle is 50%, then the time to output high level: 26.3/2=13.15us Since the system tick delay of STM32F103C8T6 supports up to us level, Therefore, the decimal point is omitted here, and the high and low levels are directly delayed by 13us.
The 9ms PWM has a total of 9ms/26=346.
So the code has:

/************************************************
函数功能:红外发送同步头
函数名:NEC_IE_Start
函数形参:None
函数返回值:
备注:  
// ①引导码:载波发射9ms,不发射4.5ms
**************************************************/
//------------------------------------------------------------
void NEC_IE_Start(void)
{
    
    
	u16 i;
// 载波发射 9ms ≈ 26.3us * 346
	for(i=0;i<346;i++) 
	{
    
    
		PBout(7)=1;	// IE抬高,发射红外光
		Systick_Delay_us(13);	// 延时13us
		PBout(7)=0;;	// IE拉低,不发射红外光
		Systick_Delay_us(13);	// 延时13us
	}
	// 载波不发射 4.5ms ≈ 26.3us * 171
	for(i=0;i<171;i++)
	{
    
    
		PBout(7)=0;	// IE拉低,不发射红外光
		Systick_Delay_us(26);	// 延时26us
	}
}

3. Send logic "0" and logic "1"

The common part of logic "0" and logic "1" is the PWM waveform of 560us. The difference lies in the latter part. Let's look at the
insert image description here
logic "1" first. In addition to the 560us PWM, it also needs a low power of 2.25ms-560us=1690us Ping, PWM still refers to the above ideas, so the code to send logic "1" will be:

/************************************************
函数功能:红外发送逻辑“1”
函数名:NEC_IE_Send_one
函数形参:None
函数返回值:
备注:  
// NEC协议数据"1" = 载波发射0.56ms + 载波不发射1.68ms
**************************************************/
//-------------------------------------------------
void NEC_IE_Send_one(void)
{
    
    
	u8 i;
	// 载波发射0.56ms ≈ 26.3us * 21
	//-------------------------------
	for(i=0;i<22;i++)
	{
    
    
		//26.3us(载波发射周期)占空比50%
		//------------------------------------
		PBout(7)=1;    // IE抬高,发射红外光
		Systick_Delay_us(13);	// 延时13us
		
		PBout(7)=0;  // IE拉低,不发射红外光
		Systick_Delay_us(13);	// 延时13us
		//------------------------------------
	}
	
	// 载波不发射1.69ms ≈ 26us * 65
	//--------------------------------
	for(i=0;i<65;i++)
	{
    
    
		//26us(载波不发射周期)
		//------------------------------------
		PBout(7)=0;	// IE拉低,不发射红外光
		Systick_Delay_us(26);	// 延时26us
	}
}

The idea of ​​​​the same logic "0" is similar, and the code is given directly:


/************************************************
函数功能:红外发送逻辑“0”
函数名:NEC_IE_Send_zero
函数形参:None
函数返回值:
备注:  
// NEC协议数据"0"= 载波发射0.56ms + 载波不发射0.56ms
**************************************************/
//-------------------------------------------------
void NEC_IE_Send_zero(void)     
{
    
    
	u8 i;
	
	// 载波发射0.56ms ≈ 26.3us * 21
	//-------------------------------
	for(i=0;i<22;i++)
	{
    
    
        //26.3us(载波发射周期)
		//------------------------------------
		PBout(7)=1;	// IE抬高,发射红外光
		Systick_Delay_us(13);	// 延时13us                       
											
		PBout(7)=0;	// IE拉低,不发射红外光
		Systick_Delay_us(13);	// 延时13us
		//------------------------------------
	}

	
	// 载波不发射0.56ms ≈ 26.3us * 21
	//-------------------------------
	for(i=0;i<21;i++)
	{
    
    
        //26.3us(载波不发射周期)
		//------------------------------------
		PBout(7)=0;	// IE拉低,不发射红外光
		Systick_Delay_us(26);	// 延时26us
		//------------------------------------
	}
}

send a byte of data

After getting the logic "0" and logic "1", the next step is naturally to encapsulate a function that can send 8 bits at a time, that is, one byte. What needs to be noted here is the low position first.
insert image description here
So the code is as follows:

/************************************************
函数功能:红外发送一个字节
函数名:NEC_IE_One_Data
函数形参:u8 IE_One_Data
函数返回值:
备注:  发送一个字节的数据,一次发8位,低位在前。
**************************************************/
//----------------------------------------------------------------------------------------------
void NEC_IE_One_Data(u8 IE_One_Data)
{
    
    
	u8 i;
	
	for(i=0;i<8;i++)
	{
    
    
		if( IE_One_Data & 0x01 )
			NEC_IE_Send_one();
		else
			NEC_IE_Send_zero();
			
		IE_One_Data>>=1;
	}
}

send a frame of data

The data format of a frame has been introduced earlier, here it is enough to make a combination according to the frame format and the above functions.
code show as below:


/************************************************
函数功能:发送NEC 一帧数据
函数名:NEC_IE_code_message
函数形参:u8 IE_One_Data
函数返回值:
备注: 
// 将一帧数据调制为NEC协议规定的红外载波发射出去
// 一帧数据格式:低位在前,由低到高发送8位数据
// 这帧数据是:②8位用户码字节(8位) / ③8位用户码反码(8位) / ④8位数据码 / ⑤8位数据码的反码
**************************************************/
void NEC_IE_code_message(u8 user_code_8bit, u8 data_code_8bit)
{
    
    
	// ①引导码:载波发射9ms,不发射4.5ms
	NEC_IE_Start();
	//------------------------------------------------------------
	//------------------------------------------------------------
	// ②8位用户码	:8位数据
	NEC_IE_One_Data(user_code_8bit);
	
	// ③8位用户码的反码:8位数据
	NEC_IE_One_Data(~user_code_8bit);
	
	// ④8位数据码 :8位数据
	NEC_IE_One_Data(data_code_8bit);
	
	// ⑤8位数据码的反码:8位数据
	NEC_IE_One_Data(~data_code_8bit);
	//------------------------------------------------------------
	// ⑥结束码‘0’
	//--------------
	NEC_IE_Send_zero();
	//--------------
}

end code

Regarding the end code, after the 32-bit data is sent, no matter whether the logic of the last bit is 0 or 1, the end is always PBout(7)=0; // IE pulls down and does not emit infrared light; theoretically, this It is feasible not to add an additional end code; but the author tried it, and if the end code of sending logic "0" is not added at the end, the logic analyzer cannot parse the data. In order to parse the data normally, it is necessary to send 32 Add a sentence of NEC_IE_Send_zero() after the bit data.
It should be noted that most of the actual remote controllers do not have this end signal.
insert image description here
insert image description here
insert image description here

As for the timing of the continuous code, as shown in the figure below, if you are interested, you can try it yourself, and you can feed it after the adjustment.
insert image description here
Now that the basic usage of infrared transmission is done, the biggest idea is to control equipment such as air conditioners, but it should be noted that the protocols of air conditioners of different manufacturers are not the same, and further modification is required on the basis of the above code.
For the specific introduction, please refer to these big guys——
STM32 Getting Started Development: Making Infrared Remote Control (Smart Home-Universal Remote Control)
Gree Air Conditioner Infrared Code Analysis
STM32 Analysis of Midea Air Conditioner Infrared Remote Control
Gree Air Conditioner Infrared Code
insert image description here

Phenomenon

Here, the author has not changed the coding of the air conditioner, but only implemented a simple function. The actual waveform captured and the analyzed data are as follows:
insert image description here

Summarize

The introduction of using GPIO analog timing to drive the infrared emission tube is first recorded here. As for the control of the air conditioner, this is the first pigeon, or if you have made it, you can kick me. If there are deficiencies in the article, criticism and correction are welcome.

Guess you like

Origin blog.csdn.net/qq_41954556/article/details/131414915