红外NEC通信协议
一、NEC简介
红外(Infrared,IR)遥控是一种无线、非接触控制技术,常用于遥控器、无线键盘、鼠标等设备之间的通信。IR协议的工作原理是,发送方通过红外线发送一个特定的编码,接收方通过识别该编码来执行相应的操作。
IR协议是指红外线通信协议的总称,而NEC协议是IR协议中的一种具体实现。红外遥控系统分为发射和接收两部分,发射部分的发射元件为红外发光二极管,它发出的是红外线而不是可见光;接收电路的红外接收管是一种光敏二极管。
二、NEC传输格式
NEC协议采用PPM(Pulse Position Modulation,脉冲位置调制)的形式进行编码,数据的每一位(Bit)脉冲长度为560us,由38KHz的载波脉冲 (carrier burst) 进行调制,推荐的载波占空比为 1/3至 1/4。有载波脉冲的地方,其宽度都为 560us,而载波脉冲的间隔时间是不同的。
逻辑“1”的载波脉冲+载波脉冲间隔时间为2.25ms;逻辑“0”的载波脉冲+载波脉冲间隔时间为逻辑“1”的一半,即1.125ms.
每次信息都是按照引导码 (9ms载波脉冲+4.5ms 空闲信号)地址码、地址反码、控制码和控制反码的格式进行传输,因此,单次信息传输的时间是固定不变的。
当红外遥控器上的按键被一直按下时,红外遥控器只会发送一次完整的信息,其后会每隔 110ms 发送一次重复码(连发码)。重复码的数据格式比较简单,同样是由 9ms的载波脉冲开始,紧接着是2.25ms的空闲信号,随后是560us的载波脉冲。
红外接收头通常被厂家集成在一个元件中,成为一体化红外接收头。红外接收头内部的三极管电路具有信号反向的功能,也就是将1变为0,0变为1,即数据0是0.56ms的低电平和0.56ms的高电平,数据1是0.5ms的低电平和1.69ms的高电平,9ms是高电平变为低电平。
三、FPGA实现
通过三段式状态机实现红外驱动模块
module ir_rcv(input clk , //系统时钟input rst_n , //系统复位信号,低电平有效input remote_in , //红外接收信号output reg repeat_en , //重复码有效信号output reg data_en , //数据有效信号output reg [7:0] data //红外控制码);//parameter define
parameter idle = 5'b0_0001; //空闲状态
parameter start_low_9ms = 5'b0_0010; //监测同步码低电平
parameter start_judge = 5'b0_0100; //判断重复码和同步码高电平(空闲信号)
parameter rec_data = 5'b0_1000; //接收数据
parameter repeat_code = 5'b1_0000; //重复码//reg define
reg [4:0] cur_state ; //当前状态
reg [4:0] next_state ; //下一状态reg [11:0] div_cnt ; //分频计数器
reg div_clk ; //分频时钟
reg remote_in_d0 ; //对输入的红外信号延时打拍
reg remote_in_d1 ;
reg [7:0] time_cnt ; //对红外的各个状态进行计数reg time_cnt_clr ; //计数器清零信号
reg time_done ; //计时完成信号
reg error_en ; //错误信号
reg judge_flag ; //检测出的标志信号 0:同步码高电平(空闲信号) 1:重复码
reg [15:0] data_temp ; //暂存收到的控制码和控制反码
reg [5:0] data_cnt ; //对接收的数据进行计数 //wire define
wire ir_pos ; //输入红外信号的上升沿
wire ir_neg ; //输入红外信号的下降沿//*****************************************************
//** main code
//*****************************************************assign ir_pos = (~remote_in_d1) & remote_in_d0;
assign ir_neg = remote_in_d1 & (~remote_in_d0);//对50MHz时钟进行分频,50Mhz/(2*(3124+1))=8khz,T=0.125ms,得到一个周期为0.125ms(8KHz)的时钟
//对时钟进行分频,是因为红外信号接收的过程用时较长,如果使用50Mhz的时钟采样,内部定义的计数器位宽会比较大,也可以分频成其它频率的时钟
always @(posedge clk or negedge rst_n ) beginif (!rst_n) begindiv_cnt <= 12'd0;div_clk <= 1'b0;end else if(div_cnt == 12'd3124) begindiv_cnt <= 12'd0;div_clk <= ~div_clk;end elsediv_cnt <= div_cnt + 12'b1;
end//对红外的各个状态进行计数,例如监测同步码低电平、判断重复码和同步码高电平等
always @(posedge div_clk or negedge rst_n) beginif(!rst_n)time_cnt <= 8'b0;else if(time_cnt_clr)time_cnt <= 8'b0;else time_cnt <= time_cnt + 8'b1;
end //对输入的remote_in信号延时打拍,即在一个时钟周期内,获取两个不同的红外信号采样值,以便后续的上升沿和下降沿检测
always @(posedge div_clk or negedge rst_n) beginif(!rst_n) beginremote_in_d0 <= 1'b0;remote_in_d1 <= 1'b0;endelse beginremote_in_d0 <= remote_in;remote_in_d1 <= remote_in_d0;end
end//采用三段式状态机对红外信号进行解析
always @ (posedge div_clk or negedge rst_n) beginif(!rst_n)cur_state <= idle;elsecur_state <= next_state ;
endalways @(*) beginnext_state = idle; case(cur_state)idle : begin //默认在空闲状态,time_cnt_clr的值置为1,time_cnt也就为0if(remote_in_d0 == 1'b0) //在空闲状态中检测到下降沿,则进入9ms低电平判断next_state = start_low_9ms; //此时time_cnt_clr的值置为0,time_cnt开始计数elsenext_state = idle; //否则一直保持空闲状态endstart_low_9ms : begin //监测同步码低电平if(time_done) //计数达到9ms,跳转判断重复码和同步码高电平next_state = start_judge;else if(error_en) //计数不在9ms范围,发生错误,跳转到空闲状态next_state = idle;elsenext_state = start_low_9ms; //否则一直保持在start_low_9msendstart_judge : begin //判断重复码和同步码高电平(空闲信号)if(time_done) beginif(judge_flag == 1'b0) //如果是同步码,则跳转到接收数据状态next_state = rec_data;else next_state = repeat_code; //否则跳转到重复码状态endelse if(error_en)next_state = idle;elsenext_state = start_judge;endrec_data : begin //接收数据,当数据传输完成,跳转到空闲状态if(ir_pos && data_cnt == 6'd32) next_state = idle;elsenext_state = rec_data; endrepeat_code : begin //重复码if(ir_pos)next_state = idle; //进入空闲状态elsenext_state = repeat_code; end default : next_state = idle;endcase
endalways @(posedge div_clk or negedge rst_n ) begin if (!rst_n) begin time_cnt_clr <= 1'b0;time_done <= 1'b0;error_en <= 1'b0;judge_flag <= 1'b0;data_en <= 1'b0;data <= 8'd0;repeat_en <= 1'b0;data_cnt <= 6'd0;data_temp <= 32'd0;endelse begintime_cnt_clr <= 1'b0;time_done <= 1'b0;error_en <= 1'b0;repeat_en <= 1'b0;data_en <= 1'b0;case(cur_state)idle : begintime_cnt_clr <= 1'b1;if(remote_in_d0 == 1'b0)time_cnt_clr <= 1'b0;end start_low_9ms : begin //9ms/0.125ms = 72if(ir_pos) begin //当检测到ir_pos(红外信号上升沿)为高电平时,说明此时红外信号拉高,即同步码低电平结束time_cnt_clr <= 1'b1; //停止计数 if(time_cnt >= 69 && time_cnt <= 75) //判断time_cnt的值是否接近9ms,如果接近9ms,跳转到start_judee状态time_done <= 1'b1; else //如果time_cnt的值不接近9ms,则发生了错误,跳转到空闲状态error_en <= 1'b1;end endstart_judge : beginif(ir_neg) begin time_cnt_clr <= 1'b1; if(time_cnt >= 15 && time_cnt <= 20) begin //重复码高电平2.25ms 2.25/0.125 = 18time_done <= 1'b1;judge_flag <= 1'b1; //检测出是重复码,跳转到repeat_code重复码状态end else if(time_cnt >= 33 && time_cnt <= 38) begin //同步码高电平4.5ms 4.5/0.125 = 36time_done <= 1'b1;judge_flag <= 1'b0; //检测出是同步码,跳转到rec_data接收数据状态 endelseerror_en <= 1'b1;end endrec_data : begin if(ir_pos) begin //当有红外信号上升沿time_cnt_clr <= 1'b1;if(data_cnt == 6'd32) begin //有32个数据即32个上升沿或下降沿,分别为16位地址码以及16位数据data_en <= 1'b1; //当计数到32即数据传输完成data_cnt <= 6'd0;data_temp <= 16'd0;if(data_temp[7:0] == ~data_temp[15:8]) //校验控制码和控制反码data <= data_temp[7:0];endendelse if(ir_neg) begin //当有红外信号下降沿time_cnt_clr <= 1'b1;data_cnt <= data_cnt + 1'b1; //每当1bit数据到来时也就是一个下降沿到来时,数据位数计数器加1//解析控制码和控制反码,判断是560us还是1690us计数完成,进而得到这个数据位是0还是1 if(data_cnt >= 6'd16 && data_cnt <= 6'd31) begin if(time_cnt >= 2 && time_cnt <= 6) begin //0.565/0.125 = 4.52data_temp <= {1'b0,data_temp[15:1]}; //逻辑“0”endelse if(time_cnt >= 10 && time_cnt <= 15) //1.69/0.125 = 13.52data_temp <= {1'b1,data_temp[15:1]}; //逻辑“1”endendendrepeat_code : begin if(ir_pos) begin time_cnt_clr <= 1'b1;repeat_en <= 1'b1;endenddefault : ;endcaseend
endendmodule
相关文章:

红外NEC通信协议
一、NEC简介 红外(Infrared,IR)遥控是一种无线、非接触控制技术,常用于遥控器、无线键盘、鼠标等设备之间的通信。IR协议的工作原理是,发送方通过红外线发送一个特定的编码,接收方通过识别该编码来执行相应的操作。 IR协议是指红外…...

数据分析DAY1
数据分析 引言 这一周:学习了python的numpy和matplotlib以及在飞桨paddle上面做了几个小项目 发现numpy和matplotlib里面有很多api,要全部记住是不可能的,也是不可能全部学完的,所以我们要知道并且熟悉一些常用的api࿰…...

算法通关村—迭代实现二叉树的前序,中序,后序遍历
1. 前序中序后序递归写法 前序 public void preorder(TreeNode root, List<Integer> res) {if (root null) {return;}res.add(root.val);preorder(root.left, res);preorder(root.right, res);}后序 public static void postOrderRecur(TreeNode head) {if (head nu…...

二叉搜索树(BST)的模拟实现
序言: 构造一棵二叉排序树的目的并不是为了排序,而是为了提高查找效率、插入和删除关键字的速度,同时二叉搜索树的这种非线性结构也有利于插入和删除的实现。 目录 (一)BST的定义 (二)二叉搜…...

【MFC】01.MFC框架-笔记
基本概念 MFC Microsoft Fundation class 微软基础类库 框架 基于Win32 SDK进行的封装 属性:缓解库关闭 属性->C/C/代码生成/运行库/MTD 属性->常规->MFC的使用:在静态库中使用MFC,默认是使用的共享DLL,运行时库 SD…...

基于ArcGIS污染物浓度及风险的时空分布
在GIS发展的早期,专业人士主要关注于数据编辑或者集中于应用工程,以及主要把精力花费在创建GIS数据库并构造地理信息和知识。慢慢的,GIS的专业人士开始在大量的GIS应用中使用这些知识信息库。用户应用功能全面的GIS工作站来编辑地理数据集&am…...

【项目开发计划制定工作经验之谈】
一、背景介绍 随着信息技术的发展,项目管理越来越受到企业和组织的重视。项目管理是一项旨在规划、组织、管理和控制项目的活动,以达到特定目标的过程。项目开发计划是项目管理的一个重要组成部分,它是指定项目目标、工作范围、进度、质量、…...

基于STM32的格力空调红外控制
基于STM32的格力空调红外控制 1.红外线简介 在光谱中波长自760nm至400um的电磁波称为红外线,它是一种不可见光。目前几乎所有的视频和音频设备都可以通过红外遥控的方式进行遥控,比如电视机、空调、影碟机等,都可以见到红外遥控的影子。这种技…...

rust中thiserror怎么使用呢?
thiserror 是一个Rust库,可以帮助你更方便地定义自己的错误类型。它提供了一个类似于 macro_rules 的宏,可以帮助你快速地定义错误类型,并为错误添加上下文信息。下面是一个使用 thiserror 的示例: 首先,在你的Rust项…...

ceph tier和bcache区别
作者:吴业亮 博客:wuyeliang.blog.csdn.net Ceph tier(SSD POOL HDD POOL)不推荐的原因: 数据在两个资源池之间迁移代价太大,存在粒度问题(对象级别),且需要进行write…...

Idea 2023.2 maven 打包时提示 waring 问题解决
Version idea 2023.2 问题 使用 Maven 打包 ,控制台输出 Waring 信息 [WARNING] [WARNING] Plugin validation issues were detected in 7 plugin(s) [WARNING] [WARNING] * org.apache.maven.plugins:maven-dependency-plugin:3.3.0 [WARNING] * org.apache.…...

docker数据持久化
在Docker中若要想实现容器数据的持久化(所谓的数据持久化即数据不随着Container的结束而销毁),需要将数据从宿主机挂载到容器中。目前Docker提供了三种不同的方式将数据从宿主机挂载到容器中。 (1)Volumes:…...

安全防护,保障企业图文档安全的有效方法
随着企业现在数据量的不断增加和数据泄露事件的频发,图文档的安全性成为了企业必须高度关注的问题。传统的纸质文件存储方式已不适应现代企业的需求,而在线图文档管理成为了更加安全可靠的数字化解决方案。那么在在线图文档管理中,如何采取有…...

Open3D (C++) 基于拟合平面的点云地面点提取
目录 一、算法原理1、原理概述2、参考文献二、代码实现三、结果展示1、原始点云2、提取结果四、相关链接本文由CSDN点云侠原创,原文链接。爬虫网站自重,把自己当个人,爬些不完整的误导别人有意思吗???? 一、算法原理...

【Linux】Kali Linux 渗透安全学习笔记(2) - OneForAll 简单应用
OneForAll (以下简称“OFA”)是一个非常好用的子域收集工具,可以通过一级域名找到旗下的所有层级域名,通过递归的方式我们很容易就能够知道此域名下的所有域名层级结构,对于进一步通过域名推测站点功能起到非常重要的作…...

DAY56:单调栈(二)下一个最大元素Ⅱ(环形数组处理思路)
文章目录 思路写法1完整版环形数组处理:i取模,遍历两遍写法2完整版(环形数组推荐写法)debug测试:逻辑运算符短路特性result数组在栈口取元素,是否会覆盖原有数值? 给定一个循环数组 nums &#…...

kafka简介
kafka是什么? Kafka最初采用Scala语言开发的一个多分区、多副本并且基于ZooKeeper协调的分布式消息系统。目前Kafka已经定位为一个分布式流式处理平台,它的特性有高吞吐、可持久化、可水平扩展、支持流处理。 Apache Kafka是一个分布式的发布-订阅消息系…...

Kafka-消费者组消费流程
消费者向kafka集群发送消费请求,消费者客户端默认每次从kafka集群拉取50M数据,放到缓冲队列中,消费者从缓冲队列中每次拉取500条数据进行消费。...

FFmepg视频解码
1 前言 上一篇文章<FFmpeg下载安装及Windows开发环境设置>介绍了FFmpeg的下载安装及环境配置,本文介绍最简单的FFmpeg视频解码示例。 2 视频解码过程 本文只讨论视频解码。 FFmpeg视频解码的过程比较简单,实际就4步: 打开媒体流获取…...

SpringCloud深入理解 | 生产者、消费者
💗wei_shuo的个人主页 💫wei_shuo的学习社区 🌐Hello World ! SpringCloud Spring Cloud是一组用于构建分布式系统和微服务架构的开源框架和工具集合。它是在Spring生态系统的基础上构建的,旨在简化开发人员构建分布式…...

web题型
0X01 命令执行 漏洞原理 没有对用户输入的内容进行一定过滤直接传给shell_exec、system一类函数执行 看一个具体例子 cmd1|cmd2:无论cmd1是否执行成功,cmd2将被执行 cmd1;cmd2:无论cmd1是否执行成功,cmd2将被执行 cmd1&cmd2:无论cmd1是否执行成…...

使用curl和postman调用Azure OpenAI Restful API
使用curl在cmd中调用时,注意:json大括号内的每一个双引号前需要加上\ curl https://xxxopenai.openai.azure.com/openai/deployments/Your_deployid/chat/completions?api-version2023-05-15 -H "Content-Type: application/json" -H "…...

草莓叶病害数据集
1.草莓数据集有两个文件夹 训练集 健康文件夹(2819张) 草莓叶焦病害(3327张) 数据集可以关注最后一行 import numpy as np import os import matplotlib.pyplot as plt import cv2import warnings warnings.filterwarnings(igno…...

安卓音视频多对多级联转发渲染
最近利用自己以前学习和用到的音视频知识和工程技能做了一个android的sdk,实现了本地流媒体ipc rtsp 拉流以及自带mip usb等camera audio节点产生的流媒体通过webrtc sfu的方式进行多对多级联发布共享,网状结构,p2p组网,支持实时渲染以及转推rtmp&#x…...

2023年电赛---运动目标控制与自动追踪系统(E题)OpenART mini的代码移植到OpenMV
前言 (1)已经有不少同学根据我上一篇博客完成了前三问,恭喜恭喜。有很多同学卡在了第四问。 (2)我说了OpenART mini的代码是可行的。但是他们不会移植到OpenMV上,再次我讲移植之后的代码贴出来。 ÿ…...

SAP CAP篇十二:AppRouter 深入研究
本文目录 本系列文章理解现有程序app文件夹中的package.json理解approuter.js 修改现有程序修改package.json新建index.js在Approuter中显示额外的逻辑 添加一些额外的Logger对应代码及branch 本系列文章 SAP CAP篇一: 快速创建一个Service,基于Java的实现 SAP CAP…...

HDFS中数据迁移的使用场景和考量因素
HDFS中数据迁移的使用场景和考量因素 数据迁移使用场景数据迁移要素考量HDFS分布式拷贝工具-DistCpdistcp的优势性能命令 数据迁移使用场景 冷热集群数据同步、分类存储集群数据整体搬迁 当公司业务迅速的发展,导致的当前的服务器数量资源出现临时紧张的时候&#…...

科普 | 以太坊坎昆升级是什么
坎昆升级是什么 坎昆,是墨西哥一个著名的旅游城市,也是 Devcon 3 大会的举办地,按照以太坊升级命名的规律,以地名命名的升级,是针对以太坊执行层的升级。 之前同样命名的还有柏林升级、伦敦升级和这次的上海升级等。…...

C# 一些知识整理
C#反射和特性 反射Reflection Type 类型 Name NameSpace Assembly GetFields() GetProperties() GetMethods() 特性Attribute Obsolete弃用 Condit…...

SpringBoot复习:(15)Spring容器的核心方法refresh是在哪里被调用的?
在SpringApplication的run方法: refreshContext代码如下: 其中调用的refresh方法代码如下: 其中调用的refresh方法代码如下: 其中调用的fresh方法代码如下: 其中调用了super.refresh();而这个super.refresh()就是…...