发射器为普通的红外遥控器,接收器为1838T(VCC/GND/OUT);
软件协议:NEC(还有一种常用协议,SONY);
协议介绍:
引导码:9ms低电平+4.5ms高电平;
客户代码:C0-C7,C0-C7(反码);
用户码:D0-D7,D0-D7(反码);
停止位:低脉冲(560us);
重复码:若按键时间过长,会在发送完一帧正常数据之后,每隔110ms,发送重复码(9ms电平+2.25ms高电平+停止位);
逻辑电平介绍:
协议中,客户代码和用户代码涉及到逻辑0和逻辑1的问题,其中,逻辑0用560us低电平和560us高电平标识,高电平用560us低电平和1.69ms高电平标识(实际脉宽会存在一些误差)。
码值对应关系
客户代码:每一个遥控器不一样,需要测试;
用户码:数字0到数字9,依次为:
0x16,0x0c,0x18,0x5e,0x08,0x1c,0x5a,0x42,0x52,0x4a
Verilog编程注意事项
逻辑0和逻辑1的持续时间不相同,因此,不可以用等间隔采样的方法实现;
实际信号的上升沿和下降沿都需要一定的时间,设计时需要特别注意,通过检测电平的方式实现时,一定要控制好时钟频率,太快会导致逻辑混乱!!!这一点,及时前仿真、后仿真全都通过,也没有办法验证;
实际测试时发现,很容易引起按键重复的情况,状态机可能会进入意想不到的状态,因此,若不需要处理重复码,需要屏蔽;
具体代码如下:
module IR(clk,rst,ir,led_seg,led_dig,led);
parameter HL = 100;//高低电平
parameter CTN = 400;//重发码
input clk;//系统时钟
input rst;//系统复位
input ir;//红外输入
output reg [7:0] led_seg;//数码管断码
output reg [3:0] led_dig;//数码管位码
output reg led;
reg clk_r;//10us时钟
reg [7:0] clk_r_cnt;//10us时钟计数器
reg [7:0] ir_state;//IR状态机
reg [8:0] delay_cnt;//IR延时计数器
reg [7:0] dat;//IR用户码
always @ (posedge clk or negedge rst) begin//生成10us时钟
if(!rst) begin
clk_r <= 1'b0;
clk_r_cnt <= 8'd0;
end
else begin
if(clk_r_cnt == 250) begin//10us
clk_r_cnt <= 8'd0;
clk_r <= ~clk_r;
end
else begin
clk_r_cnt <= clk_r_cnt + 1;
end
end
end
always @ (posedge clk_r or negedge rst) begin//接收并显示
if(!rst) begin
ir_state <= 8'd0;
led_seg <= 8'd0;
delay_cnt <= 9'd0;
dat <= 8'd0;
led <= 1'b1;
end
else begin
case(ir_state)
//引导
8'd0 : if(ir == 0) ir_state <= ir_state + 1;//9msd
8'd1 : if(ir == 1) ir_state <= ir_state + 1;//4.5ms
//客户代码(前8bit)
8'd2 : if(ir == 0) ir_state <= ir_state + 1;//560us
else delay_cnt <= delay_cnt + 1;
8'd3 : if(ir == 1) begin//剔除重发
if(delay_cnt < CTN) ir_state <= 8'd0;
else ir_state <= ir_state + 1;
delay_cnt <= 9'd0;
end
else delay_cnt <= delay_cnt + 1;
8'd4 : if(ir == 0) ir_state <= ir_state + 1;//560us
8'd5 : if(ir == 1) ir_state <= ir_state + 1;
8'd6 : if(ir == 0) ir_state <= ir_state + 1;//560us
8'd7 : if(ir == 1) ir_state <= ir_state + 1;
8'd8 : if(ir == 0) ir_state <= ir_state + 1;//560us
8'd9 : if(ir == 1) ir_state <= ir_state + 1;
8'd10 : if(ir == 0) ir_state <= ir_state + 1;//560us
8'd11 : if(ir == 1) ir_state <= ir_state + 1;
8'd12 : if(ir == 0) ir_state <= ir_state + 1;//560us
8'd13 : if(ir == 1) ir_state <= ir_state + 1;
8'd14 : if(ir == 0) ir_state <= ir_state + 1;//560us
8'd15 : if(ir == 1) ir_state <= ir_state + 1;
8'd16 : if(ir == 0) ir_state <= ir_state + 1;//560us
8'd17 : if(ir == 1) ir_state <= ir_state + 1;
//客户代码(后8bit)
8'd18 : if(ir == 0) ir_state <= ir_state + 1;//560us
8'd19 : if(ir == 1) ir_state <= ir_state + 1;
8'd20 : if(ir == 0) ir_state <= ir_state + 1;//560us
8'd21 : if(ir == 1) ir_state <= ir_state + 1;
8'd22 : if(ir == 0) ir_state <= ir_state + 1;//560us
8'd23 : if(ir == 1) ir_state <= ir_state + 1;
8'd24 : if(ir == 0) ir_state <= ir_state + 1;//560us
8'd25 : if(ir == 1) ir_state <= ir_state + 1;
8'd26 : if(ir == 0) ir_state <= ir_state + 1;//560us
8'd27 : if(ir == 1) ir_state <= ir_state + 1;
8'd28 : if(ir == 0) ir_state <= ir_state + 1;//560us
8'd29 : if(ir == 1) ir_state <= ir_state + 1;
8'd30 : if(ir == 0) ir_state <= ir_state + 1;//560us
8'd31 : if(ir == 1) ir_state <= ir_state + 1;
8'd32 : if(ir == 0) ir_state <= ir_state + 1;//560us
8'd33 : if(ir == 1) ir_state <= ir_state + 1;
//用户码(前8bit)
8'd34 : if(ir == 0) ir_state <= ir_state + 1;//560us
8'd35 : if(ir == 1) ir_state <= ir_state + 1;
8'd36 : if(ir == 0) begin
ir_state <= ir_state + 1;//560us
dat[0] <= (delay_cnt > HL) ? 1'b1 : 1'b0;
delay_cnt <= 16'd0;
end
else delay_cnt <= delay_cnt + 1;
8'd37 : if(ir == 1) ir_state <= ir_state + 1;
8'd38 : if(ir == 0) begin
ir_state <= ir_state + 1;//560us
dat[1] <= (delay_cnt > HL) ? 1'b1 : 1'b0;
delay_cnt <= 16'd0;
end
else delay_cnt <= delay_cnt + 1;
8'd39 : if(ir == 1) ir_state <= ir_state + 1;
8'd40 : if(ir == 0) begin
ir_state <= ir_state + 1;//560us
dat[2] <= (delay_cnt > HL) ? 1'b1 : 1'b0;
delay_cnt <= 16'd0;
end
else delay_cnt <= delay_cnt + 1;
8'd41 : if(ir == 1) ir_state <= ir_state + 1;
8'd42 : if(ir == 0) begin
ir_state <= ir_state + 1;//560us
dat[3] <= (delay_cnt > HL) ? 1'b1 : 1'b0;
delay_cnt <= 16'd0;
end
else delay_cnt <= delay_cnt + 1;
8'd43 : if(ir == 1) ir_state <= ir_state + 1;
8'd44 : if(ir == 0) begin
ir_state <= ir_state + 1;//560us
dat[4] <= (delay_cnt > HL) ? 1'b1 : 1'b0;
delay_cnt <= 16'd0;
end
else delay_cnt <= delay_cnt + 1;
8'd45 : if(ir == 1) ir_state <= ir_state + 1;
8'd46 : if(ir == 0) begin
ir_state <= ir_state + 1;//560us
dat[5] <= (delay_cnt > HL) ? 1'b1 : 1'b0;
delay_cnt <= 16'd0;
end
else delay_cnt <= delay_cnt + 1;
8'd47 : if(ir == 1) ir_state <= ir_state + 1;
8'd48 : if(ir == 0) begin
ir_state <= ir_state + 1;//560us
dat[6] <= (delay_cnt > HL) ? 1'b1 : 1'b0;
delay_cnt <= 16'd0;
end
else delay_cnt <= delay_cnt + 1;
8'd49 : if(ir == 1) ir_state <= ir_state + 1;
//用户码(后8bit)
8'd50 : if(ir == 0) begin
ir_state <= ir_state + 1;//560us
dat[7] <= (delay_cnt > HL) ? 1'b1 : 1'b0;
delay_cnt <= 16'd0;
end
else delay_cnt <= delay_cnt + 1;
8'd51 : if(ir == 1) ir_state <= ir_state + 1;
8'd52 : if(ir == 0) ir_state <= ir_state + 1;//560us
8'd53 : if(ir == 1) ir_state <= ir_state + 1;
8'd54 : if(ir == 0) ir_state <= ir_state + 1;//560us
8'd55 : if(ir == 1) ir_state <= ir_state + 1;
8'd56 : if(ir == 0) ir_state <= ir_state + 1;//560us
8'd57 : if(ir == 1) ir_state <= ir_state + 1;
8'd58 : if(ir == 0) ir_state <= ir_state + 1;//560us
8'd59 : if(ir == 1) ir_state <= ir_state + 1;
8'd60 : if(ir == 0) ir_state <= ir_state + 1;//560us
8'd61 : if(ir == 1) ir_state <= ir_state + 1;
8'd62 : if(ir == 0) ir_state <= ir_state + 1;//560us
8'd63 : if(ir == 1) ir_state <= ir_state + 1;
8'd64 : if(ir == 0) ir_state <= ir_state + 1;//560us
8'd65 : if(ir == 1) ir_state <= ir_state + 1;
//结束位
8'd66 : if(ir == 0) ir_state <= ir_state + 1;
8'd67 : if(ir == 1) begin
ir_state <= 8'd0;
delay_cnt <= 9'd0;
dat <= 8'd0;
case(dat)
8'h16 : led_seg <= 8'hc0;
8'h0c : led_seg <= 8'hf9;
8'h18 : led_seg <= 8'ha4;
8'h5e : led_seg <= 8'hb0;
8'h08 : led_seg <= 8'h99;
8'h1c : led_seg <= 8'h92;
8'h5a : led_seg <= 8'h82;
8'h42 : led_seg <= 8'hf8;
8'h52 : led_seg <= 8'h80;
8'h4a : led_seg <= 8'h90;
default : led_seg <= 8'h8e;
endcase
end
default : ;
endcase
end
end
endmodule