[ESP32] 用RMT模块做红外遥控发射

本文采用ESP32内部只带的RMT模块作为发送红外遥控的发射器。

红外协议来自 美的R05D功能说明书: https://wenku.baidu.com/view/c46594141ed9ad51f01df2c3.html

  1. 通常编码格式为: L,A,A’,B,B’,C,C’, S, L,A,A’,B,B’,C,C’ T
  2. 第一帧和第二帧相同
  3. 采用MSB在先,LSB在后;也就是高位先发
  4. L为引导码;S为分隔码;A为识别码(A=10110010=0xB2,预留方案时A=10110111=0xB7),A’为A的反码;B’为B的反码;C’为C的反码。T为终结码
  5. 数据B,C的部分含义如下图

开机码: b2 4d bf 40 d0 2f - b2 4d bf 40 d0 2f        【自动风,26度,制冷】

关机码: b2 4d 7b 84 e0 1f -b2 4d 7b 84 e0 1f       【B2位是开关位】

工程模式:b9 46 f7 08 00 ff-b9 46 f7 08 00 ff

灯光码:b5 4a f5 0a a5 5a -b5 4a f5 0a a5 5a

 6.引导码 Lead : 4400us 低 + 4400us高

7.分割码 Split : 540us 低 + 5220us 高

8. 发送Bit1 :  540us 低 + 1620us 高

9. 发送Bit0: 540us 低 + 540us 高

10.终结符 Terminator: 540us 低 + 一直高

11.两个控制帧信号间最小间隔>5.22ms


#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/rmt.h"
#include "driver/gpio.h"

// 编码格式:L AA` BB` CC`  S L AA` BB` CC`  T [共48*2+3=99Bits]
// value 1: High, 0:Low
#define FRAMES_LEN_MAX 99
static rmt_item32_t g_encode_frame[FRAMES_LEN_MAX] =
    {
        {{{4400, 0, 4400, 1}}}, // Leading
};

#define KEY_1 45
#define KEY_2 46
#define GPIO_INPUT_PIN_SEL ((1ULL << KEY_1) | (1ULL << KEY_2))

#define LED_R 47
#define LED_G 48
#define LED_B 41
#define GPIO_OUTPUT_PIN_SEL ((1ULL << LED_R) | (1ULL << LED_G) | (1ULL << LED_B))

void sleep_ms(int ms)
{
    vTaskDelay(pdMS_TO_TICKS(ms));
}

static void led_gpio_init()
{

    gpio_config_t io_conf; // 定义一个gpio_config类型的结构体,下面的都算对其进行的配置

    io_conf.intr_type = GPIO_INTR_DISABLE;      // 禁止中断
    io_conf.mode = GPIO_MODE_OUTPUT;            // 选择输出模式
    io_conf.pin_bit_mask = GPIO_OUTPUT_PIN_SEL; // 配置GPIO_OUT寄存器
    io_conf.pull_up_en = 1;
    io_conf.pull_down_en = 0;

    gpio_config(&io_conf);

    io_conf.intr_type = GPIO_INTR_DISABLE;
    io_conf.mode = GPIO_MODE_INPUT;            // 选择输入模式
    io_conf.pin_bit_mask = GPIO_INPUT_PIN_SEL; // 配置GPIO_INPUT寄存器
    io_conf.pull_up_en = 1;
    io_conf.pull_down_en = 1;
    gpio_config(&io_conf);
}

void led_color_set(uint8_t r, uint8_t g, uint8_t b)
{
    gpio_set_level(LED_R, r);
    gpio_set_level(LED_G, g);
    gpio_set_level(LED_B, b);
}

void set_item_date(int item_index, uint16_t duration0, uint8_t level0, uint16_t duration1, uint8_t level1)
{
    g_encode_frame[item_index].duration0 = duration0;
    g_encode_frame[item_index].level0 = level0;
    g_encode_frame[item_index].duration1 = duration1;
    g_encode_frame[item_index].level1 = level1;
}

void make_one_byte_data(int item_index, uint8_t byte_value)
{
    uint8_t bit_value = 0;

    for (int i = 7; i >= 0; i--)
    {
        bit_value = (byte_value >> i) & 0x01;

        if (bit_value == 1)
            set_item_date(item_index++, 540, 0, 1620, 1); // BIT1
        else
            set_item_date(item_index++, 540, 0, 540, 1); // BIT0
    }
}

// 设置整帧数据,共99bit数据
void make_frame_date(uint8_t byteA, uint8_t byteB, uint8_t byteC)
{
    int item_index = 0;

    set_item_date(item_index++, 4400, 0, 4400, 1); // leading code

    make_one_byte_data(item_index, byteA);
    item_index += 8;
    make_one_byte_data(item_index, ~byteA);
    item_index += 8;

    make_one_byte_data(item_index, byteB);
    item_index += 8;
    make_one_byte_data(item_index, ~byteB);
    item_index += 8;

    make_one_byte_data(item_index, byteC);
    item_index += 8;
    make_one_byte_data(item_index, ~byteC);
    item_index += 8;

    set_item_date(item_index++, 540, 0, 5220, 1); // splice code

    make_one_byte_data(item_index, byteA);
    item_index += 8;
    make_one_byte_data(item_index, ~byteA);
    item_index += 8;

    make_one_byte_data(item_index, byteB);
    item_index += 8;
    make_one_byte_data(item_index, ~byteB);
    item_index += 8;

    make_one_byte_data(item_index, byteC);
    item_index += 8;
    make_one_byte_data(item_index, ~byteC);
    item_index += 8;

    set_item_date(item_index++, 540, 0, 0, 1); // ending code
}

static void rmt_tx_init(void)
{
    // 01 rmt driver共有部分
    rmt_config_t rmt;
    rmt.channel = RMT_CHANNEL_0; // RMT有0-7共8通道
    rmt.clk_div = 80;            // 默认的时钟是80MHZ,分频器是8位的,如果80分频,每个Tick是1us
    rmt.mem_block_num = 1;       // 默认每个通道使用1个block。一共block是64x32bit 这么大。 也就是能储存128个数据
    rmt.rmt_mode = RMT_MODE_TX;  // 配置发送模式
    rmt.gpio_num = GPIO_NUM_1;   // 自定义红外发射引脚

    // 02 配置tx独有的部分
    rmt.tx_config.carrier_en = true;                     // 打开载波
    rmt.tx_config.carrier_freq_hz = 38000;               // 38khz载波
    rmt.tx_config.carrier_duty_percent = 50;             // 占空比50%
    rmt.tx_config.carrier_level = RMT_CARRIER_LEVEL_LOW; // 载波默认为高电平H
    rmt.tx_config.idle_output_en = true;                 // 空闲输出打开
    rmt.tx_config.idle_level = RMT_IDLE_LEVEL_HIGH;      // 空闲时候为低电平L
    rmt.tx_config.loop_en = false;                       // 关闭持续发送

    // 03 进行配置, 加载配置
    rmt_config(&rmt);
    rmt_driver_install(RMT_CHANNEL_0, 0, 0); // 发送不需要缓冲区,中断级别默认
}

void app_main()
{
    printf("configTICK_RATE_HZ=%d.build at:[%s %s] \n", configTICK_RATE_HZ, __DATE__, __TIME__);

    rmt_tx_init();
    led_gpio_init();

    
    int cnt = 0;
    while (1)
    {
        //循环发送测试
        printf("sendA index:%d \n", ++cnt);
        make_frame_date(0xb2, 0xbf, 0xd0); // power_on [自动风,26度,制冷]
        led_color_set(1, 0, 0);
        rmt_write_items(RMT_CHANNEL_0, g_encode_frame, FRAMES_LEN_MAX, true);
        sleep_ms(1500);

        printf("sendB index:%d \n", ++cnt);
        make_frame_date(0xb2, 0xbf, 0xbc); // power_on [自动风,30度,制热]
        led_color_set(0, 1, 0);
        rmt_write_items(RMT_CHANNEL_0, g_encode_frame, FRAMES_LEN_MAX, true);
        sleep_ms(1500);

        printf("sendC index:%d \n", ++cnt);
        make_frame_date(0xb9, 0xf7, 0x00); // 工程模式
        led_color_set(0, 0, 1);
        rmt_write_items(RMT_CHANNEL_0, g_encode_frame, FRAMES_LEN_MAX, true);
        sleep_ms(1500);

        printf("sendD index:%d \n", ++cnt);
        make_frame_date(0xb2, 0x7b, 0xe0); // power_off
        led_color_set(1, 1, 1);
        rmt_write_items(RMT_CHANNEL_0, g_encode_frame, FRAMES_LEN_MAX, true);
         sleep_ms(1500);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/525573.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

武汉星起航深入分析市场动态,赢得跨境市场的高度认可

随着全球跨境电商的蓬勃发展&#xff0c;武汉星起航以其独到的市场洞察和深度合作模式在行业中崭露头角。公司凭借对市场趋势、消费者需求和竞争格局的敏锐洞察而声名鹊起&#xff0c;不仅成功跟随市场脉搏&#xff0c;更在竞争激烈的跨境电商领域中脱颖而出。 武汉星起航在制…

摄像头校准漫反射板提高识别物体

摄像头校准漫反射板是一种用于摄像头校准的重要工具。在摄像头成像过程中&#xff0c;由于各种因素的影响&#xff0c;如光线、角度、镜头畸变等&#xff0c;会导致摄像头成像出现偏差。为了消除这些偏差&#xff0c;提高摄像头的成像质量&#xff0c;需要使用摄像头校准漫反射…

短剧App开发:打造沉浸式观剧体验,引领短剧新风尚

在移动互联网时代&#xff0c;短视频、短剧等短内容形式正以其独特的魅力迅速崛起。为了满足广大用户对短剧内容的需求&#xff0c;我们致力于开发一款全新的短剧App&#xff0c;为用户带来沉浸式的观剧体验&#xff0c;引领短剧新风尚。 短剧App的开发&#xff0c;旨在为用户…

在python读取相邻两行的数据进行运算

​在数据处理和分析的过程中&#xff0c;我们经常需要从关系型数据库中提取数据。Python作为一种强大的编程语言&#xff0c;提供了多种库和工具来与SQL数据库进行交互。当我们需要获取SQL表中筛选后的行数时&#xff0c;可以使用Python结合SQL查询来实现。本文将详细介绍如何使…

arm交叉编译器工具

下载地址&#xff1a; Builds & Downloads | Linaro 进入首页后&#xff0c;点击" GNU Toolchain Integration Builds" 有以下版本&#xff1a; 根据自己的选择下载对应的版本&#xff0c;本例选择14.0-2023.06-1 根据板端对应的版本选择相应的下载 比如下载3…

OpenAI Sora:浅析文生视频模型Sora以及技术原理简介

一、Sora是什么&#xff1f; Sora官方链接&#xff1a;https://openai.com/sora 视频模型领头羊Runway Gen 2、Pika等AI视频工具&#xff0c;都还在突破几秒内的连贯性&#xff0c;而OpenAI&#xff0c;已经达到了史诗级的纪录。 OpenAI&#xff0c;永远快别人一步&#xff0…

MG-APP使用不同分析中心计算前向滤波PPP结果

下面分别使用了WUM和COD分析中心产品&#xff0c;基于MG-APP使用不同分析中心计算前向滤波PPP结果&#xff1a; 在使用MG-APP情况下&#xff0c;COD计算PPP比WUM计算效果好一点。 数据下载&#xff1a; 1、卫星轨道和钟差下载链接&#xff1a; 需要浏览器&#xff1a; CODE:h…

DESON德尚登录HOTELEX上海展,新品派对诠释品牌理念

3月27日&#xff0c;DESON德尚&#xff08;下简称DESON&#xff09;亮相第三十二届上海国际酒店及餐饮业博览会&#xff08;下简称HOTELEX上海展&#xff09;。在为期四天的展会中&#xff0c;DESON携其全新产品系列&#xff0c;与来自世界各地的3000余家展商&#xff0c;超20万…

LeetCode 24.两两交换链表中的节点

给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题&#xff08;即&#xff0c;只能进行节点交换&#xff09;。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4] 输出&#xff1a;[2,1,4…

【GPT-4 Turbo】、功能融合:OpenAI 首个开发者大会回顾

GPT-4 Turbo、功能融合&#xff1a;OpenAI 首个开发者大会回顾 就在昨天 2023 年 11 月 6 日&#xff0c;OpenAI 举行了首个开发者大会 DevDay&#xff0c;即使作为目前大语言模型行业的领军者&#xff0c;OpenAI 卷起来可一点都不比同行差。 OpenAI 在大会上不仅公布了新的 …

机器学习 —— 数据分析与图表绘制

本文使用工具 Anaconda下载安装与使用 Jupyter Notebook的使用 本文使用数据集 机器学习实验所需内容.zip 以朝阳医院2018年销售数据为例&#xff0c;目的是了解朝阳医院在2018年里的销售情况&#xff0c;这就需要知道几个业务指标&#xff0c;本次的分析…

Redis 和 Mysql 数据库数据如何保持一致性

1.1前言 我们在实际项目中经常会使用到Redis缓存用来缓解数据库压力&#xff0c;但是当更新数据库时&#xff0c;如何保证缓存及数据库一致性&#xff0c;一般我们采用延时双删策略。 目前系统中常用的做法是一个查询接口&#xff0c;先查询Redis&#xff0c;如果不存在则查询…

在展会上如何介绍产品和公司,柯桥俄语培训

1.Приглашаем Вас… 邀请您…… 2. Позвольте пригласить Вас… 请允许邀请您…… 3.Имеем честь пригласить Вас … 诚挚邀请您…… 4. Посылаем Вам приглашение на… 给您&#xff0…

性能优化 - 你能说一说,为什么做了骨架屏,FCP的指标还是没有提升吗

难度级别:中高级及以上 提问概率:80% FCP的全程是First Contentful Paint,是衡量网页性能的一个重要指标,很多人把FCP理解为元素内容首次渲染到浏览器上的时间。但由于现在比较流行的Vue或是React项目中,HTML文档最初只有一个id为app的DIV…

Qt使用iostream的cout

在QT想使用iostream的cout。 参考以下博客&#xff1a; &#xff08;转载&#xff09;Qt中使用cout输出的方法 pro里加上; CONFIG console勾选 Run in Terminal clean工程&#xff0c;重新构建 上面是cout的&#xff0c;下面是我的另一个函数的qDebug输出的。

上位机图像处理和嵌入式模块部署(qmacvisual之tcp客户端)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 视觉算法出了结果之后&#xff0c;一般都要通知到其他设备进行某些动作的。以前通信的方式&#xff0c;一般都是有线的&#xff0c;什么232、485、…

【Linux】HTTPS协议

HTTPS协议 1.什么是"加密"2.为什么要加密3.常见的加密方式4.数据摘要&&数据指纹5.数字签名6.理解链 - 承上启下7.HTTPS 的工作过程探究方案一&#xff1a;只使用对称加密方案二&#xff1a;只使用非对称加密方案三&#xff1a;双方都使用非对称加密方案四&am…

C顺序表:通讯录

目录 前言 通讯录数据结构 通讯录初始化 查找名字 增加联系人 删除联系人 展示所有联系人 查找联系人 修改信息 销毁通讯录 完整通讯录代码 前言 数据结构中的顺序表如果已经学会了&#xff0c;那么我们就可以基于顺序表来完成一个通讯录了 通讯录其实我们使用前…

项目运维方案资料-(word原件)31页

1. 文档介绍 2. 人员与责任 3. 运维过程内容 4. 运维资源 5. 运维服务规划保障 6. 事件处置 7. 质量改进 8. 运维边界及内容 软件开发管理全套资料获取方式①&#xff1a;点我获取 获取方式②&#xff1a;本文末个人名片直接获取。

SpringBoot快速入门笔记(5)

文章目录 一、elemetnUI1、main.js2、App.vue3、fontAwesome 一、elemetnUI 开源前端框架&#xff0c;安装 npm i element-ui -S 建议查看官方文档 Element组件&#xff0c;这里是Vue2搭配elementUI&#xff0c;如果是vue3就搭配elementPlus&#xff0c;这里初学就以Vue2为例子…