(總結)(原創)LCD屏的學習總結(針對ST7920)
前言:這麼長時間一直沒有寫部落格,是因為總結的東西不能随便的發出來,因為不夠完善,尤其對于我這種初學者,但經過一段時間的經曆,必須要有深思熟慮,有自己的親身經曆在裡面。在這兩個星期的時間裡,在一個簡單的LCD屏的驅動上汲取了許多 營養。該有個學習總結了。
1、學習态度和做事的方式。
認真、全面、仔細、耐心。這是最重要的幾點,我一共寫了多達3個完全不同的版本去驅動LCD,卻一直沒有我想要的結果,一直在懷疑我的軟體問題,可到最後在發現是我沒有仔細閱讀通信協定,在初始化的過程中 少了一個指令。另外在仿真的時候也沒有對所有的情況做一個完整的檢查。
2、将組合電路和時序電路的分離。
一個好用的設計應該是在設計的初期就應該預想到寄存器的個數和它的功能,我認為在電路設計中有很大的部分是在于決定我的寄存器的安放。 在我最後的設計中,我使用了一個移位寄存器,一個發送資料緩沖器,對于每行的資料存儲區的輸出也有一個資料緩沖,以應對于作出顯示内容的選擇。我在初學設計的時候使用的都是時序群組合混合的方式,但在這次的設計中我使用的是分開描述的方式,這樣書寫的方式有利于對于整個系統的了解和實作,對于電路綜合後有一個預測和把握。剛開始的時候應用的不是很熟練,漸漸的發現自己對于Verilog的語句和實作方式都沒有很好的了解,比如阻塞指派和非阻塞指派沒有很好的了解,對于begin和end塊語句的順序執行方式也沒有體會到。
3、軟體代碼和說明
(1)我沒有使用專門的ROM是直接自己書寫的ROM。
(2)我對于發送資料的方式有點問題,應該是先發高位再發低位,我做成了先發低位再發高位,隻需要将右移改為左移,将高8位輸出。
(3)控制方式,我将每行要發送的漢字存儲到ROM裡,然後根據輸入的顯示編碼,就達到文字的改變(這是因為我是為任意波形發生器寫的專門的調節顯示子產品的,經過改進可以應用于其他方式),然後向LCD發送資料是從第一行向最後一行不斷地重複掃描。
(4)希望大家提出建議,誠懇的需要大家的批評。
(5) 本文是針對st7920寫的驅動。
4、源代碼如下:
//-----------------------------------------------------
// Design Name : lcd
// File Name : gz_lcd_v3.v
// Function : lcd
// Aurthor : guanzhou
//Vertion : v 3.0
//Date : 2009.10.22
//-----------------------------------------------------
`timescale 1ns/100ps
module lcd
(
//input
rclk,rst,
addr_f,addr_p,addr_m,
control,
//ouput
e,rs,rw,
data
);
parameter max_count_f = 4_749_999;
//parameter max_count_f = 2;
parameter wide_count_f = 23;
parameter wide_f = 3,
wide_p = 3,
wide_m = 3;
parameter word_size = 11;
parameter max_b = 63;
parameter order_set = 8\'b0011_0000,
cursor_set = 8\'b0000_1110,
addr_set = 8\'b0000_0001,
display_set = 8\'b0000_0100;
parameter idle = 4\'b0001,
mode = 4\'b0010,
freq = 4\'b0100,
phase = 4\'b1000;
input rclk,rst;
input [wide_f-1:0] addr_f;
input [wide_p-1:0] addr_p;
input [wide_m-1:0] addr_m;
input [2:0] control;
output e,rs,rw;
output [7:0] data;
reg shift;
//========================================================
//分頻
//========================================================
reg [wide_count_f-1:0] count_f;
reg clk;
always @(posedge rclk or negedge rst)
begin
if(!rst)
begin
count_f <= 0;
clk <= 0;
end
else if(count_f==max_count_f)
begin
count_f <= 0;
clk <= ~clk;
end
else
count_f <= count_f + 1\'b1;
end
wire e;
assign e = clk; //讀寫信号為4Hz的時鐘信号
reg [max_b+15:0] data_f,
data_p,
data_m;
always @(addr_m or addr_f or addr_p) //定義ROM
begin
case(addr_m)
3\'d0: data_m[max_b-1:0] = 64\'hCEF7_D3CA_CEA2_B5E7;
3\'d1: data_m[max_b-1:0] = 64\'hCFE0_CEBB_CFE0_CEBB;
3\'d2: data_m[max_b-1:0] = 64\'hC6B5_C2CA_C6B5_C2CA;
3\'d3: data_m[max_b-1:0] = 64\'hCEF7_D3CA_CEA2_B5E7;
3\'d4: data_m[max_b-1:0] = 64\'hCEF7_D3CA_CEA2_B5E7;
3\'d5: data_m[max_b-1:0] = 64\'hCFE0_CEBB_CFE0_CEBB;
3\'d6: data_m[max_b-1:0] = 64\'hC6B5_C2CA_C6B5_C2CA;
3\'d7: data_m[max_b-1:0] = 64\'hCEF7_D3CA_CEA2_B5E7;
endcase
case(addr_f)
3\'d0: data_f[max_b-1:0] = 64\'hC6B5_C2CA_C6B5_C2CA;
3\'d1: data_f[max_b-1:0] = 64\'hCFE0_CEBB_CFE0_CEBB;
3\'d2: data_f[max_b-1:0] = 64\'hCEF7_D3CA_CEA2_B5E7;
3\'d3: data_f[max_b-1:0] = 64\'hCFE0_CEBB_CFE0_CEBB;
3\'d4: data_f[max_b-1:0] = 64\'hC6B5_C2CA_C6B5_C2CA;
3\'d5: data_f[max_b-1:0] = 64\'hCEF7_D3CA_CEA2_B5E7;
3\'d6: data_f[max_b-1:0] = 64\'hCFE0_CEBB_CFE0_CEBB;
3\'d7: data_f[max_b-1:0] = 64\'hCEF7_D3CA_CEA2_B5E7;
endcase
case(addr_p)
3\'d0: data_p[max_b-1:0] = 64\'hCFE0_CEBB_CFE0_CEBB;
3\'d1: data_p[max_b-1:0] = 64\'hC6B5_C2CA_C6B5_C2CA;
3\'d2: data_p[max_b-1:0] = 64\'hCFE0_CEBB_CFE0_CEBB;
3\'d3: data_p[max_b-1:0] = 64\'hCEF7_D3CA_CEA2_B5E7;
3\'d4: data_p[max_b-1:0] = 64\'hC6B5_C2CA_C6B5_C2CA;
3\'d5: data_p[max_b-1:0] = 64\'hCFE0_CEBB_CFE0_CEBB;
3\'d6: data_p[max_b-1:0] = 64\'hCEF7_D3CA_CEA2_B5E7;
3\'d7: data_p[max_b-1:0] = 64\'hC6B5_C2CA_C6B5_C2CA;
endcase
end
always @(control) //要求在每一行前面加上訓示星号,表明目前的波形設定
begin
case(control)
3\'b001:
begin
data_m[max_b+15:max_b] <= 16\'hA1F2;
data_f[max_b+15:max_b] <= 16\'hA2A0;
data_p[max_b+15:max_b] <= 16\'hA2A0;
end
3\'b010:
begin
data_m[max_b+15:max_b] <= 16\'hA2A0;
data_f[max_b+15:max_b] <= 16\'hA1F2;
data_p[max_b+15:max_b] <= 16\'hA2A0;
end
3\'b100:
begin
data_m[max_b+15:max_b] <= 16\'hA2A0;
data_f[max_b+15:max_b] <= 16\'hA2A0;
data_p[max_b+15:max_b] <= 16\'hA1F2;
end
default:
begin
data_m[max_b+15:max_b] <= 16\'hA2A0;
data_f[max_b+15:max_b] <= 16\'hA2A0;
data_p[max_b+15:max_b] <= 16\'hA2A0;
end
endcase
end
//========================================================
//行掃描循環控制狀态機
//========================================================
reg [7:0] data;
reg rs,rw;
reg [4:0] bit_count;
reg [4:0] state,next_state;
reg [max_b+15:0] data_shift;
always @(state or bit_count)
begin
shift = 0;
next_state = state;
case(state)
idle:
begin
if(bit_count==word_size-2)
shift = 1;
if(bit_count==word_size-3)
next_state = mode;
end
mode:
begin
if(bit_count==word_size-2)
shift = 1;
if(bit_count==word_size-3)
next_state = freq;
end
freq:
begin
if(bit_count==word_size-2)
shift = 1;
if(bit_count==word_size-3)
next_state = phase;
end
phase:
begin
if(bit_count==word_size-2)
shift = 1;
if(bit_count==word_size-3)
next_state = mode;
end
default:
begin
shift = 0;
next_state = state;
end
endcase
end
always @(posedge clk or negedge rst)
begin
if(!rst)
state <= idle;
else
state <= next_state;
end
//==========================================================
//發送文字資訊資料
//==========================================================
always @(posedge clk or negedge rst)
begin
if(!rst)
begin
data <= order_set;
bit_count <= 0;
data_shift <= {39\'d0,display_set,addr_set,cursor_set,order_set,order_set};
end
else
begin
if(shift) // ?????
case(state)
idle:
begin
data_shift <= {39\'d0,display_set,addr_set,cursor_set,order_set,order_set};
data <= order_set;
end
mode:
begin
data_shift <= data_m;
data <= 8\'h90;
end
freq:
begin
data_shift <= data_f;
data <= 8\'h80;
end
phase:
begin
data_shift <= data_p;
data <= 8\'h98;
end
default:
begin
data_shift <= data_shift;
data <= 8\'h00;
end
endcase
else
begin
data <= data_shift[7:0];
data_shift <= {8\'b1111_1111,data_shift[max_b+15:8]};
end
if(shift)
bit_count <= 0;
else
bit_count <= bit_count + 1\'b1;
end
end
//================================================================
//發送資料格式指令
//================================================================
always @(posedge clk or negedge rst)
begin
if(!rst)
begin
rw <= 1;
rs <= 1;
end
else
if(state==idle)
begin
rs <= 0;
rw <= 0;
end
else if(shift)
begin
rs <= 0;
rw <= 0;
end
else
begin
rs <= 1;
rw <= 0;
end
end
endmodule
