实战篇:基于HT6221的红外遥控解码实现

17 篇文章 6 订阅

本次主要实现红外遥控解码模块的实现,红外模块发送端采用的是HT6221的编码芯片,而在接收端由于红外对管,生成的正好是与发送端电平相反的信号。要实现解码模块程序编写,需先知道协议的过程以及编码的格式,还有模块的输入输出。

1. HT6221介绍

是一款基于红外遥控协议(NEC协议)的遥控编码芯片。一共24个引脚,其PIN定义如下:

When one of the keys (32 or 64 keys) is triggered for over 36ms, the oscillator is enabled and the chip is activated. If the key is pressed and held for 108ms or less, the 108ms transmission codes are enabled and comprised of a header code (9ms), an off code (4.5ms), low byte address codes (9ms~18ms), high byte address codes (9ms~18ms), 8-bit data codes (9ms~18ms), and the inverse codes of the 8-bit data codes (18ms~9ms). After the pressed key is held for 108ms, if the key is still held down, the transmission codes turn out to be a composition of header (9ms) and off codes (2.5ms) only.

To avoid mistakes made by keyboard scanning or simultaneous two-key inputs (except for the three double-key active functions (K21+K22, K21+K23, and K21+K24), the HT6221/HT6222 are facilitated with 36ms starting time. The HT6221/HT6222 also provide three double-key active functions (K21+K22, K21+K23, and K21+K24) for tape deck recording operations.

The double-key operation rules are shown in timing 4 and timing 6. Transmission Codes The transmission codes of the HT6221/HT6222 consist of a 9ms header code, a 4.5ms off code, 16-bit address codes (18ms~36ms), 9ms~18ms 8-bit data codes, and the inverse code of the 8-bit data codes. The following is an illustration of the transmission codes

 

 

如上,NEC协议主要时发送9ms的高电平,然后4.5ms的低电平,然后是地址和数据。其中地址和数据的1,0采用PPM编码,即用不同时长的高低电平表示二进制1,0。

2. 红外解码模块设计

模块接口如下,因为实际接收时,接收头接收到的信号后输出的波形刚好与编码产生的波形相反。因此需要decode模块将这个相反的时序识别出来。

1)计数模块

这里需要产生9ms,4.5ms,0.56ms,1.69ms这四个时间点判断,但由于不同硬件电路,晶振,不同实际场景下这个时间可能不会这么精确,因此需要以包含这个时间前后一段范围的时间段进行判断。

2)代码

整个NEC协议,在识别过程中主要是根据上面的时间点判断协议目前在那个状态,如果在数据传输状态则根据高低电平时间判断传输的是1还是0,然后将数据转换后输出。NEC协议只有4个状态,但是在数据传输这个状态下输出和判断信息比较复杂,所以用三段式的状态机实现。

module decoder_top(
	input clk,rst_n,
	input iIR,
	output wire [15:0]irData,
	output wire [15:0]irAddr,
	output reg end_flag);
	
reg [19:0]tim_cnt;
reg tim_clear;
reg [3:0]main_state;
parameter IDLE   =4'b0000,
			 ST_high=4'b0001,
			 ST_low =4'b0010,
			 ST_data=4'b0100;
			 
reg data_done;
reg [6:0] data_cnt;
reg [31:0]data_r;
assign irAddr=data_r[15:0];
assign irData=data_r[23:16];		 
/*************************************			 
parameter time_9ms=20'd900000;
parameter time_4_5ms=20'd450000;
parameter time_0_56ms=20'd56000;
parameter time_1_68ms=20'd168000;
*************************************/

reg [1:0]iIR_r;
wire iIR_pos_flag,iIR_neg_flag;
assign iIR_pos_flag = (~iIR_r[1] & iIR_r[0])?1'b1:1'b0;
assign iIR_neg_flag = (iIR_r[1] & (~iIR_r[0]))?1'b1:1'b0;
always@(posedge clk or negedge rst_n)begin
	if(~rst_n) iIR_r<=0;
	else begin
		iIR_r[0]<=iIR;
		iIR_r[1]<=iIR_r[0];
		end
	end	
	
always@(posedge clk or negedge rst_n)begin
	if(~rst_n) tim_cnt<=0;
	else if(tim_clear)  tim_cnt<=0;
	else tim_cnt<=tim_cnt+1'b1;
	end
	
always @(posedge clk or negedge rst_n) begin
	if(~rst_n)begin
		main_state<=IDLE;
		tim_clear<=1;
		end
	else if(tim_cnt<20'd500000) begin
		case (main_state)
		IDLE:begin
			if(iIR_neg_flag) begin
				main_state<=ST_high;
				tim_clear<=1;
				end
			else begin
				main_state<=IDLE;
				tim_clear<=0;
				end
			end
		ST_high:begin
			if (iIR_pos_flag)begin
				if (tim_cnt>20'd325000 && tim_cnt<20'd495000) begin
					main_state<=ST_low;
					tim_clear<=1;
					end
				else begin
					main_state<=IDLE;
					tim_clear<=0;
					end
				end
			else begin
				main_state<=ST_high;
				tim_clear<=0;
				end
			end
		ST_low:begin
			if(iIR_neg_flag)begin
				if(tim_cnt>20'd152500 &&tim_cnt<20'd277500)begin
					main_state<=ST_data;
					tim_clear<=1;
					end
				else begin
					main_state<=IDLE;
					tim_clear<=0;
					end
				end
			else begin
				main_state<=ST_low;
				tim_clear<=0;
				end
			end
		ST_data:begin
			if(data_done) begin
				main_state<=IDLE;
				tim_clear<=0;
				end
			else if(iIR_pos_flag)begin
				if(tim_cnt>20'd20000 && tim_cnt<20'd35000)begin
					tim_clear<=1;
					end
				else begin
					main_state<=IDLE;
					tim_clear<=0;
					end
				end
			else if(iIR_neg_flag)begin
				if((tim_cnt>20'd20000 && tim_cnt<20'd35000) || (tim_cnt>20'd75000 && tim_cnt<20'd90000))begin
					tim_clear<=1;
					end
				else begin
					main_state<=IDLE;
					tim_clear<=0;
					end
				end
			else begin
				main_state<=ST_data;
				tim_clear<=0;
				end
			end
			endcase
		end
	end


always @(posedge clk or negedge rst_n)begin
		if(~rst_n)begin
			data_done<=0;
			data_cnt<=0;
			data_r<=0;
			end_flag<=0;
			end
		else if (main_state==IDLE)begin
			data_done<=0;
			end_flag<=0;
			data_r<=0;
			end
		else if (main_state==ST_data) begin
			if(data_cnt==7'd32) begin
				data_cnt<=0;
				data_done<=1;
				end_flag<=1;
				end
			else if(iIR_neg_flag )begin
				if(tim_cnt>20'd20000 && tim_cnt<20'd35000) data_r[data_cnt]<=0;
				if(tim_cnt>20'd75000 && tim_cnt<20'd90000) data_r[data_cnt]<=1;
				data_cnt<=data_cnt+1'b1;
				end
		
			end
		end	
endmodule

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值