前言
紅外線(Infrared)是波長(zhǎng)介乎微波與可見(jiàn)光之間的電磁波,波長(zhǎng)在760納米(nm)至1毫米(mm)之間,比紅光長(zhǎng)的非可見(jiàn)光。紅外線遙控是目前使用最廣泛的一種通信和遙控手段。由于紅外線遙控裝置具有體積小、功耗低、功能強(qiáng)、成本低等特點(diǎn),因而,繼彩電、錄像機(jī)之后,在錄音機(jī)、音響設(shè)備、空凋機(jī)以及玩具等其它小型電器裝置上也紛紛采用紅外線遙控?,F(xiàn)在工業(yè)設(shè)備中,也已經(jīng)廣泛在使用。
設(shè)計(jì)原理
紅外遙控系統(tǒng)主要由紅外的發(fā)送裝置和接收裝置組成,發(fā)送裝置可由按鍵,編碼模塊,發(fā)射電路等組成,接收裝置由紅外接收電路,遙控,解碼模塊等組成,此次設(shè)計(jì)我們用到的硬件平臺(tái)式是Altera的DE1_SOC,晶振為50MHZ。
在紅外的編碼中,我們對(duì)1 和 0 的編碼是通過(guò)38KHZ的脈沖來(lái)定義的,在紅外的的編碼中每個(gè)脈沖的為256.25us長(zhǎng)的38KHZ載波頻率(26.3us),對(duì)0,1的脈沖的定義的時(shí)間如下圖:
紅外的數(shù)據(jù)格式為包括引導(dǎo)碼,用戶碼,數(shù)據(jù)碼和數(shù)據(jù)糾錯(cuò)碼,停止位編碼總為32位。數(shù)據(jù)反碼是數(shù)據(jù)碼反相后的編碼,可用于對(duì)數(shù)據(jù)的糾錯(cuò)。此外第二段的用戶碼可以在遙控應(yīng)用電路中設(shè)置為第一段用戶碼的反碼。
數(shù)據(jù)格式如下圖:
一幀數(shù)據(jù)在發(fā)送時(shí)先發(fā)送9MS的高電平,然后發(fā)送4.5MS的低電平的起始位,然后發(fā)送用戶碼,數(shù)據(jù)碼,數(shù)據(jù)反碼。然后再發(fā)送一位的停止位。不發(fā)送數(shù)據(jù)時(shí)數(shù)據(jù)線一直為低。
發(fā)送的時(shí)序圖如下:
接受的時(shí),接收到的時(shí)序和發(fā)送的時(shí)序恰恰相反,如發(fā)送時(shí)先發(fā)送9ms的高,4.5ms的低,接收為接收9ms的低電平,4.5ms低電平。
接收的控制器我們用的時(shí)紅外遙控裝置,按鍵發(fā)送的數(shù)據(jù)如下圖所示:
設(shè)計(jì)框架
設(shè)計(jì)的總框架如下圖:
在設(shè)計(jì)中分頻模塊提供所需要的38KHZ的時(shí)鐘,當(dāng)按鍵按下時(shí)發(fā)送我們的發(fā)送模塊發(fā)送一個(gè)給定的數(shù)值,我用戶碼為8'b0,第二段用戶碼為8'hff,然后發(fā)送給定的數(shù)據(jù)碼,和數(shù)據(jù)反碼。上電后我們的設(shè)計(jì)會(huì)發(fā)一次我們給定的數(shù)據(jù)碼,然后在接受模塊會(huì)接受到其發(fā)送的數(shù)據(jù)并在數(shù)碼管上顯示出來(lái),之后我們可以用我們我的遙控鍵盤(pán)來(lái)發(fā)送數(shù)據(jù),接收模塊接收顯示出來(lái),通過(guò)驗(yàn)證我們接收和發(fā)送的正確。
設(shè)計(jì)代碼
頂層模塊infrared代碼:
module infrared(clk, rst_n, key, tx, seg1, seg2, rx); input clk, rst_n; input key; output tx; input rx; wire [7:0] show_data; output [7:0] seg1,seg2; wire [31:0] data_n; wire clk_38khz; clk_frep clk_frep_dut( .clk(clk), .rst_n(rst_n), .clk_38khz(clk_38khz) ); encode encode_dut( .clk(clk_38khz), .rst_n(rst_n), .d_out(data_n), .key(key) ); tttxxx tx_dut( .clk(clk_38khz), .rst_n(rst_n), .data_n(data_n), .tx(tx), .key(key) ); seg seg01( .clk(clk), .rst_n(rst_n), .seg7(seg1), .data_in(show_data[3:0]) ); seg seg02( .clk(clk), .rst_n(rst_n), .seg7(seg2), .data_in(show_data[7:4]) ); rx_led led_dut( .clk(clk_38khz), .rst_n(rst_n), .rx(rx), .show_data(show_data) ); endmodule
發(fā)送模塊tttxxx代碼:
module tttxxx(clk, rst_n, data_n, tx, key); input clk, rst_n; input key; input [31:0] data_n; output reg tx; reg [31:0] temp; reg [8:0] count; reg [2:0] state; reg data; reg [13:0] num; reg [31:0] d_data; parameter T9ms = 342; //9000/26.3; parameter T4500us = 171; //4500/26.3; parameter T0 = 21; //(1125-562.25)/26.3; parameter T1 = 63; //(2250-562.25)/26.3; parameter T562us = 21; //562.25/26.3; parameter T = 2666; reg T9_flag; reg T45_flag; reg T0_flag; reg T1_flag; reg T9_down; reg T45_down; reg T0_down; reg T1_down; reg [9:0] cnt9; reg [9:0] cnt45; reg [9:0] cnt0; reg [9:0] cnt1; reg [9:0] cnt562; reg t0_clk, t1_clk; always @ (posedge clk) if(!rst_n) begin count <= 0; state <= 0; tx <= 0; data <= 0; num <= 0; temp <= 0; d_data <= {8'b0,8'hff, 8'b10100010, 8'b01011101}; end else case (state) 0 : if(count < 10) begin tx <= 0; count <= count + 1; end else if(!key) begin count <= 0; state <= 1; T9_flag <= 1; tx <= 1; end 1 : if(T9_down) begin state <= 2; T45_flag <= 1; tx <= 0; T9_flag <= 0; end else begin tx <= 1; state <= 1; end 2 : if(T45_down) begin state <= 3; tx <= 0; T45_flag <= 0; end else tx <= 0; 3 : if(count < 32) begin count <= count + 1; if(!d_data[31 - count]) begin T0_flag <= 1; state <= 4; T1_flag <= 0; end else begin T1_flag <= 1; state <= 5; T0_flag <= 0; end end else begin count <= 0; state <= 6; T0_flag <= 0; T1_flag <= 0; end 4 : if(T0_down) begin state <= 3; tx <= 0; end else begin tx <= t0_clk; end 5 : if(T1_down) begin state <= 3; tx <= 0; end else tx <= t1_clk; 6 : if(count < T562us - 1) begin count <= count + 1; tx <= 1; end else begin tx <= 0; end default: state <= 0; endcase always @ (posedge clk) if(!rst_n) begin T9_down <= 0; cnt9 <= 0; end else if (T9_flag) begin if(cnt9 < T9ms - 1) begin T9_down <= 0; cnt9 <= cnt9 + 1; end else begin T9_down <= 1; cnt9 <= 0; end end always @ (posedge clk) if(!rst_n) begin T45_down <= 0; cnt45 <= 0; end else if (T45_flag) begin if(cnt45 < T4500us - 1) begin T45_down <= 0; cnt45 <= cnt45 + 1; end else begin T45_down <= 1; cnt45 <= 0; end end reg [9:0] cnt00; always @ (posedge clk) if(!rst_n) begin t0_clk <= 0; T0_down <= 0; cnt0 <= 0; cnt00 <= 0; end else if (T0_flag) begin if(cnt0 < T562us - 1) begin t0_clk <= 1; cnt0 <= cnt0 + 1; T0_down <= 0; end else begin if(cnt00 < T0 - 1) begin cnt00 <= cnt00 + 1; t0_clk <= 0; T0_down <= 0; end else begin T0_down <= 1; cnt0 <= 0; cnt00 <= 0; end end end reg [9:0] cnt11; always @ (posedge clk) if(!rst_n) begin t1_clk <= 0; T1_down <= 0; cnt1 <= 0; cnt11 <= 0; end else if (T1_flag) begin if(cnt1 < T562us - 1) begin t1_clk <= 1; cnt1 <= cnt1 + 1; T1_down <= 0; end else begin if(cnt11 < T1 - 1) begin cnt11 <= cnt11 + 1; t1_clk <= 0; T1_down <= 0; end else begin T1_down <= 1; cnt1 <= 0; cnt11 <= 0; end end end endmodule?
接收模塊rx_led代碼:
0 module rx_led(clk, rst_n, rx, show_data); 1 2 input clk, rst_n; 3 input rx; 4 output reg [7:0] show_data; 5 6 reg [1:0] state; 7 reg [7:0] cnt; 8 reg temp; 9 reg [9:0] num; 10 reg flag; 11 reg [31:0] data; 12 reg [1:0] state_s; 13 reg flag_x; 14 reg [12:0] count; 15 16 parameter T = 2566; // 一幀數(shù)據(jù)的時(shí)間 17 18 //這個(gè)模塊是中因?yàn)榻邮艿?2位編碼數(shù)據(jù)中,不管是位0還是位1,接受的低電平都是相同的, 19 //我們可以通過(guò)來(lái)判斷高電平的時(shí)間來(lái)確定為位1 還是位0,位’1‘ 1.68MS,位0 562.25us 20 always @ (posedge clk) 21 if(!rst_n) 22 begin 23 num <= 0; 24 data <= 0; 25 state_s <= 0; 26 flag_x <= 0; 27 count <= 0; 28 end 29 else 30 begin 31 case (state_s) 32 0 : if(!rx) //判斷起始位,是否接受=收數(shù)據(jù) 33 begin 34 state_s <= 1; 35 flag_x <= 0; 36 count <= count + 1; 37 end 38 else 39 begin 40 flag_x <= 0; 41 state_s <= 0; 42 count <= count + 1; 43 end 44 45 1 : if(num < (342 + 171 - 1)) //延遲9ms + 4.5ms的起始時(shí)間 46 begin 47 num <= num + 1; 48 state_s <= 1; 49 count <= count + 1; 50 end 51 else 52 begin 53 num <= 0; 54 state_s <= 2; 55 count <= count + 1; 56 end 57 58 2 : if(flag && num < 32) //flag來(lái)的時(shí)候表示接到了位1 ,或者位0, 59 //通過(guò)移位寄存器來(lái)獲取32位數(shù)據(jù) 60 begin 61 data <= {data[30:0],temp}; 62 state_s <= 2; 63 num <= num + 1; 64 count <= count + 1; 65 end 66 else if(num == 32) 67 begin 68 state_s <= 3; 69 num <= 0; 70 count <= count + 1; 71 end 72 else 73 state_s <= 2; 74 75 3 : if(num < 21 - 1) //延遲結(jié)束位的時(shí)間 76 begin 77 num <= num + 1; 78 count <= count + 1; 79 end 80 else 81 begin 82 if(count == T - 1) //延遲一幀數(shù)據(jù)的時(shí)間后,發(fā)送一個(gè)標(biāo)志位 83 begin 84 num <= 0; 85 state_s <= 0; 86 flag_x <= 1; 87 count <= 0; 88 count <= count + 1; 89 end 90 else 91 count <= count + 1; 92 end 93 default: state_s <= 0; 94 endcase 95 end 96 97 always @ (posedge clk) 98 if(!rst_n) 99 begin 100 cnt <= 0; 101 state <= 0; 102 temp <= 0; 103 flag <= 0; 104 end 105 else 106 if(state_s > 1 && state_s < 3) 107 case (state) 108 0 : if(rx) 109 begin 110 cnt <= cnt + 1; 111 state <= 1; 112 flag <= 0; 113 end 114 else 115 begin 116 state <= 0; 117 flag <= 0; 118 end 119 120 1 : if(!rx) 121 begin 122 cnt <= cnt; 123 state <= 2; 124 end 125 else 126 cnt <= cnt + 1; 127 128 2 : if(400 < cnt * 26 && cnt * 26 < 600) //判斷高電平的時(shí)間 129 begin 130 temp <= 0; 131 flag <= 1; 132 state <= 0; 133 cnt <= 0; 134 end 135 else if (1400 < cnt * 26 && cnt * 26 < 1700) //判斷高電平的時(shí)間 136 begin 137 temp <= 1; 138 flag <= 1; 139 state <= 0; 140 cnt <= 0; 141 end 142 else 143 begin 144 state <= 0; 145 cnt <= 0; 146 end 147 default: state <= 0; 148 endcase 149 150 always @ (*) //接收完一幀數(shù)據(jù)后,當(dāng)標(biāo)志位來(lái)的時(shí)候通過(guò)對(duì)數(shù)據(jù)的糾錯(cuò)來(lái)捕獲數(shù)據(jù) 151 //我們接收的數(shù)據(jù)用的是左移,而發(fā)送的時(shí)候先發(fā)的是低位 152 if(!rst_n) 153 show_data <= 0; 154 else if((data[7:0] == ~data[15:8]) && (data[31:24] == ~data[23:16]) && flag_x) 155 begin 156 show_data[0] <= data[15]; 157 show_data[1] <= data[14]; 158 show_data[2] <= data[13]; 159 show_data[3] <= data[12]; 160 show_data[4] <= data[11]; 161 show_data[5] <= data[10]; 162 show_data[6] <= data[9]; 163 show_data[7] <= data[8]; 164 165 end 166 else 167 show_data <= show_data; 168 169 endmodule
數(shù)碼管seg模塊:
0 module seg(clk, rst_n, seg7, data_in); 1 2 input clk; 3 input rst_n; 4 input [3:0] data_in; 5 6 output reg [7:0] seg7; 7 8 9 `define T1ms 50_000 //分頻出1k的時(shí)鐘 10 //`define T1ms 5 11 reg [15:0] count; 12 reg flag; 13 always @ (posedge clk or negedge rst_n) 14 if(!rst_n) 15 begin 16 count <= 15'b0; 17 flag <= 1; 18 end 19 else 20 if(count == `T1ms /2 - 1) 21 begin 22 count <= 15'b0; 23 flag <= ~flag; 24 end 25 else 26 begin 27 count <= count + 1'b1; 28 end 29 30 always @ (posedge flag) 31 if(!rst_n) 32 seg7 <= 8'b1010_0100; 33 else 34 begin 35 case (data_in) 36 0:seg7 <= 8'b1100_0000; 37 1:seg7 <= 8'b1111_1001; 38 2:seg7 <= 8'b1010_0100; 39 3:seg7 <= 8'b1011_0000; 40 4:seg7 <= 8'b1001_1001; 41 5:seg7 <= 8'b1001_0010; 42 6:seg7 <= 8'b1000_0010; 43 7:seg7 <= 8'b1111_1000; 44 8:seg7 <= 8'b1000_0000; 45 9:seg7 <= 8'b1001_0000; 46 10:seg7 <= 8'b1000_1000; 47 11:seg7 <= 8'b1000_0011; 48 12:seg7 <= 8'b1100_0110; 49 13:seg7 <= 8'b1010_0001; 50 14:seg7 <= 8'b1000_0110; 51 15:seg7 <= 8'b1000_1110; 52 default:; 53 endcase 54 end 55 56 endmodule
分頻模塊clk_frep代碼:
0 module clk_frep(clk, rst_n, clk_38khz); 1 2 input clk, rst_n; 3 output reg clk_38khz; 4 5 reg [9:0] count; 6 7 //分頻出紅外模塊所用的38Khz的時(shí)鐘 8 //也可以用占空比為1:3的38khz的時(shí)鐘 9 10 always @ (posedge clk or negedge rst_n) 11 if(!rst_n) 12 begin 13 count <= 0; 14 clk_38khz <= 1; 15 end 16 else if(count == (50_000_000 / 38000 / 2 - 1)) 17 begin 18 clk_38khz <= ~clk_38khz; 19 count <= 0; 20 end 21 else 22 count <= count + 1'd1; 23 24??endmodule仿真測(cè)試
測(cè)試模塊infrared_tb代碼:
0 `timescale 1ns/1ps 1 2 module infrared_tb(); 3 4 reg clk, rst_n; 5 reg key; 6 wire tx; 7 wire [7:0] show_data; 8 9 //因?yàn)槲覀兇a中只發(fā)送一次數(shù)據(jù),所以可以把key一直拉低 10 11 initial begin 12 clk = 1; 13 rst_n = 0; 14 key = 1; 15 16 #100.1 rst_n = 1; 17 18 #200 key = 0; 19 20 end 21 22 always # 10 clk = ~clk; 23 24 infrared dut( 25 .clk(clk), 26 .rst_n(rst_n), 27 .key(key), 28 .tx(tx), 29 .rx(rx), 30 .seg1(seg1), 31 .seg2(seg2) 32 ); 33 34 endmodule
仿真圖:
仿真中我們可以把數(shù)碼管模塊的計(jì)數(shù)器的值改小一點(diǎn),便于仿真。
如圖中所示的我們發(fā)的是32’h00ffa25d,那么數(shù)據(jù)為是8’b1010_0010,那么先發(fā)送時(shí)就時(shí)就按下面的序列開(kāi)始0100_0101接收到的為45,所以工程正確。
審核編輯:劉清
-
FPGA
+關(guān)注
關(guān)注
1629文章
21729瀏覽量
602978 -
控制器
+關(guān)注
關(guān)注
112文章
16332瀏覽量
177803 -
數(shù)碼管
+關(guān)注
關(guān)注
32文章
1882瀏覽量
91062 -
電磁波
+關(guān)注
關(guān)注
21文章
1454瀏覽量
53815 -
紅外遙控系統(tǒng)
+關(guān)注
關(guān)注
0文章
9瀏覽量
7632
原文標(biāo)題:源碼系列:基于FPGA的紅外線遙控系統(tǒng)設(shè)計(jì)(附源工程)
文章出處:【微信號(hào):HXSLH1010101010,微信公眾號(hào):FPGA技術(shù)江湖】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論