全志R128 SDK HAL 模块开发指南——IR红外无线传输

IR

红外是一种电磁波,可以实现数据的无线传输,由发送和接收两个部分组成。发送端对红外信号进行脉冲编码,接收端完成对红外信号的脉冲解码。红外遥控协议有多种,如 NEC、SIRC、 RC-5 等,这些协议都比较简单,基本都是以脉冲宽度或脉冲间隔来编码。当遥控器按下按键时,遥控器逻辑单元会产生一个完整的脉冲波形,包含遥控指令的信息,即红外传输的基带信号。这个波形被送到遥控器的调制单元,经调制单元调制成高频红外电磁波信号,由发光二极管发射出去,如下图所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

红外电磁波信号一般使用一体化接收头接收,同时完成信号的解调和放大,其输出信号就是红外的基带脉冲信号。解调后的信号可直接送入信号处理单元,由处理单元对脉冲波形进行解码,典型红外接收电路如下图所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

相对应的,IR RX 模块属于INPUT 输入设备,支持红外遥控器的按键遥控。具体规格如下所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

整个系统框架流程如上图所示:当用户按下遥控器的时候,会触发一个中断。IR 驱动会进入中断,然后解析遥控器发送的键值,然后对该电压值进行解码,然后将该事件上报给INPUT 子系统。INPUT 子系统找到相应的事件处理程序之后,会将该按键事件上报给用户空间,等待用户程序对该按键信息的读取与处理。

IR TX 发送 (CIR_TX)

模块内部调制原理

内部调制原理如下图所示。其中 IMS(Internal Modulation Select),为选择使用内部调制或不调制。软件需设置使用IMS。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

载波频率设置

载波频率计算公式为:

Fc = Fclk / [(RFMC + 1) * (DRMC + 2)] (公式1)

其中

  • Fc为载波频率;
  • Fclk为Sunxi IR-TX时钟源,目前配置为12MHz;
  • RFMC为载波分频系数,由MCR寄存器(0x04)bit[7:0]设定;
  • DRMC为载波占空比设置,由GLR寄存器(0x00)bit[6:5]设定,可配置1/2、1/3或1/4。

通常,载波占空比DRMC 和载波频率 Fc 由应用层设定,因此设置载波占空比即转换为设置GLR bit[6:5],设置载波频率即转换成设置MCR bit[7:0],由公式1 变换得计算RFMC 的公式为:

RFMC = Fclk / [Fc *(DRMC + 2)] - 1 (公式2)

数据发送流程

CIR-TX 驱动数据发送流程如下图所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

设置载波占空比

由于硬件只支持1/4、1/3 和1/2 三挡占空比设置,因此Sunxi IR-TX 驱动设置载波占空比的流
程比较简单:上层传递一个0~100 的数值,如果该数值小于30,则设定占空比为1/4;如果该
数值大于30 且小于40,则设定占空比为1/3;如果该数值大于40,则设定占空比为1/2。最后
更新硬件配置。

设置载波频率

IR-TX 驱动设置载波频率流程如下图所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

模块配置介绍

IR_TX 在 menuconfig 中配置如下

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

模块源码结构

CIR_TX 模块源码结构如下所示:

rtos-hal/
|--hal/source/cir_tx/hal_cir_tx     // hal层接口代码
|--include/hal/sunxi_hal_cir_tx.h   // 头文件

模块接口说明

头文件

#include <sunxi_hal_cir_tx.h>
IRTX 初始化

IRTX 模块初始化,主要完成clk 初始化

函数原型:

cir_tx_status_t hal_cir_tx_init(struct sunxi_cir_tx_t *cir_tx);

参数:

  • cir_tx :操作结构体

返回值:

  • 0:成功初始化
  • 负数:初始化失败
IRTX 设置载波占空比

配置 IRTX 模块占空比

函数原型:

void hal_cir_tx_set_duty_cycle(int duty_cycle);

参数:

  • duty_cycle:占空比大小

返回值:

IRTX 设置载波频率

设置载波频率

函数原型:

void hal_cir_tx_set_carrier(int carrier_freq);

参数:

  • carrier_freq:载波频率大小

返回值:

IRTX 使能发送

发送IRTX 数据

函数原型:

void hal_cir_tx_xmit(unsigned int *txbuf, unsigned int count);

参数:

  • txbuf: 代表数据 buf
  • count: 代表数据长度

返回值:

模块使用范例

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>#include <hal_cmd.h>#include "sunxi_hal_cir_tx.h"#define NS_TO_US(nsec) ((nsec) / 1000)#define NEC_NBITS 32
#define NEC_UNIT 562500 /* ns. Logic data bit pulse length */
#define NEC_HEADER_PULSE \(16 * NEC_UNIT) /* 9ms. 16 * Logic data bit pulse length*/
#define NEC_HEADER_SPACE (8 * NEC_UNIT) /* 4.5ms */
#define NEC_BIT_PULSE (1 * NEC_UNIT)
#define NEC_BIT_0_SPACE (1 * NEC_UNIT)
#define NEC_BIT_1_SPACE (3 * NEC_UNIT)
#define NEC_TRAILER_PULSE (1 * NEC_UNIT)
#define NEC_TRAILER_SPACE (10 * NEC_UNIT) /* even longer */#define GPIO_IR_RAW_BUF_SIZE 128
#define DEFAULT_DUTY_CYCLE 33
#define DEFAULT_CARRIER_FREQ 38000#define LIRC_MODE2_PULSE 0x01000000
#define LIRC_MODE2_SPACE 0x00000000#define LIRC_VALUE_MASK 0x00FFFFFF
#define LIRC_MODE2_MASK 0xFF000000#define LIRC_PULSE(val) (((val)&LIRC_VALUE_MASK) | LIRC_MODE2_PULSE)
#define LIRC_SPACE(val) (((val)&LIRC_VALUE_MASK) | LIRC_MODE2_SPACE)uint32_t tx_raw_buf[GPIO_IR_RAW_BUF_SIZE];static int nec_modulation_byte(uint32_t *buf, uint8_t code) {int i = 0;uint8_t mask = 0x01;while (mask) {if (code & mask) {/* bit 1 */*(buf + i) = LIRC_PULSE(NS_TO_US(NEC_BIT_PULSE));*(buf + i + 1) = LIRC_SPACE(NS_TO_US(NEC_BIT_1_SPACE));} else {/* bit 0 */*(buf + i) = LIRC_PULSE(NS_TO_US(NEC_BIT_PULSE));*(buf + i + 1) = LIRC_SPACE(NS_TO_US(NEC_BIT_0_SPACE));}mask <<= 1;i += 2;}return i;
}static int ir_lirc_transmit_ir(uint32_t *raw_buf, size_t n) {int ret, count;count = n / sizeof(unsigned int);if (count > 1024 || count % 2 == 0) {return -1;}
}static int nec_ir_encode(uint32_t *raw_buf, uint32_t key_code) {uint8_t address, reverse_address, command, reverse_command;uint32_t *head_p, *data_p, *stop_p;address = (key_code >> 24) & 0xff;reverse_address = (key_code >> 16) & 0xff;command = (key_code >> 8) & 0xff;reverse_command = (key_code >> 0) & 0xff;/* head bit */head_p = raw_buf;*(head_p) = LIRC_PULSE(NS_TO_US(NEC_HEADER_PULSE));*(head_p + 1) = LIRC_PULSE(NS_TO_US(NEC_HEADER_SPACE));/* data bit */data_p = raw_buf + 2;nec_modulation_byte(data_p, address);data_p += 16;nec_modulation_byte(data_p, reverse_address);data_p += 16;nec_modulation_byte(data_p, command);data_p += 16;nec_modulation_byte(data_p, reverse_command);/* stop bit */stop_p = data_p + 16;*(stop_p) = LIRC_PULSE(NS_TO_US(NEC_TRAILER_PULSE));*(stop_p + 1) = LIRC_PULSE(NS_TO_US(NEC_TRAILER_SPACE));return ((NEC_NBITS + 2) * 2 - 1);
}int cmd_test_cir_tx(int argc, char **argv) {int key_code = 0x04fb13ec;int i, size;int count = 67;struct sunxi_cir_tx_t *cir_tx;hal_cir_tx_init(cir_tx);hal_cir_tx_set_duty_cycle(DEFAULT_DUTY_CYCLE);hal_cir_tx_set_carrier(DEFAULT_CARRIER_FREQ);size = nec_ir_encode(tx_raw_buf, key_code);for (i = 0; i < size; i++) {printf("%d ", *(tx_raw_buf + i) & 0x00FFFFFF);if ((i + 1) % 8 == 0) {printf("\n");}}printf("\n");for (i = 0; i < size; i++) tx_raw_buf[i] = (tx_raw_buf[i] & 0x00FFFFFF);hal_cir_tx_xmit(tx_raw_buf, count);printf("end test!\n");return 0;
}

IR RX 接收(CIR)

模块配置介绍

IR 在 menuconfig 中配置如下

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

模块源码结构

CIR 模块源码结构如下所示:

rtos-hal/
|--hal/source/cir/hal_cir.c     // hal层接口代码
|--include/hal/sunxi_hal_cir.h  // 头文件

模块返回值定义

返回值枚举定义
-4CIR_PIN_ERR配置的 CIR 引脚错误
-3CIR_CLK_ERR配置的 CIR 模块时钟错误
-2CIR_IRQ_ERR中断配置错误
-1CIR_PORT_ERR配置 CIR 端口错误
0CIR_OK成功
typedef enum {CIR_PIN_ERR = -4,CIR_CLK_ERR = -3,CIR_IRQ_ERR = -2,CIR_PORT_ERR = -1,CIR_OK = 0,
} cir_status_t;

模块接口说明

头文件

#include <sunxi_hal_cir.h>
IR 初始化接口

IR 模块初始化,主要初始化采样率、通道选择及注册中断等

函数原型:

cir_status_t sunxi_cir_init(cir_port_t port);

参数:

  • port :CIR 通道

返回值:

  • 0:成功初始化
  • 负数:初始化失败
IR 注册回调接口

向应用层提供注册回调接口的功能

函数原型:

void sunxi_cir_callback_register(cir_port_t port, cir_callback_t callback);

参数:

  • port :CIR 通道
  • callback:应用层回调接口

返回值:

IR 去初始化接口

函数原型:

void sunxi_cir_deinit(cir_port_t port);

参数:

  • port :CIR 通道

返回值:

模块使用范例

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>#include <hal_cmd.h>
#include <hal_log.h>#include "sunxi_hal_cir.h"static cir_callback_t cir_irq_callback(uint32_t data_type, uint32_t data) {printf("reg_val:0x%u\n", data);return 0;
}int cmd_test_cir(int argc, char **argv) {cir_port_t port;int ret = -1;int timeout_sec = 15;TickType_t start_ticks, current_ticks;printf("Run ir test\n");if (argc < 2) {hal_log_err("usage: hal_ir channel\n");return -1;}port = strtol(argv[1], NULL, 0);ret = sunxi_cir_init(port);if (ret) {hal_log_err("cir init failed!\n");return -1;}sunxi_cir_callback_register(port, cir_irq_callback);start_ticks = xTaskGetTickCount();printf("start_ticks: %u\n", start_ticks);while (1) {current_ticks = xTaskGetTickCount();if ((current_ticks - start_ticks) * portTICK_PERIOD_MS >=timeout_sec * 1000) {printf("current_ticks: %u\n", current_ticks);break;}}sunxi_cir_deinit(port);return 0;
}

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

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

相关文章

【触想智能】工业一体机和普通电脑的区别是什么?

工业一体机和普通电脑的区别是什么&#xff0c;工业一体机可以当普通电脑一样使用吗? 要想了解工业一体机和普通电脑的区别是什么?我们首先来看看工业一体机是什么&#xff0c;它跟普通电脑有哪些相似的地方?下面小编就为大家来详细介绍一下。 在工作原理上&#xff0c;工业…

镭速集成SMTP开发邮件发送客户端

随着信息技术的不断进步&#xff0c;电子邮件已经成为商务交流和日常信息传递的关键工具。开发邮件客户端&#xff0c;尤其是整合了SMTP服务的客户端&#xff0c;对于增强企业内部的沟通效率和提升客户服务品质扮演着至关重要的角色。本文将深入探讨如何通过整合SMTP服务&#…

Linux系统Docker部署Apache Superset并实现公网实时访问本地数据

文章目录 前言1. 使用Docker部署Apache Superset1.1 第一步安装docker 、docker compose1.2 克隆superset代码到本地并使用docker compose启动 2. 安装cpolar内网穿透&#xff0c;实现公网访问3. 设置固定连接公网地址 前言 Superset是一款由中国知名科技公司开源的“现代化的…

基于springboot实现母婴商城管理系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现母婴商城系统演示 摘要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本母婴商城系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在…

Vue - 你知道Vue2中对象动态新增属性,视图无法更新的原因吗

难度级别:中高级及以上 提问概率:55% 这道题面试官会这样描述,比如有这样一个场景,一个对象里有name属性,可以正常显示在页面中。但后续动态添加了一个age属性,通过调试打印发现对象里的age属性已经添加了上了,但试图中却没有展示出来,…

pytest的时候输出一个F后面跟很多绿色的点解读

使用pytest来测试pyramid和kotti项目&#xff0c;在kotti项目测试的时候&#xff0c;输出一个F后面跟很多绿色的点&#xff0c;是什么意思呢&#xff1f; 原来在使用pytest进行测试时&#xff0c;输出中的“F”代表一个失败的测试&#xff08;Failed&#xff09;&#xff0c;而…

C#+net微信预约挂号系统源码,掌上医院挂号,在线缴费、检查、检验报告,住院服务

微信公众号预约挂号系统、支付宝小程序预约挂号系统主要是让自费、医保患者在手机上就能实现就医全过程&#xff0c;实时预约挂号、自费、医保结算&#xff0c;同时还可以查询检查检验报告等就诊信息&#xff0c;真正实现了让信息“多跑路”&#xff0c;让群众“少跑腿”。系统…

MySQL 底层数据结构 聚簇索引以及二级索引 Explain的使用

数据结构 我们知道MySQL的存储引擎Innodb默认底层是使用B树的变种来存储数据的 下面我们来复习一下B树存储 B树存储 哈希存储的区别 哈希存储,只能使用等值查询 B树与B树存储 我们知道B树实际上就是B树的变种 那么为啥使用B树而不是使用B树呢? 我们知道效率的高低主要取决于…

JUC基础

1.JUC概念 JUC是文件Java官方文档下面的java.Util下面的工具包。作用于多线程&#xff0c;内容有lock锁&#xff0c;以及callable等内容。JDK官方文档路径。基础多线程不了解可以看多线程子线程结束&#xff0c;执行主线程 2.线程、进程 1.进程&#xff1a; 一个程序是线程…

Python第四次作业

周六&#xff1a; 1. 找出10000以内能被5或6整除&#xff0c;但不能被两者同时整除的数&#xff08;函数&#xff09; def find_number():for number in range(0,10000):if number % 5 0 or number % 6 0:if number % 5 ! number % 6:ls.append(number)print(ls)ls [] fin…

如何快速摸清一个行业?

作为一名职场人&#xff0c;或多或少都会遇到需要了解自己不熟悉的行业&#xff0c;比如&#xff1a; 职业选择&#xff0c;跳槽换工作时&#xff1a;哪家企业所在的行业有优势&#xff0c;未来会有更多的机会&#xff1f;哪个行业给的薪资会更高&#xff1f;行业内当下及未来的…

MATLAB | 怎样绘制更有立体感的柱状图

之前写了一篇文章说明了MATLAB图例可以自己diy&#xff0c;这次又有了diy的机会&#xff0c;我开发了一个简单的小工具&#xff0c;能够实现绘制伪3d的柱状图&#xff0c;大概效果如下&#xff1a; 使用说明 由于涉及的代码比较接近MATLAB底层的图形对象&#xff0c;有点东西还…