找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 4183|回復(fù): 0
打印 上一主題 下一主題
收起左側(cè)

利用SPI驅(qū)動12864液晶

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:105323 發(fā)表于 2016-2-23 17:37 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
SPI 發(fā)送模塊在這里,我們要在主機上建立,一個向從機寫入數(shù)據(jù)的SPI發(fā)送模塊,首先我們先從C語言上了解幾個主機在SPI寫操作上容易被疏忽的小細節(jié):我們知道SPI設(shè)備在傳輸都有一個規(guī)則,SCL 時鐘信號在“上升沿”的時候是“鎖存數(shù)據(jù)”,SCL時鐘信號在“下降沿”是“設(shè)置數(shù)據(jù)”。在這里我們SPI 主機(FPGA),寫操作要干的工作就是在“拉高SCL時鐘信號之前”設(shè)置數(shù)據(jù)(移位數(shù)據(jù)),設(shè)置數(shù)據(jù)之后,再拉高時鐘信號。但是我們常常會忽略了一些具體的細節(jié)。

上面有兩個主機的SPI_Send函數(shù)(寫函數(shù)),左邊的寫法是最常用,但是也是最容易忽略小細節(jié)。相比右邊的寫法比較謹慎,在最低的程度上符合一寫小細節(jié)。

再來,我們繼續(xù)引用ST7565P芯片的寫入時序圖,分析并且區(qū)分上邊的兩個寫法。關(guān)于SCL信號在空閑的時候總是處于高電平。當主機開始向從機寫入數(shù)據(jù),主機會先拉低CS 信號,再拉低SCL信號,然后“設(shè)置”數(shù)據(jù),亦即主機(FPGA)更新SI 的數(shù)據(jù)(主機數(shù)據(jù)移位操作),最后再拉高SCL信號。同一時間,從機會因為SCL 的上升沿變化,從機(液晶資源)“鎖存”(從機讀取數(shù)據(jù)操作)SI上的數(shù)據(jù)。很明顯左邊的寫法沒有符合這些細節(jié),然而右邊的寫法卻符合這些細節(jié)。無論是左邊的寫法還是右邊的寫法,都忽略了一個致命的細節(jié),兩種寫法都無法確定SPI時鐘信號的時鐘頻率。
module spi_write_module
(
CLK,RSTn,Start_Sig,SPI_Data,Done_Sig,SPI_Out
);
input CLK;
input RSTn;
input Start_Sig;
output [9:0] SPI_Data;
output Done_Sig;
output [3:0]SPI_Out;//[3]CS,[2]A0[1]CLK [0]D0
parameter T0P5US=4'd9;//0.5us
always@(posedge CLK or negedgeRSTn)
if(!RSTn)
Count1<=4'd0;
else if(Count1==T0P5US)
Count1<4'd0;
else if(Start_Sig)
Count1<=Count1+1'b1;
else
Count1<=4'd0;
reg[4:0]i;
reg rCLK;
reg rDO;
reg isDone;
always@(posedge CLK or negedgeRSTn)
if(!RSTn)
begin
i<=5'd0;
rCLK<=1'b1;
rDO<=1'b0;
isDone<=1'b0;
end
else if(Start_Sig)
case(i)
5'd0,5'd2,5'd4,5'd6,5'd8,5'd10,5'd12,5'd14:
if(Count1==T0P5US)beginrCLK<=1'b0;rDO<=SPI_Data[7-(i>>1)];i<=1+1'b1;end
5'd1,5'd3,5'd5,5'd7,5'd9,5'd11,5'd13,5'd15:
if(Count==T0P5US)beginrCLK<=1'b1;i<=i+1'b1;end
5'd16:
beginisDone<=1'b1;i<=i+1'b1;end
5'd17:
beginisDone<=1'b0;i<=5'd0;end
endcase

assign Done_Sig=isDone;
assignSPI_Out={SPI_Data[9],SPI_Data[8],rCLK,rDO};
endmodule
SCL 的時鐘頻率定義為1Mhz , 也就是說周期時間是1us,半周期就是0.5us 。如果以20Mhz 來定時,那么計數(shù)的結(jié)果是10。在19行定義了0.5us 的常量,第23~33 行是0.5us的定時器。但是比較不同的是,這個定時器平時不工作,當Start_Sig拉高的時候才開始計數(shù)(第30 行)。第37~65 行是spi_write_module.v的核心功能。i 寄存器表示操作步驟,rCLK 寄存器表示SCL 然而rDO 寄存器表示SI。如同前面所述那樣,SCL 時鐘信號,處于空閑狀態(tài)
時是出于高電平,所以rCLK 復(fù)位值是邏輯1(46 行)。
SPI_Data : 第9 位表示CS,第8 位表示A0,第7 .. 0位表示一字節(jié)數(shù)據(jù)。
SPI_Out : 第3 位表示CS,第2 位表示A0,第1位表示SCL,第0 位表示SI。
當Start_Sig 拉高的同時,定時器開始計數(shù)(30行),該模塊也開始執(zhí)行(50 行)。
當?shù)谝粋0.5us 定時產(chǎn)生的時候(54行),也就是第一個時鐘的前半周期,亦即下降沿,
rCLK 設(shè)置為邏輯0。根據(jù)SPI傳輸?shù)囊?guī)則,下降沿的時候主機設(shè)置數(shù)據(jù),rDO 賦予SPI_Data 信號的第7 位(SPI傳輸是從最高位開始,最低位結(jié)束),最后i 遞增以示下一個步驟。當i 等于1 的時候并且定時產(chǎn)生(56行),這表示第一個時鐘的后半周期,亦即上升沿,rCLK 設(shè)置為邏輯1。在SPI傳輸?shù)囊?guī)則中上升沿的時候,從機鎖存數(shù)據(jù)。然后i 遞增以示下一個步驟。
上述的步驟會一直重復(fù)到第八次,直到一字節(jié)的數(shù)據(jù)發(fā)送完畢。最后會產(chǎn)生一個完成信號(59~63 行)。
這里有一個表達式需要說明一下:
i >> 1 : 表示i / 2。右移操作也代表了“i /j2”(j 是右移次數(shù))。
假設(shè)8 >> 2 ,亦即8 / 22 等于2。8>> 3, 亦即8 / 23 等于1。
最后還有一個重點就是SPI_Out 的驅(qū)動(70行)。在上面我已經(jīng)重復(fù)過SPI_Out 是占4位的輸出。而且每一個位都有意義。
SPI_Out 第3 位:表示了CS,所以直接由SPI_Data 的第9位驅(qū)動。
SPI_Out 第2 位:表示了A0,同樣也是直接由SPI_Data的第8 位驅(qū)動。
SPI_Out 第1 位:表示了SCL,以寄存器rCLK來驅(qū)動。
SPI_Out 第0 位:表示了SI,以寄存器rDO來驅(qū)動。
這樣的目的是簡化連線的復(fù)雜度。我們知道Verilog HDL語言的位操作是很強大。懂得善用,會對建模提到很大的幫助。






分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復(fù) 返回頂部 返回列表