基于FPGA的红外线型学习遥控器

更新时间:2024-03-19 01:29:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

重庆大学本科生课外实践

项目名称:学院: 专业: 指导老师: 实验日期:技术报告

基于FPGA的学习型红外遥控器设计

1

引言

随着人们生活水平的提高,家用电器的种类增多,红外遥控器的种类也随之增加,不同种类的遥控器之间由于采用的编码格式不同,使得不同产品的遥控器不能相互兼容,用户在使用的过程中容易产生混乱,给人们的生活带来诸多不便。

针对这一现况,万能遥控器便应需出现了,目前主要分为两种类型,编码型和学习型。编码型万能遥控器需要各大电器制造商生产的遥控器的控制码编码格式,使用时选定相应机型,遥控器便可提取出其编码,再和38k的载波进行ASK调制便可驱动红外线发射管进行控制信号发射了,但其显著的缺点是使用时需要查询冗长的机器型号手册。相对之下另外一种学习型的万能遥控器机理就比较简单了,其对不同遥控器发出的信号(解调后的信号)进行记录,待控制时调用出存储的信号对载波进行调制,便可驱动红外线发射管发射红外线对设备进行控制了。通过对比这两种万能遥控器的设计方案可知,相对编码型遥控器,自主学习型遥控器原理简单,实现较为方便。

基于此本文尝试着设计了一款基于FPGA的红外线学习型遥控器,主要由FPGA控制模块、红外线接收模块、红外线发射模块和存储模块组成。在本文中详细的给出了设计的原理、技术方案、软硬件的实现过程等,并在附录中给出了各单元电路图、主程序和仿真电路图。

1 设计方案与指标

1.1 设计原理简介

基于FPGA制作一个红外遥控器,并可通过程序控制记忆按键功能,达到遥控器的自主学习功能,其实现原理框图如下:

图1系统框图

由原理框图可知,本设计主要由5个部分组成,FPGA控制器、红外线发射器、红外线接收器、学习遥控指示灯和操作键组成。遥控器自主学习工作进程如

2

下:一、红外线接收器接收红外信号;二、红外接收模块对信号进行放大、检波、整形,解调出基带信号;三、FPGA控制器将解调出的信号的高、低电平的时间宽度进行储存;四、当要发射红外信号时,从储存区中还原出相应的红外遥控编码,以其对38kHz的载波信号进行调制;五、调制出的控制信号驱动红外发光二极管发射红外信号,从而实现对设备的控制。 红外编码解码原理:

遥控发射器专用芯片很多,根据编码格式可以分成两大类,这里我们采用的是NEC类型。当发射器按键按下后,即有遥控码发出,所按的键不同遥控编码也不同。这种遥控码具有以下特征:

采用脉宽调制的串行码,以脉宽为0.565ms、间隔0.56ms、周期为1.125ms的组合表示二进制的“0”;以脉宽为0.565ms、间隔1.685ms、周期为2.25ms的组合表示二进制的“1”,其波形如图2所示。

上述“0”和“1”组成的32位二进制码经38kHz的载频进行二次调制以提高发射效率,达到降低电源功耗的目的。然后再通过红外发射二极管产生红外线向空间发射,如图3所示。

遥控编码是连续的32位二进制码组,其中前16位为用户识别码,能区别不同的电器设备,防止不同机种遥控码互相干扰。该芯片的用户识别码固定为十六进制01H;后16位为8位操作码(功能码)及其反码。遥控器在按键按下后,周期性地发出同一种32位二进制码,周期约为108ms。一组码本身的持续时间随它包含的二进制“0”和“1”的个数不同而不同,大约在45~63ms之间,图4为发射波形图。

当一个键按下超过36ms,振荡器使芯片激活,将发射一组108ms的编码脉冲,这108ms发射代码由一个起始码(9ms),一个结果码(4.5ms),低8位地址码

3

(9ms~18ms),高8位地址码(9ms~18ms),8位数据码(9ms~18ms)和这8位数据的反码(9ms~18ms)组成。如果键按下超过108ms仍未松开,接下来发射的代码(连发代码)将仅由起始码(9ms)和结束码(2.5ms)组成。

解码的关键是如何识别“0”和“1”,从位的定义我们可以发现“0”、“1”均以0.56ms的低电平开始,不同的是高电平的宽度不同,“0”为0.56ms,“1”为1.68ms,所以必须根据高电平的宽度区别“0”和“1”。如果从0.56ms低电平过后,开始延时,0.56ms以后,若读到的电平为低,说明该位为“0”,反之则为“1”,为了可靠起见,延时必须比0.56ms长些,但又不能超过1.12ms,否则如果该位为“0”,读到的已是下一位的高电平,因此取(1.12ms+0.56ms)/2=0.84ms最为可靠,一般取0.84ms左右均可。

根据码的格式,应该等待9ms的起始码和4.5ms的结果码完成后才能读码。 1.2 技术指标

实现对能够通过学习来控制大多数需要红外线控制的设备(如:电视、空调等),并且设备能正确执行控制指令。

2 遥控器硬件组成

2.1 器件的选择

在本设计中,控制模块利用的是手中已有的资源,Altera公司的芯片EP3C10E144C7,红外线发射模块选用Arduino电子积木红外发射模块IR Transmitter,红外线接收模块选用TSOP4838。并且购进了一个组合的红外接收发射模块发射模块,该模块基于940红外发射管,高电平驱动,所需拉电流小,控制简易,应用广泛,接收模块基于HL-A838红外一体化接收头,可接收38KHz的红外信号,并解调成逻辑电平,即收到信号即输出低电平,否则输出高电平。低功耗、宽角度及长距离接收。

4

2.2 PCB板的绘制和投板

3 程序设计

系统的程序设计部分主要有以下几个具体模块电路:按键去抖动、分频模块、红外发射、红外接收、存储模块(各个模块VHDL程序见附录)其系统顶层电路原理图如下所示:

图2 系统顶层设计原理图

5

4设计成果展示

硬件完整电路图片以及操作视频

(视频在文件夹里)

5总结

通过本次设计一个实用的万能遥控器,我们对课题设计的完整流程有了深入的认识,包括项目的选择、资料的收集、元件购买、PCB板的绘制投板、模块程序设计以及报账流程等,最主要的是因为我们的设计程序在网上的相关资料很少,所以我们是自己根据要实现的功能尝试着自己写程序,自己调试,受益匪浅,不仅很好地巩固和理解了课堂理论知识,更为以后做项目参加比赛等积累了很好的经验。同时,4人小组的合作也很成功,经过这次设计懂得了团队协作和正确分工的重要性!

6

6元件清单

名称 贴片电阻 贴片电容 S9013三极管 IR5308C-C-45 HL-A838 排针1*3

数量 150 100 20 20 20 30 单价/元 0.15 0.24 1.85 1.85 3.7 1.85 总计/元 22.5 24 37 37 74 55.5 250 附录

去抖动程序 LIBRARY ieee;

USE ieee.std_logic_1164.all; USE ieee.std_logic_unsigned.all; ENTITY hw_qd IS

PORT(clk : IN STD_LOGIC ; kin : IN STD_LOGIC ; kout : OUT STD_LOGIC); END ENTITY;

7

ARCHITECTURE behav OF hw_qd IS SIGNAL kh,kl:std_logic_vector(3 downto 0); BEGIN

PROCESS(kin, clk) BEGIN

if rising_edge(clk) then if (kin='0') then kl<=kl+1; else kl<=\if; end if; END PROCESS ; PROCESS(kin, clk) BEGIN

if rising_edge(clk) then if (kin='1') then kh<=kh+1; else kh<=\if; end if; END PROCESS ; PROCESS(clk,kh,kl) BEGIN

if rising_edge(clk) then if (kh>\then kout<='1'; elsif (kl>\then kout<='0'; end if; end if; END PROCESS ; END behav;

红外接收程序

library ieee;

use ieee.std_logic_1164.all; entity hw_InfraredPort is port(CLK:in std_logic;--50MHz RST:in std_logic; IRIN:in std_logic; RD:in std_logic; CS:in std_logic; led:out std_logic;

DATA:out std_logic_vector(31 downto 0)); end entity hw_InfraredPort;

architecture one of hw_InfraredPort is type state is(s0,s1,s2,s3,s4); signal sta:state;

signal vData:std_logic_vector(31 downto 0); signal clk_1m:std_logic; --1MHz begin

8

process(CLK)

variable clk_counter:integer range 0 to 25; begin

if(CLK'event and CLK='1')then clk_counter:=clk_counter+1; if(clk_counter=25)then clk_counter:=0; clk_1m<=not clk_1m; end if; end if; end process; process(RST,CLK)

variable step:integer range 0 to 32; variable counter:integer range 0 to 10000; begin

if(RST='0')then sta<=s0;

vData<=X\led<='0';

elsif(clk_1m'event and clk_1m='1')then case sta is when s0=>led<='0'; counter:=0; if(IRIN='0')then sta<=s1; end if;

when s1=>led<='0'; if(IRIN='0')then counter:=counter+1;

elsif(counter>3200)then --time(9ms) > 3.2ms sta<=s2; counter:=0; else sta<=s0; end if;

when s2=>led<='0'; if(IRIN='1')then counter:=counter+1;

if(counter>8000)then --time(4.5ms) > 8ms,back to begin sta<=s0; end if;

elsif(counter<8000)then --time(4.5ms) < 8ms,continue

9

sta<=s3; counter:=0; step:=0; else sta<=s0; end if;

when s3=>led<='1'; if(IRIN='0')then counter:=counter+1;

elsif(counter<1600)then --time(0.56ms)<1.6ms,continue sta<=s4; counter:=0; else sta<=s0; end if;

when s4=>led<='1'; if(IRIN='1')then counter:=counter+1;

if(counter>3200)then --time(1.12ms)>3.2ms,back to begin sta<=s0; DATA<=vData; end if; else

if(counter>800)then --time>0.8ms,get the data 1 vData(step)<='1'; else

vData(step)<='0'; --time<0.8ms,get the data 0 end if; step:=step+1; sta<=s3; counter:=0; end if; end case; end if; end process;

end architecture one; 存储写入程序:

library ieee;

use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; entity hw_address is port(clk:in std_logic;

10

data:in std_logic_vector(31 downto 0); anjian1:in std_logic; anjian2:in std_logic; anjian3:in std_logic;

od:out std_logic_vector(15 downto 0); ad:out std_logic_vector(4 downto 0)); end entity;

architecture behav of hw_address is type state is(s0,s1,s2,s3); signal sta:state;

signal addr:std_logic_vector(4 downto 0); begin ad<=addr;

process(anjian1,anjian2,anjian3,clk) begin

if(anjian1='1'and anjian2='1'and anjian3='1')then sta<=s0; od<=x\addr<=\

elsif(clk'event and clk ='1')then case sta is

when s0=>if(anjian1='0')then od<=x\ addr<=\ sta<=s1;

elsif(anjian2='0')then od<=x\ addr<=\ sta<=s1;

elsif(anjian3='0')then od<=x\ addr<=\ sta<=s1; end if; when s1=>addr<=addr;

od<=data(15 downto 0); sta<=s2; when s2=>addr<=addr+'1';

od<=data(31 downto 16); sta<=s3; when s3=>sta<=s3; end case;

11

end if; end process; 存储读出程序

library ieee;

use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; entity hw_adout is port(clk:in std_logic;

inin:in std_logic_vector(15 downto 0); anjian1:in std_logic; anjian2:in std_logic; anjian3:in std_logic;

output:out std_logic_vector(31 downto 0)); end entity;

architecture behav of hw_adout is type state is(s0,s1,s2,s3); signal sta:state;

signal in1:std_logic_vector(15 downto 0); signal out1:std_logic_vector(31 downto 0); begin in1<=inin; output<=out1; process(anjian1,clk) begin

if(anjian1='1'and anjian2='1'and anjian3='1')then sta<=s0;

out1<=x\

elsif(clk'event and clk ='1')then case sta is when s0=>

out1(15 downto 0)<=in1; sta<=s1; when s1=>if(out1=in1)then sta<=s1; else

out1(15 downto 0)<=in1; sta<=s2; end if; when s2=>if(out1=in1)then sta<=s2; else

out1(31 downto 16)<=in1;

12

sta<=s3; end if; when s3=>sta<=s3; end case; end if; end process; end behav; 红外发射程序

library ieee;

use ieee.std_logic_1164.all;

entity hw_OUTPUT is

port(CLK:in std_logic;--50MHz kin:in std_logic;

DATA:in std_logic_vector(31 downto 0); IROUT:out std_logic); end entity hw_OUTPUT ;

architecture one of hw_OUTPUT is type state is(s0,s1,s2,s3,s4); signal sta:state;

signal clk_1m:std_logic; --1MHz signal clk_38k:std_logic; --38kHz begin process(CLK)

variable clk_counter:integer range 0 to 25; begin

if(CLK'event and CLK='1')then clk_counter:=clk_counter+1; if(clk_counter=25)then clk_counter:=0; clk_1m<=not clk_1m; end if; end if; end process;

process(CLK)

variable clk_counter:integer range 0 to 658; begin

if(CLK'event and CLK='1')then clk_counter:=clk_counter+1; if(clk_counter=658)then

13

clk_counter:=0; clk_38k<=not clk_38k; end if; end if; end process;

process(kin,clk_1m)

variable step:integer range 0 to 32; variable counter:integer range 0 to 100000; begin

if(kin='1')then IROUT<='0'; step:=0; sta<=s1; counter:=0;

elsif(clk_1m'event and clk_1m='1')then case sta is

when s0=>IROUT<='0'; if(counter<100000)then counter:=counter+1; else sta<=s1; counter:=0; end if; when s1=>IROUT<=clk_38k; if(counter<9000)then counter:=counter+1; else sta<=s2; counter:=0; end if; when s2=>IROUT<='0'; if(counter<4500)then counter:=counter+1; else sta<=s3; counter:=0; end if;

when s3=>IROUT<=clk_38k; if(counter<560)then counter:=counter+1; else sta<=s4; counter:=0; end if;

when s4=>IROUT<='0';

14

if(DATA(step)='0')then if(counter<565)then counter:=counter+1; elsif(step<32)then sta<=s3; step:=step+1; counter:=0; else sta<=s0; step:=0; counter:=0; end if;

elsif(DATA(step)='1')then

if(counter<1690)then counter:=counter+1; elsif(step<32)then sta<=s3; step:=step+1; counter:=0; else sta<=s0; step:=0; counter:=0; end if; end if; end case; end if; end process;

end architecture one;

15

本文来源:https://www.bwwdw.com/article/rdv8.html

Top