大港油田建设网站,重庆在线课程开放平台,天津重型网站建设推荐,母版页做网站例子一、NEC简介 红外(Infrared#xff0c;IR)遥控是一种无线、非接触控制技术#xff0c;常用于遥控器、无线键盘、鼠标等设备之间的通信。IR协议的工作原理是#xff0c;发送方通过红外线发送一个特定的编码#xff0c;接收方通过识别该编码来执行相应的操作。 IR协议是指红外…一、NEC简介 红外(InfraredIR)遥控是一种无线、非接触控制技术常用于遥控器、无线键盘、鼠标等设备之间的通信。IR协议的工作原理是发送方通过红外线发送一个特定的编码接收方通过识别该编码来执行相应的操作。 IR协议是指红外线通信协议的总称而NEC协议是IR协议中的一种具体实现。红外遥控系统分为发射和接收两部分发射部分的发射元件为红外发光二极管它发出的是红外线而不是可见光接收电路的红外接收管是一种光敏二极管。 二、NEC传输格式 NEC协议采用PPM(Pulse Position Modulation脉冲位置调制)的形式进行编码数据的每一位(Bit)脉冲长度为560us由38KHz的载波脉冲 (carrier burst) 进行调制推荐的载波占空比为 1/3至 1/4。有载波脉冲的地方其宽度都为 560us而载波脉冲的间隔时间是不同的。 逻辑“1”的载波脉冲载波脉冲间隔时间为2.25ms逻辑“0”的载波脉冲载波脉冲间隔时间为逻辑“1”的一半即1.125ms. 每次信息都是按照引导码 (9ms载波脉冲4.5ms 空闲信号)地址码、地址反码、控制码和控制反码的格式进行传输因此单次信息传输的时间是固定不变的。 当红外遥控器上的按键被一直按下时红外遥控器只会发送一次完整的信息其后会每隔 110ms 发送一次重复码(连发码)。重复码的数据格式比较简单同样是由 9ms的载波脉冲开始紧接着是2.25ms的空闲信号随后是560us的载波脉冲。 红外接收头通常被厂家集成在一个元件中成为一体化红外接收头。红外接收头内部的三极管电路具有信号反向的功能也就是将1变为00变为1即数据0是0.56ms的低电平和0.56ms的高电平数据1是0.5ms的低电平和1.69ms的高电平9ms是高电平变为低电平。 三、FPGA实现
通过三段式状态机实现红外驱动模块 module ir_rcv(input clk , //系统时钟input rst_n , //系统复位信号低电平有效input remote_in , //红外接收信号output reg repeat_en , //重复码有效信号output reg data_en , //数据有效信号output reg [7:0] data //红外控制码);//parameter define
parameter idle 5b0_0001; //空闲状态
parameter start_low_9ms 5b0_0010; //监测同步码低电平
parameter start_judge 5b0_0100; //判断重复码和同步码高电平(空闲信号)
parameter rec_data 5b0_1000; //接收数据
parameter repeat_code 5b1_0000; //重复码//reg define
reg [4:0] cur_state ; //当前状态
reg [4:0] next_state ; //下一状态reg [11:0] div_cnt ; //分频计数器
reg div_clk ; //分频时钟
reg remote_in_d0 ; //对输入的红外信号延时打拍
reg remote_in_d1 ;
reg [7:0] time_cnt ; //对红外的各个状态进行计数reg time_cnt_clr ; //计数器清零信号
reg time_done ; //计时完成信号
reg error_en ; //错误信号
reg judge_flag ; //检测出的标志信号 0:同步码高电平(空闲信号) 1:重复码
reg [15:0] data_temp ; //暂存收到的控制码和控制反码
reg [5:0] data_cnt ; //对接收的数据进行计数 //wire define
wire ir_pos ; //输入红外信号的上升沿
wire ir_neg ; //输入红外信号的下降沿//*****************************************************
//** main code
//*****************************************************assign ir_pos (~remote_in_d1) remote_in_d0;
assign ir_neg remote_in_d1 (~remote_in_d0);//对50MHz时钟进行分频,50Mhz/(2*(31241))8khz,T0.125ms得到一个周期为0.125ms(8KHz)的时钟
//对时钟进行分频是因为红外信号接收的过程用时较长如果使用50Mhz的时钟采样内部定义的计数器位宽会比较大也可以分频成其它频率的时钟
always (posedge clk or negedge rst_n ) beginif (!rst_n) begindiv_cnt 12d0;div_clk 1b0;end else if(div_cnt 12d3124) begindiv_cnt 12d0;div_clk ~div_clk;end elsediv_cnt div_cnt 12b1;
end//对红外的各个状态进行计数例如监测同步码低电平、判断重复码和同步码高电平等
always (posedge div_clk or negedge rst_n) beginif(!rst_n)time_cnt 8b0;else if(time_cnt_clr)time_cnt 8b0;else time_cnt time_cnt 8b1;
end //对输入的remote_in信号延时打拍即在一个时钟周期内获取两个不同的红外信号采样值以便后续的上升沿和下降沿检测
always (posedge div_clk or negedge rst_n) beginif(!rst_n) beginremote_in_d0 1b0;remote_in_d1 1b0;endelse beginremote_in_d0 remote_in;remote_in_d1 remote_in_d0;end
end//采用三段式状态机对红外信号进行解析
always (posedge div_clk or negedge rst_n) beginif(!rst_n)cur_state idle;elsecur_state next_state ;
endalways (*) beginnext_state idle; case(cur_state)idle : begin //默认在空闲状态time_cnt_clr的值置为1time_cnt也就为0if(remote_in_d0 1b0) //在空闲状态中检测到下降沿则进入9ms低电平判断next_state start_low_9ms; //此时time_cnt_clr的值置为0time_cnt开始计数elsenext_state idle; //否则一直保持空闲状态endstart_low_9ms : begin //监测同步码低电平if(time_done) //计数达到9ms跳转判断重复码和同步码高电平next_state start_judge;else if(error_en) //计数不在9ms范围发生错误跳转到空闲状态next_state idle;elsenext_state start_low_9ms; //否则一直保持在start_low_9msendstart_judge : begin //判断重复码和同步码高电平(空闲信号)if(time_done) beginif(judge_flag 1b0) //如果是同步码则跳转到接收数据状态next_state rec_data;else next_state repeat_code; //否则跳转到重复码状态endelse if(error_en)next_state idle;elsenext_state start_judge;endrec_data : begin //接收数据当数据传输完成跳转到空闲状态if(ir_pos data_cnt 6d32) next_state idle;elsenext_state rec_data; endrepeat_code : begin //重复码if(ir_pos)next_state idle; //进入空闲状态elsenext_state repeat_code; end default : next_state idle;endcase
endalways (posedge div_clk or negedge rst_n ) begin if (!rst_n) begin time_cnt_clr 1b0;time_done 1b0;error_en 1b0;judge_flag 1b0;data_en 1b0;data 8d0;repeat_en 1b0;data_cnt 6d0;data_temp 32d0;endelse begintime_cnt_clr 1b0;time_done 1b0;error_en 1b0;repeat_en 1b0;data_en 1b0;case(cur_state)idle : begintime_cnt_clr 1b1;if(remote_in_d0 1b0)time_cnt_clr 1b0;end start_low_9ms : begin //9ms/0.125ms 72if(ir_pos) begin //当检测到ir_pos(红外信号上升沿)为高电平时说明此时红外信号拉高即同步码低电平结束time_cnt_clr 1b1; //停止计数 if(time_cnt 69 time_cnt 75) //判断time_cnt的值是否接近9ms如果接近9ms跳转到start_judee状态time_done 1b1; else //如果time_cnt的值不接近9ms则发生了错误跳转到空闲状态error_en 1b1;end endstart_judge : beginif(ir_neg) begin time_cnt_clr 1b1; if(time_cnt 15 time_cnt 20) begin //重复码高电平2.25ms 2.25/0.125 18time_done 1b1;judge_flag 1b1; //检测出是重复码跳转到repeat_code重复码状态end else if(time_cnt 33 time_cnt 38) begin //同步码高电平4.5ms 4.5/0.125 36time_done 1b1;judge_flag 1b0; //检测出是同步码跳转到rec_data接收数据状态 endelseerror_en 1b1;end endrec_data : begin if(ir_pos) begin //当有红外信号上升沿time_cnt_clr 1b1;if(data_cnt 6d32) begin //有32个数据即32个上升沿或下降沿分别为16位地址码以及16位数据data_en 1b1; //当计数到32即数据传输完成data_cnt 6d0;data_temp 16d0;if(data_temp[7:0] ~data_temp[15:8]) //校验控制码和控制反码data data_temp[7:0];endendelse if(ir_neg) begin //当有红外信号下降沿time_cnt_clr 1b1;data_cnt data_cnt 1b1; //每当1bit数据到来时也就是一个下降沿到来时数据位数计数器加1//解析控制码和控制反码判断是560us还是1690us计数完成进而得到这个数据位是0还是1 if(data_cnt 6d16 data_cnt 6d31) begin if(time_cnt 2 time_cnt 6) begin //0.565/0.125 4.52data_temp {1b0,data_temp[15:1]}; //逻辑“0”endelse if(time_cnt 10 time_cnt 15) //1.69/0.125 13.52data_temp {1b1,data_temp[15:1]}; //逻辑“1”endendendrepeat_code : begin if(ir_pos) begin time_cnt_clr 1b1;repeat_en 1b1;endenddefault : ;endcaseend
endendmodule