设计背景:
红外线(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,然后发送给定的数据码,和数据反码。上电后我们的设计会发一次我们给定的数据码,然后在接受模块会接受到其发送的数据并在数码管上显示出来,之后我们可以用我们我的遥控键盘来发送数据,接收模块接收显示出来,通过验证我们接收和发送的正确。
设计代码:
顶层代码:
00moduleinfrared(clk,rst_n,key,tx,seg1,seg2,rx);
01
02inputclk,rst_n;
03inputkey;
04outputtx;
05inputrx;
06wire[7:0]show_data;
07output[7:0]seg1,seg2;
08wire[31:0]data_n;
09wireclk_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
发送模块:
000moduletttxxx(clk,rst_n,data_n,tx,key);
001
002inputclk,rst_n;
003inputkey;
004input[31:0]data_n;
005outputregtx;
006
007parameterT9ms=342;//9000/26.3
008parameterT4500us=171; //4.5ms 4500/26.3
009parameterT0=21; //(1125-562.25)/26.3
010parameterT1=63; //(2250-562.25)/26.3
011parameterT562us=21; // 562.25/26.3;
012parameterT=2666;// 一帧数据
013regT9_flag;
014regT45_flag;
015regT0_flag;
016regT1_flag;
017regT9_down;
018regT45_down;
019regT0_down;
020regT1_down;
021reg[9:0]cnt9;
022reg[9:0]cnt45;
023reg[9:0]cnt0;
024reg[9:0]cnt1;
025reg[9:0]cnt562;
026regt0_clk,t1_clk;
027reg[8:0]count;
028reg[2:0]state;
029regdata;
030reg[31:0]d_data;
031
032always@(posedgeclk)
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@(posedgeclk) //计数一个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@(posedgeclk) //计数一个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@(posedgeclk) //产生位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@(posedgeclk) //产生位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
接收模块:
0modulerx_led(clk,rst_n,rx,show_data);
1
2inputclk,rst_n;
3inputrx;
4outputreg[7:0]show_data;
5
6reg[1:0]state;
7reg[7:0]cnt;
8regtemp;
9reg[9:0]num;
10regflag;
11reg[31:0]data;
12reg[1:0]state_s;
13regflag_x;
14reg[12:0]count;
15
16parameterT=2566;// 一帧数据的时间
17
18 //这个模块是中因为接受的32位编码数据中,不管是位0还是位1,接受的低电平都是相同的,
19 //我们可以通过来判断高电平的时间来确定为位1 还是位0,位’1‘ 1.68MS,位0 562.25us
20always@(posedgeclk)
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@(posedgeclk)
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
数码管模块:
0moduleseg(clk,rst_n,seg7,data_in);
1
2inputclk;
3inputrst_n;
4input[3:0]data_in;
5
6outputreg[7:0]seg7;
7
8
9 `defineT1ms 50_000//分频出1k的时钟
10 //`define T1ms 5
11reg[15:0]count;
12regflag;
13always@(posedgeclkornegedgerst_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@(posedgeflag)
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
分频模块:
0moduleclk_frep(clk,rst_n,clk_38khz);
1
2inputclk,rst_n;
3outputregclk_38khz;
4
5reg[9:0]count;
6
7 //分频出红外模块所用的38Khz的时钟
8 //也可以用占空比为1:3的38khz的时钟
9
10always@(posedgeclkornegedgerst_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
2moduleinfrared_tb();
3
4regclk,rst_n;
5regkey;
6wiretx;
7wire[7:0]show_data;
8
9 //因为我们代码中只发送一次数据,所以可以把key一直拉低
10
11initialbegin
12 clk=1;
13 rst_n=0;
14 key=1;
15
16 #100.1rst_n=1;
17
18 #200key=0;
19
20end
21
22always#10clk=~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,所以工程正确。
-
红外线
+关注
关注
14文章
616浏览量
56088 -
编码
+关注
关注
6文章
935浏览量
54759
原文标题:FPGA学习系列:34. 红外线遥控系统的设计
文章出处:【微信号:FPGAer_Club,微信公众号:FPGAer俱乐部】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
相关推荐
评论