简单的人机界面——LCD1602+PS2

 

 

 

  在被4*4的矩阵键盘搞的有点晕的时候,我决定换成PS2的键盘和LCD1602,在初步认识和简单调试出来1602后,今天准备学习PS2。在FPGA的学习上一直都是这种状态深入不下去,客观上是DE0带的资料确实有点少,一直也没找到一个好的突破口,主要还是付出不够。OK,1602和PS2键盘分别已经基本搞懂了,先总结一下遇到的问题,再来想一下两者中间的连接模块。参考DE2上面的LCD1602的例程。只是它一个LCD1602的控制模块写了两部分,在另一个部分就控制了一个LED_EN,我觉得没有必要就直接写成了一个LCD_Controller模块。

 

  

  在看PS2协议写PS2代码时,有一个地方说的比较含糊。PS2只有两根线要注意,clkdata,在没有键按下时,时钟和数据线都是高电平,只有有键按下时,时钟线上才会产生时钟信号,原来以为时钟是一直都有的,看来是大错特错了!这样也比较好,按我的错误理解如果没有键按下也有时钟信号的话,那cpu岂不是要一直判断数据线上的信号,看是否为0,来判断起始位。这样CPU势必会比较累。

  看黑金的代码觉得还是有点问题的,只是它在控制器的那个模块忽略了8'hf0的情况,如果加上这种情况,那我想演示一定会有问题的,主要的错因还是在于中间模块的数据提取,我们知道一个键按下时会发通码,那我就接受了这个通码,判断不等于8'hf0, 状态机就直接跳到23,当我放开此键时又会发送断码,我还是会接受断码,也就是我oDATA还是8'hf0 那么在判断是否等于 8'hf0 , 现在是等于了,结果后面又什么都没做。呵呵,这是值得改进的地方。它之所以没有出错的原因前面已经说了。

  今天在写代码时遇到了一个以前没遇到过的问题,觉得比较搞笑,我的PS2_TEST模块的演示时通过LED显示的,大的分就要分两个部分:一个PS2模块,一个译码显示模块,PS2模块就是根据clkdata信号把被按下键的通码取出了组成一个8位的并行数据送给显示模块去译码再显示,我屁颠屁颠的把PS2模块写完,编译出现25个警告,这还没事,最怕的是编译结果报告:

  100多行的代码竟然没有消耗一个逻辑单元,我就很诧异了,找半天原因,因为之前从来没有遇到过这种情况。后来看了一下警告,它说的大概意思也就是说我没有输出,或者我的输入没有驱动输出,恩,后来我把译码显示模块一写完,OK,成功下载到板子上测试,恩,对。

 

工程代码如下:

代码

module LCD_Controller(
iCLK,iRST_N,
iDATA,iDONE,
LCD_RS,LCD_RW,LCD_EN,LCD_BLON,LCD_DATA );

input iCLK,iRST_N;
input iDONE;
input[7:0] iDATA;
output LCD_RS,LCD_RW,LCD_EN,LCD_BLON;
reg LCD_RS,LCD_EN;
output[7:0] LCD_DATA;
reg[7:0] LCD_DATA;

//Internal Wires/Registers
reg[2:0] ST;
reg[4:0] E_DLY;
reg[17:0] mDLY;
reg[5:0] LUT_INDEX;
reg[8:0] LUT_DATA;
reg[7:0] wDATA;
reg Write;


parameter E_DELAY = 16;
parameter LCD_INTIAL = 0;
parameter LCD_LINE1 = 5;
parameter LUT_SIZE = LCD_LINE1;

assign LCD_BLON = 1'b1; //Blacklight On
assign LCD_RW = 1'b0; //Only Write

always@(posedge iCLK or negedge iRST_N)
begin
if(!iRST_N)
begin
LUT_INDEX
<= 0;
Write
<= 0;
LCD_EN
<= 0;
LCD_DATA
<= 0;
LCD_RS
<= 0;
E_DLY
<= 0; //LCD_E Delay > 150ns
mDLY <= 0; //Write a byte delay > 400ns
ST <= 0;
end
else
begin
if(LUT_INDEX<LUT_SIZE)
begin
case(ST)
0: begin
LCD_DATA
<= LUT_DATA[7:0]; //
LCD_RS <= LUT_DATA[8]; //Instrction Register
LCD_EN <= 1'b1; //LCD Enable
ST <= 1; //

end
1: begin
if(E_DLY < E_DELAY)
E_DLY
<= E_DLY + 1'b1; //Delay 16*20 = 320ns
else
begin
E_DLY
<= 5'd0;
ST <= 2;
end
end
2: begin
LCD_EN
<= 1'b0;
ST <= 3;
end
3: begin
if(mDLY<18'h3FFFE) //Delay a long time
mDLY <= mDLY+1;
else
begin
mDLY
<= 0;
ST
<= 4;
end
end
4: begin
LUT_INDEX
<= LUT_INDEX+1;
ST
<= 0;
end
endcase
end
/*--------------------------------------------------------------------------------*/
else if(iDONE == 1'b0) //Why can't == 1;
Write
<= 1'b1;
else if(Write == 1'b1)
begin
case(ST)
0: begin
LCD_DATA
<= wDATA; //
LCD_RS <= 1; //Instrction Register
LCD_EN <= 1'b1; //LCD Enable
ST <= 1; //
end
1: begin
if(E_DLY < E_DELAY)
E_DLY
<= E_DLY + 1'b1; //Delay 16*20 = 320ns
else
begin
E_DLY
<= 5'd0;
ST <= 2;
end
end
2: begin
LCD_EN
<= 1'b0;
ST <= 3;
end
3: begin
if(mDLY<18'h3FFFE) //Delay a long time
mDLY <= mDLY+1;
else
begin
mDLY
<= 0;
ST
<= 4;
end
end
4: begin
Write
<= 1'b0;
ST <= 0;
end
endcase
end
end
end

always
begin
case(LUT_INDEX)
// Initial
LCD_INTIAL+0: LUT_DATA <= 9'h038; //
LCD_INTIAL+1: LUT_DATA <= 9'h00C; //Function set:8-bit,2-line,5*8 dots
LCD_INTIAL+2: LUT_DATA <= 9'h001; //clear display
LCD_INTIAL+3: LUT_DATA <= 9'h006; //Entry Mode Set
LCD_INTIAL+4: LUT_DATA <= 9'h080; //Set DDRAM Address
endcase
end

always
begin
case(iDATA)
8'h1c: wDATA <= 8'h41; //A,前面的8'h1c是PS2键值表,后面的ASCII码
8'h32: wDATA <= 8'h42; //B
8'h21: wDATA <= 8'h43; //C
8'h23: wDATA <= 8'h44; //D
8'h24: wDATA <= 8'h45; //E
8'h2b: wDATA <= 8'h46; //F
8'h34: wDATA <= 8'h47; //G
8'h33: wDATA <= 8'h48; //H
8'h43: wDATA <= 8'h49; //I
8'h3b: wDATA <= 8'h4a; //J
8'h42: wDATA <= 8'h4b; //K
8'h4b: wDATA <= 8'h4c; //L
8'h3a: wDATA <= 8'h4d; //M
8'h31: wDATA <= 8'h4e; //N
8'h44: wDATA <= 8'h4f; //O
8'h4d: wDATA <= 8'h50; //P
8'h15: wDATA <= 8'h51; //Q
8'h2d: wDATA <= 8'h52; //R
8'h1b: wDATA <= 8'h53; //S
8'h2c: wDATA <= 8'h54; //T
8'h3c: wDATA <= 8'h55; //U
8'h2a: wDATA <= 8'h56; //V
8'h1d: wDATA <= 8'h57; //W
8'h22: wDATA <= 8'h58; //X
8'h35: wDATA <= 8'h59; //Y
8'h1a: wDATA <= 8'h5a; //Z
8'h45: wDATA <= 8'h30; //0
8'h16: wDATA <= 8'h31; //1
8'h1e: wDATA <= 8'h32; //2
8'h26: wDATA <= 8'h33; //3
8'h25: wDATA <= 8'h34; //4
8'h2e: wDATA <= 8'h35; //5
8'h36: wDATA <= 8'h36; //6
8'h3d: wDATA <= 8'h37; //7
8'h3e: wDATA <= 8'h38; //8
8'h46: wDATA <= 8'h39; //9
endcase
end

endmodule

 

 

posted on 2010-11-06 22:34  zxl2431  阅读(996)  评论(0编辑  收藏  举报

导航