完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
之前在单片机上加过红外接头,感觉质量不是很好,这次刚好利用一下锆石FPGA板载的红外接头。发货套装里面的遥控器不知道被上一个人搞到哪里去了,手头上有一个友善的遥控器。接下来从代码到效果全面展示一下。 一、概述 首先要获取每个按键对应的编码输出。据说红外的发射频率都是38HKZ左右,那么由50MHZ信号源经过512分频的100Khz左右的时钟来对红外接头的输出进行采样,可以满足二倍频率关系。红外编码脉冲大概如下图: 在低电平高电平的引导码接收之后,通过32位保持时间或长或短的高电平来存储信息。经测试F2键和UP键盘的编码分别如下(令先发射的编码为高位): 11011100001000110101100010100111; 11011100001000111011000001001111; 测试采用signaltap。 二、基本原理 内部的主体是一个计数器,每个采样时钟来临的时候,如果连续为1,则计数器加1,当计数器值高于1000时就认为没有信号,内部复位; 当上一个信号是高而这一个信号是低,说明红外发射出了一个下降沿,此时对比计数结果,如果满足这是一个长电平,将code寄存器组的高位设为1,如果是低电平,设为0;同时code寄存器组的编号num改变,下一次计数之后填写的将是code寄存器组的下一位值。 最终,如果检测到上一个num是31,而当前num是0,说明32位编码全部输出,此时将flag设为1;另外一个always块检测到flag为1,则将code数组和所有键的键值对比,从而将某个键对应的输出位设为1,并在下一个时钟来临时将其设为0。整个模块对外的有效输出就是一个个上升沿。 三、代码及signaltap运行结果 //不再识别引导码; module redline( input clk0, input en, input irda, output key_up, output key_f2); reg key_f2_0; reg key_up_0; reg [4:0]num;//用来标记现在记录的是第几个编号 reg [4:0]num1;//原来的办法是num到了31就操作flag,可是由于num到了31后,还要经过数十个clk采样周期,flag会震荡,导致led闪不回去。 reg [9:0]counter1; reg last_irda; reg [31:0]code; reg flag;//立个flag,如果num走到了倒数第一个,把flag立为1;此周期最后一位编码被读取,在下个周期读取编码并将flag复位; assign key_f2=key_f2_0; assign key_up=key_up_0; assign clk=clk0; always@(posedge clk) begin if((last_irda==1)&&(irda==1)) counter1<=counter1+1; if((last_irda==1)&&(irda==0)) begin counter1<=0; if((counter1>=160)&&(counter1<=170)) begin num<=num+1;code[31-num]<=1;end if((counter1>=50)&&(counter1<=60)) begin num<=num+1;code[31-num]<=0;end end if(counter1>1000) begin counter1<=0; num<=0; end if ((num==0)&&(num1==31)&&(flag==0))flag<=1; else flag<=0; last_irda<=irda; num1<=num; end //根据flag来判断是否识别编码; always@(posedge clk) begin if(flag==1) begin if(code==32'b11011100001000111011000001001111) key_up_0<=1; if(code==32'b11011100001000110101100010100111) key_f2_0<=1; end else begin key_f2_0<=0; key_up_0<=0; end end endmodule module lab4( input ck0, input irda, output reg led1, output reg led2); reg clk; reg en=1; reg [7:0]counter; wire key_up; wire key_f2; always@(posedge ck0) begin counter<=counter+1; if(counter==0)clk<=~clk; end redline u1(clk,en,irda,key_up,key_f2); always@(posedge key_up)led1<=~led1; always@(posedge key_f2)led2<=~led2; endmodule 四、一些说明 代码中没有对引导码进行检测的部分;红外模块设置了一个使能位,但是发现主模块里面单独的一个reg en=1和红外模块是连接不上的,所以就把红外模块里面的en有关项去掉了。 signaltap的采样资源受限于FPGA芯片。如果模块较小的话,可以采用最大的深度也就是2*64k segment,如果需要观测的节点比较多,需要调小一点,这里采用2*4k segment。 最后附上优酷视频效果: https://v.youku.com/v_show/id_XMjk4NDk0NDczMg==.html?spm=a2hzp.8253869.0.0 10秒左右。 |
|
相关推荐
1 个讨论
|
|
你正在撰写讨论
如果你是对讨论或其他讨论精选点评或询问,请使用“评论”功能。
1421 浏览 1 评论
1215 浏览 0 评论
矩阵4x4个按键,如何把识别结果按编号01-16(十进制)显示在两个七段数码管上?
1426 浏览 0 评论
913 浏览 0 评论
2229 浏览 0 评论
1429 浏览 34 评论
5616 浏览 113 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-22 13:28 , Processed in 0.565035 second(s), Total 64, Slave 46 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号