您当前的位置: 首页 >  fpga开发

正点原子

暂无认证

  • 0浏览

    0关注

    382博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

【正点原子FPGA连载】第二十六章红外遥控实验 -摘自【正点原子】新起点之FPGA开发指南_V2.1

正点原子 发布时间:2021-11-03 10:53:19 ,浏览量:0

1)实验平台:正点原子新起点V2开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id=609758951113 2)全套实验源码+手册+视频下载地址:http://www.openedv.com/thread-300792-1-1.html 3)对正点原子FPGA感兴趣的同学可以加群讨论:994244016 4)关注正点原子公众号,获取最新资料更新 在这里插入图片描述

第二十六章红外遥控实验

红外遥控是一种无线、非接触控制技术,具有抗干扰能力强、信息传输可靠、功耗低、易实现等显著特点,被诸多电子设备特别是家用电器广泛采用,并越来越多的应用到计算机系统中。本章我们将使用新起点FPGA开发板接收红外遥控器发出的红外信号,并将数据显示在数码管上,如果监测到重复码,则通过LED灯闪烁指示。 本章分为以下几个章节: 2525.1简介 25.2实验任务 25.3硬件设计 25.4程序设计 25.5下载验证 26.1简介 红外遥控是一种无线、非接触控制技术,由于它不具有像无线电遥控那样可以穿过障碍物去控制被控对象的能力,所以同类产品的红外遥控器,可以有相同的遥控频率或编码,而不会隔墙控制或干扰邻居的家用电器,这对于大批量生产以及在家用电器上普及红外遥控器提供了极大的方便。红外遥控器发射出的实际上是一种红外光(红外线),其波长范围在1mm到760nm之间,而人眼可见光的波长范围一般在400nm到760nm之间,所以我们并不能看到红外遥控器发出的红外光,因此对环境的影响很小,也不会影响临近的无线电设备。 红外遥控器的编码目前广泛使用的是:NEC协议和Philips RC-5协议。新起点FPGA开发板配套的遥控器使用的是NEC协议,其逻辑电平编码格式如图 26.1.1所示。 在这里插入图片描述

图 26.1.1 NEC协议逻辑电平编码格式 NEC协议采用PPM调制(Pulse Position Modulation,脉冲位置调制)的形式进行编码,数据的每一位(Bit)脉冲长度为560us,由38KHz的载波脉冲(carrier burst)进行调制,推荐的载波占空比为1/3至1/4。由上图可知,有载波脉冲的地方,其宽度都为560us,而载波脉冲的间隔时间是不同的。逻辑“1”的载波脉冲+载波脉冲间隔时间为2.25ms;逻辑“0”的载波脉冲+载波脉冲间隔时间约为逻辑“1”的一半,也就是1.12ms。 在这里插入图片描述

图 26.1.2 NEC协议的数据传输格式 图 26.1.2为NEC协议的数据传输格式。由图可知,传输数据时低位在前,图中的地址码(Address)为0x59,控制码(Command)为0x16。一个信息的发送由9ms的AGC(自动增益控制)载波脉冲开始,用于在早期的IR红外接收器中设置增益;紧接着是4.5ms的空闲信号;随后是地址码和控制码。地址码和控制码分别传输了两次,第二次传输的地址码和控制码都是反码,用于对地址码和控制码做校验,当然,也可以直接忽略地址码反码和控制码反码。每次信息都是按照同步码(9ms载波脉冲+4.5ms空闲信号)、地址码、地址反码、控制码和控制反码的格式进行传输,因此,单次信息传输的时间是固定不变的。 当红外遥控器上的按键被一直按下时,红外遥控器只会发送一次完整的信息,其后会每隔110ms发送一次重复码(也叫连发码)。重复码的数据格式比较简单,同样是由9ms的AGC(自动增益控制)载波脉冲开始,紧接着是2.25ms的空闲信号,随后是560us的载波脉冲,重复码的数据格式如图 26.1.3和图 26.1.4所示。 在这里插入图片描述

图 26.1.3 重复码的数据格式 在这里插入图片描述

图 26.1.4 一直发送重复码 以上部分是对NEC协议的介绍,也就是红外遥控器发送数据时所遵循的协议规范,接下来我们了解下开发板板载的红外接收头,其型号为HS0038B,实物图和结构框图如图 26.1.5和图 26.1.6所示。 在这里插入图片描述

图 26.1.5 HS0038B实物图 在这里插入图片描述

图 26.1.6 HS0038B结构框图 红外接收头通常被厂家集成在一个元件中,成为一体化红外接收头。内部集成了红外监测二极管、自动增益放大器(AGC)、带通滤波器(Band Pass)、解调器(Demodulator)等电路。红外遥控器发出的信息经38KHz的载频进行二级调制以提高发射效率,达到降低电源功率的目的,然后再经过红外发射二极管产生红外线向空间中发射。红外接收头通过红外监测二极管,将光信号转换成电信号,经过电路调制之后,最终输出可以被FPGA采集的TTL电平信号。这里要注意的一点是,红外接收头内部的三极管电路具有信号反向的功能,也就是将1变为0,0变为1,那么上面的整个协议则电平反过来接收。9ms本来是高电平,那么将变为低电平,以此类推如图 26.1.7所示,接收解码对应的波形是FPGA最终接收到的红外信号。 在这里插入图片描述

图 26.1.7 红外接收解码接收图 下图为红外解码接收到的完整波形。 在这里插入图片描述

图 26.1.8 红外解码接收到的完整波形 从图 26.1.8可以看到,地址码为0,控制码为0x15。在一段时间之后,我们还可以收到几个脉冲,这就是NEC协议规定的重复码(连发码),如果一帧数据发送完毕之后,按键仍然没有放开,则发射重复码,可以通过统计重复码来标记按键按下的长短/次数。 下图是红外遥控的按键对应的键码值。 在这里插入图片描述

图 26.1.9 红外遥控对应的键码值 需要注意的是,上图中右侧的键码值是以十进制数进行显示的。 26.2实验任务 本节实验任务是使用新起点FPGA开发板接收红外遥控器发出的红外信号,并将数据显示在数码管上;如果监测到重复码,则通过LED灯闪烁指示。 26.3硬件设计 HS0038电路原理图如图 26.3.1所示,图中REMOTE_IN信号为红外接收头的电平输出端。 在这里插入图片描述

图 26.3.1 HS0038B电路原理图 本实验的管脚分配如下表所示 表 26.3.1 红外遥控数码管显示实验管脚分配 在这里插入图片描述

remote_in input M15 红外遥控输入信号 因为本节实验用到的管脚基本都是数码管的引脚,在数码管实验章节已经给出了,这里就不再提供TCL约束文件了。 26.4程序设计 根据实验任务可大致规划出控制流程,红外驱动模块解析红外数据,将控制码输出至数码管驱动模块,重复码有效信号输出至LED控制模块。数码管驱动模块将对应的位选和段选信号发送至数码管,使相应的数字显示在数码管上,LED控制模块根据重复码信号控制LED灯的亮灭。系统框图如下所示。 在这里插入图片描述

图 26.4.1 红外遥控实验系统框图 顶层模块原理图如下所示 在这里插入图片描述

图 26.4.2 顶层模块原理图 FPGA顶层(top_remote_rcv)例化了以下两个模块:红外驱动模块(remote_rcv)和数码管动态显示模块(seg_led),实现各模块间信号的交互。 顶层模块代码如下:

1  module top_remote_rcv(
2      input             sys_clk  ,    //系统时钟 
3      input             sys_rst_n,    //系统复位信号,低电平有效
4      input             remote_in,    //红外接收信号
5      output     [5:0]  sel      ,    //数码管位选信号
6      output     [7:0]  seg_led  ,    //数码管段选信号
7      output            led           //led灯
8  );
9  
10 //wire define
11 wire  [7:0]   data       ;
12 wire          repeat_en  ;
13 
14 //*****************************************************
15 //**                    main code
16 //*****************************************************
17 
18 //数码管显示模块
19 seg_led u_seg_led(
20     .clk            (sys_clk),   
21     .rst_n          (sys_rst_n),
22     .sel            (sel),   
23     .seg_led        (seg_led),
24     .data           (data),           //红外数据
25     .point          (6'd0),           //无小数点
26     .en             (1'b1),           //使能数码管
27     .sign           (1'b0)            //无符号显示
28     );
29 
30 //HS0038B驱动模块
31 remote_rcv u_remote_rcv(               
32     .sys_clk        (sys_clk),  
33     .sys_rst_n      (sys_rst_n),    
34     .remote_in      (remote_in),
35     .repeat_en      (repeat_en),                
36     .data_en        (),
37     .data           (data)
38     );
39 
40 led_ctrl  u_led_ctrl(
41     .sys_clk       (sys_clk),
42     .sys_rst_n     (sys_rst_n),
43     .repeat_en     (repeat_en),
44     .led           (led)
45     );
46 
47 endmodule 

顶层模块完成对其他模块的例化,红外驱动模块输出的控制码(data)连接至数码管显示模块,输出的repeat_en(重复码有效信号)连接至LED控制模块。 由本章简介部分介绍的红外传输时序可以发现,红外传输时序非常适合使用状态机来编写。红外驱动模块状态跳转图如下图所示。 在这里插入图片描述

图 26.4.3 红外驱动模块状态跳转图 红外驱动模块使用三段式状态机来解析红外遥控信号,从上图可以比较直观的看到每个状态实现的功能以及跳转都下一个状态的条件。由于一次完整的红外信息和重复码都是以同步码(9ms的低电平)开始,其空闲信号高电平的时间是不一样的,一次完整的红外信息空闲信号高电平时间是4.5ms,而重复码的空闲信号高电平时间是2.25ms。所以我们在st_start_judge状态判断空闲信号高电平的时间,如果时间是4.5ms,则跳转到st_rec_data状态;如果时间是2.25ms,则跳转到st_repeat状态。 红外驱动模块部分代码如下:

1   module remote_rcv(
2       input                  sys_clk   ,  //系统时钟
3       input                  sys_rst_n ,  //系统复位信号,低电平有效
4       
5       input                  remote_in ,  //红外接收信号
6       output    reg          repeat_en ,  //重复码有效信号
7       output    reg          data_en   ,  //数据有效信号
8       output    reg  [7:0]   data         //红外控制码
9       );
10  
11  //parameter define
12  parameter  st_idle           = 5'b0_0001;  //空闲状态
13  parameter  st_start_low_9ms  = 5'b0_0010;  //监测同步码低电平
14  parameter  st_start_judge    = 5'b0_0100;  //判断重复码和同步码高电平(空闲信号)
15  parameter  st_rec_data       = 5'b0_1000;  //接收数据
16  parameter  st_repeat_code    = 5'b1_0000;  //重复码
17  
18  //reg define
19  reg    [4:0]    cur_state      ;
20  reg    [4:0]    next_state     ;
21  
22  reg    [11:0]   div_cnt        ;  //分频计数器
23  reg             div_clk        ;  //分频时钟
24  reg             remote_in_d0   ;  //对输入的红外信号延时打拍
25  reg             remote_in_d1   ;
26  reg    [7:0]    time_cnt       ;  //对红外的各个状态进行计数
27  
28  reg             time_cnt_clr   ;  //计数器清零信号
29  reg             time_done      ;  //计时完成信号
30  reg             error_en       ;  //错误信号
31  reg             judge_flag     ;  //检测出的标志信号 0:同步码高电平(空闲信号)  1:重复码
32  reg    [15:0]   data_temp      ;  //暂存收到的控制码和控制反码
33  reg    [5:0]    data_cnt       ;  //对接收的数据进行计数       
34  
35  //wire define
36  wire            pos_remote_in  ;  //输入红外信号的上升沿
37  wire            neg_remote_in  ;  //输入红外信号的下降沿
38  
39  //*****************************************************
40  //**                    main code
41  //*****************************************************
42  
43  assign  pos_remote_in = (~remote_in_d1) & remote_in_d0;
44  assign  neg_remote_in = remote_in_d1 & (~remote_in_d0);
45  
46  //时钟分频,50Mhz/(2*(3124+1))=8khz,T=0.125ms
47  always @(posedge sys_clk or negedge sys_rst_n  ) begin
48      if (!sys_rst_n) begin
49          div_cnt             
关注
打赏
1665308814
查看更多评论
0.0391s