第二十二章 INFRARED_TRANSMISSION实验
前上一章中,我们通过红外接收头来接收遥控器发过来的红外信号,在本章,我们将向大家介绍如何通过红外发射头来发送红外信号,同时来模拟我们的红外遥控器。正点原子ESP32-S3开发板板载了一个红外发射头,我们可以通过软件编程来直接实现红外信号的发送,同时我们利用上一章红外接收实验来实现开发板的红外信号自发自收功能。
本章分为如下几个小节:
22.1 红外发射介绍
22.2 硬件设计
22.3 软件设计
22.4 下载验证
22.1 红外发射介绍
在上一章中,我们已经讲解了红外遥控器的原理,这里请大家参考上一章的内容进行学习。我们将使用正点原子ESP32-S3开发板上的板载红外发射头来模拟红外遥控器的功能,从而实现开发板上的红外信号自发自收功能。
若要使用IRremoteESP8266库的函数,需要先定义一个IRsend对象,具体操作如下:
IRsend irsend(pin);
其中pin是连接到红外发送器输出引脚的数字引脚号。
接下来,介绍本例程用到IRremoteESP8266库的函数。
第一个函数:begin函数,该函数功能是初始化红外发射引脚。
void IRsend::begin();
无参数。
无返回值。
第二个函数:sendNEC函数,该函数的功能是以NEC编码格式发送指定值。
void IRsend::sendNEC(uint64_t data, uint16_t bnits, uint16_t repeat);
只需要关注参数data即可,调用该函数只带data参数即可;
无返回值。
22.2 硬件设计
1. 例程功能
开机后在LCD上显示一些信息,然后等待红外接收触发解码,在死循环里面,我们利用红外发射头发送键值(每200ms加1),同时在LCD上显示当前发送键值与接收到的键值,来观察自发自收情况。其中LED用来指示程序运行状态。
2. 硬件资源
1)LED灯
LED-IO1
2)USART0
U0TXD-IO43 U0RXD-IO44
3)XL9555
IIC_SDA-IO41 IIC_SCL-IO42
4)SPILCD
CS-IO21 SCK-IO12 SDA-IO11
DC-IO40(在P5端口,使用跳线帽将IO_SET和LCD_DC相连)
PWR- IO1_3(XL9555) RST- IO1_2(XL9555)
5)红外接收头
REMOTE_IN-IO2
6)红外发射头
RMT-AIN(IO8)(在P3端口,使用跳线帽将RMT和AIN相连)
3. 原理图
红外发送相关原理图,如下图所示。

图22.2.1 红外发送原理图
22.3 软件设计
22.3.1 程序流程图
下面看看本实验的程序流程图:

图22.3.1 程序流程图
22.3.2 程序解析
1. EMISSION驱动代码
这里我们只讲解核心代码,详细的源码请大家参考光盘本实验对应源码。EMISSION驱动源码包括两个文件:emission.cpp和emission.h。
下面我们先解析emission.h的程序。对红外发射引脚做了相关定义。
#define RMT_TX_PIN 8
我们选择使用IO8作为红外发射引脚。
下面我们解析emission.cpp的程序,首先先来看一下初始化函数emission_init,代码如下:
/**
* @brief 红外发送初始化
* @param 无
* @retval 无
*/
void emission_init(void)
{
irsend.begin();
}
在红外发送的初始化函数中,直接调用begin函数接口初始化红外发射引脚。
接下来,看一下红外发送数据函数,代码如下:
/**
* @brief 发送红外数据
* @param data:控制码
* @retval 无
*/
void emission_send(uint8_t data)
{
uint32_t send_data = 0;
uint8_t data_oppo = 0;
data_oppo = ~data;
send_data = 0x00FF0000UL | data << 8 | data_oppo;
irsend.sendNEC(send_data);
}
该函数主要调用sendNEC函数把数据发送出去。
2. 16_infrared_transmission.ino代码
在16_infrared_transmission.ino里面编写如下代码:
#include "led.h"
#include "uart.h"
#include "xl9555.h"
#include "spilcd.h"
#include "remote.h"
#include "emission.h"
uint8_t key_value = 0;
uint8_t t = 0;
/**
* @brief 当程序开始执行时,将调用setup()函数,通常用来初始化变量、函数等
* @param 无
* @retval 无
*/
void setup()
{
led_init(); /* LED初始化 */
uart_init(0, 115200); /* 串口0初始化 */
xl9555_init(); /* IO扩展芯片初始化 */
lcd_init(); /* LCD初始化 */
remote_init(); /* 红外接收初始化 */
emission_init(); /* 红外发送初始化 */
lcd_show_string(30, 50, 200, 16, LCD_FONT_16, "ESP32-S3", RED);
lcd_show_string(30, 70, 200, 16, LCD_FONT_16, "EMISSION TEST", RED);
lcd_show_string(30, 90, 200, 16, LCD_FONT_16, "ATOM@ALIENTEK", RED);
lcd_show_string(30, 110, 200, 16, LCD_FONT_16, "TX KEYVAL:", RED);
lcd_show_string(30, 130, 200, 16, LCD_FONT_16, "RX KEYVAL:", RED);
}
/**
* @brief 循环函数,通常放程序的主体或者需要不断刷新的语句
* @param 无
* @retval 无
*/
void loop()
{
t++;
if (t == 0)
{
t = 1;
}
emission_send(t); /* 红外发送键值 */
lcd_show_num(110, 110, t, 3, LCD_FONT_16, BLUE); /* 显示红外发送键值 */
key_value = remote_scan(); /* 红外接收键值 */
if (key_value)
{
lcd_show_num(110, 130, key_value, 3, LCD_FONT_16, BLUE);
/* 显示红外接收键值 */
}
LED_TOGGLE();
delay(200);
}
在setup函数中,调用led_init函数完成LED初始化,uart_init函数完成串口初始化,调用xl9555_init函数完成XL9555初始化,调用lcd_init函数完成LCD屏初始化,调用remote_init函数完成红外解码初始化,调用emission_init函数完成红外发射初始化,然后LCD显示实验信息。
在loop函数中,间隔200毫秒调用emission_send函数发送红外数据,然后调用remote_scan函数获取红外数据,在LCD显示发送的数据以及接收的数据。
22.4 下载验证
下载代码后,可以看到LCD显示如下图所示。

图22.4.1 红外发射实验测试图
我们可以看到我们开发板发送的红外信号全部红外接收头接收到,说明我们已经实现了红外接收头的自发自收功能。同时LED会闪烁,指示程序正在运行。温馨提示:由于开发板的红外接收头和红外发射头没有正对,有可能会造成接收不到数据情况,这样我们需要一个提供一个反射面,最简单的做法就是将手放在传感器正前方大约10cm左右的位置。