原创 EasyFPGA030进阶(一)--红外接收

2009-4-7 09:16 3166 5 12 分类: FPGA/CPLD

EasyFPGA030 DIY实验


http://blog.ednchina.com/yicheng/177861/message.aspx


 


1.实验设备<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />


(1)       硬件:PC机,EasyFPGA030实验板,红外接收头,遥控器(具体型号下面介绍)


(2)       软件:Libero


 


2.应用的器件


1)红外接收头


2)遥控器:本文使用的遥控器内部芯片为HS6221


 


3.实验内容


     遥控器使用方便,应用广泛,同时具有长远的发展前景,因此本实验想通过红外接收在FPGA中的应用来说明红外的个别工作原理,希望通过举一反三,使读者能够对红外遥控熟练掌握。


 


4.实验原理


本文使用的遥控器内部使用的芯片为HS6221,因此着重针对其的原理来展开说明,同时据业内人士介绍,很多的数字机顶盒的遥控都适用的。


首先介绍一下接收头,由于是接收、放大一体化,所以接收性能还是比较理想的。实物如下图:


<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" />


0a3c7ee3-9455-4aa2-8a80-b01bce4568f0.jpg


仔细观察一下引脚的排列,只有地,5V电源,数据端,安装十分方便。


硬件就这么简单,接下来就是程序的编写了,当然还要先知道遥控发射数据的格式,然后就是一个相反的过程。


遥控器发射的信号由一串01的二进制代码组成。不同的芯片对01的编码有所不同。通常有曼彻斯特编码和脉冲宽度编码。HS622101采用PWM方法编码,即脉冲宽度调制,<?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />00.56ms低电平和0.565ms高电平组合而成,脉冲宽度为1125ms1056ms低电平和1.69ms高电平组合而成。脉冲宽度为225ms。在编写解码程序时,通过判断脉冲的宽度,即可得到01


HS6221以及同类的芯片的数据格式包括引导码(起始码),用户码(地址码),用户反码(地址反码),数据码,数据反码,编码总共32位,数据反码是数据码反相后的编码,用户反码原理一样,可以用来对数据的纠错。具体格式如下:点击看大图


当我们按下遥控器的按键时,遥控器将发出如上图的一串二进制代码,我们称它为一帧数据。根据各部分的功能。可将它们分为5部分,分别为引导码、用户码、用户反码、数据码、数据反码。遥控器发射代码时,均是低位在前。高位在后。由图中分析可以得到,引导码高电平为9ms,低电平为4.5ms,当接收到此码时,表示一帧数据的开始。FPGA可以准备接收下面的数据。地址码由8位二进制组成,共256种,图中用户反码主要是加强遥控器的可靠性,不同的设备可以拥有不同的地址码。因此,同种编码的遥控器只要设置地址码不同,也不会相互干扰。在同一个遥控器中,所有按键发出的地址码都是相同的。数据码为8位,可编码256种状态,代表实际所按下的键。数据反码是数据码的各位求反,通过比较数据码与数据反码,可判断接收到的数据是否正确。如果数据码与数据反码之间的关系不满足相反的关系,则本次遥控接收有误,数据应丢弃。在同一个遥控器上。所有按键的数据码均不相同。


上面对工作原理粗略的介绍了一下,虽然只停留于理论层面,但这个原理可是放于四海皆准,经过本人实验,无论是单片机还是ACTELALTERAFPGA都是十分适用。下面给出是程序代码:


//**************************IR_CTRL.V*****************************************************


//模块名称:IR_CTRL.V


//功能描述:红外接收模块


//适用范围:HS6221,HS6222,CS6121,包含引导码,地址码,地址反码,数据码,数据反码


//


//版权声明:


//    1)本代码属个人知识产权,保留最终解析权。


//    2)本代码仅供交流学习,未经本人同意不能用于其它用途。


//  


//_______________________________________________________________________________


//


// Created by:                    YI CHENG


// QQ:                                506009199


// Email:                             fsyicheng@21cn.com


// Created date:                  2008-10-29


// Version:                          1.1


//********************************************************************************


module IR_CTRL(clk,IR,OUTDATA,led);


input clk;             //系统时钟


input IR;              //红外接收


output OUTDATA;        //beel


output [7:0]led;       //指示LED


//reg OUTDATA;


assign OUTDATA="IR";    //beel


reg led1;


reg led2;


reg led3;


reg [7:0]led;


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


reg [14:0]divcnt;


reg divclk;


reg [2:0]state;


reg [6:0]cnt;                                   


reg [31:0]datatemp;                               //数据寄存器


reg [4:0]bitcnt;                                  //位计算器


reg ok_flag;                                      //接收完成


 


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


parameter                 guide_down=3'b000,      //引导码


                          guide_up=3'b001,


                          num_down=3'b010,               //数据码接收


                          num_up=3'b011,


                          key=3'b101,


                          num_judge=3'b100;               //01判断状态机


                         


 


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


always@(posedge clk)                //0.125ms


 begin


   if(divcnt==15'd3000)              //50MHz       3125


     begin                                      //48MHz       3000


         divclk=~divclk;


         divcnt=0;


     end


   else


     begin


         divcnt=divcnt+1'b1;


     end


 end


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


 


always @(posedge divclk)


 begin


    case(state)


    guide_down:


      begin


        if(IR==0)


           begin


             cnt<=cnt+1'b1;


             ok_flag<=0;


           end


        if(IR==1)


           begin


             if(cnt>7'd50 && cnt<7'd90)


                 begin


                    cnt<=0;


                    state<=guide_up;


                 end


             else


                 begin


                   cnt<=0;


                   state<=guide_down;


                 end


           end


      end


  


     guide_up:


      begin


        if(IR==1)


           begin


             cnt<=cnt+1'b1;


           end


        if(IR==0)


           begin


             if(cnt>7'd26 && cnt<7'd46)


                 begin


                    cnt<=0;


                    state<=num_down;


                 end


             else


                 begin


                   cnt<=0;


                   state<=guide_down;


                 end


           end


        end


     


      key:


         begin


           state<=num_down;


           cnt<=0;


         end


 


      num_down:


         begin


          if(IR==0)


             begin


                cnt<=cnt+1'b1;


             end


          if(IR==1)


              begin


                  if(cnt<7'd6)


                      begin


                       cnt<=0;


                       state<=num_up;


                      end


                  else


                      begin


                         cnt<=0;


                         state<=guide_down;


                      end                   


               end


         end


        


      num_up:


      begin


        if(IR==1)


           begin


             cnt<=cnt+1'b1;


           end


        if(IR==0)


           begin


             if(cnt<7'd15)


                 begin


                   state<=num_judge;


                 end


             else


                 begin


                   cnt<=0;


                   state<=guide_down;


                 end


           end


        end


 


       num_judge:


        begin           


            if(cnt<7'd6)


               begin


                  datatemp[bitcnt]<=0;


                  cnt<=0;


                     if(bitcnt==5'd31)


                         begin


                           state<=guide_down;


                           bitcnt<=0;


                           ok_flag<=1;


                         end


                      else


                         begin


                           bitcnt<=bitcnt+1'b1;


                           state<=num_down;


                         end


 


               end


             else


               begin


                  datatemp[bitcnt]<=1;


                  cnt<=0;


                     if(bitcnt==5'd31)


                         begin


                           state<=guide_down;


                           bitcnt<=0;


                           ok_flag<=1;


                         end


                      else


                         begin


                           bitcnt<=bitcnt+1'b1;


                           state<=num_down;


                         end


              end


       end


      default:state<=guide_down;


    endcase


 


 end


 


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


always@(posedge ok_flag)


  begin


     case(datatemp)


        32'hF50AF708:                                       //ON/OFF


            begin


              led<=8'b00000001;


            end


        32'hE01FF708:                                       //左右声道


            begin


              led<=8'b00000010;


            end


        32'hF40BF708:                                       //消声


            begin


              led<=8'b00000011;


            end


        32'hFE01F708:                                       //1


            begin


              led<=8'b00000100;


            end


        32'hFD02F708:                                       //2


            begin


              led<=8'b00000101;


            end


        32'hFC03F708:                                       //3


            begin


              led<=8'b00000110;


            end


        32'hFB04F708:                                       //4


            begin


              led<=8'b00000111;


            end


        32'hFA05F708:                                       //5


            begin


              led<=8'b00001000;


            end


        32'hF906F708:                                       //6


            begin


              led<=8'b00001001;


            end


        32'hF807F708:                                       //7


            begin


              led<=8'b00001010;


            end


        32'hF708F708:                                       //8


            begin


              led<=8'b00001011;


            end


        32'hF609F708:                                       //9


            begin


              led<=8'b00001100;


            end


        32'hFF00F708:                                       //0


            begin


              led<=8'b00001101;


            end


        32'hBA45F708:                                       //节目表


            begin


              led<=8'b00001110;


            end


        32'hEF10F708:                                       //清除


            begin


              led<=8'b00001111;


            end


        32'hF10EF708:                                       //返回


            begin


              led<=8'b00010000;


            end


        32'hBF40F708:                                       //喜爱


            begin


              led<=8'b00010001;


            end


        32'hE718F708:                                       //菜单


            begin


              led<=8'b00010010;


            end


        32'hB748F708:                                       //退出


            begin


              led<=8'b00010011;


            end


        32'hEA15F708:                                       //ok


            begin


              led<=8'b00010100;


            end


        32'hEE11F708:                                       //up


            begin


              led<=8'b00010101;


            end


        32'hED12F708:                                       //down


            begin


              led<=8'b00010110;


            end


        32'hEC13F708:                                       //left


            begin


              led<=8'b00010111;


            end


        32'hEB14F708:                                       //right


            begin


              led<=8'b00011000;


            end


        32'hF30CF708:                                       //音量+


            begin


              led<=8'b00011001;


            end


        32'hB946F708:                                       //音量-


            begin


              led<=8'b00011010;


            end


        32'hF00FF708:                                       //频道+


            begin


              led<=8'b00011011;


            end


        32'hE817F708:                                       //频道-


            begin


              led<=8'b11111100;


            end


     default:;


     endcase


       


   


  end


 


 


 


endmodule


 


 


 


       上面的代码均加有注释,因此不再重复讲述,如有疑问欢迎联系本人,大家相互讨论。


把上面的代码放到你自己的实验平台上就可以使用,特别提醒的就是注意一下系统的工作时钟,本人使用的EasyFPGA030板上是48MALTERA1C650M,因此上面提供了两种时钟方案,只要稍微修改一下就可以通用了。


 


 


5.上电实验


    把程序下载到实验板上(注意管脚配置),当你按不同的按键,实验板上的LED就会显示不同的状态,同时蜂鸣器会发出不同的声音,至此实验就证明成功了,当然你可以通过遥控去控制其他的仪器。


 


6.实验总结


实验的难度一般,同时采用了较多的顺序思维,说透一点,就是把单片机的程序搬到FPGA上来,而且,如果比较熟悉单片机的话,可以先用单片机来验证原理的有效性,然后就可以直接把思想保留,修改语言,适应对应的平台就可以了。


附:


如果你曾使用过FUSION的话,那你更方便,因为FUSION可以嵌入MCU的软核,然后使用普通的MCU程序就可以运行了,相比其他的SOPC平台,其优点显而易见。


 


 


 


 


 


 


下例预告:


      下例的内容初定为红外线测障,如果有兴趣的朋友可以提出自己的意见以及方案,本人希望通过网络等交流平台,与大家一起共同学习,交流,实现“分享传递价值”的理念,助人自助,提升自我,实现双赢。


 


联系方式:


QQ      506009199


EMAIL:    fsyicheng@21cn.com

PARTNER CONTENT

文章评论7条评论)

登录后参与讨论

用户212563 2010-2-5 11:53

支持

用户513348 2009-1-1 15:40

谢谢楼主

用户1485490 2008-12-1 10:02

楼主你好,很喜欢你这里的东西.但我找不着protel99cn.zip .楼主可以发一份给我吗?我的邮箱是jiacai13@126.com 谢谢

用户1532875 2008-11-17 10:55

谢谢大家的支持!

用户1448907 2008-11-13 07:52

楼主的精神很值得学习,多多交流

用户18411 2008-11-13 07:52

楼主的精神很值得学习,多多交流

用户1532875 2008-11-5 09:33

谢谢,您们的支持是我前进的动力! 哈哈!

用户461316 2008-11-4 16:00

支持楼主!!!!!

用户46900 2008-4-30 22:02

路过

echo2005 2008-3-31 14:55

这个是大家常见的一些问题,现在感觉还是很有用的啊,希望对大家有用!呵呵
相关推荐阅读
用户1532875 2010-09-08 09:34
2010IIC秋季展-让我失望的盛会
    怀着兴奋的心情踏上2010IIC秋季展会征途,却抱着失落的心情而回,包括IIC展和LED展,好不容易度过了3个小时,我觉得必须通过这个总结来弥补今天的付出,好让我记忆此刻半导体的现状,所以其中...
用户1532875 2010-07-16 22:24
改版
ps:不好意思,忘记了如何把图弄上来,所以大家可以到以下链接去看图。方便大家浏览。   http://blog.ednchina.com/yicheng/0/gallery.aspx  全文再续书接上...
用户1532875 2010-07-16 22:16
CAT4238(LED升压DC-DC)调试记录
近来买了一个4.3寸的TFT屏,本来以为是编程可能会有点麻烦,没想到背光就是第一道门槛,背光电压要达到30V左右,电流大概是25MA,内部是10个串联的LED,对于一个3.3V的系统,不可能为了这个T...
用户1532875 2010-04-25 22:47
DIY烧写工具
        前些日子,接到朋友的使用要求,特然冒出一个点子,倒不如自己做这个相关工具,然后凑些世博路费都不错。于是想到就做。        刚开始,想用万用板简单了事,但后来发觉那样太“山寨”了,...
用户1532875 2010-04-10 14:58
国产化的反思
        近来在调试一个项目的时候,发现了原来的下载工具竟然在下载的时候出现了问题,开始的时候以为是板子的问题,于是又重新焊接了一个新的板子,没想到问题依然存在,于是就找了一个以前的板子,意外地...
用户1532875 2010-03-22 17:25
2010深圳IIC展会
      上周连续两天跑了两个展会,分别是广州的灯光展和深圳的IIC展,今天终于有时间来回顾和总结一下。灯光展就没有什么好说的了,无非今年以及未来几年的重点就是LED照明以及LED广告屏,这些不是我...
EE直播间
更多
我要评论
7
5
关闭 站长推荐上一条 /3 下一条