特权同学

红外解码芯片IRM3638的verilog实现

0
阅读(2936)

最近关注奥运是大事,我的开发板进展放缓,主要原因是在红外编解码这一块卡壳了,没法继续。上来肯定是要先看看电路的:

 

 

       一个是发一个是收,似乎很简单。所以我就想当然的以为它们之间的通信无非就是发1收1发0收0了,然后就有我苦日子了。随送的pdf里是介绍PT2222的通信协议(看后感觉和以前用过的PT2262/2276这对红外编解码芯片通信协议类似),问题也出在看资料不够认真,有些关键的字句没有好好揣摩,导致了理解错误,参考代码也是研究了(还是有些细节没有研究透),当然自己的verilog也没能成功,郁闷了好几天。Download了这个电路里的红外解码芯片的IRM-3638的datasheet,其实给的也很简单,没有详细的介绍。最后在原来的pdf里发现了一句话,然后重新对红外的编解码有一个了解,这才搞定。学了一个教训,任何看似简单的东西越是要细心揣摩(不知哪位高人说过:细节决定成败),绝不能想当然,磨刀不误砍柴功啊,基本通信原理要先弄懂,别急着下手,一步到位是不可能的,但是少走弯路是可以做到的。

       又感悟了一大堆,说说这个红外吧。具体什么叫红外也没什么好说,网上一搜一大堆,相信也没有人没听说过,这里就来讨论基于红外解码芯片IRM-3638的通信。硬件电路上面给了,一发一收,貌似很简单,其实确实不难,复杂问题都在IRM-3638里给你解决了。先说说我开始学习时的认识误区,前面也谈到了,这对芯片是不是发1收1发0收0呢?答案显然不对,这样的协议明显抗干扰效果不佳。实际上,IRM-3638是一个红外解码芯片,内部有晶振。发送端持续发0时,接收端输出的是1,但是发送端持续发1时,接收端可不是输出0,这就用到了晶振。发送时必须用33kHz的载波,也就是约26.3us的时钟周期(高电平持续约8.77us,低电平持续约16.53us的方波),当持续发出这样的载波信号时,接收端经过IRM-3638处理后,最后输出的信号是0。明白了吧,呵呵,实践一下吧!

       以下的Verilog代码是要实现sw1,sw2,sw3三个按键任意键按下时原理不亮的三个LED灯(led_d2,led_d3,led_d4)同时点亮,键值是通过前面介绍的红外对射电路实现传输的。

       Verilog代码:

 

module topirda(clk,rst_n,irda_receive,irda_send,sw1,sw2,sw3,led_d2,led_d3,led_d4);

 

input clk;       //50M主时钟

input rst_n;    //复位信号

input irda_receive;       //红外数据接收端口

output irda_send;         //红外数据发送端口

input sw1;      //按键1

input sw2;      //按键2

input sw3;      //按键3

output led_d2;             //发光二极管2

output led_d3;             //发光二极管3

output led_d4;             //发光二极管4

//------------------------------------------------

              //按键检测部分

reg[19:0] cnt_20ms;    //20ms计数寄存器

reg key_value;             //每20ms检测一次键值,低电平表示按下

 

always @ (posedge clk or negedge rst_n)

       if(!rst_n) cnt_20ms <= 20'd0;

       else cnt_20ms <= cnt_20ms+'b1;

 

always @ (posedge clk or negedge rst_n)

       if(!rst_n) key_value <= 1'b1;

       else if(cnt_20ms == 20'hfffff) key_value <= sw1 & sw2 & sw3;

 

//------------------------------------------------

              //红外编码发送部分

reg[10:0] cnt_1315;     //26.3us计数寄存器,载波周期

 

always @ (posedge clk or negedge rst_n)

       if(!rst_n) cnt_1315 <= 11'd0;

       else if(cnt_1315 < 11'd1315) cnt_1315 <= cnt_1315+1'b1;

       else cnt_1315 <= 11'd0;

 

reg irda_send_r;   //发送数据寄存器

 

always @ (posedge clk or negedge rst_n)

       if(!rst_n) irda_send_r <= 1'b0;

       else if(!key_value)//有键按下时发送载波信号

              if((cnt_1315 >= 11'd0) && (cnt_1315 <= 11'd438)) irda_send_r <= 1'b1;

              else irda_send_r <= 1'b0;

       else irda_send_r <= 1'b0;   //无键按下时持续发送0

 

assign irda_send = irda_send_r;

 

//------------------------------------------------

              //红外接收部分

assign {led_d2,led_d3,led_d4} = irda_receive ? 3'b111:3'b000;

 

endmodule

Baidu
map