[FPGA][红外遥控]驱动程序

一、开发环境

  • Verilog
  • Quartus 13.1
  • Modelsim
  • 基于NEC协议

二、准备工作

2.1、需要具备的知识

  • Verilog的基本语法包括但不限于
  1. case
  2. always
  3. 时钟分频
  4. 状态机
  • 红外线通讯时序

2.2、红外线基础

  • NEC协议的特征
  1. 8位地址和8位指令长度
    地址用来区分不同的红外遥控器,指令是我们主要关注的部分。
  2. 地址和指令都将传输两次
    传输顺序由先到后(地址码-地址反码-控制码-控制反码)这样做主要目的是确保数据的可靠。
  3. 脉冲位置调制
  4. 载波频率是38Khz
  5. 位持续的时间1.125ms以及2.25ms
  • NEC位定义

形象的波形

  • NEC传输协议

形象的波形

三、代码部分

/*Copyright belong to afterdm@qq.com
 *Create data 2020/11/18
 *Last modified data 2020/11/24
 *Version v1.0.0.3
 *Descriptions infrared drive
 *Please delete within 24 hours without special circumstances
*/
module infrared(
	input 				clk,
	input 				rst,
	input 				signal,
	output reg [7:0]	command,
	output reg			repetition
);
//define parameter
/******define state machine*****/
parameter IFDState_setout	= 5'b00001;
parameter IFDState_standard = 5'b00010;
parameter IFDState_select	= 5'b00100;
parameter IFDState_getdata	= 5'b01000;
parameter IFDState_command	= 5'b10000;
/******define time duration*****/
parameter IFDstandard	= 10'd900;
parameter IFDgetdata	= 10'd450;
parameter IFDcommand	= 10'd225;
parameter IFDhivalue	= 10'd168;
parameter IFDlovalue	= 10'd56;
/******define permissible error*/
parameter IFDpermissible = 4'd10;
//define reg
/******define div signal********/
reg divClk;
reg [8:0] divClkCount;
/******define timekeep**********/
reg IFDtimeFlag;
reg [5:0] IFDtimeCount;
/******define state machine*****/
reg [5:0] IFDstate, IFDnextState;
/******define data container****/
reg [5:0] IFDdataCount;
reg [31:0] IFDdata;
//div clk (the input clk is 50M, generate 0.1M = 10vs)
always @(posedge clk or negedge rst) begin
	if(rst == 1'b0) begin
		divClkCount <= 9'b0;
		divClk <= 1'b0;
	end
	else if(divClkCount == 9'd249) begin
		divClkCount <= 9'b0;
		divClk <= ~divClk;
	end
	else begin
		divClkCount <= divClkCount + 1'b1;
	end
end
//state machine
always @(posedge divClk or negedge rst) begin
	if(rst == 1'b0) begin
		IFDstate <= IFDState_setout;
	end
	else begin
		IFDstate <= IFDnextState;
	end
end
//signal duration count
always @(posedge divClk or negedge rst) begin
	if(rst == 1'b0) begin
		IFDtimeCount <= 10'b0;
	end
	else if(IFDtimeFlag == 1'b1) begin
		IFDtimeCount <= IFDtimeCount + 1'b1;
	end
	else begin
		IFDtimeCount <= 10'b0;
	end
end
//handle function
always @(posedge divClk or negedge rst) begin
	if(rst == 1'b0) begin
		IFDtimeFlag <= 1'b0;
		IFDnextState <= IFDState_setout;
		IFDdata <= 32'b0;
		IFDdataCount <= 6'b0;
        command <= 16'd0;
        repetition <= 1'b0;
	end
	else begin
		if(signal == 1'b0) begin
			case(IFDstate)
				IFDState_setout : begin
					IFDtimeFlag <= 1'b1;
					IFDnextState <= IFDState_standard;
				end
				IFDState_select : begin
					IFDtimeFlag <= 1'b0;
					if ((IFDtimeCount > IFDgetdata - IFDpermissible) &&
						(IFDtimeCount < IFDgetdata + IFDpermissible)) begin
						IFDnextState <= IFDState_getdata;
						IFDdata <= 32'b0;
						IFDdataCount <= 6'd0;
					end
					else if((IFDtimeCount > IFDcommand - IFDpermissible) &&
							(IFDtimeCount < IFDcommand + IFDpermissible)) begin
						IFDnextState <= IFDState_command;
						repetition <= 1'b1;
					end
					else begin
						IFDnextState <= IFDState_setout;
					end
				end
				IFDState_getdata : begin
					if(IFDtimeFlag == 1'b1) begin
						IFDtimeFlag <= 1'b0;
						IFDdataCount <= IFDdataCount + 1'b1;
						if ((IFDtimeCount > IFDhivalue - IFDpermissible) &&
							(IFDtimeCount < IFDhivalue + IFDpermissible)) begin
							IFDdata <= {1'b1, IFDdata[31:1]};
						end
						else if((IFDtimeCount > IFDlovalue - IFDpermissible) &&
								(IFDtimeCount < IFDlovalue + IFDpermissible)) begin
							IFDdata <= {1'b0, IFDdata[31:1]};
						end
						else begin
							IFDnextState <= IFDState_setout;
						end
					end
				end
				default : begin
				end
			endcase
		end
		else begin
			case(IFDstate)
				IFDState_setout : begin
					IFDtimeFlag <= 1'b0;
				end
				IFDState_standard : begin
					if ((IFDtimeCount > IFDstandard - IFDpermissible) &&
						(IFDtimeCount < IFDstandard + IFDpermissible)) begin
						IFDnextState <= IFDState_select;
						IFDtimeFlag <= 1'b0;
					end
					else begin
						IFDnextState <= IFDState_setout;
					end
				end
				IFDState_select : begin
					IFDtimeFlag <= 1'b1;
				end
				IFDState_getdata : begin
                    if(IFDdataCount == 6'd32) begin
                        if (((IFDdata[7:0] ^ IFDdata[15:8]) == 8'hff) &&
                            ((IFDdata[23:16] ^ IFDdata[31:24]) == 8'hff)) begin
                            command <= IFDdata[23:16];
                            IFDnextState <= IFDState_setout;
                        end
                        else begin
                            IFDnextState <= IFDState_setout;
                        end
                    end
                    else begin
                        IFDtimeFlag = 1'b1;
                    end
				end
				IFDState_command : begin
					repetition <= 1'b0;
					IFDnextState <= IFDState_setout;
				end
				default : begin
				end
			endcase
		end
	end
end
endmodule

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

永恒盛夏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值