基于sparant6系列FPGA的小项目设计(3)

基于FPGA的红外遥控解码设计

说明:红外遥控是一种无线、非接触控制技术,具有抗干扰能力强,信息传输可靠,功耗低,成本低,易实现等显著优点。本周开始进行红外遥控解码学习,遥控按键按下发射包含按键信息的红外信号,FPGA通过红外接收传感器接收信号,并进行解码,将信息显示到数码管上。

1.对于这个设计,首先我们要了解红外遥控的编码协议,常见的红外遥控编码协议有:NEC、Philips RC-5、Philips RC-6、Sony SIRC等,而使用用最多的为NEC协议,本次也是解析NEC协议。NEC协议采用的是PPM(Pulse Position Modulation,脉冲位置调制)进行编码。当我们按下遥控器的一个按键时,会发送一帧的数据。这一帧数据由引导码、地址码、地址反码、数据码、数据反码以及一位结束位(可忽略)组成,如下图所示。
在这里插入图片描述
其中9ms的高电平脉冲和之后的4.5ms的低电平组成了引导码。接着后面是地址码及数据码,低位在前,高位在后。最后是562.5um 脉冲突发以表示消息传输的结束。其中地址码加上地址反码的时间和数据码加上数据反码的时间是固定不变的(如数据码为00000111,则数据反码则为11111000),总是由8个“1”和8个“0”组成。

2.由下图可以看出,逻辑“1”由560us的高脉冲加上1.69ms的低电平组成,而逻辑“0”由560us的高脉冲加上560us的低电平组成,并且在查看数据手册了解到,假如长按遥控按键不放,则在发送完数据后,每隔110ms会发送一个重复码,重复码由9ms的高电平和2.25ms的低电平以及560us的高电平(结束标志)组成。
在这里插入图片描述
3.对于FPGA上的红外接收端,接收到的信号输出给FPGA的波形刚好与发送的波形相反。发送高电平,接收后输出就为低电平;发送低电平,接收后输出就为高电平,其波形如下图所示。
在这里插入图片描述

代码实例

1.声明输入输出

module HT6221_rev(
	input sys_clk,
	input rst_n,
	input IR_i,  //红外接收
	
	output reg[31:0]data	//输出到数码管显示
);

2.给输出data赋值
在32位数据接收完成时,flag标志位拉高,同时将数据输出

//给data赋值
always@(posedge sys_clk or negedge rst_n)begin
	if(!rst_n)begin
		data <= 0;
	end
	else begin
		if(flag == 1)begin	//32位数据接收完毕标志
			data <= {temp[23:16],24'h000000};
		end
	end
	
end

3.同步信号,同时利用前面学习的沿检测方法检测前导码电平

//同步外部输入红外信号,预防干扰信号
reg IR_R;
always@(posedge sys_clk or negedge rst_n)begin
	if(!rst_n)begin
		IR_R <= 0;
	end
	else begin
		IR_R <= IR_i;
	end
	
end


//信号边沿检测_缓存IR_R的值
reg IR_key;
always@(posedge sys_clk or negedge rst_n)begin
	if(!rst_n)begin
		IR_key <= 1;
	end
	else begin
		IR_key <= IR_R;
	end
	
end
wire pos_flag;
wire neg_flag;
assign pos_flag = (~IR_key)&IR_R;  //检测上升沿
assign neg_flag = IR_key&(~IR_R);  //检测下降沿

4.根据原理图,首先我们再复位时将flag标志位拉低,复位结束后开始检测前导码,对低电平进行计数,看在上升沿来临之前,低电平持续时间是否够9ms,假如保持时间不够,则可认为是干扰信号,这个时候我们清零计数器,额案后重新检测前导码,直到满足要求,则状态跳转到下一个状态。注意:经过实际测试,由于环境等一些干扰存在,所以在检测计数时并不是一个准确值,而是一个较为准确的范围,只要满足这个计数范围一样可以认定时满足条件。

0:begin		//检测前导码9ms
				flag <= 0;
				if(pos_flag)begin
					if(counter>325000&&counter<495000)begin
						counter <= 0;
						state <= 1;
					end
					else begin	//上升沿到来低电平时间不够为干扰
						counter <= 0;
						state <= 0;
					end
				end
				else begin
					if(IR_R==0)begin
						counter <= counter + 1'b1;
					end
				end
			end

5.前导码9ms检测成功后,继续检测4.5ms高电平前导码,按照前面同样的办法进行检测,直到满足条件则跳转到下一个状态,否则认为时干扰信号,则重新开始检测整个前导码。

1:begin		//检测前导码4.5ms
				if(neg_flag)begin
					if(counter>152500&&counter<277500)begin
						counter <= 0;
						state <= 2;
					end
					else begin	//上升沿到来低电平时间不够为干扰
						counter <= 0;
						state <= 0;
					end
				end
				else begin
					if(IR_R==1)begin
						counter <= counter + 1'b1;
					end
				end
			end

6.接着我们开始检测数据用户地址码和按键数据码,由于不管是“1”还是“0”信息,其前半部分电平均为0.56ms低电平,因此我们在检测完整个前导码之后,继续检测0.56ms低电平,满足条件则跳转到下一个状态,否则认定为干扰,跳回状态0重新检测。

2:begin		//检测数据码低电平0.56ms
				if(pos_flag)begin
					if(counter>20000&&counter<35000)begin
						counter <= 0;
						state <= 3;
					end
					else begin	//上升沿到来低电平时间不够为干扰
						counter <= 0;
						state <= 0;
					end
				end
				else begin
					if(IR_R==0)begin
						counter <= counter + 1'b1;
					end
				end
			end

7.在前面状态都满足后,在此状态继续检测高电平时间即可,假如高电平维持时间为0.56ms,则可认为此时传输信号表示0;假如高电平维持时间为1.69ms,则可认为此时传输信号表示1。然后再跳回状态2重新检测0.56ms低电平,再继续检测高电平,如此往复,直到全部的32位信息接收完毕,我们将flag标志位拉高,同时将接收到的按键数据传输给数码管模块进行显示

3:begin		//检测数据码高电平0.56ms
				if(neg_flag)begin
					if(counter>20000&&counter<35000)begin
						if(num < 31)begin
							counter <= 0;
							temp[num] <= 0;
							num <= num + 1'b1;
							state <= 2;
						end
						else begin
							counter <= 0;
							state <= 0;
							temp[num] <= 0;
							num <= 0;
							flag <= 1;   //32位数据接收完毕标志
						end
					end
					else if(counter>75000&&counter<90000)begin//1.69ms
						if(num < 31)begin
							counter <= 0;
							temp[num] <= 1;
							num <= num + 1'b1;
							state <= 2;
						end
						else begin
							counter <= 0;
							state <= 0;
							temp[num] <= 1;
							num <= 0;
							flag <= 1;   //32位数据接收完毕标志
						end
					end
					else begin	//高低电平延时均不符合,返回重新检测
						counter <= 0;
						state <= 0;
						temp <= 0;
						num <= 0;
					end
				end
				else begin
					if(IR_R==1)begin
						counter <= counter + 1'b1;
					end
				end
			end

红外遥控解码的RTL级视图

在这里插入图片描述
总结:至此整个项目基本设计完毕,其中数码管模块并未给出,此次设计重点在于使用状态机来一步一步实现逻辑控制,在具体的项目设计中使用状态机设计不容易出现逻辑问题,从而大大减轻了调试的问题。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值