如何设计红外线遥控系统?

电子说

1.3w人已加入

描述

设计背景:

红外线(Infrared)是波长介乎微波与可见光之间的电磁波,波长在760纳米(nm)至1毫米(mm)之间,比红光长的非可见光。 红外线遥控是目前使用最广泛的一种通信和遥控手段。由于红外线遥控装置具有体积小、功耗低、功能强、成本低等特点,因而,继彩电、录像机之后,在录音机、音响设备、空凋机以及玩具等其它小型电器装置上也纷纷采用红外线遥控。现在工业设备中,也已经广泛在使用。

设计原理:

红外遥控系统主要由红外的发送装置和接收装置组成,发送装置可由按键,编码模块,发射威廉希尔官方网站 等组成,接收装置由红外接收威廉希尔官方网站 ,遥控,解码模块等组成,此次设计我们用到的硬件平台式是Altera的DE1_SOC,晶振为50MHZ。

在红外的编码中,我们对1 和 0 的编码是通过38KHZ的脉冲来定义的,在红外的的编码中每个脉冲的为256.25us长的38KHZ载波频率(26.3us),对0,1的脉冲的定义的时间如下图

编码

红外的数据格式为包括引导码,用户码,数据码和数据纠错码,停止位编码总为32位。数据反码是数据码反相后的编码,可用于对数据的纠错。此外第二段的用户码可以在遥控应用威廉希尔官方网站 中设置为第一段用户码的反码。

数据格式如下图:

编码

一帧数据在发送时先发送9MS的高电平,然后发送4.5MS的低电平的起始位,然后发送用户码,数据码,数据反码。然后再发送一位的停止位。不发送数据时数据线一直为低。

发送的时序图如下:

接受的时,接收到的时序和发送的时序恰恰相反,如发送时先发送9ms的高,4.5ms的低,接收为接收9ms的低电平,4.5ms低电平。

接收的控制器我们用的时红外遥控装置,按键发送的数据如下图所示

设计架构图:

设计的总框架如下图:

在我们的设计中分频模块提供所需要的38KHZ的时钟,当按键按下时发送我们的发送模块发送一个给定的数值,我的设计中用户码为8’b0第二段用户码为8’hff,然后发送给定的数据码,和数据反码。上电后我们的设计会发一次我们给定的数据码,然后在接受模块会接受到其发送的数据并在数码管上显示出来,之后我们可以用我们我的遥控键盘来发送数据,接收模块接收显示出来,通过验证我们接收和发送的正确。

设计代码:

顶层代码:

00module infrared(clk, rst_n, key, tx, seg1, seg2, rx);

01

02input clk, rst_n;

03input key;

04output tx;

05input rx;

06wire[7:0] show_data;

07output[7:0] seg1,seg2;

08wire[31:0] data_n;

09wire  clk_38khz;

10

11

12 clk_frep clk_frep_dut(    //分频模块

13  .clk(clk),

14  .rst_n(rst_n),

15  .clk_38khz(clk_38khz)

16);

17

18

19 tttxxx tx_dut(     //发送模块

20  .clk(clk_38khz),

21  .rst_n(rst_n),

22  .data_n(data_n),

23  .tx(tx),

24  .key(key)

25);

26

27 seg seg01(      //数码管模块

28  .clk(clk),

29  .rst_n(rst_n),

30  .seg7(seg1),

31  .data_in(show_data[3:0])

32);

33

34 seg seg02(

35  .clk(clk),

36  .rst_n(rst_n),

37  .seg7(seg2),

38  .data_in(show_data[7:4])

39);

40

41  rx_led led_dut(    //接收模块

42  .clk(clk_38khz),

43  .rst_n(rst_n),

44  .rx(rx),

45  .show_data(show_data)

46);

47

48

49endmodule

发送模块:

000module tttxxx(clk, rst_n, data_n, tx, key);

001

002input clk, rst_n;

003input key;

004input[31:0] data_n;

005outputreg tx;

006

007parameter T9ms=342;            //9000/26.3

008parameter T4500us=171;  //4.5ms 4500/26.3

009parameter T0=21;    //(1125-562.25)/26.3

010parameter T1=63;    //(2250-562.25)/26.3

011parameter T562us=21;    // 562.25/26.3;

012parameter T=2666;            // 一帧数据

013reg T9_flag;

014reg T45_flag;

015reg T0_flag;

016reg T1_flag;

017reg T9_down;

018reg T45_down;

019reg T0_down;

020reg T1_down;

021reg[9:0] cnt9;

022reg[9:0] cnt45;

023reg[9:0] cnt0;

024reg[9:0] cnt1;

025reg[9:0] cnt562;

026reg t0_clk, t1_clk;

027reg[8:0] count;

028reg[2:0] state;

029reg data;

030reg[31:0] d_data;

031

032always@(posedge clk)

033  if(!rst_n)

034  begin

035    count<=0;

036    state<=0;

037    tx<=0;

038    d_data<={8'b0,8'hff,8'b10100010,8'b01011101};//默认的发送数据

039  end

040  else

041  case(state)

042    0:if(count<10)

043      begin

044        tx<=0;

045        count<= count+1;

046      end

047      elseif(!key)

048      begin

049        count<=0;

050        state<=1;

051        T9_flag<=1;

052        tx<=1;

053      end

054    

055    1:if(T9_down)    //起始位 高电平9 ms

056      begin

057        state<=2;

058        T45_flag<=1;

059        tx<=0;

060        T9_flag<=0;

061      end

062      else

063      begin

064        tx<=1;

065        state<=1;

066      end

067    

068    2:if(T45_down)   // 低电平 4.5ms

069      begin

070        state<=3;

071        tx<=0;

072        T45_flag<=0;

073      end

074      else

075       tx<=0;

076    

077    3:if(count<32)   //32位的数据编码,如果那一位       为1(0)跳转4(5)状态通过发送标志结束来发送出位 1的时序

078      begin

079        count<= count+1;

080        if(!d_data[31- count])

081        begin

082          T0_flag<=1;

083          state<=4;

084          T1_flag<=0;

085        end

086        else

087        begin

088          T1_flag<=1;

089          state<=5;

090          T0_flag<=0;

091        end

092      end

093      else

094      begin

095        count<=0;

096        state<=6;

097        T0_flag<=0;

098        T1_flag<=0;

099      end

100    

101    4:if(T0_down)    //位0的设置

102      begin

103        state<=3;

104        tx<=0;

105      end

106      else

107      begin

108        tx<= t0_clk;

109      end

110    

111    5:if(T1_down)   //位1的设置

112      begin

113        state<=3;

114        tx<=0;

115      end

116      else

117       tx<= t1_clk;

118    

119    6:if(count< T562us-1) //停止位

120      begin

121        count<= count+1;

122        tx<=1;

123      end

124      else

125      begin

126        

127        tx<=0;

128      end

129    default:state<=0;

130  endcase

131

132always@(posedge clk)   //计数一个9ms

133  if(!rst_n)

134  begin

135    T9_down<=0;

136    cnt9<=0;

137  end

138  elseif(T9_flag)

139  begin

140    if(cnt9< T9ms-1)

141    begin

142      T9_down<=0;

143      cnt9<= cnt9+1;

144    end

145    else

146    begin

147      T9_down<=1;

148      cnt9<=0;

149    end

150  end

151

152always@(posedge clk)    //计数一个4.5ms

153  if(!rst_n)

154  begin

155    T45_down<=0;

156    cnt45<=0;

157  end

158  elseif(T45_flag)

159  begin

160    if(cnt45< T4500us-1)

161    begin

162      T45_down<=0;

163      cnt45<= cnt45+1;

164    end

165    else

166    begin

167      T45_down<=1;

168      cnt45<=0;

169    end

170  end

171

172reg[9:0] cnt00;

173always@(posedge clk)   //产生位0的时序

174  if(!rst_n)

175  begin

176    t0_clk<=0;

177    T0_down<=0;

178    cnt0<=0;

179    cnt00<=0;

180  end

181  elseif(T0_flag)

182  begin

183    if(cnt0< T562us-1)

184    begin

185      t0_clk<=1;

186      cnt0<= cnt0+1;

187      T0_down<=0;

188    end

189    else

190    begin

191      if(cnt00< T0-1)

192      begin

193        cnt00<= cnt00+1;

194        t0_clk<=0;

195        T0_down<=0;

196      end

197      else

198      begin

199        T0_down<=1;

200        cnt0<=0;

201        cnt00<=0;

202      end

203    end

204  end

205

206reg[9:0] cnt11;

207always@(posedge clk)   //产生位1的时序

208  if(!rst_n)

209  begin

210    t1_clk<=0;

211    T1_down<=0;

212    cnt1<=0;

213    cnt11<=0;

214  end

215  elseif(T1_flag)

216  begin

217    if(cnt1< T562us-1)

218    begin

219      t1_clk<=1;

220      cnt1<= cnt1+1;

221      T1_down<=0;

222    end

223    else

224    begin

225      if(cnt11< T1-1)

226      begin

227        cnt11<= cnt11+1;

228        t1_clk<=0;

229        T1_down<=0;

230      end

231      else

232      begin

233        T1_down<=1;

234        cnt1<=0;

235        cnt11<=0;

236      end

237    end

238  end

239

240endmodule

接收模块:

0  module rx_led(clk, rst_n, rx, show_data);

1  

2  input clk, rst_n;

3  input rx;

4  outputreg[7:0] show_data;

5  

6  reg[1:0] state;

7  reg[7:0] cnt;

8  reg temp;

9  reg[9:0] num;

10reg flag;

11reg[31:0] data;

12reg[1:0] state_s;

13reg flag_x;

14reg[12:0] count;

15

16parameter T=2566;   // 一帧数据的时间

17

18 //这个模块是中因为接受的32位编码数据中,不管是位0还是位1,接受的低电平都是相同的,

19 //我们可以通过来判断高电平的时间来确定为位1 还是位0,位’1‘ 1.68MS,位0 562.25us

20always@(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)     //判断起始位,是否接受=收数据

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的起始时间

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来的时候表示接到了位1 ,或者位0,

59              //通过移位寄存器来获取32位数据

60        begin

61         data<={data[30:0],temp};

62         state_s<=2;

63         num<= num+1;

64         count<= count+1;

65        end

66      elseif(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) //延迟结束位的时间

76        begin

77         num<= num+1;

78         count<= count+1;

79        end

80      else

81        begin

82        if(count== T-1) //延迟一帧数据的时间后,发送一个标志位

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

97always@(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) //判断高电平的时间

129      begin

130        temp<=0;

131        flag<=1;

132        state<=0;

133        cnt<=0;

134      end

135      elseif(1400< cnt*26&& cnt*26<1700)//判断高电平的时间

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

150always@(*)  //接收完一帧数据后,当标志位来的时候通过对数据的纠错来捕获数据

151       //我们接收的数据用的是左移,而发送的时候先发的是低位

152  if(!rst_n)

153   show_data<=0;

154  elseif((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

169endmodule

数码管模块:

0module seg(clk, rst_n, seg7, data_in);

1

2input clk;

3input rst_n;

4input[3:0] data_in;

5

6outputreg[7:0] seg7;

7

8

9 `define T1ms  50_000//分频出1k的时钟

10 //`define T1ms  5

11reg[15:0] count;

12reg flag;

13always@(posedge clkornegedge 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

30always@(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

55endmodule

分频模块:

0module clk_frep(clk, rst_n, clk_38khz);

1

2input clk, rst_n;

3outputreg  clk_38khz;

4

5reg[9:0] count;

6

7 //分频出红外模块所用的38Khz的时钟

8 //也可以用占空比为1:3的38khz的时钟

9

10always@(posedge clkornegedge rst_n)

11  if(!rst_n)

12  begin

13    count<=0;

14    clk_38khz<=1;

15  end

16  elseif(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

24endmodule8

测试模块:

0 `timescale1ns/1ps

1

2module infrared_tb();

3

4reg clk, rst_n;

5reg key;

6wire tx;

7wire[7:0] show_data;

8

9 //因为我们代码中只发送一次数据,所以可以把key一直拉低

10

11initialbegin

12  clk=1;

13  rst_n=0;

14  key=1;

15

16  #100.1 rst_n=1;

17

18  #200  key=0;

19

20end

21

22always#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

34endmodule

仿真图:

仿真中我们可以把数码管模块的计数器的值改小一点,便于仿真

如图中所示的我们发的是32’h00ffa25d,那么数据为是8’b1010_0010,那么先发送时就时就按下面的序列开始0100_0101接收到的为45,所以工程正确。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分