FPGA 24 红外遥控(NEC协议)解码

主要功能 :设计了一个红外 NEC协议的解码模块

实现(设计)流程:通过遥控器发送的红外信号,外围红外信号接收传感器对数据进行接收,得到一个在基频上的高低电平的(非方波)的输入信号IIR,fpga内部设计该模块,实现对该信号进行解码,设计一个状态机,最终判断数据解析是否完整接收,进而判断数据是否正确。接收正确以后,数据解析出来的地址和数据,以及本次解析完成的标志信号。

实验目的 : ①解决非方波信号协议的数据解码 ② 状态机判断和时间计数器在状态机中的灵活使用。③标志信号和always 块的相互分离,本次实验中,状态机数据接收的32个bit信号,我们是在外面用了一个always 块来处理数据接收的情况的,时间计数器的使能和不使能在实验中用的也是非常的灵活,这个是我们需要掌握的一些比较好的设计方法,让自己的代码更具有可读性.

实验现象 : 按下红外遥控上的按键,然后在QuartusⅡ软件中使用Iln system sources and probeseditor中观察解码结果,根据解码结果与红外遥控实际发出的数值进行比较从而判断解码的正确性。

HT6221芯片是一款基于NEC红外通信协议的遥控编码芯片,基于HT6221芯片的红外遥控发送一次数据的数据帧定义如下图所示:

一帧数据由引导码、地址码和数据码以及数据反码组成.

其中,引导码由9ms的载波波形和4.5ms的低电平组成,代表一个数据帧的帧头;

地址码共16位,低位在前,高位在后,因此,该协议理论上支持最局65536个个同的用户;

8位数据码及其反码也是低位在前,高位在后。因此,理论上该协议支持高达256个用户指令。

该协议采用脉冲之间不同时长的时间间隔来区分“1”和“O”,下图为其编码协议中“1”.

但是(注这里很重要): 而在实际接收时,接收头接收到信号后【输出的波形刚好与此波形反相】。

所以:这里有两种处理方式,①在输入的fpga信号端加入一个非门,最后来回改发送的信号编写状态机的解析协议

② 对原始信号取反,直接对其反相信号进行解码(本次实验使用的是这种方式.)

即实际的接收数据会变成如下所示:

实际接收到信号如下所示:

使用signal_tap-II 真实采样到的数据波形:

IDEL : 空闲状态(IDEL),等待IR接收信号下降沿的到来。表示引导码信号开始到来.进入到LEADER_T9 状态.

LEADER_T9 : 识别9ms 的低电平引导码,识别成功则继续识别4.5ms的高电平引导码状态LEADER_T4_5 ,否则返回空闲态。

LEADER_T4_5 : 识别4.5ms的高电平引导码,识别成功则进入读码(DATE_GET )状态,否则返回空闲态。

DATE_GET : 读码状态,若32个码字已经读完或者读取过程中发生了错误,则返回空闲态(IDEL)。

ir_decode.文件

module ir_decode(Clk,Rst_n,iIR,Get_Flag,irData,irAddr
);input Clk;    //时钟input Rst_n;  //复位input iIR;      //红外模块信号输入output Get_Flag;  //解码成功标志信号output [15:0]irData;    //接收的数据 数据核数据反码output [15:0]irAddr;    //接收的地址  低8位核高8位reg [18:0]cnt;//time counterreg [3:0]state;// 定义一个时钟到达的计数器标志位reg T9ms_ok;reg T4_5ms_ok;reg T_56ms_ok;reg T1_69ms_ok;reg Get_Data_Done;reg Cnt_en;reg timeout;reg [5:0]data_cnt;reg [31:0]data_tmp;assign irAddr = data_tmp[15:0];assign irData = data_tmp[31:16];//状态机状态参数localparam IDEL = 4'b0001,LEADER_T9 = 4'b0010,LEADER_T4_5 = 4'b0100,DATE_GET = 4'b1000;reg s_IR0,s_IR1;//消除亚稳态always@(posedge Clk or negedge Rst_n)if(!Rst_n)begins_IR0 <= 1'b0;s_IR1 <= 1'b0;endelse begins_IR0 <= iIR;s_IR1 <= s_IR0;endreg s_IR0_Temp,s_IR1_Temp;// 获取上升沿和下降沿always@(posedge Clk or negedge Rst_n)if(!Rst_n)begins_IR0_Temp <= 1'b0;s_IR1_Temp <= 1'b0;endelse begins_IR0_Temp <= s_IR1;s_IR1_Temp <= s_IR0_Temp;//    s_IR1_Temp:当前时刻t0   s_IR0_Temp:后一个时刻t1endwire ir_pedge,ir_nedge;assign ir_pedge = !s_IR1_Temp && s_IR0_Temp;   //上升沿:当前时刻是低电平,后一时刻是高电平assign ir_nedge = s_IR1_Temp && !s_IR0_Temp;   //下降沿:当前时刻是高电平,后一时刻是低电平//时间计数器  cnt_en 使能信号always@(posedge Clk or negedge Rst_n)if(!Rst_n) cnt <= 19'd0;else if(Cnt_en == 1'b1)cnt <= cnt + 1'b1;elsecnt <= 19'd0;// T9ms_ok 标志位always@(posedge Clk or negedge Rst_n)if(!Rst_n)T9ms_ok <= 1'b0;else if(cnt > 19'd325000 && cnt <19'd495000)  //  8.5ms ~ 9.5ms T9ms_ok <= 1'b1;elseT9ms_ok <= 1'b0;// T4_5ms_ok标志位  4ms ~ 5msalways@(posedge Clk or negedge Rst_n)if(!Rst_n)T4_5ms_ok <= 1'b0;else if(cnt > 19'd152500 && cnt <19'd277500) //4ms ~ 5msT4_5ms_ok <= 1'b1;elseT4_5ms_ok <= 1'b0;// T_56ms_ok标志位  0.5ms ~ 0.6msalways@(posedge Clk or negedge Rst_n)if(!Rst_n)T_56ms_ok <= 1'b0;else if(cnt > 19'd20000 && cnt <19'd35000)  // 0.5ms ~ 0.6msT_56ms_ok <= 1'b1;elseT_56ms_ok <= 1'b0;// T1_69ms_ok标志位  1.6ms ~ 1.8msalways@(posedge Clk or negedge Rst_n)if(!Rst_n)T1_69ms_ok <= 1'b0;else if(cnt > 19'd75000 && cnt <19'd90000)T1_69ms_ok <= 1'b1;elseT1_69ms_ok <= 1'b0;//计数器 timeout 超时处理always@(posedge Clk or negedge Rst_n)if(!Rst_n)    timeout <= 1'b0;else if(cnt >= 19'd500000)timeout <= 1'b1;else timeout <= 1'b0;// always@(posedge Clk or negedge Rst_n)if(!Rst_n)beginstate <= IDEL;   //默认空闲状态Cnt_en <= 1'b0;endelse if(!timeout  //没有发出超时信号begin  case(state)IDEL:if(ir_nedge)begin          // ir_nedge :下降沿到来,根据引导码的编码方式// 它是先是高电平,随后变成低电平的一个信号,所以检测下降沿Cnt_en <= 1'b1;     // 如果是检测到下降沿,则Cnt_en=1,计时器开始计时state <= LEADER_T9; // 开始计数,进入 LEADER_T9 (9ms 低电平信号)状态endelse begin           //位检测到上升沿,保持该状态不变state <= IDEL;Cnt_en <= 1'b0;endLEADER_T9:if(ir_pedge)begin  // 判断是否检测到上升沿,当检测到上升沿时,表示要么进入下一状态,// 要么就是数据从出错if(T9ms_ok)begin //检测到帧头信号9ms的低电平时间在某个区间内 T9ms_ok 就会等于 1Cnt_en <= 1'b0;      // Cnt_en=0 ,主要目的是计数器清零state <= LEADER_T4_5; //进入到下一个状态endelse begin          //否则没数据检测错误state <= IDEL;   endendelse begin        //还未检测到上升沿state <= LEADER_T9;   //状态保持Cnt_en <= 1'b1;      //计数器继续计数endLEADER_T4_5: if(ir_nedge)begin          // 判断是否检测到下降沿,当检测到下降沿时,表示要么进入下一状态(数据接收状态),if(T4_5ms_ok)begin//检测到帧头信号接收正确的标志位Cnt_en <= 1'b0;// Cnt_en=0 ,计数器清零state <= DATE_GET;//进入到下一个状态(数据接收状态)endelse beginstate <= IDEL;     //否则没数据检测错误endendelse begin  //还未检测到上升沿state <= LEADER_T4_5;Cnt_en <= 1'b1;endDATE_GET:if(ir_pedge && !T_56ms_ok)  //当我们接收到上升沿(也就是说是之前是低电平560ms),且低电平时间不等于560us,那么数据接收错误state <= IDEL;else if(ir_nedge && (!T_56ms_ok && !T1_69ms_ok)) //高电平时间 既不是高电平560us、1.69ms ,那么数据接收错误state <= IDEL;         else if(Get_Data_Done)  //数据接收完成,进行空闲状态state <= IDEL;    else if(ir_pedge && T_56ms_ok)begin // ir_pedge && T_56ms_ok 表示前面发送的是560us 低电平信号,进入高电平信号的判断Cnt_en <= 1'b0;   //正确接受到560us的低电平信号,时间计数器清零.endelse if(ir_nedge && (T_56ms_ok || T1_69ms_ok))begin //ir_nedge && (T_56ms_ok || T1_69ms_ok) 高电平信号,且正常接收到 560us 的高电平或者 1.69ms 的高电平 Cnt_en <= 1'b0;      //本次bit数据接收完成,时间计数器清零          endelseCnt_en <= 1'b1;default:;endcaseendelse begin    //超时状态的话,让状态机复位Cnt_en <= 1'b0;state <= IDEL;    end// 数据计数器模块 always@(posedge Clk or negedge Rst_n)if(!Rst_n)begin//复位信号  Get_Data_Done <= 1'b0;data_cnt <= 6'd0;data_tmp <= 32'd0;endelse if(state == DATE_GET)begin  //状态机状态 DATE_GET 时候 ,进入数据判断任务状态if(ir_pedge && (data_cnt == 6'd32))begin //检测到上升沿的时候,且数据计数到33个上升沿的时候,表明数据已经接收完成data_cnt <= 6'd0;Get_Data_Done <= 1'b1; //发送 Get_Data_Doneendelse begin  //注:下降沿到来,表示数据的高电平时间发送完成if(ir_nedge) //只要检测到一个下降沿,数据计数器位+1  ,接收最后一个(第33个)下降沿的时候,变成 data_cnt = 32data_cnt <= data_cnt + 1'b1;if(ir_nedge && T_56ms_ok)  //检测到下降沿,且计数器时间位 0.56us ,数据为0data_tmp[data_cnt] <= 1'b0;else if(ir_nedge && T1_69ms_ok) //检测到下降沿,且计数器时间位 0.56us ,数据为0data_tmp[data_cnt] <= 1'b1;Get_Data_Done <= 1'b0;end    endassign Get_Flag = Get_Data_Done;endmodule

ir_decode_tb.v 仿真测试文件

`timescale 1ns/1ns`define clk_period 20module ir_decode_tb;reg Clk;reg Rst_n;reg iIR;wire Get_Flag;wire [15:0]irData;wire [15:0]irAddr;integer i;ir_decode ir_decode(.Clk(Clk),.Rst_n(Rst_n),.iIR(iIR),.Get_Flag(Get_Flag),.irData(irData),.irAddr(irAddr));initial Clk = 1'b1;always#(`clk_period/2)Clk = ~Clk;initial beginRst_n = 1'b0;iIR = 1'b1;#(`clk_period*10+1'b1);Rst_n = 1'b1;#2000;iIR = 1'b1;send_data(1,8'h12); //调用 send_data任务#60000000;send_data(3,8'heb); //调用 send_data任务#60000000;$stop   ;endtask send_data;input [15:0]addr;input [7:0]data;beginiIR = 0;#9000000; //发送帧头保持9msiIR = 1;#4500000; //发送高电平保持4.5msfor(i=0;i<=15;i=i+1)begin //发送地址,调用 bit_send task任务bit_send(addr[i]);     endfor(i=0;i<=7;i=i+1)begin //发送数据bit_send(data[i]);     endfor(i=0;i<=7;i=i+1)begin //发送数据反码bit_send(~data[i]);      endiIR = 0;#560000;    //发送停止位数延时0.56msiIR = 1;          //发送停止位的高电平endendtasktask bit_send; input one_bit;beginiIR = 0; #560000; //发送数据0,延时0.56msiIR = 1;if(one_bit)   //发送1,高电平维持1.69ms#1690000;else        //发送0,高电平维持0.56ms#560000;end endtaskendmodule

FPGA 24 工程模块 红外遥控(NEC协议)解码相关推荐

  1. 【物联网毕设基础】单片机:NEC 协议红外遥控器

    文章目录 NEC 协议红外遥控器 NEC 协议红外遥控器 家电遥控器通信距离往往要求不高,而红外的成本比其它无线设备要低的多,所以家电遥控器应用中红外始终占据着一席之地.遥控器的基带通信协议很多,大概 ...

  2. 嵌入式 STM32 红外遥控

    目录 红外遥控 NEC码的位定义 硬件设计 软件设计 源码程序 红外遥控 红外遥控是一种无线.非接触控制技术,具有抗干扰能力强,信息传输可靠,功耗低,成本低,容易实现等显著的特点,被诸多电子设备特别是 ...

  3. 51单片机tea5767收音机 红外遥控 自动搜台 存台 DIY

    转自:https://www.cnblogs.com/ningci/p/5464679.html 日向宁次 博客园 首页 新闻 新随笔 联系 管理 订阅 随笔- 55  文章- 0  评论- 1  5 ...

  4. 红外遥控协议-NEC协议

    为方便理解所看到的波形是从红外接收管出来的信号,跟协议所说的信号高低(0或1)刚好相反. NEC协议是众多红外遥控协议的其中一种,除NEC外,还有RC5.RC6等其它的.市面上买到的非学习型万能电视遥 ...

  5. NEC协议——红外遥控的使用

    NEC协议是众多红外遥控协议的其中一种,下面以蓝桥杯的单片机开发板实现红外解码. 相关芯片与元器件介绍 此图为跳线帽的解法,在做红外通信时应接3,5:4,6. 此图左为红外发射装置和HX1838集成芯 ...

  6. NEC红外协议编码,38K红外遥控编码,红外遥控发射接收电路选型设计

    NEC为红外遥控最常用的编码,红外载波频率为38KHz,其协议小巧简单,非常适合家电设备的控制.其他的还有 Phillips(RCA)的RC-5和RC-6,但那只是IR协议的少数. 本篇博文参照国外博 ...

  7. 红外遥控协议分析之:NEC协议

    红外遥控协议分析之:NEC协议 2009-04-08 19:55:28|  分类: 个人日记|字号 订阅 红外遥控协议分析之:NEC协议  特点    8 位地址和 8 位命令 为提高可靠性,地址和命 ...

  8. 红外遥控c语言,NEC协议红外遥控器

    家电遥控器通信距离往往要求不高,而红外的成本比其它无线设备要低的多,所以家电遥控器应用中红外始终占据着一席之地.遥控器的基带通信协议很多,大概有几十种,常用的就有 ITT 协议.NEC 协议.Shar ...

  9. 基于FPGA的红外遥控解码与PC串口通信

    基于FPGA的红外遥控解码与PC串口通信 zouxy09@qq.com http://blog.csdn.net/zouxy09 这是我的<电子设计EDA>的课程设计作业(呵呵,这个月都拿 ...

最新文章

  1. AbutionGraph:构建以知识图谱为核心的下一代数据中台
  2. python ssh模块_windows下python SSH的使用——paramiko模块
  3. android 通过GPS获取用户地理位置并监听位置变化
  4. Hyper-V 2016 系列教程15 Hyper-V Cmdlets PowerShell 命令提示符
  5. java火焰纹章攻略女神之剑_《火焰纹章风花雪月》白云之章-女神再生仪式图文攻略...
  6. 计算机指令就是一串开关吗,什么是非法关机?常按计算机开关,还是直接拔掉电源插头才算啊?...
  7. python主要简介_Python的简介
  8. python常用代码大全-大神整理的python资源大全
  9. js打开新页面的两种方式
  10. 视频教程-思科CCNP专题系列②:EIGRP路由协议-思科认证
  11. 海康威视NVR硬盘录像机DS-7808N安装调试教程,监控系统安装教程
  12. 学生:无效文件.dsn问题
  13. 计算机可以谭音乐吗,谭晶怎么被叫谭哈哈 《歌手》谭晶演唱什么歌曲
  14. 学习嵌入式,需要哪些硬核技能?
  15. shawl.qiu Javascript 前景色背景色调色类 / BgColorScheme v1.1
  16. 长度标注神器----MarkMan
  17. 最新江苏水利水电安全员模拟真题及答案解析
  18. DVDFab Photo Enhancer AI一款声称可以将图片无损放大到夸张的40倍大小的人工智能软件
  19. 奇虎360公司董事长周鸿祎发布2015新年信
  20. data whitening

热门文章

  1. PHP用Socket上传图片
  2. Unity 3d 最新下载与安装
  3. linux音乐服务器mpd,OpenWRT中使用mpd作为音频Server及其使用
  4. html设置button水平居中,html的button怎么居中
  5. mysql add months,mysql里有没有类似oracle里的ADD_MONTHS函数,自能的提取间隔的月份...
  6. 监控摄像机常用专业术语解释(二)
  7. ubuntu-CPU频率调节
  8. 明日又天涯——蝶舞萧霞
  9. 如何看电脑内存型号?
  10. 崩坏3服务器维护2月8号,崩坏3版本更新公告 2月8号2.1版本降临