SPI使用介紹

2021-09-17 22:14:17 字數 3921 閱讀 8348

spi協議介紹:

硬體連線:

spi flash和spi oled。

兩種方式:

用gpio模擬spi

用s3c2440的spi控制器

我們先介紹下spi協議,硬體框架如下:

sck:提供時鐘

do:作為資料輸出

di:作為資料輸入

cs0/cs1:作為片選

同一時刻只能有乙個spi裝置處於工作狀態。

假設現在2440傳輸乙個0x56(二進位制就是0b0101 0110)資料給spi flash,時序如下:

在spi協議中,有兩個值來確定spi的模式。

cpol:表示spiclk的初始電平,0為低電平,1為高電平

cpha:表示相位,即第乙個還是第二個時鐘沿取樣資料,0為第乙個時鐘沿,1為第二個時鐘沿。

cpol cpha 模式 含義

0 0 0 初始電平為低電平,在第乙個時鐘沿取樣資料

0 1 1 初始電平為低電平,在第二個時鐘沿取樣資料

1 0 2 初始電平為高電平,在第乙個時鐘沿取樣資料

1 1 3 初始電平為高電平,在第二個時鐘沿取樣資料

我們常用的是模式0和模式3,因為它們都是在上公升沿取樣資料,不用去在乎時鐘的初始電平是什麼,只要在上公升沿採集資料就行。

極性選什麼?格式選什麼?通常去參考外接的模組的晶元手冊。比如對於oled,檢視它的晶元手冊時序部分:

sclk的初始電平我們並不需要關心,只要保證在上公升沿取樣資料就行。

使用gpio實現spi協議操作oled

現在開始寫**,使用gpio實現spi協議操作。

我們現在想要操作oled,通過三條線(sck、do、cs)與oled相連,這裡沒有di是因為2440只會向oled傳資料而不用接收資料。

我們要用gpio來實現soc向oled寫資料,這一層用gpio_spi.c來實現,負責傳送資料。

對於oled,有專門的指令和資料格式,要傳輸的資料內容,在oled.c這一層來實現,負責組織資料。

因此,我們需要實現以上兩個檔案。

需要實現的函式:先spi初始化spiint(),再初始化oledoledinit(),最後再顯示oledprint()。

新建乙個gpio_spi.c檔案,實現spi初始化spiint()

void spiinit(void)

具體實現spi_gpio_init()。這裡使用gpio實現spi協議:

gpf1作為oled片選引腳,設定為輸出;

gpg2作為flash片選引腳,設定為輸出;

gpg4作為oled的資料(data)/命令(command)選擇引腳,設定為輸出;

gpg5作為spi的miso,設定為輸入;

gpg6作為spi的mosi,設定為輸出;

gpg7作為spi的時鐘clk,設定為輸出;

/ 用gpio模擬spi /static void spi_gpio_init(void)

再新建乙個oled.c檔案,以實現初始化oledoledinit(),對於oled,除了spi的片選、時鐘、資料引腳,還有乙個資料/命令切換引腳。

這裡的d/c即資料(data)/命令(command)選擇引腳,它為高電平時,oled即認為收到的是資料;它為低電平時,oled即認為收到的是命令。

對於oled,命令由開啟/關閉顯示、背光亮度等,具體有什麼命令,可以查閱oled的主控晶元手冊

因此,在編寫oledwritecmd()時,需要先設定為命令模式:

static void oledwritecmd(unsigned char cmd)

即:先設定為命令模式,再片選oled,再傳輸命令,再恢復成原來的模式和取消片選。

片選函式和模式切換函式都比較簡單,設定為對應的高低電平即可:

static void oled_set_dc(char val)

static void oled_set_cs(char val)

還剩下spisendbyte()函式,它屬於spi協議,放在gpio_spi.c裡面:

void spisendbyte(unsigned char val)

}傳送資料要滿足spi的時序要求,參考前面:

先設定clk為低,然後資料引腳輸出資料的最高位,然後clk為高,在clk這個上公升沿中,oled就讀取了一位資料。接著左移一位,將原來的第7位移動到了第8位,重複8次,傳輸完成。

再完成spi_set_clk()和spi_set_do():

static void spi_set_clk(char val)

static void spi_set_do(char val)

至此,spi初始化和oled初始化就基本完成了,接下來就是oled顯示部分。

使用spi控制器:

前面我們都是通過gpio管腳來實現的spi通訊,這節我們使用2440裡面的gpio控制器來實現spi通訊。

前面使用gpio傳送資料時,是手工的控制時鐘線、資料線,我們使用spi控制器的話,只需要

把資料寫入暫存器,它就可以幫我自動那些時鐘線和資料線,我們繼續在上一節的基礎上修改,新增乙個檔案s3c2440_spi.c和s3c2440_spi.h,同時修改makefile,替換gpio_spi.c為s3c2440_spi.o。

從初始化函式開始,需要管腳初始化和spi控制器初始化:

void spiinit(void)

管腳初始化即需要把spi相關的clk、mosi、miso配置為對應的功能引腳:

static void spi_gpio_init(void)

然後是spi控制器的初始化,控制器的初始化可以參考晶元手冊介紹的程式設計步驟:

首先是設定波特率,要根據外設所能接受的範圍來設定,比如查閱oled的晶元手冊得知其時鐘最小值為100ns,即最小為10mhz;flash時鐘支援最大104mhz,為了**簡單,就直接取10mhz,根據等式推出暫存器值:

baud rate = pclk / 2 / (prescaler value + 1)

10 = 50 / 2 / (prescaler value + 1)

prescaler value = 1.5 = 2

實際的波特率為:50/2/3=8.3mhz

根據參考流程,接下來設定spi控制暫存器:

[6:5]設定為查詢模式: 00 polling mode

[4]設定時鐘使能: 1 = enable

[3]設定為主機模式: 1 = master

[2]設定無資料時時鐘為低電平: 0

[1]設定工作模式為模式a: 0 = format a

[0]設定傳送資料時無需讀取資料: 0 = normal mode

static void spicontrollerinit(void)

傳送資料時,先檢查狀態暫存器,判斷傳送/接收資料是否準備好了,準備好後就把資料放在暫存器sptdat1裡,spi控制器就自己控制時序把資料自動傳送出去了。

void spisendbyte(unsigned char val)

接收資料時,先寫0xff到暫存器sptdat1,再檢查狀態暫存器,判斷傳送/接收資料是否準備好了,準備好後就讀取暫存器sptdat1,讀取出來的就是接收到的資料。

unsigned char spirecvbyte(void)

SPI 介紹與使用

spi全稱是service provider inte ce,服務提供方介面,服務通常是指乙個介面或者乙個抽象類,服務提供方是對這個介面或者抽象類的具體實現,由第三方來實現介面提供具體的服務。spi提供了一種動態的對應用程式進行擴充套件的機制,通常用作框架服務的拓展或者可替換的服務元件。public...

SPI協議介紹

spi協議介紹 一 基本資訊 spi synchronous peripheral inte ce 同步外圍裝置介面 是序列介面的一種。該介面協議由motorola公司提出並形成規範。1 資料線 spi介面包含四條線 cs sck mosi miso,含義和作用如下 1 cs 片選訊號,低電平有效,...

SPI協議介紹

spi 序列外圍裝置介面,主要應用在 eeprom flash 實時時鐘 ad轉換器,以及數字訊號處理器和數碼訊號解碼器之間。是一種高速的,全雙工,同步通訊匯流排,只占用四根線,節約了晶元的管腳,為 pcb的布局節省了空間,現在越來越多的晶元整合了這種通訊協議。spi介面一般使用 4條線通訊 mis...