抱着“不气馁、不放弃、誓不罢休、搞不定你我还能搞其他玩意吗”的心态,调试许久的PS2鼠标实验,终于在今天被我搞定了。发几张图显摆一下,嘿嘿。。。

PS2鼠标+LCD12864实验——终于OK 了

                                 左键按下+鼠标移动

PS2鼠标+LCD12864实验——终于OK 了

                               右键按下+鼠标移动

PS2鼠标+LCD12864实验——终于OK 了

                                中键按下+鼠标移动

一、程序框架:

PS2鼠标+LCD12864实验——终于OK 了

大概情况:

1、先由控制模块启动发送模块,把指令0xff发送给鼠标,进入复位模式。

2、发送完后,通知控制模块启动接收模块,接收鼠标应答数据fa、aa、00。

3、接收完后,在次给鼠标发送0xf4,鼠标进入待发数据状态。

4、发送完后,启动接收模块,接收鼠标应答数据fa。

5、回复的数据都OK后,就让程序进入一直处于接收数据状态,每当鼠标按下一次或移动,鼠标都会发送三个字节的数据,提取数据进行解析让在LCD实时显示。

二、鼠标和键盘不管是向鼠标发送数据还是接收数据,都有特定的格式,每一组数据都是一个起始位、8位有效数据、一个校验位、一个停止位。

三、主机到设备时序图:这里注意停止位发送完后,鼠标会在产生一个时钟,并向主机发送一个应答位,在时钟为高时,数据线是从高到底变化的,有点像主机接收设备发送过来的起始信号,伪起始信号,如果这步没处理好,启动接收模块时就会认为此时是一个起始信号,结果接收到的数据把真正起始信号“0”给处理了,我当时就在这里犯错了。主机在发送数据时,是在时钟的下降沿改变数据。

 PS2鼠标+LCD12864实验——终于OK 了

发送模块流程:(ps2_clk 和ps2_data 都定义双向端口)

1、拉低时钟,至少要保持100us,程序中设置的是200us,这个时间不是越大约好,从主机拉低时钟到设备真正产生时钟时时间不能大于15MS。

2、200us后,拉低数据线,给鼠标发送请求状态。

3、释放时钟线,link_clk设置为0,让FPGA把该ps2_clk管脚置为高阻态,在高阻态时,该管脚可以接收高低电平,也就成了输入管脚。若设置为1,那么就成了输出管脚。
      assign ps2_clk = link_clk ? ps2_clk_out : 1'bz; 

4、在时钟的下降沿开始发送数据,8bit数据、一位校验位、一位停止位。

5、释放数据线,鼠标发送应答位,link_data设置为0,原理同link_clk。

     assign ps2_data = link_data ? ps2_data_out : 1'bz;

6、等到最后一个时钟产生完,发送完标志产生send_done_sig = 1'b1;

7、马上又进入send_done_sig清零状态,为了下次在送数据做好准备。

注意:释放时钟或释放数据一定要在准确位置释放。

四、设备到主机时序图:

时序比较简单,属于单向通信,设备发,主机只接收。程序中起始位、奇偶校验、停止位都不作处理。这个就不多讲。由于接收模块只作为接收,所以ps2_clk 和ps2_data 都定输入端口。

PS2鼠标+LCD12864实验——终于OK 了

五、发送、接收和显示都处于待命状态后,由控制模块来协调工作,到这里,对整个控制流程应该很清楚了吧。

代码实现:(由于把所有接收到数据都显示到LCD上,所以有些地方代码写的比较繁琐,暂时先这样吧)

ps2_data_control.v

  1 module ps2_data_control(
  2                          //input 
  3                          sys_clk,
  4                          rst_n, 
  5                          send_done_sig,  //发送完标志
  6                          rx_done_sig,    //接收完标志
  7                          data_buf,        //接收到的数据
  8                          
  9                          //output
 10                          rx_en,            //接收使能
 11                          send_en,        //发送使能
 12                          send_cmd,        //要发送的命令
 13                          dis_data_low1,        //要显示的数据
 14                          dis_data_hig1,
 15                          
 16                          dis_data_low2,        //要显示的数据
 17                          dis_data_hig2,
 18                          
 19                          dis_data_low3,        //要显示的数据
 20                          dis_data_hig3,
 21                          
 22                          dis_data_low4,        //要显示的数据
 23                          dis_data_hig4,
 24                          
 25                          dis_x_low,
 26                          dis_x_hig,
 27                     
 28                          dis_y_low,
 29                          dis_y_hig,
 30                     
 31                          dis_data_btn
 32                          );
 33 input sys_clk;
 34 input rst_n;
 35 input send_done_sig;
 36 input rx_done_sig;
 37 input [7:0] data_buf;
 38 
 39 output rx_en;
 40 output send_en;
 41 output [7:0] send_cmd;
 42 output [7:0] dis_data_low1;
 43 output [7:0] dis_data_hig1;
 44 output [7:0] dis_data_low2;
 45 output [7:0] dis_data_hig2;
 46 output [7:0] dis_data_low3;
 47 output [7:0] dis_data_hig3;
 48 output [7:0] dis_data_low4;
 49 output [7:0] dis_data_hig4;
 50 output [7:0] dis_data_btn;
 51 output [7:0] dis_x_low;
 52 output [7:0] dis_x_hig;
 53 output [7:0] dis_y_low;
 54 output [7:0] dis_y_hig;
 55 /**********************************************************************/
 56 parameter   T100MS        = 23'd4_999_999;
 57 parameter   PS2_RST       = 8'hff;  //复位cmd
 58 parameter   PS2_EN        = 8'hf4;  //数据报告使能cmd
 59 parameter   IDLE          = 4'd0,
 60             SEND_PS2_RST  = 4'd1,
 61             RX_EN1        = 4'd2,
 62             RX_ANSWER_FA  = 4'd3,
 63             RX_ANSWER_AA  = 4'd4,
 64             RX_ANSWER_ID  = 4'd5,
 65             SEND_PS2_EN   = 4'd6,
 66             RX_EN2        = 4'd7,
 67             RX_ANSWER2    = 4'd8,
 68             RX_BYTE1      = 4'd9,
 69             RX_BYTE2      = 4'd10,
 70             RX_BYTE3      = 4'd11,
 71             DELAY         = 4'd12,
 72             STOP          = 4'd13;        
 73 /**********************************************************************/
 74 reg [22:0] cnt;
 75 always @(posedge sys_clk or negedge rst_n)
 76 if(!rst_n)
 77     cnt <= 23'd0;
 78 else if(!cnt_en || cnt == T100MS)
 79     cnt <= 23'd0;
 80 else 
 81     cnt <= cnt + 1'b1;
 82 /**********************************************************************/
 83 reg    send_en;
 84 reg rx_en;
 85 reg [7:0] data_answer;    //保存应答位
 86 reg [7:0] x_move;  //x的偏移量
 87 reg [7:0] y_move;  //y的偏移量
 88 reg [3:0] state;
 89 reg [7:0] dis_data_temp1;
 90 reg [7:0] dis_data_temp2;
 91 reg [7:0] dis_data_temp3;
 92 reg [7:0] dis_data_temp4;
 93 reg [7:0] dis_data_btn;
 94 reg cnt_en;
 95 reg [7:0] send_cmd;
 96 always @(posedge sys_clk or negedge rst_n)
 97 if(!rst_n) begin
 98     send_en <= 1'b0;
 99     rx_en <= 1'b0;
100     data_answer <= 8'h00;
101     state <= IDLE;
102     dis_data_temp1 <= 8'h00;
103     dis_data_temp2 <= 8'h00;
104     dis_data_temp3 <= 8'h00;
105     dis_data_temp4 <= 8'h00;
106     cnt_en <= 1'b0;
107     dis_data_btn <= "X";
108     send_cmd <= 8'h00;
109 end
110 else begin
111     case(state)
112         IDLE: 
113         begin
114             state <= SEND_PS2_RST;
115             cnt_en <= 1'b1;
116         end
117         
118         SEND_PS2_RST: //发送复位 0xff
119         if(cnt == T100MS) begin
120             cnt_en <= 1'b0;
121             send_en <= 1'b1; //启动发送
122             send_cmd <= PS2_RST;
123             state <= RX_EN1;//RX_EN1;
124         end
125         else
126             state <= SEND_PS2_RST;
127         
128         RX_EN1:
129         if(send_done_sig) begin
130             rx_en <= 1'b1;
131             send_en <= 1'b0;
132             state <= RX_ANSWER_FA;
133         end 
134         else
135             state <= RX_EN1;
136         
137         RX_ANSWER_FA:  //接收鼠标发回的应答数据0xfa
138         if(rx_done_sig) begin
139             dis_data_temp1 <= data_buf;
140             state <= RX_ANSWER_AA;//RX_BYTE1;
141         end
142         else
143             state <= RX_ANSWER_FA;
144         
145         RX_ANSWER_AA:  //接收鼠标发回的应答数据0xaa
146         if(rx_done_sig) begin
147             dis_data_temp2 <= data_buf;
148             state <= RX_ANSWER_ID;
149         end
150         else
151             state <= RX_ANSWER_AA;
152         
153         RX_ANSWER_ID:  //接收鼠标发回的应答数据0x00
154         if(rx_done_sig) begin
155             dis_data_temp3 <= data_buf;
156             cnt_en <= 1'b1;
157             rx_en <= 1'b0;
158             state <= SEND_PS2_EN;
159         end
160         else
161             state <= RX_ANSWER_ID;
162         
163         SEND_PS2_EN: //发送0xf4
164         if(cnt == T100MS)begin
165             cnt_en <= 1'b0;
166             send_en <= 1'b1; //启动发送
167             send_cmd <= PS2_EN;
168             state <= RX_EN2;
169         end
170         else
171             state <= SEND_PS2_EN;
172         
173         RX_EN2:
174         if(send_done_sig) begin
175             rx_en <= 1'b1; //启动接收
176             send_en <= 1'b0;
177             state <= RX_ANSWER2;
178         end 
179         else
180             state <= RX_EN2;
181         
182         RX_ANSWER2:  //第二次应答位
183         if(rx_done_sig) begin
184             dis_data_temp4 <= data_buf;
185             state <= RX_BYTE1;
186         end
187         else
188             state <= RX_ANSWER2;
189         
190         RX_BYTE1:
191         if(rx_done_sig) begin
192             if(data_buf[0] == 1'b1)//左键被按下
193                 dis_data_btn <= "L";  
194             else if(data_buf[1] == 1'b1) //右键被按下
195                 dis_data_btn <= "R";  
196             else if(data_buf[2] == 1'b1)  //中键被按下
197                 dis_data_btn <= "M";
198     
199             state <= RX_BYTE2;
200         end
201         else
202             state <= RX_BYTE1;
203         
204         RX_BYTE2:
205         if(rx_done_sig) begin //接收到第二个字节
206             x_move <= data_buf;
207             state <= RX_BYTE3;
208         end
209         else
210             state <= RX_BYTE2;
211         
212         RX_BYTE3:  //接收到第三个字节
213         if(rx_done_sig) begin
214             y_move <= data_buf;
215             state <= STOP;
216             cnt_en <= 1'b1;
217         end 
218         else
219             state <= RX_BYTE3;
220         
221         STOP:
222         if(cnt == T100MS) 
223         begin
224             cnt_en <= 1'b0;
225             state <= RX_BYTE1;
226         end
227         else
228             state <= STOP;
229             
230     endcase
231 end
232 
233 reg [7:0] dis_data_low1;
234 always @(dis_data_temp1[3:0])
235     case(dis_data_temp1[3:0])
236         4'h0: dis_data_low1 = "0";
237         4'h1: dis_data_low1 = "1";
238         4'h2: dis_data_low1 = "2";
239         4'h3: dis_data_low1 = "3";
240         4'h4: dis_data_low1 = "4";
241         4'h5: dis_data_low1 = "5";
242         4'h6: dis_data_low1 = "6";
243         4'h7: dis_data_low1 = "7";
244         4'h8: dis_data_low1 = "8";
245         4'h9: dis_data_low1 = "9";
246         4'ha: dis_data_low1 = "a";
247         4'hb: dis_data_low1 = "b";
248         4'hc: dis_data_low1 = "c";
249         4'hd: dis_data_low1 = "d";
250         4'he: dis_data_low1 = "e";
251         4'hf: dis_data_low1 = "f";
252     endcase
253 
254 reg [7:0] dis_data_hig1;
255 always @(dis_data_temp1[7:4])
256     case(dis_data_temp1[7:4])
257         4'h0: dis_data_hig1 = "0";
258         4'h1: dis_data_hig1 = "1";
259         4'h2: dis_data_hig1 = "2";
260         4'h3: dis_data_hig1 = "3";
261         4'h4: dis_data_hig1 = "4";
262         4'h5: dis_data_hig1 = "5";
263         4'h6: dis_data_hig1 = "6";
264         4'h7: dis_data_hig1 = "7";
265         4'h8: dis_data_hig1 = "8";
266         4'h9: dis_data_hig1 = "9";
267         4'ha: dis_data_hig1 = "a";
268         4'hb: dis_data_hig1 = "b";
269         4'hc: dis_data_hig1 = "c";
270         4'hd: dis_data_hig1 = "d";
271         4'he: dis_data_hig1 = "e";
272         4'hf: dis_data_hig1 = "f";
273     endcase
274     
275 reg [7:0] dis_data_low2;
276 always @(dis_data_temp2[3:0])
277     case(dis_data_temp2[3:0])
278         4'h0: dis_data_low2 = "0";
279         4'h1: dis_data_low2 = "1";
280         4'h2: dis_data_low2 = "2";
281         4'h3: dis_data_low2 = "3";
282         4'h4: dis_data_low2 = "4";
283         4'h5: dis_data_low2 = "5";
284         4'h6: dis_data_low2 = "6";
285         4'h7: dis_data_low2 = "7";
286         4'h8: dis_data_low2 = "8";
287         4'h9: dis_data_low2 = "9";
288         4'ha: dis_data_low2 = "a";
289         4'hb: dis_data_low2 = "b";
290         4'hc: dis_data_low2 = "c";
291         4'hd: dis_data_low2 = "d";
292         4'he: dis_data_low2 = "e";
293         4'hf: dis_data_low2 = "f";
294     endcase
295 
296 reg [7:0] dis_data_hig2;
297 always @(dis_data_temp2[7:4])
298     case(dis_data_temp2[7:4])
299         4'h0: dis_data_hig2 = "0";
300         4'h1: dis_data_hig2 = "1";
301         4'h2: dis_data_hig2 = "2";
302         4'h3: dis_data_hig2 = "3";
303         4'h4: dis_data_hig2 = "4";
304         4'h5: dis_data_hig2 = "5";
305         4'h6: dis_data_hig2 = "6";
306         4'h7: dis_data_hig2 = "7";
307         4'h8: dis_data_hig2 = "8";
308         4'h9: dis_data_hig2 = "9";
309         4'ha: dis_data_hig2 = "a";
310         4'hb: dis_data_hig2 = "b";
311         4'hc: dis_data_hig2 = "c";
312         4'hd: dis_data_hig2 = "d";
313         4'he: dis_data_hig2 = "e";
314         4'hf: dis_data_hig2 = "f";
315     endcase
316 
317 reg [7:0] dis_data_low3;
318 always @(dis_data_temp3[3:0])
319     case(dis_data_temp3[3:0])
320         4'h0: dis_data_low3 = "0";
321         4'h1: dis_data_low3 = "1";
322         4'h2: dis_data_low3 = "2";
323         4'h3: dis_data_low3 = "3";
324         4'h4: dis_data_low3 = "4";
325         4'h5: dis_data_low3 = "5";
326         4'h6: dis_data_low3 = "6";
327         4'h7: dis_data_low3 = "7";
328         4'h8: dis_data_low3 = "8";
329         4'h9: dis_data_low3 = "9";
330         4'ha: dis_data_low3 = "a";
331         4'hb: dis_data_low3 = "b";
332         4'hc: dis_data_low3 = "c";
333         4'hd: dis_data_low3 = "d";
334         4'he: dis_data_low3 = "e";
335         4'hf: dis_data_low3 = "f";
336     endcase
337 
338 reg [7:0] dis_data_hig3;
339 always @(dis_data_temp3[7:4])
340     case(dis_data_temp3[7:4])
341         4'h0: dis_data_hig3 = "0";
342         4'h1: dis_data_hig3 = "1";
343         4'h2: dis_data_hig3 = "2";
344         4'h3: dis_data_hig3 = "3";
345         4'h4: dis_data_hig3 = "4";
346         4'h5: dis_data_hig3 = "5";
347         4'h6: dis_data_hig3 = "6";
348         4'h7: dis_data_hig3 = "7";
349         4'h8: dis_data_hig3 = "8";
350         4'h9: dis_data_hig3 = "9";
351         4'ha: dis_data_hig3 = "a";
352         4'hb: dis_data_hig3 = "b";
353         4'hc: dis_data_hig3 = "c";
354         4'hd: dis_data_hig3 = "d";
355         4'he: dis_data_hig3 = "e";
356         4'hf: dis_data_hig3 = "f";
357     endcase
358     
359 reg [7:0] dis_data_low4;
360 always @(dis_data_temp4[3:0])
361     case(dis_data_temp4[3:0])
362         4'h0: dis_data_low4 = "0";
363         4'h1: dis_data_low4 = "1";
364         4'h2: dis_data_low4 = "2";
365         4'h3: dis_data_low4 = "3";
366         4'h4: dis_data_low4 = "4";
367         4'h5: dis_data_low4 = "5";
368         4'h6: dis_data_low4 = "6";
369         4'h7: dis_data_low4 = "7";
370         4'h8: dis_data_low4 = "8";
371         4'h9: dis_data_low4 = "9";
372         4'ha: dis_data_low4 = "a";
373         4'hb: dis_data_low4 = "b";
374         4'hc: dis_data_low4 = "c";
375         4'hd: dis_data_low4 = "d";
376         4'he: dis_data_low4 = "e";
377         4'hf: dis_data_low4 = "f";
378     endcase
379 
380 reg [7:0] dis_data_hig4;
381 always @(dis_data_temp4[7:4])
382     case(dis_data_temp4[7:4])
383         4'h0: dis_data_hig4 = "0";
384         4'h1: dis_data_hig4 = "1";
385         4'h2: dis_data_hig4 = "2";
386         4'h3: dis_data_hig4 = "3";
387         4'h4: dis_data_hig4 = "4";
388         4'h5: dis_data_hig4 = "5";
389         4'h6: dis_data_hig4 = "6";
390         4'h7: dis_data_hig4 = "7";
391         4'h8: dis_data_hig4 = "8";
392         4'h9: dis_data_hig4 = "9";
393         4'ha: dis_data_hig4 = "a";
394         4'hb: dis_data_hig4 = "b";
395         4'hc: dis_data_hig4 = "c";
396         4'hd: dis_data_hig4 = "d";
397         4'he: dis_data_hig4 = "e";
398         4'hf: dis_data_hig4 = "f";
399     endcase
400 //move x
401 reg [7:0] dis_x_low;
402 always @(x_move[3:0])
403     case(x_move[3:0])
404         4'h0: dis_x_low = "0";
405         4'h1: dis_x_low = "1";
406         4'h2: dis_x_low = "2";
407         4'h3: dis_x_low = "3";
408         4'h4: dis_x_low = "4";
409         4'h5: dis_x_low = "5";
410         4'h6: dis_x_low = "6";
411         4'h7: dis_x_low = "7";
412         4'h8: dis_x_low = "8";
413         4'h9: dis_x_low = "9";
414         4'ha: dis_x_low = "a";
415         4'hb: dis_x_low = "b";
416         4'hc: dis_x_low = "c";
417         4'hd: dis_x_low = "d";
418         4'he: dis_x_low = "e";
419         4'hf: dis_x_low = "f";
420     endcase
421 
422 reg [7:0] dis_x_hig;
423 always @(x_move[7:4])
424     case(x_move[7:4])
425         4'h0: dis_x_hig = "0";
426         4'h1: dis_x_hig = "1";
427         4'h2: dis_x_hig = "2";
428         4'h3: dis_x_hig = "3";
429         4'h4: dis_x_hig = "4";
430         4'h5: dis_x_hig = "5";
431         4'h6: dis_x_hig = "6";
432         4'h7: dis_x_hig = "7";
433         4'h8: dis_x_hig = "8";
434         4'h9: dis_x_hig = "9";
435         4'ha: dis_x_hig = "a";
436         4'hb: dis_x_hig = "b";
437         4'hc: dis_x_hig = "c";
438         4'hd: dis_x_hig = "d";
439         4'he: dis_x_hig = "e";
440         4'hf: dis_x_hig = "f";
441     endcase
442 //move y
443 reg [7:0] dis_y_low;
444 always @(y_move[3:0])
445     case(y_move[3:0])
446         4'h0: dis_y_low = "0";
447         4'h1: dis_y_low = "1";
448         4'h2: dis_y_low = "2";
449         4'h3: dis_y_low = "3";
450         4'h4: dis_y_low = "4";
451         4'h5: dis_y_low = "5";
452         4'h6: dis_y_low = "6";
453         4'h7: dis_y_low = "7";
454         4'h8: dis_y_low = "8";
455         4'h9: dis_y_low = "9";
456         4'ha: dis_y_low = "a";
457         4'hb: dis_y_low = "b";
458         4'hc: dis_y_low = "c";
459         4'hd: dis_y_low = "d";
460         4'he: dis_y_low = "e";
461         4'hf: dis_y_low = "f";
462     endcase
463 
464 reg [7:0] dis_y_hig;
465 always @(y_move[7:4])
466     case(y_move[7:4])
467         4'h0: dis_y_hig = "0";
468         4'h1: dis_y_hig = "1";
469         4'h2: dis_y_hig = "2";
470         4'h3: dis_y_hig = "3";
471         4'h4: dis_y_hig = "4";
472         4'h5: dis_y_hig = "5";
473         4'h6: dis_y_hig = "6";
474         4'h7: dis_y_hig = "7";
475         4'h8: dis_y_hig = "8";
476         4'h9: dis_y_hig = "9";
477         4'ha: dis_y_hig = "a";
478         4'hb: dis_y_hig = "b";
479         4'hc: dis_y_hig = "c";
480         4'hd: dis_y_hig = "d";
481         4'he: dis_y_hig = "e";
482         4'hf: dis_y_hig = "f";
483     endcase
484 endmodule 
485         
View Code

相关文章:

  • 2021-05-18
  • 2022-12-23
  • 2022-02-07
  • 2021-07-31
  • 2021-08-02
  • 2021-12-26
猜你喜欢
  • 2022-12-23
  • 2021-11-18
  • 2021-09-28
  • 2022-12-23
  • 2022-02-07
  • 2021-05-26
相关资源
相似解决方案