OpenHarmony——Linux之IR驱动

news2024/9/28 3:28:25

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) // space
            pwm_disable(pwm);
        else
            pwm_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.coloradmin.cn/o/1387109.html

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

相关文章

leetcode 142 环形链表II

题目 给定一个链表的头节点 head &#xff0c;返回链表开始入环的第一个节点。 如果链表无环&#xff0c;则返回 null。 如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;则链表中存在环。 为了表示给定链表中的环&#xff0c;评测系统内部使…

阳光抑郁症测试

大部分人对抑郁症的理解&#xff0c;就是每天无精打采&#xff0c;死气沉沉&#xff0c;可实际上&#xff0c;还有一种阳光抑郁症&#xff0c;完全不是这个样子。这种抑郁症的人&#xff0c;做事情非常有活力&#xff0c;魅力十足&#xff0c;给人感觉十分有自信&#xff0c;但…

2024Flutter岗位面试题总结

StatelessWidget和StatefulWidget的区别是什么&#xff1f; StatelessWidget是一个不可变的类&#xff0c;充当UI布局中某些部分的蓝图&#xff0c;当某个组件在显示期间不需要改变&#xff0c;或者说没有状态&#xff08;State&#xff09;&#xff0c;你可以使用它。 Statef…

什么是DDOS高防ip?DDOS高防ip是怎么防护攻击的

随着互联网的快速发展&#xff0c;网络安全问题日益突出&#xff0c;DDoS攻击和CC攻击等网络威胁对企业和网站的正常运营造成了巨大的威胁。为了解决这些问题&#xff0c;高防IP作为一种网络安全服务应运而生。高防IP通过实时监测和分析流量&#xff0c;识别和拦截恶意流量&…

MySQL 协议(非常详细适合小白学习)

MySQL 查询过程 MySQL 查询过程大致如下&#xff1a; 1&#xff09;客户端与服务器端建立连接&#xff1b; 2&#xff09;客户端登陆 MySQL&#xff1b; 3&#xff09;客户端向服务器端发起一条请求&#xff1b; 4&#xff09;服务器端先检查查询缓存&#xff0c;如果命中缓…

ArkUI-X跨平台已至,何需其它!

运行环境 DevEco Studio&#xff1a;4.0Release OpenHarmony SDK API10 开发板&#xff1a;润和DAYU200 自从写了一篇ArkUI-X跨平台的文章之后&#xff0c;好多人都说对这个项目十分关注。 那么今天我们就来完整的梳理一下这个项目。 1、ArkUI-X 我们之前可能更多接触的…

运动模型非线性扩展卡尔曼跟踪融合滤波算法(Matlab仿真)

卡尔曼滤波的原理和理论在CSDN已有很多文章&#xff0c;这里不再赘述&#xff0c;仅分享个人的理解和Matlab仿真代码。 1 单目标跟踪 匀速转弯&#xff08;CTRV&#xff09;运动模型下&#xff0c;摄像头输出目标状态camera_state [x, y, theta, v]&#xff0c;雷达输出目标状…

windows的换行符与linux风格的换行符不同的问题

问题展示&#xff1a; 说明&#xff1a; 出现这个错误的原因是脚本文件包含了windows风格换行符&#xff08;‘\r\n’&#xff09;&#xff0c;而在linux环境下&#xff0c;通常使用unix风格的换行符&#xff08;‘\n’&#xff09;.这个问题通常在windows环境下编辑脚本文件然…

档案数字化加工是如何利用档案的

档案数字化加工是通过将实体档案转化为电子形式&#xff0c;利用数字化技术对档案进行处理和管理。这样做可以带来以下几个方面的利益&#xff1a; 1. 提高档案的可访问性&#xff1a;数字化档案可以轻松存储在电脑或云存储中&#xff0c;可以随时随地通过计算机或移动设备访问…

Zung氏抑郁自评量表SDS

抑郁症是常见的心理障碍&#xff0c;其症状表现为&#xff1a;心境低落、思维迟缓、意志活动减退、认知功能损害、躯体症状等。在生活中常有悲观消沉&#xff0c;灰心丧气&#xff0c;对所有事情都提不起兴趣&#xff0c;严重的还会出现肢体僵硬和耳鸣等症状。 部分人有明显的…

操作系统进程定义和PCB详解

进程的定义和PCB 什么是进程&#xff1f;进程就是一个运行起来&#xff08;也就是说加载到内存&#xff09;的一个程序。而程序的本质就是文件&#xff0c;当我们写完代码保存&#xff0c;它便形成了一个保存在磁盘上的二进制代码文件。由于冯诺伊曼体系&#xff0c;cpu只和存储…

RK3568笔记九: DRM显示摄像头

若该文为原创文章&#xff0c;转载请注明原文出处。 一、介绍 学习DRM的目的是想做类似NVR显示多路实时流&#xff0c;通过勇哥&#xff08;Marc)的指导&#xff0c;大概流程是通过Zlmedia拉流&#xff0c;RK3568的MPP解码,DRM显示&#xff0c;可以使用HDMI或DIS屏幕&#xf…

数据结构学习 jz59 滑动窗口的最大值

关键词&#xff1a;排序 大顶堆 双端队列 题目&#xff1a; 望远镜中最高的海拔 方法一&#xff1a;维护一个辅助队列。 方法二&#xff1a;大顶堆。 我还在主站 239 写了找最小值的方法。 方法一&#xff1a;最优解 这个方法和jz30维护一个非严格递减的辅助栈是基本一样的…

15.鸿蒙HarmonyOS App(JAVA)进度条与圆形进度条

15.鸿蒙HarmonyOS App(JAVA)进度条与圆形进度条 progressBar2.setIndeterminate(true);//设置无限模式,运行查看动态效果 //创建并设置无限模式元素 ShapeElement element new ShapeElement(); element.setBounds(0,0,50,50); element.setRgbColor(new RgbColor(255,0,0)); …

jetson nano VNC远程桌面配置及使用(nomachine)

文章目录 jetson nano VNC远程桌面配置及使用1.Nomachine介绍2.在电脑端安装Nomachine3.在Jetson Nano端安装Nomachine4.电脑端连接及使用步骤5.修改分辨率6.NoMachine常见问题6.1 黑屏6.2 白屏 jetson nano VNC远程桌面配置及使用 本节适用于Jetson Nano没有单独显示器可以给…

数据库结构文档生成方法二(EZDML)

EZDML 下载链接&#xff1a;EZDML - 下载 我们常用的是数据建模有PowerDesigner,EZDML也是一款数据建模工具&#xff0c;而且功能很多&#xff0c;除了生成sql&#xff0c;还可以生成前端后端代码等等。 我们直接下载最新版后点击安装&#xff0c;打开后会默认打开示例&#…

活动 | Mint Blockchain 将于 2024 年 1 月 17 号启动 MintID 限量发行活动

MintID 是 Mint Blockchain 生态的超级权益卡&#xff0c;用于探索 NFT PASS 在未来各种应用场景下的可能性。MintID 将通过限时限量有价发售的方式对外释放&#xff0c;持有人将成为 Mint Blockchain 的核心权益用户。 MintID 总量&#xff1a;10,000 枚 铸造价格&#xff1a…

linux docker安装 rustdesk

这里写自定义目录标题 1&#xff1a;软件介绍&#xff1a;2&#xff1a;安装1. 服务器端2. 客户端 3&#xff1a;配置5&#xff1a;其他1:rustdesk 官方Docker Compose 1&#xff1a;软件介绍&#xff1a; 名称作用官网项目地址rustdesk实现多端互控https://rustdesk.com/inde…

【闯关练习】—— 1400分(构造)

&#x1f30f;博客主页&#xff1a;PH_modest的博客主页 &#x1f6a9;当前专栏&#xff1a;cf闯关练习 &#x1f48c;其他专栏&#xff1a; &#x1f534;每日一题 &#x1f7e1; C跬步积累 &#x1f7e2; C语言跬步积累 &#x1f308;座右铭&#xff1a;广积粮&#xff0c;缓…

谁知道try里面放return,finally还会执行吗?

在前面几篇文章中&#xff0c;我们已经了解了关于执行上下文、作用域、闭包之间的关系。 今天&#xff0c;我们则要说一说更为细节的部分&#xff1a;语句。 语句是任何编程语言的基础结构&#xff0c;与 JavaScript 对象一样&#xff0c;JavaScript 语句同样具有“看起来很像…