加入星計(jì)劃,您可以享受以下權(quán)益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴(kuò)散
  • 作品版權(quán)保護(hù)
  • 300W+ 專(zhuān)業(yè)用戶(hù)
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長(zhǎng)期合作伙伴
立即加入
  • 正文
    • 設(shè)計(jì)原理
    • 設(shè)計(jì)框架
    • 設(shè)計(jì)代碼
    • 仿真測(cè)試
  • 推薦器件
  • 相關(guān)推薦
  • 電子產(chǎn)業(yè)圖譜
申請(qǐng)入駐 產(chǎn)業(yè)圖譜

源碼系列:基于FPGA的紅外線(xiàn)遙控系統(tǒng)設(shè)計(jì)(附源工程)

03/27 11:50
3139
閱讀需 27 分鐘
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

大俠好,歡迎來(lái)到FPGA技術(shù)江湖,江湖偌大,相見(jiàn)即是緣分。大俠可以關(guān)注FPGA技術(shù)江湖,在“闖蕩江湖”、"行俠仗義"欄里獲取其他感興趣的資源,或者一起煮酒言歡。

今天給大俠帶來(lái)基于FPGA的紅外線(xiàn)遙控系統(tǒng)設(shè)計(jì),附源碼,獲取源碼,請(qǐng)?jiān)凇癋PGA技術(shù)江湖”公眾號(hào)內(nèi)回復(fù)“紅外線(xiàn)遙控系統(tǒng)設(shè)計(jì)源碼”,可獲取源碼文件。話(huà)不多說(shuō),上貨。

前言

紅外線(xiàn)(Infrared)是波長(zhǎng)介乎微波與可見(jiàn)光之間的電磁波,波長(zhǎng)在760納米(nm)至1毫米(mm)之間,比紅光長(zhǎng)的非可見(jiàn)光。?紅外線(xiàn)遙控是目前使用最廣泛的一種通信和遙控手段。由于紅外線(xiàn)遙控裝置具有體積小、功耗低、功能強(qiáng)、成本低等特點(diǎn),因而,繼彩電、錄像機(jī)之后,在錄音機(jī)、音響設(shè)備、空凋機(jī)以及玩具等其它小型電器裝置上也紛紛采用紅外線(xiàn)遙控?,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)碼,用戶(hù)碼,數(shù)據(jù)碼和數(shù)據(jù)糾錯(cuò)碼,停止位編碼總為32位。數(shù)據(jù)反碼是數(shù)據(jù)碼反相后的編碼,可用于對(duì)數(shù)據(jù)的糾錯(cuò)。此外第二段的用戶(hù)碼可以在遙控應(yīng)用電路中設(shè)置為第一段用戶(hù)碼的反碼。

數(shù)據(jù)格式如下圖:

一幀數(shù)據(jù)在發(fā)送時(shí)先發(fā)送9MS的高電平,然后發(fā)送4.5MS的低電平的起始位,然后發(fā)送用戶(hù)碼,數(shù)據(jù)碼,數(shù)據(jù)反碼。然后再發(fā)送一位的停止位。不發(fā)送數(shù)據(jù)時(shí)數(shù)據(jù)線(xiàn)一直為低。

發(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ù)值,我用戶(hù)碼為8'b0,第二段用戶(hù)碼為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.25us20   always @ (posedge clk)21     if(!rst_n)22       begin23         num <= 0;24         data <= 0;25         state_s <= 0;26         flag_x <= 0;27         count <= 0;28       end29     else30       begin31         case (state_s)32           0  :   if(!rx)            //判斷起始位,是否接受=收數(shù)據(jù)33                 begin34                   state_s <= 1;35                   flag_x <= 0;36                   count <= count + 1;37                 end38               else39                 begin40                   flag_x <= 0;41                   state_s <= 0;42                   count <= count + 1;43                 end44           45           1  :  if(num < (342 + 171 - 1))  //延遲9ms + 4.5ms的起始時(shí)間46                 begin47                   num <= num + 1;48                   state_s <= 1;49                   count <= count + 1;50                 end51               else52                 begin53                   num <= 0;54                   state_s <= 2;55                   count <= count + 1;56                 end57           58           2  :   if(flag && num < 32)    //flag來(lái)的時(shí)候表示接到了位1 ,或者位0,59                             //通過(guò)移位寄存器來(lái)獲取32位數(shù)據(jù)60                 begin61                   data <= {data[30:0],temp};62                   state_s <= 2;63                   num <= num + 1;64                   count <= count + 1;65                 end66               else if(num == 32)67                 begin68                   state_s <= 3;69                   num <= 0;70                   count <= count + 1;71                 end72               else73                 state_s <= 2;74           75           3  :  if(num < 21 - 1)    //延遲結(jié)束位的時(shí)間76                 begin77                   num <= num + 1;78                   count <= count + 1;79                 end80               else81                 begin82                   if(count == T - 1)    //延遲一幀數(shù)據(jù)的時(shí)間后,發(fā)送一個(gè)標(biāo)志位83                     begin84                       num <= 0;85                       state_s <= 0;86                       flag_x <= 1;87                       count <= 0;88                       count <= count + 1;89                     end90                   else91                     count <= count + 1;92                 end93           default: state_s <= 0;94         endcase95       end96       97   always @ (posedge clk)98     if(!rst_n)99       begin100        cnt <= 0;101        state <= 0;102        temp <= 0;103        flag <= 0;104      end105    else106      if(state_s > 1 && state_s < 3)107      case (state)108        0  :   if(rx)    109              begin110                cnt <= cnt + 1;111                state <= 1;112                flag <= 0;113              end114            else115              begin116                state <= 0;117                flag <= 0;118              end119              120        1  :  if(!rx) 121              begin122                cnt <= cnt;123                state <= 2;124              end125            else126              cnt <= cnt + 1;127        128        2  :  if(400 < cnt * 26 &&  cnt * 26 < 600)    //判斷高電平的時(shí)間129              begin130                temp <= 0;131                flag <= 1;132                state <= 0;133                cnt <= 0;134              end135            else if (1400 < cnt * 26 && cnt * 26 < 1700)  //判斷高電平的時(shí)間136              begin137                temp <= 1;138                flag <= 1;139                state <= 0;140                cnt <= 0;141              end142            else143              begin144                state <= 0;145                cnt <= 0;146              end147        default: state <= 0;148      endcase149  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      begin156        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      end166    else167      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  511  reg [15:0] count;12  reg flag;13  always @ (posedge clk or negedge rst_n) 14    if(!rst_n)15      begin16        count <= 15'b0;17        flag <= 1;18      end19    else20      if(count == `T1ms /2 - 1)21        begin22          count <= 15'b0;23          flag <= ~flag;24        end25      else26        begin27          count <= count + 1'b1;28        end29  30  always @ (posedge flag)31    if(!rst_n)32      seg7 <= 8'b1010_0100;33    else34      begin35        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        endcase54      end5556 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      begin13        count <= 0;14        clk_38khz <= 1;15      end16    else if(count == (50_000_000 / 38000 / 2 - 1))17      begin18        clk_38khz <= ~clk_38khz;19        count <= 0;20      end21    else22      count <= count + 1'd1;2324??endmodule

仿真測(cè)試

測(cè)試模塊infrared_tb代碼:

0   `timescale 1ns/1ps1 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 begin12    clk = 1;13    rst_n = 0;14    key = 1;15    16    #100.1 rst_n = 1;17    18    #200  key = 0;    1920  end21  22  always # 10 clk = ~clk;2324  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  );3334 endmodule

仿真圖:?

仿真中我們可以把數(shù)碼管模塊的計(jì)數(shù)器的值改小一點(diǎn),便于仿真。

如圖中所示的我們發(fā)的是32’h00ffa25d,那么數(shù)據(jù)為是8’b1010_0010,那么先發(fā)送時(shí)就時(shí)就按下面的序列開(kāi)始0100_0101接收到的為45,所以工程正確。

推薦器件

更多器件
器件型號(hào) 數(shù)量 器件廠(chǎng)商 器件描述 數(shù)據(jù)手冊(cè) ECAD模型 風(fēng)險(xiǎn)等級(jí) 參考價(jià)格 更多信息
XC7A12T-1CSG325C 1 AMD Xilinx Field Programmable Gate Array, PBGA325, BGA-325
$40.49 查看
ATF22V10C-15PU 1 Microchip Technology Inc IC PLD 10MC 15NS 24DIP

ECAD模型

下載ECAD模型
$1.85 查看
5M80ZE64I5N 1 Altera Corporation Flash PLD, 14ns, 64-Cell, CMOS, PQFP64, 9 X 9 MM, 0.40 MM PITCH, LEAD FREE, PLASTIC, EQFP-64
$3.86 查看

相關(guān)推薦

電子產(chǎn)業(yè)圖譜

任何技術(shù)的學(xué)習(xí)就好比一個(gè)江湖,對(duì)于每一位俠客都需要不斷的歷練,從初入江湖的小白到歸隱山林的隱世高人,需要不斷的自我感悟自己修煉,讓我們一起仗劍闖FPGA乃至更大的江湖。