VHDL Altera 的DE2板中红外接收数据同一按键每次总是不一样

EXPORT_SYMBOL 2013-06-13 01:04:24
我使用的是DE2板,用的时钟频率是50MHz,用的遥控器是ht6221型号的。接收数据是有,但同一按键每次接收到的数据不一样,搞了好久,我采用51单片机的红外解码思想,用状态机来写的vhdl代码如下:希望得到高人的指点迷津,谢谢!
vhdl代码:

------------------------------------------------------------------------------------------------

--date : 2013-06-05
--author :
--ver : 3.0
--模块名称:红外接收控制模块
--功能: 接收红外遥控器的按键数据
--红外遥控器型号:HT6221
--为了准确,对IR接收要进行范围限定以增加稳定性和准确性
--50Mhz的周期为20ns
--引导码:9ms低电平与4.5ms高电平
--位0:0.56ms低电平与0.56ms高电平
--位1:0.56ms低电平与1.68ms高电平
--红外接收解码的关键是根据脉冲宽度来判断是0还是1的
--因为0与1的低电平的脉冲宽度是一样的,所以最主要看高电平的脉冲宽度
--取值:(0.56+1.12)/2 = 0.84 ms 最可靠!
--以0.1ms也即10K(100_000ns)进行脉冲宽度计量(周期越小,准确率越高),则0与1的高电平脉冲宽度计数值范围为:
--0.56ms(560_000ns) : ()
--1.68ms(1680_000ns) : ()
--0.84ms(840_000ns) : (>=8)

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;

-- 实体声明
entity IrDARxdCtrl is
port(
clk_in : in std_logic ;
rst : in std_logic ;--采用异步复位方式(低电平有效)
Ir_in : in std_logic ;
IrDataOut : out std_logic_vector(31 downto 0);--红外接收的一帧数据(包括地址码,地址反码,数据码,数据反码)
err_out : out std_logic --接受数据错误输出
);
end IrDARxdCtrl;

-- IrDARxdCtrl 的结构体系声明
architecture behaviral_IrDARxdCtrl of IrDARxdCtrl is

--定义 Ir_states 为枚举类型,构造符号化状态机
TYPE Ir_states IS ( st_idle ,guide_9ms,guide_4_5ms,data_down,data_up,nextD_down,data_recognize);
SIGNAL curr_state : Ir_states := st_idle ;
--//
--分频用到的计数器
signal divcnt : integer range 0 to 5001 := 0 ;
--分频标志
signal div_flag : std_logic := '0';
--采样次数用到的计数器
signal cnt : integer range 0 to 50 := 0 ;
--接收数据位计数器,每一个按键均发送32位(一帧数据)
signal data_bit_cnt : integer range 0 to 32 := 0;
--接收错误标志
signal error_flag : std_logic := '0';
--接收到的一帧数据
signal frame_data : std_logic_vector(31 downto 0);
--接收完一帧数据通知标志
signal frame_finish_flag : std_logic := '0';
--红外信号输入移位寄存器
SIGNAL IR_DIN_REG : STD_LOGIC_VECTOR(2 DOWNTO 0);


begin
div2500 : process(clk_in,rst)
begin
if(rst = '0')then
divcnt <= 0 ;
div_flag <= '0';
IR_DIN_REG <= "000";
elsif(rising_edge(clk_in))then
IR_DIN_REG <= IR_DIN_REG(1 DOWNTO 0) & Ir_in;
if(divcnt < 5000)then --
divcnt <= divcnt + 1;
div_flag <= '0';
else
div_flag <= '1';
divcnt <= 0 ;
end if;
end if ;
end process div2500 ;

--红处接收有限状态机的时序进程
stateREG : process(div_flag)
begin
if(rst = '0')then
curr_state <= st_idle ; --复位,初始状态为空闲状态
frame_data <= (OTHERS => '0');
data_bit_cnt <= 0 ;
cnt <= 0 ;
frame_finish_flag <= '0'; --一帧数据没接收完成
elsif(rising_edge(div_flag))then
case curr_state is
--空闲状态
when st_idle =>
--{
if(IR_DIN_REG(2) = '0')then --有红外信号(低电平),则转向引导前9ms状态
-- cnt <= cnt + 1 ;
-- if(cnt > 40)then --在空闲状态下采样红外低电平是否确实是处于9ms的低电平引导状态,增强抗干扰能力
-- cnt <= 0 ; --如果确实是处于9ms的低电平引导状态,就开始进入
curr_state <= guide_9ms ;
-- else
-- curr_state <= st_idle ;
-- end if;
else
cnt <= 0 ;
frame_data <= (OTHERS => '0');
frame_finish_flag <= '0';--一帧数据没接收完成
curr_state <= st_idle ;
end if;
--}
--跳过引导前9ms状态
when guide_9ms =>
--{
if(IR_DIN_REG(2) = '1')then
curr_state <= guide_4_5ms ;
else
curr_state <= guide_9ms ;
end if;
--}
--跳过引导后4.5ms状态
when guide_4_5ms =>
--{
if(IR_DIN_REG(2) = '0')then
curr_state <= data_down ;
else
curr_state <= guide_4_5ms ;
end if;
--}
--数据接收低电平状态
when data_down =>
--{
if(IR_DIN_REG(2) = '1')then
cnt <= 0 ;
curr_state <= data_up ;
else
curr_state <= data_down ;
end if;
--}
--数据高电平状态
when data_up =>
--{
if(IR_DIN_REG(2) = '1')then --延时约0.84ms
cnt <= cnt + 1 ;
if(cnt < 6)then
curr_state <= data_up ;
else
cnt <= 0 ;
curr_state <= data_recognize ; --延时时间已到,进入识别状态
end if;
else
cnt <= 0 ;
curr_state <= st_idle ;
end if ;
--}
--数据识别状态(因为0和1的低电平的宽度是一样的,所以根据高电平的宽度来判断)
when data_recognize => --识别接收到的数据是0还是1状态
--{
if(IR_DIN_REG(2) = '1')then
--可以用另一方法实现位移:frame_data(31 downto 1) <= frame_data(30 downto 0);
--又或者是:frame_data <= frame_data(30 downto 0) & '1';
frame_data(data_bit_cnt) <= '1'; --接收到的是1
if(data_bit_cnt = 31)then --完成一帧数据的处理
frame_finish_flag <= '1';
data_bit_cnt <= 0 ;
curr_state <= st_idle ;
else
data_bit_cnt <= data_bit_cnt + 1;
curr_state <= nextD_down ; --进入等待下一位的数据低电平状态
end if ;
else
frame_data(data_bit_cnt) <= '0'; --接收到的是0
if(data_bit_cnt = 31)then --完成一帧数据的处理
frame_finish_flag <= '1';
data_bit_cnt <= 0 ;
curr_state <= st_idle ;
else
data_bit_cnt <= data_bit_cnt + 1;
curr_state <= data_down ;
end if ;
end if;
--}
--等待下一位的数据低电平状态
when nextD_down =>
--{
if(IR_DIN_REG(2) = '0')then
curr_state <= data_down ;
else
curr_state <= nextD_down ;
end if;
--}
--默认状态
when others =>
--{
cnt <= 0 ;
curr_state <= st_idle ;
--}
end case ;
end if;
end process stateREG ;

-- 完成一帧数据处理进程
handle_data : process(frame_finish_flag)
begin
if(rst = '0')then
error_flag <= '0';
IrDataOut <= frame_data ;
elsif(rising_edge(frame_finish_flag))then
IrDataOut <= frame_data ; --输出一帧数据
--对接收到的数据进行纠错
if((frame_data(31 downto 24) /= frame_data(23 downto 16)) or
(frame_data(15 downto 8) /= frame_data(7 downto 0)))then
error_flag <= '1';
else
error_flag <= '0';
end if;
end if;
end process handle_data ;

err_out <= error_flag;

end behaviral_IrDARxdCtrl;

...全文
65 点赞 收藏 回复
写回复
回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
相关推荐
发帖
其他开发语言
创建于2007-08-27

3381

社区成员

其他开发语言 其他开发语言
申请成为版主
帖子事件
创建了帖子
2013-06-13 01:04
社区公告
暂无公告