原创 FPGA外设篇之红外通信

2014-12-6 19:32 772 10 10 分类: FPGA/CPLD

遥控器发射的信号由一串0 和1 的二进制代码组成。不同的芯片对0 和1 的编码有所不同。通常有曼彻斯特编码和脉冲宽度编码。HS6221 的0 和1 采用PWM 方法编码,即脉冲宽度调制,0 码由0.56ms 低电平和0.565ms 高电平组合而成,脉冲宽度为1.125ms。1码由0.56ms 低电平和1.69ms 高电平组合而成。脉冲宽度为2.25ms。在编写解码程序时,通过判断脉冲的宽度,即可得到0 或1。

HS6221 以及同类的芯片的数据格式包括引导码(起始码),用户码(地址码),用户反码(地址反码),数据码,数据反码,编码总共32 位,数据反码是数据码反相后的编码,用户反码原理一样,可以用来对数据的纠错。具体格式如下:

当我们按下遥控器的按键时,遥控器将发出如上图的一串二进制代码,我们称它为一帧数据。根据各部分的功能。可将它们分为5 部分,分别为引导码、用户码、用户反码、数据码、数据反码。遥控器发射代码时,均是低位在前。高位在后。由图中分析可以得到,引导码高电平为9ms,低电平为4.5ms,当接收到此码时,表示一帧数据的开始。FPGA 可以准备接收下面的数据。地址码由8 位二进制组成,共256 种,图中用户反码主要是加强遥控器的可靠性,不同的设备可以拥有不同的地址码。因此,同种编码的遥控器只要设置地址码不同,也不会相互干扰。在同一个遥控器中,所有按键发出的地址码都是相同的。数据码为8 位,可编码256 种状态,代表实际所按下的键。数据反码是数据码的各位求反,通过比较数据码与数据反码,可判断接收到的数据是否正确。如果数据码与数据反码之间的关系不满足相反的关系,则本次遥控接收有误,数据应丢弃。在同一个遥控器上。所有按键的数据码均不相同。

程序如下:

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer:       jiahua
// 
// Create Date:    15:49:43 10/29/2014 
// Design Name: 
// Module Name:    commuication 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module commuication(
sys_clk ,
sys_rstn ,
data_tx ,
key ,
ir ,
sm_seg ,
sm_bit ,
led
);
 
//////////////////////////////////////////////////////////////////////////////////
input key;
input sys_clk;
input sys_rstn;
input ir;
output [7:0]sm_seg;
output sm_bit;
output data_tx;
output led;
wire key_done;
 
 light_tx u1 (
.sys_clk(sys_clk) ,
.sys_rstn(sys_rstn) ,
.data_tx(data_tx) ,
.key_done(key_done) ,
.send_data(send_data)
);
///////////////////////////////////////////////////////////////////////////////////////
 key u3 (
.sys_clk(sys_clk),
.sys_rstn(sys_rstn),
.key(key),
.key_done(key_done),
 
);
//////////////////////////////////////////////////////////////////////////////
light_dx u2
(
.sys_clk(sys_clk)    ,
  .sys_rstn(sys_rstn)  ,
  .ir(ir)         ,
  .sm_seg(sm_seg)     ,
  .sm_bit(sm_bit)     ,
.r_data(r_data)
  );        
 
///////////////////////////////////////////////////////////////////////////////
 correct u4(
.sys_clk(sys_clk),
.r_data(r_data),
.send_data(send_data),
.led(led)
);
 
 
endmodule
 
 
module correct(
sys_clk,
r_data,
send_data,
led
);
///////////////////////////////////////////////////
input sys_clk;
input [7:0]r_data;
input [7:0]send_data;
output led;
////////////////////////////////////////////////////
 
assign led = (r_data == send_data)? 1'b1:1'b0;
 
endmodule
 
 
 
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: jiahua
// 
// Create Date:    15:49:43 10/13/2014 
// Design Name: 
// Module Name:clock
// Project Name:clock
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
 
module key(
sys_clk,
sys_rstn,
key,
key_done
);
 
/////////////////////////////////////////////////////////////////////////
input sys_clk;
input sys_rstn;
input key;
output key_done;
wire key;
wire key_done;
 
 
////////////////////////////////////////////////////////////////////////
//20ms  50M=20NS 10^6
////////////////////////////////////////////////////////////////////////
parameter  t20ms =  20'd1000_000;
reg [19:0]cnt;
wire key_start;
always@(posedge sys_clk )
begin
if(!sys_rstn)
cnt <= 20'b0;
else if(key_start)
cnt <= 20'b0;
else
cnt <= cnt + 1'b1;
end
////////////////////////////////////////////////////////////////////////
reg key_in;
reg key_in_next;
always@(posedge sys_clk)
if(!sys_rstn)
key_in <= 1'b1;
else 
begin
key_in <= key;
key_in_next <= key_in;
end
 
assign key_start = key_in &(~key_in_next);
 
reg key2_in;
reg key2_in_next;
 
always@(posedge sys_clk)
begin
if(!sys_rstn)
begin
key2_in <= 1'b1;
key2_in_next <= 1'b1;
end
else if(cnt == t20ms)
begin
key2_in <= key_in;
end
else 
key2_in_next <= key2_in;
 
end
///////////////////////////////////////////////////////////
assign key_done= key2_in&(~key2_in_next);
endmodule
 
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:        
// Engineer:       
// 
// Create Date:    11:07:14 02/27/2013 
// Design Name: 
// Module Name:   
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module light_dx
(sys_clk    ,
  sys_rstn   ,
  ir         ,
  sm_seg     ,
  sm_bit     ,
r_data
  );         
//杈撳叆銆佽緭鍑轰俊鍙锋帴鍙e畾涔? 
input          sys_clk    ;
input          sys_rstn   ;
input          ir         ;
output  [7:0]  sm_seg     ;
output         sm_bit     ;
output [7:0]r_data  ;
//瀵勫瓨鍣ㄥ畾涔?             
reg     [7:0]  sm_seg     ;
reg     [9:0]  delay_cnt  ;
reg            div_clk    ;
reg            ir_reg0    ;
reg            ir_reg1    ;
reg     [8:0]  ir_cnt     ;
reg     [4:0]  rec_cnt    ;
reg     [7:0]  key_code   ;
reg     [31:0] data       ;
wire           sm_bit     ;
wire           ir_posedge ;
wire     ir_negedge ;
wire           t_9ms      ;
wire           t_4ms      ;
wire           low        ;
wire           high       ;
assign         t_9ms=((9'd217 < ir_cnt)& (ir_cnt < 9'd297)) ;//257  
assign         t_4ms=((9'd88 < ir_cnt) & (ir_cnt < 9'd168)) ;//128
assign         low=((9'd22 < ir_cnt) & (ir_cnt < 9'd42))  ;// 32
assign         high=((9'd54 < ir_cnt) & (ir_cnt < 9'd74))  ;// 63
assign         ir_posedge=(~ir_reg1)&ir_reg0;
assign         ir_negedge=ir_reg1&(~ir_reg0);
assign         sm_bit = 1'b0;
//鐘舵€佹満瀹氫箟
reg     [7:0]  ir_state   ;
parameter
     idle          =8'h01  ,
  waite_posedge =8'h02  ,
  check_9ms     =8'h04  ,
  waite_negedge =8'h08  ,
  check_4ms     =8'h10  ,
  rec_code      =8'h20  ;
//鏃堕挓鍒嗛
always@(posedge sys_clk or negedge sys_rstn)
begin
if(!sys_rstn)
begin
delay_cnt<=10'd0;
div_clk<=1'b0;
end
else if(delay_cnt==11'd874)
begin
delay_cnt<=10'd0 ;
div_clk<=~div_clk;
end
else
begin
delay_cnt<=delay_cnt+1'b1 ;
div_clk<=div_clk;
end
end
//鎹曟崏绾㈠淇″彿鐨勪笂涓嬫部
always@(posedge div_clk or negedge sys_rstn)
begin
if(!sys_rstn)
begin
ir_reg0<=1'b0;
ir_reg1<=1'b0;
end
else
begin
ir_reg0<=ir;
ir_reg1<=ir_reg0;
end
end
always@(posedge div_clk or negedge sys_rstn)
begin
if(!sys_rstn)
begin
ir_cnt<=9'd0;
rec_cnt<=5'd0;
key_code<=8'h0;
data<=32'h0;
ir_state<=idle;
end
else
begin
case(ir_state)
idle:
begin
if(~ir_reg0)
begin
ir_state<=waite_posedge;
ir_cnt<=9'd0;
rec_cnt<=5'd0;
end
else
ir_state<=idle;
end
waite_posedge:
begin
ir_cnt<=ir_cnt+1'b1;
if(ir_posedge)
ir_state<=check_9ms;
else
ir_state<=waite_posedge;
end
check_9ms:
begin
if(t_9ms)
begin
ir_state<=waite_negedge;
ir_cnt<=9'd0;
end
else
ir_state<=idle;
end
waite_negedge:
begin
ir_cnt<=ir_cnt+1'b1;
if(ir_negedge)
ir_state<=check_4ms;
else
ir_state<=waite_negedge;
end
check_4ms:
begin
if(t_4ms)
begin
ir_state<=rec_code;
ir_cnt<=9'd0;
end
else
ir_state<=idle;
end
rec_code:
begin
ir_cnt<=ir_cnt+1'b1;
if(ir_negedge)
begin
rec_cnt<=rec_cnt+1'b1;  
ir_cnt<=9'd0;
if(low)
data[rec_cnt] <= 1'b0;
else if(high)
data[rec_cnt] <= 1'b1;
else
ir_state<=idle;
if(rec_cnt==5'd31)
begin
ir_state<=idle;
key_code<=data[23:16];
end
end
else
ir_state<=rec_code;
end
default:
ir_state<=idle;
endcase
end
end
assign r_data = data[23:16];
always @(key_code)
begin
case (key_code)  
8'h16 : sm_seg = 8'hc0;   // "0"
8'h0c : sm_seg = 8'hf9;   // "1"
8'h18 : sm_seg = 8'ha4;   // "2"
8'h5e : sm_seg = 8'hb0;   // "3"
8'h08 : sm_seg = 8'h99;   // "4"
8'h1c : sm_seg = 8'h92;   // "5"
8'h5a : sm_seg = 8'h82;   // "6"
8'h42 : sm_seg = 8'hf8;   // "7"
8'h52 : sm_seg = 8'h80;   // "8"
8'h4a : sm_seg = 8'h90;   // "9"
default:
   sm_seg = 8'hc0;   // "0"
endcase 
    end
endmodule
// Create Date:    15:49:43 10/29/2014 
// Design Name: 
// Module Name:    commuication 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module light_tx(
sys_clk,
key_done,
sys_rstn,
data_tx,
send_data
);
 
//////////////////////////////////////////////////////////////////////////////////
input sys_clk;
input key_done;
input sys_rstn;
output [7:0]send_data;
output data_tx;
reg [7:0]send_data;
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//閸掑棝顣剁拋鈩冩殶  50m t=20ns   1101_1011_1011_1010_0000_0   
reg [20:0]count;
reg clear;
parameter t9ms = 21'd449_999;            //450000
parameter t4_5ms = 21'd224_999;  //225000
parameter t1_125ms = 21'd56_249;  //56250
parameter t0_56ms = 21'd27_999;  //28000
parameter t2_25ms = 21'd112_499;  //112500
parameter t1_678ms = 21'd83_899;  //83900
reg [2:0]n;
reg [2:0]m;
always @(posedge sys_clk or negedge sys_rstn)
begin
if(!sys_rstn)
count <= 21'd0;
else if(clear)
count <= 21'd0;
else 
count <= count + 1'b1;
end
//////////////////////////////////////////////////////////////////////////////////
//div 38k  1/38   2.63157894 * 10^-5  s   26.3157us  n=760  1110_1111_0110_0
//50Mhz 20ns 
//1khz 1ms  1100_0011_0101_0000
parameter t1k  = 15'd25000;
parameter t66k = 15'd379; 
parameter t38k = 15'd657;
reg [15:0]cnt_div;
reg div_switch;
reg clk_frequence;
always @(posedge sys_clk)
begin
if(!sys_rstn)
begin
cnt_div <= 16'd0;
clk_frequence <= 1'b1;
end
else if(div_switch)
begin
if(cnt_div == t38k)
clk_frequence = ~clk_frequence;
else
cnt_div <=cnt_div + 1'b1;
end
else
cnt_div <= 16'd0;
end
 
//////////////////////////////////////////////////////////////////////////////////
reg [5:0]state;
//////////////////////////////////////////////////////////////////////////////////
 
reg [7:0]user_data;
reg [2:0]i;
reg [2:0]j;
reg data;
always @(posedge sys_clk)
begin
if(!sys_rstn)
state <= 6'd0;
else
case(state)
6'd0:
//if(key_done)
begin
clear <= 1'b1;
user_data <= 8'b1111_1111;
state <= state + 1'b1;
send_data <= 8'b0000_0001;
div_switch <= 1'b0;
i <= 3'd0;
j <= 3'd0;
n <= 3'd0;
m <= 3'd0;
end
//else
//state <= 6'd0;
6'd1:
begin
if(count == t9ms)
begin
clear <= 1'b1;
state <= state + 1'b1;
div_switch <= 1'b0;
end
else
begin
data <= 1'd1;
clear <= 1'b0;
div_switch <= 1'b0;
end
end
6'd2:
begin
if(count == t4_5ms)
begin
state <= state + 1'b1;
clear <= 1'b1;
div_switch <= 1'b0;
end
else
begin
clear <= 1'b0;
data  <= 1'd0;
div_switch <= 1'b0;
end
end
6'd3,6'd4,6'd5,6'd6,6'd7,6'd8,6'd9,6'd10:  //8娴e秵鏆熼幑
begin
if(user_data == 1'b0)
begin
if(count == t1_125ms)
begin
clear <= 1'b1;
i <= i + 1'b1;
state <= state + 1'b1;
div_switch <= 1'b0;
end
else if(count >= t0_56ms)
begin
clear <= 1'b0;
data <= 1'b0;
div_switch <= 1'b0;
end
else
begin
clear <= 1'b0;
div_switch <= 1'b1;
end
end
else
begin
if(count == t2_25ms)
begin
clear <= 1'b1;
i <= i + 1'b1;
state <= state + 1'b1;
div_switch <= 1'b0;
end
else if(count >= t0_56ms)
begin
data <= 1'b0;
clear <= 1'b0;
div_switch <= 1'b0;
end
else
begin
div_switch <= 1'b1;
clear <= 1'b0;
end
end
 
end
6'd11,6'd12,6'd13,6'd14,6'd15,6'd16,6'd17,6'd18:
begin
if(user_data[j] == 1'b1)
begin
if(count == t1_125ms)
begin
clear <= 1'b1;
j <= j + 1'b1;
state <= state + 1'b1;
div_switch <= 1'b0;
end
else if(count >= t0_56ms)
begin
clear <= 1'b0;
data <= 1'b0;
div_switch <= 1'b0;
end
else
begin
clear <= 1'b0;
div_switch <= 1'b1;
end
end
else
begin
if(count == t2_25ms)
begin
clear <= 1'b1;
j <= j + 1'b1;
state <= state + 1'b1;
div_switch <= 1'b0;
end
else if(count >= t0_56ms)
begin
data <= 1'b0;
clear <= 1'b0;
div_switch <= 1'b0;
end
else
begin
div_switch <= 1'b1;
clear <= 1'b0;
end
end
 
end
6'd19,6'd20,6'd21,6'd22,6'd23,6'd24,6'd25,6'd26:
begin
if(send_data[n] == 1'b0)
begin
if(count == t1_125ms)
begin
clear <= 1'b1;
div_switch <= 1'b0;
n <= n + 1'b1;
state <= state + 1'b1;
end
else if(count >= t0_56ms)
begin
clear <= 1'b0;
data <= 1'b0;
div_switch <= 1'b0;
end
else
begin
clear <= 1'b0;
div_switch <= 1'b1;
end
end
else
begin
if(count == t2_25ms)
begin
clear <= 1'b1;
n <= n + 1'b1;
div_switch <= 1'b0;
state <= state + 1'b1;
end
else if(count >= t0_56ms)
begin
data <= 1'b0;
div_switch <= 1'b0;
clear <= 1'b0;
end
else
begin
div_switch <= 1'b1;
clear <= 1'b0;
end
end
 
end
6'd27,6'd28,6'd29,6'd30,6'd31,6'd32,6'd34,6'd35:
begin
if(send_data[m] == 1'b1)
begin
if(count == t1_125ms)
begin
clear <= 1'b1;
div_switch <= 1'b0;
m <= m + 1'b1;
state <= state + 1'b1;
end
else if(count >= t0_56ms)
begin
clear <= 1'b0;
div_switch <= 1'b0;
data <= 1'b0;
end
else
begin
clear <= 1'b0;
div_switch <= 1'b1;
end
end
else
begin
if(count == t2_25ms)
begin
clear <= 1'b1;
div_switch <= 1'b0;
m <= m + 1'b1;
state <= state + 1'b1;
end
else if(count >= t0_56ms)
begin
data <= 1'b0;
div_switch <= 1'b0;
clear <= 1'b0;
end
else
begin
div_switch <= 1'b1;
clear <= 1'b0;
end
end
 
end
 
6'd36:
begin
if(count == t1_678ms)
begin
clear <= 1'b1;
div_switch <= 1'b0;
data <= 1'b0;
state <= 6'd0;
end
else 
begin
div_switch <= 1'b1;
clear <= 1'b0;
end
end
default:
state <= 6'd0;
endcase
end
assign data_tx = (div_switch == 1'b1)? clk_frequence : data;
 
 
 
endmodule

文章评论0条评论)

登录后参与讨论
我要评论
0
10
关闭 站长推荐上一条 /2 下一条