OpenHarmony——Linux之IR驱动

Linux之IR驱动

背景

在光谱中波长自760nm至400um的电磁波称为红外线,它是一种不可见光。红外遥控成本很低,以前广泛应用在电视,空调等电器的控制上面,现在随着蓝牙遥控器慢慢普及,红外遥控越来越少,但在某些场景,还保留着红外通信

红外属于media子系统里面的rc(remote control)模块,所以相关驱动代码目录为 drivers/media/rc/

相关内核文档:

  • Documentation/devicetree/bindings/media/gpio-ir-receiver.txt
  • Documentation/devicetree/bindings/media/rc.yaml

下面就从红外的接收、发送和编解码协议简单记录下

接收

红外接收的处理有很多种方式,有些soc有专门的硬件模块,有些使用的是通用的gpio,这里以常见的gpio为例,其他的都大同小异。

用通用的GPIO来接收红外原理比较简单,代码实现主要在:

  • drivers/media/rc/gpio-ir-recv.c
  • drivers/media/rc/rc-main.c
  • drivers/media/rc/rc-ir-raw.c

主要流程

probe函数:--> devm_rc_register_device 注册rc设备--> devm_request_irq 申请gpio中断(上升沿和下降沿)中断处理函数 gpio_ir_recv_irq:--> gpiod_get_value 获取gpio状态--> ir_raw_event_store_edge 保存边沿事件数据

重点的是这里的 devm_rc_register_device() 和 ir_raw_event_store_edge() 函数,下面分开具体来看

devm_rc_register_device()函数

devm_rc_register_device-> rc_register_device-> ir_raw_event_prepare-> timer_setup ir_raw_edge_handle: 设置一个定时器-> INIT_KFIFO: 初始化一个fifo,用来保存ir数据-> rc_prepare_rx_device: rc_map,keymap相关处理-> lirc_register: 注册lirc,后面转发keycodes数据给用户空间-> rc_setup_rx_device: 注册input设备-> ir_raw_event_register-> kthread_run ir_raw_event_thread: 运行一个内核线程,-> kfifo_out: 从上面fifo里拿数据-> decode: 根据协议解码数据-> lirc_raw_event: 通过 lirc 转发到用户空间

注:

  • LIRC(Linux Infrared Remote Control), 主要提供与核外的交互接口,核外有一个对应的开源软件包,这里对 lirc 就不展开了
  • 关于keymap协议相关处理
  • 关于decode解码在后面的部分专门来说明

ir_raw_event_store_edge()函数

ir_raw_event_store_edge: 保存这次的电平pulse及上次边沿到这次边沿的时长duration-> ir_raw_event_store_with_timeout: -> ktime_get: 保存这次的时间,为last_event-> ir_raw_event_store -> kfifo_put: 保存包含pulse和duration数据(struct ir_raw_event结构)到上面的fifo中-> timer 设置timeout 默认15ms

定时器回调函数ir_raw_edge_handle()里面的处理:

ir_raw_edge_handle-> 判断时间间隔,ir_raw_event_store 保存超时事件-> ir_raw_event_handle -> wake_up_process(dev->raw->thread) 唤醒处理线程

判断时间间隔说明:

如果从上次边沿触发到这次定时器触发的间隔时间interval大于 dev->timeout[这里gpio的方式默认为 IR_DEFAULT_TIMEOUT(125ms)] 就保存一个超时事件 timeout event,否则修改定时器的超时时间为 dev->timeout - ktime_to_us(interval)

发送

发送是接收的逆过程,红外发送主要有通用gpio、pwm等实现方式,主要代码在:

  • drivers/media/rc/gpio-ir-tx.c
  • drivers/media/rc/pwm-ir-tx.c
  • drivers/media/rc/rc-ir-raw.c
  • drivers/media/rc/lirc_dev.c

这里主要记录下常用的pwm方式,原理比较简单:

probe 函数: devm_rc_register_device: 注册rc 设备,重要的代码如下:

rcdev->priv = pwm_ir;
rcdev->driver_name = DRIVER_NAME;
rcdev->device_name = DEVICE_NAME;
rcdev->tx_ir = pwm_ir_tx;
rcdev->s_tx_duty_cycle = pwm_ir_set_duty_cycle;
rcdev->s_tx_carrier = pwm_ir_set_carrier;rc = devm_rc_register_device(&pdev->dev, rcdev);
if (rc < 0)dev_err(&pdev->dev, "failed to register rc device\n");

最主要是下面三个函数:

pwm_ir_tx() 发送最重要的函数,负责控制pwm来发送红外,用户空间通过lirc最后会调用到这里

  • pwm_ir_set_duty_cycle(): 设置pwm的占空比
  • pwm_ir_set_carrier(): 设置pwm载波的频率,默认的是38000,即38K
  • pwm_ir_tx()函数说明

代码如下,

static int pwm_ir_tx(struct rc_dev *dev, unsigned int *txbuf,unsigned int count)
{struct pwm_ir *pwm_ir = dev->priv;struct pwm_device *pwm = pwm_ir->pwm;int i, duty, period;ktime_t edge;long delta;period = DIV_ROUND_CLOSEST(NSEC_PER_SEC, pwm_ir->carrier);duty = DIV_ROUND_CLOSEST(pwm_ir->duty_cycle * period, 100);pwm_config(pwm, duty, period);edge = ktime_get();for (i = 0; i < count; i++) {if (i % 2) // spacepwm_disable(pwm);elsepwm_enable(pwm);edge = ktime_add_us(edge, txbuf[i]);delta = ktime_us_delta(edge, ktime_get());if (delta > 0)usleep_range(delta, delta + 10);}pwm_disable(pwm);return count;
}

为啥发送这里没有协议编码相关的呢?

上面已经说了,tx_ir函数即这里的pwm_ir_tx()最后会被lirc调用到来发送,所以相关协议编码主要在lirc代码里,即lirc_transmit()里的ir_raw_encode_scancode()函数,调用流程如下:

用户空间调用lirc的write函数-> lirc_transmit()-> ir_raw_encode_scancode()-> encode(): 协议编码-> tx_ir(): 发送函数-> pwm_ir_tx(): 这里pwm就对应此函数

编解码协议

这里主要记录下最常见最常用的协议之一—NEC协议

NEC协议介绍

NEC协议是众多红外线协议中的一种,以前广泛用在电视机,投影仪设备里,之前的万能电视遥控器就是走的NEC协议

​NEC协议的特征: ​

1.8位地址码和8位命令码长度;

2.单次传输主要分为5部分(不算重复码): 引导码+地址码+地址反码+命令码+命令反码,地址和命令两次传输,提高准确性;

3.停止码主要起隔离作用,一般不进行判断

4.载波频率为38KHz

5.脉冲时间间隔调制

6.位时间为1.125ms和2.25ms,具体见下面说明

NEC码位的定义:一个脉冲对应562.5us的连续载波,一个逻辑1传输需要2.25ms(562.5us脉冲+1687.5us低电平),一个逻辑0的传输需要1.125ms(562.5us脉冲+562.5us低电平)。

​而遥控接收头在收到脉冲时为低电平​,在没有收到脉冲时为高电平,因此, 我们在接收头端收到的信号为:逻辑1应该是562.5us低+1687.5us高,逻辑0应该是562.5us低+562.5us高。

对于接收方:

  • 引导码: 9ms的低电平 + 4.5ms的高电平
  • 逻辑0: 562.5us低电平 + 562.5us高电平
  • 逻辑1: 562.5us低电平 + 1687.5us高电平
  • 重复码:9ms的低电平 + 2.25ms的高电平

对于发送方:

如果我们规定1拍是562.5us载波脉冲, 那么:

  • 引导码: 16拍的红外发射 + 8拍的空闲
  • 逻辑0: 1拍的发射 + 1拍的空闲
  • 逻辑1: 1拍的发射 + 3拍的空闲
  • 重复码:16拍的红外发射 + 4拍的空闲
  • 结束码:1拍的发射

NEC相关代码

内核中nec协议相关的源码实现在: drivers/media/rc/ir-nec-decoder.c

主要提供上面接收和发送时编解码相关的接口和参数,如decode, encode函数,carrier参数等

static struct ir_raw_handler nec_handler = {.protocols  = RC_PROTO_BIT_NEC | RC_PROTO_BIT_NECX |RC_PROTO_BIT_NEC32,.decode     = ir_nec_decode,.encode     = ir_nec_encode,.carrier    = 38000,.min_timeout    = NEC_TRAILER_SPACE,
};

想学习更多华为鸿蒙HarmonyOS开发知识,在这里我为大家准备了华为鸿蒙HarmonyOS开发者资料大全,大家可以自行点击链接领取:《做鸿蒙应用开发到底学习些啥?》

其次就是考虑到市场上还没有系统性的学习资料,同时我也整理了一份《鸿蒙 (Harmony OS)开发学习手册》特意整理成PDF文档方式,分享给大家参考学习,大家可以根据自身情况进行获取:《鸿蒙开发学习指南》

《鸿蒙 (Harmony OS)开发学习手册》

一、入门必看

1. 应用开发导读(ArkTS)

2. 应用开发导读(Java)

3.......

二、HarmonyOS 概念

1. 系统定义

2. 技术架构

3. 技术特性

4. 系统安全

5......

三、如何快速入门?《鸿蒙基础入门开发宝典!》

1. 基本概念

2. 构建第一个ArkTS应用

3. 构建第一个JS应用

4. ……

四、开发基础知识

1. 应用基础知识

2. 配置文件

3. 应用数据管理

4. 应用安全管理

5. 应用隐私保护

6. 三方应用调用管控机制

7. 资源分类与访问

8. 学习ArkTS语言

9. ……

五、基于ArkTS 开发

1. Ability开发

2. UI开发

3. 公共事件与通知

4. 窗口管理

5. 媒体

6. 安全

7. 网络与链接

8. 电话服务

9. 数据管理

10. 后台任务(Background Task)管理

11. 设备管理

12. 设备使用信息统计

13. DFX

14. 国际化开发

15. 折叠屏系列

16. ……

更多了解更多鸿蒙开发的相关知识可以参考:《做鸿蒙应用开发到底学习些啥?》

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

图像处理:孤立点的检测

图像处理-孤立点的检测 孤立点的检测在图像处理中通常涉及到检测图像中的突变或者边缘&#xff0c;而使用二阶导数是一种常见的方法。一阶导数可以帮助找到图像中的边缘&#xff0c;而二阶导数则有助于检测边缘上的峰值&#xff0c;这些峰值可能对应于孤立点或者特殊的图像结构…

AI大模型预先学习笔记二:prompt提问大模型、langchain使用大模型框架、fine tune微调大模型

文章目录 一、Prompt Engineering&#xff08;怎么去提问大模型&#xff09;1&#xff09;环境准备2&#xff09;交互代码的参数备注3&#xff09;交互代码 二、LangChain&#xff08;一个框架去使用大模型&#xff09;1&#xff09;LangChain核心介绍&#xff1a;I/O模块、数据…

TypeError: (0 , _ahooks.createUpdateEffect) is not a function

版本 "next": "14.0.4", "antd-mobile": "^5.34.0", next中使用antd-mobile可困难了.主要是因为antd-mobile不支持ssr 1.下载antd-mobile包,在next.config.js中加入 transpilePackages: [antd-mobile,], 2.在页面中引入antd-mobi…

蓝桥杯备赛day02 -- 算法训练题 拿金币Java

目录 题目&#xff1a; 问题描述 输入格式 输出格式 解题过程 第一步 定义dp数组 第二步 确定 dp 数组递推公式 第三步 dp数组的初始化 第四步 dp数组的遍历顺序 第五步 举例说明 报错&#xff1a;内存超限 用dp数组去存储位置上的金币 dp数组从二维降为一维 收获&a…

【MCAL】MCU模块详解

目录 前言 正文 1. MCU模块介绍 2. MCU依赖的模块 3. MCU模块提供服务 3.1 时钟的初始化 3.2 MCU模式的配置 3.3 MCU软件复位功能 3.4 RAM的初始化 4.MCU重要数据类型 4.1 Mcu_ResetType 4.2 Mcu_ModeType 5. MCU重要API 5.1 Mcu_Init 5.2 Mcu_InitClock 5.3 M…

信息系统安全——Linux 访问控制机制分析

实验 4 Linux 访问控制机制分析 4.1 实验名称 《Linux 访问控制机制分析》 4.2 实验目的 1 、熟悉 Linux基本访问控制机制使用和原理 2 、熟悉 Linux S 位的作用和使用 3 、熟悉强制访问控制 Selinux 原理及其使用 4.3 实验步骤及内容 1 、Linux 基本访问控制机制 &#xff08…

vue el-table 多选框回填

主要代码: //选中列&#xff0c;所有列&#xff0c;表名toggleSelection(selectRows, totalRows, tablename) {this.$refs.table.clearSelection();if (selectRows.length > 0) {this.$nextTick(() > {selectRows.forEach(item > {totalRows.forEach(item1 > {if (…

C语言天花板——指针(经典题目)

指针我们已经学习的差不多了&#xff0c;今天我来给大家分享几个经典的题目&#xff0c;来让我们相互学习&#x1f3ce;️&#x1f3ce;️&#x1f3ce;️ int main() {int a[4] { 1, 2, 3, 4 };int* ptr1 (int*)(&a 1);int* ptr2 (int*)((int)a 1);printf("%x,%…

连锁品牌如何引流获客?小魔推短视频矩阵助你流量爆棚

近几年因为大环境的影响&#xff0c;大多数实体行业的生意都不太好做&#xff0c;为了帮助更多实体行业提升品牌知名度&#xff0c;带来更多的流量与转化&#xff0c;餐赞小魔推也在不断的更新迭代&#xff0c;同时考虑到了单门店与连锁品牌使用的便捷性。 目前针对连锁品牌方&…

功能权限篇

文章目录 1. 如何设计一套权限系统1.1 目标1.2 权限模型1.2.1 模型一RBAC1.2.2 模型二ABAC 2.如何实现菜单的创建&#xff1f;2.1 表结构2.2 前端实现2.3 后端实现 3. 如何实现角色的创建&#xff1f;4.如何给用户分配权限 —— 将菜单赋予角色&#xff1f;5.如何给用户分配权限…

【目标跟踪】跨相机如何匹配像素

文章目录 前言一、计算思路二、代码三、结果 前言 本本篇博客介绍一种非常简单粗暴的方法&#xff0c;做到跨相机像素匹配。已知各相机内外参&#xff0c;计算共视区域像素投影&#xff08;不需要计算图像特征&#xff09;。废话不多说&#xff0c;直接来&#xff0c;见下图。…

QT -狗狗管理工具

QT -狗狗管理工具 一、演示效果二、UML三、关键代码四、程序链接 一、演示效果 二、UML 三、关键代码 #include <QFrame> #include <QHBoxLayout> #include <QVBoxLayout> #include <QLabel> #include <QSizePolicy> #include <QDialog> …

算法第十八天-打家劫舍Ⅱ

打家劫舍Ⅱ 题目要求 解题思路 [打家劫舍Ⅱ]是说两个相邻的房间不能同时偷&#xff0c;并且首尾两个房间是相邻的&#xff08;不能同时偷首尾房间&#xff09;明显是基于[打家劫舍Ⅰ]做的升级。[打家劫舍Ⅰ]也是说两个相邻的房间不能同时偷&#xff0c;但是首尾房间不是相邻的…

Nas群晖中安装Cpolar实现内网穿透

1、到Cpolar官网中安装对应的套间 cpolar官网&#xff1a; cpolar官网-安全的内网穿透工具 | 无需公网ip | 远程访问 | 搭建网站 2、到群晖nas中安装套间 选择好套间无脑下一步 已完成

时间序列数据的季节性检测

时间序列分析是统计学和数据科学的一个基本研究领域&#xff0c;它为理解和预测序列数据中的模式提供了一个强大的框架。特别是时间序列数据&#xff0c;它捕获连续时间间隔内的信息&#xff0c;使分析师能够揭示趋势&#xff0c;季节性模式和其他时间依赖性。在时间序列分析的…

GPT应用开发:运行你的第一个聊天程序

本系列文章介绍基于OpenAI GPT API开发应用的方法&#xff0c;适合从零开始&#xff0c;也适合查缺补漏。 本文首先介绍基于聊天API编程的方法。 环境搭建 很多机器学习框架和类库都是使用Python编写的&#xff0c;OpenAI提供的很多例子也是Python编写的&#xff0c;所以为了…

PTA(浙大版《C语言程序设计(第3版)》题目集

PTA(浙大版《C语言程序设计&#xff08;第3版&#xff09;》题目集 学习C语言程序设计的PTA题目 目录 PTA(浙大版《C语言程序设计&#xff08;第3版&#xff09;》题目集PTA(浙大版《C语言程序设计&#xff08;第3版&#xff09;》题目集) 习题2-1 求整数均值 (10 分)输入格式:…

JS常用插件 Swiper插件 实现轮播图

Swiper介绍 Swiper 是一款免费以及轻量级的移动设备触控滑块的js框架 中文官网地址: https://www.swiper.com.cn/ 点击查看Swiper演示&#xff0c;里面的功能和样式十分丰富&#xff0c;根据自己的需求选择 中文教程中详细介绍了如何使用Swiper API文档中介绍了各个模块以及参…

如何画出优秀的系统架构图-架构师系列-学习总结

--- 后之视今&#xff0c;亦犹今之视昔&#xff01; 目录 早期系统架构图 早期系统架构视图 41视图解读 41架构视图缺点 现代系统架构图的指导实践 业务架构 例子 使用场景 画图技巧 客户端架构、前端架构 例子 使用场景 画图技巧 系统架构 例子 定义 使用场…

C++面试宝典第19题:最长公共前缀

题目 编写一个函数来查找字符串数组中的最长公共前缀,如果不存在公共前缀,返回空字符串""。说明:所有输入只包含小写字母a-z。 示例1: 输入: ["flower", "flow", "flight"]输出: "fl" 示例2: 输入: ["dog",…