基于FPGA的红外线型学习遥控器.docx
《基于FPGA的红外线型学习遥控器.docx》由会员分享,可在线阅读,更多相关《基于FPGA的红外线型学习遥控器.docx(12页珍藏版)》请在冰豆网上搜索。
![基于FPGA的红外线型学习遥控器.docx](https://file1.bdocx.com/fileroot1/2023-1/7/9571d4bd-c72a-46b1-b5c2-2da4d5b4073d/9571d4bd-c72a-46b1-b5c2-2da4d5b4073d1.gif)
基于FPGA的红外线型学习遥控器
重庆大学本科生课外实践
技术报告
项目名称:
基于FPGA的学习型红外遥控器设计
学院:
专业:
指导老师:
实验日期:
引言
随着人们生活水平的提高,家用电器的种类增多,红外遥控器的种类也随之增加,不同种类的遥控器之间由于采用的编码格式不同,使得不同产品的遥控器不能相互兼容,用户在使用的过程中容易产生混乱,给人们的生活带来诸多不便。
针对这一现况,万能遥控器便应需出现了,目前主要分为两种类型,编码型和学习型。
编码型万能遥控器需要各大电器制造商生产的遥控器的控制码编码格式,使用时选定相应机型,遥控器便可提取出其编码,再和38k的载波进行ASK调制便可驱动红外线发射管进行控制信号发射了,但其显著的缺点是使用时需要查询冗长的机器型号手册。
相对之下另外一种学习型的万能遥控器机理就比较简单了,其对不同遥控器发出的信号(解调后的信号)进行记录,待控制时调用出存储的信号对载波进行调制,便可驱动红外线发射管发射红外线对设备进行控制了。
通过对比这两种万能遥控器的设计方案可知,相对编码型遥控器,自主学习型遥控器原理简单,实现较为方便。
基于此本文尝试着设计了一款基于FPGA的红外线学习型遥控器,主要由FPGA控制模块、红外线接收模块、红外线发射模块和存储模块组成。
在本文中详细的给出了设计的原理、技术方案、软硬件的实现过程等,并在附录中给出了各单元电路图、主程序和仿真电路图。
1设计方案与指标
1.1设计原理简介
基于FPGA制作一个红外遥控器,并可通过程序控制记忆按键功能,达到遥控器的自主学习功能,其实现原理框图如下:
图1系统框图
由原理框图可知,本设计主要由5个部分组成,FPGA控制器、红外线发射器、红外线接收器、学习遥控指示灯和操作键组成。
遥控器自主学习工作进程如下:
一、红外线接收器接收红外信号;二、红外接收模块对信号进行放大、检波、整形,解调出基带信号;三、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位地址码(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电子积木红外发射模块IRTransmitter,红外线接收模块选用TSOP4838。
并且购进了一个组合的红外接收发射模块发射模块,该模块基于940红外发射管,高电平驱动,所需拉电流小,控制简易,应用广泛,接收模块基于HL-A838红外一体化接收头,可接收38KHz的红外信号,并解调成逻辑电平,即收到信号即输出低电平,否则输出高电平。
低功耗、宽角度及长距离接收。
2.2PCB板的绘制和投板
3程序设计
系统的程序设计部分主要有以下几个具体模块电路:
按键去抖动、分频模块、红外发射、红外接收、存储模块(各个模块VHDL程序见附录)其系统顶层电路原理图如下所示:
图2系统顶层设计原理图
4设计成果展示
硬件完整电路图片以及操作视频
(视频在文件夹里)
5总结
通过本次设计一个实用的万能遥控器,我们对课题设计的完整流程有了深入的认识,包括项目的选择、资料的收集、元件购买、PCB板的绘制投板、模块程序设计以及报账流程等,最主要的是因为我们的设计程序在网上的相关资料很少,所以我们是自己根据要实现的功能尝试着自己写程序,自己调试,受益匪浅,不仅很好地巩固和理解了课堂理论知识,更为以后做项目参加比赛等积累了很好的经验。
同时,4人小组的合作也很成功,经过这次设计懂得了团队协作和正确分工的重要性!
6元件清单
名称
数量
单价/元
总计/元
贴片电阻
150
0.15
22.5
贴片电容
100
0.24
24
S9013三极管
20
1.85
37
IR5308C-C-45
20
1.85
37
HL-A838
20
3.7
74
排针1*3
30
1.85
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;
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<="0000";end if; end if;
END PROCESS ;
PROCESS(kin, clk)
BEGIN
if rising_edge(clk) then
if (kin='1') then kh<=kh+1;
else kh<="0000";end if; end if;
END PROCESS ;
PROCESS(clk,kh,kl)
BEGIN
if rising_edge(clk) then
if (kh>"1100") then kout<='1';
elsif (kl>"0111") 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
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"00000000";
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
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;
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"0000";
addr<="00000";
elsif(clk'event and clk ='1')then
case sta is
when s0=>if(anjian1='0')then
od<=x"0000";
addr<="00001";
sta<=s1;
elsif(anjian2='0')then
od<=x"0000";
addr<="00011";
sta<=s1;
elsif(anjian3='0')then
od<=x"0000";
addr<="00101";
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;
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"00000000";
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;
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
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';
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(s