日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

Arduino 与 SPI 结合使用 以及SPI 深层理解

發(fā)布時(shí)間:2023/12/2 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Arduino 与 SPI 结合使用 以及SPI 深层理解 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

本文主要講解兩部分內(nèi)容,不做任何轉(zhuǎn)發(fā),僅個(gè)人學(xué)習(xí)記錄:

一. Arduino 與 SPI 結(jié)合使用? :

二. SPI 深層理解

有價(jià)值的幾個(gè)好的參考:

1. 中文版:?https://blog.csdn.net/xxxxxx91116/article/details/42620413 ?這版本適合比較容易理解大概, 細(xì)節(jié)翻譯還是要去英文版:https://www.arduino.cc/en/Tutorial/SPIEEPROM

2 .https://www.cnblogs.com/adylee/p/5399742.html? 以及 https://blog.csdn.net/weixin_40117614/article/details/84070130(其中:2.2傳輸數(shù)據(jù)步驟如下 mode似乎弄混了,mode0與mode2在第一次采樣之前已發(fā)送1bit 而mode1和mode3則是正常的發(fā)送再采樣,有待考證)

?

?

?

?

一. Arduino 與 SPI 結(jié)合使用? :

1.串行外圍設(shè)備接口入門(Introduction to the Serial Peripheral Interface)

Serial Peripheral Interface (SPI)是一種同步串行數(shù)據(jù)傳輸協(xié)議,用于近距離時(shí),微控制器(Microcontrollers),如Arduino,與其他外圍設(shè)備的快速通信。他也可以用于2個(gè)微控制器的通訊。 SPI通訊通常有一個(gè)主設(shè)備(通常是Microcontrollers),用于控制外圍設(shè)備。通常會(huì)有3種線路通用于各類設(shè)備的方法。 -Master In Slave Out(MISO)- Slave line,用于Slave向Master發(fā)送數(shù)據(jù) -Master Out Slave In(MOSI)- Master line,用于Master向Slave發(fā)送數(shù)據(jù) -Serial Clock(SCK)- 時(shí)鐘脈沖,主設(shè)備用于同步數(shù)據(jù)傳輸 -Slave Select pin- 分配給所有的設(shè)備,用于enable/disable指定的設(shè)備,同時(shí)用于避免由于線路忙導(dǎo)致的錯(cuò)誤傳輸。 SPI最大的問題在于它的標(biāo)準(zhǔn)太不嚴(yán)格了,這導(dǎo)致各個(gè)設(shè)備在實(shí)現(xiàn)它的時(shí)候都有一些不同,這就意味著當(dāng)我們?cè)诰帉懡涌诖a的時(shí)候必須仔細(xì)閱讀設(shè)備數(shù)據(jù)參數(shù)。通常來說有編號(hào)為0-3的3種傳輸模式(不是4種么?)這些模式控制數(shù)據(jù)是在時(shí)鐘信號(hào)的高電平還是低電平傳入或傳出,以及在高或低電平時(shí)時(shí)鐘無效。 所有的SPI設(shè)置都由Arduino SPI控制寄存器(SPCR)來決定。這個(gè)寄存器就是微控制器內(nèi)存的一個(gè)字節(jié),它是可讀寫的。寄存器提供的服務(wù)通常有3類:控制、數(shù)據(jù)和狀態(tài)。 控制寄存器(SPCR)編碼設(shè)置控制多種微控制器的功能。通常控制寄存器中的一個(gè)位影響某個(gè)特定的設(shè)置,比如速度和極性(這個(gè)是啥?) 數(shù)據(jù)寄存器(SPDR)僅僅hold住了一個(gè)字節(jié)。比如,SPI數(shù)據(jù)寄存器hold住了要發(fā)往MOSI線的一個(gè)字節(jié),或者這個(gè)數(shù)據(jù)是要從MISO線傳入的。 狀態(tài)寄存器(SPSR)根據(jù)多種微控制器的條件改變其狀態(tài)。比如,SPI狀態(tài)寄存器(SPSR)的第七位被設(shè)置為1表示有數(shù)據(jù)從SPI傳入或傳出。 SPI控制寄存器(SPCR)共有8位,每一個(gè)都控制了一種特定的SPI設(shè)置。 SPIE:置為1時(shí),表示enable SPI的中斷 SPE:置為1時(shí),表示enable SPI DORD:發(fā)送數(shù)據(jù)時(shí),設(shè)置為1表示最低有效位,0表示最高有效位。請(qǐng)各自腦補(bǔ)最低有效位和最高有效位。。。 MSTR:設(shè)置為1表示Arduino為master模式,0為slave模式 CPOL:設(shè)置為1時(shí),數(shù)據(jù)時(shí)鐘在高時(shí)無效,設(shè)置為0時(shí),在低時(shí)無效 CPHA:設(shè)置為1時(shí),時(shí)鐘低電平時(shí)是Samples data(樣本數(shù)據(jù)?),0時(shí)時(shí)鐘高電平是Sampledata SPR1和SPR0:設(shè)置SPI的速度,00是最快的(4MHz),11是最慢的(250KHz) 這些意味著當(dāng)對(duì)一個(gè)新的SPI設(shè)備編碼的時(shí)候,我們需要注意一些事情并根據(jù)如下設(shè)置SPCR: - 數(shù)據(jù)傳入是最高有效位(MSB)還是最低有效位(LSB)? - 數(shù)據(jù)時(shí)鐘無效是在高還是低? - samples是在時(shí)鐘脈沖上升沿還是下降沿? - SPI 運(yùn)行的速度是多少? 你還要感受一下feel一下你的芯片,在你設(shè)置好之后需要暫停多久才能繼續(xù)?Let‘s go !

2.串行EEPROM簡(jiǎn)介

AT25HP512是一個(gè)65536字節(jié)串行EEPROM。它支持SPI的模式0-3,在10MHz,5V的環(huán)境下運(yùn)行,同時(shí)也可以在1.8v的低速下運(yùn)行。他的內(nèi)存被組織成512個(gè)頁,每個(gè)頁有128字節(jié)。他每次只能寫入128字節(jié),但是可以同時(shí)讀出1-128字節(jié)的數(shù)據(jù),這個(gè)設(shè)備同時(shí)提供了多種程度的寫保護(hù),但這里不涉及這個(gè)部分。 enable這個(gè)設(shè)備只需要讓片選信號(hào)CS為低即可。指令使用8位的opcodes來發(fā)送,同時(shí)在時(shí)鐘上升沿傳入數(shù)據(jù),大概使用10微秒寫入1個(gè)頁的數(shù)據(jù),所以在每個(gè)EEPROM的的寫程序后面都應(yīng)該等待10ms。

3.面包板的準(zhǔn)備

將AT25HP512芯片插入面包板,EEPROM的3,7,8引腳接到5V,引腳4接地。 紅色的線接+5V,GND線是黑色 EERPOM的引腳1連接Arduino的引腳10(Slave 片選),EEPROM的引腳2連接Arduino的引腳12(Master In Slave Out - MISO),EEPROM的引腳5連接Arduino的引腳11(Master Out Slave In - MOSI),同時(shí)EEPROM的引腳6連接Arduino的引腳13(串口時(shí)鐘 SCK)。

4.Arduino SPI 編程

現(xiàn)在我們要編寫能讓Arduino和EEPROM進(jìn)行SPI通信的代碼了。在啟動(dòng)代碼中,這個(gè)程序填充128字節(jié),或者一個(gè)EEPROM頁。在main loop中他將數(shù)據(jù)讀出來,每次讀一個(gè)字節(jié)并通過串口打印出來。我們下面用一小節(jié)來過一下代碼。 第一步是啟動(dòng)我們的預(yù)處理指令(其實(shí)就是#define啦),預(yù)處理指令是在真正的編譯開始前處理的。他們以#開頭并且不以分號(hào)(;)結(jié)尾。反正前面一段就是說,我們接下來要開始使用#define了。 下面定義在我們的SPI通訊中要用到的pins引腳,DATAOUT, DATAIN, SPICLOCK和SLAVESELECT。然后定義EEPROM的控制指令(opcodes): 接下來分配程序會(huì)用到的全局變量。我們將用char buffer[128]來保存要傳輸?shù)紼EPROM的數(shù)據(jù): 首先我們初始化我們的串口連接,設(shè)置我們的input和output模式并設(shè)置SLAVESELECT線為高時(shí)開始。這個(gè)設(shè)置可以使設(shè)備暫時(shí)失效,這樣可以防止由于線路噪聲引起的傳輸錯(cuò)誤。 現(xiàn)在我們?cè)O(shè)置SPI控制寄存器(SPCR)為二進(jìn)制數(shù)據(jù)01010000.在控制寄存器中,每一位的設(shè)置都表示不同的功能。第8位關(guān)閉SPI中斷,第七位enable SPI,第六位選擇數(shù)據(jù)傳輸是最高有效位有線,第五位設(shè)置Arduino為master模式,第四位設(shè)置數(shù)據(jù)時(shí)鐘低時(shí)無效,第三位代表SPI在數(shù)據(jù)時(shí)鐘的上升沿階段抽樣數(shù)據(jù),第二位和第一位設(shè)置SPI和系統(tǒng)的通訊速度,/4有4個(gè)級(jí)別。當(dāng)設(shè)置了控制寄存后,我們接下來從垃圾回收變量中讀取SPI的狀態(tài)寄存器(SPSR)和數(shù)據(jù)寄存器(SPDR),以清除以前運(yùn)行的臟數(shù)據(jù): 這里我們用數(shù)字來填充要發(fā)送的數(shù)組,并向EEPROM寫入一個(gè)enable指令。這個(gè)enable指令必須在任何一個(gè)寫指令之前完成。為了發(fā)送這個(gè)指令,我們將SLAVESELECT線置為低,enable這個(gè)設(shè)備后,使用spi_transfer函數(shù)發(fā)送指令。注意到我們使用了程序開始定義的WREN opcode。最后我們?cè)O(shè)置SLAVESELECT線為高來釋放它。 在短暫的delay(10)之后,我們將SLAVESELECT線置為低再次選中EEPROM設(shè)備。我們發(fā)送一個(gè)寫指令來告訴EEPROM我們將發(fā)送數(shù)據(jù)到內(nèi)存中。首先發(fā)送16位,也就是2個(gè)字節(jié)地址來開始,最高有效位。接下來發(fā)送buffer中的128字節(jié)數(shù)據(jù),一個(gè)字節(jié)接著一個(gè)字節(jié),不需要pause暫停。最后我們?cè)O(shè)置SLAVESELECT引腳為高來釋放設(shè)備,同時(shí)等待一段時(shí)間以保證EEPROM寫入數(shù)據(jù): 我們?cè)趕etup函數(shù)結(jié)束時(shí),通過串口發(fā)送hi來表示setup結(jié)束。 在我們的主函數(shù)loop中我們每次從EEPROM中讀取一個(gè)字節(jié)并通過串口將它打印出來。為了可讀性我們?cè)黾右粋€(gè)打印以及等待。每一次loop我們都增加EEPROM的一個(gè)地址去讀,當(dāng)?shù)刂吩黾拥?28后,我們重新回到0開始讀,原因很簡(jiǎn)單,因?yàn)殚_始我們只寫入了128字節(jié)數(shù)據(jù): fill_buffer函數(shù)僅僅將我們的數(shù)組用0-127這128個(gè)數(shù)字來填充。這個(gè)函數(shù)很容易就可以改寫為你應(yīng)用程序需要的數(shù)據(jù):

spi_transfer函數(shù)將要傳出的數(shù)據(jù)放入數(shù)據(jù)傳輸寄存器,然后就開始SPI傳輸了哈??梢酝ㄟ^SPI狀態(tài)寄存器(SPSR)的某個(gè)位(SPIF)來查看數(shù)據(jù)傳輸是否結(jié)束了。關(guān)于位掩碼(bit mask)可以參考這里:http://www.arduino.cc/en/Tutorial/。最后返回寫入EEPROM的數(shù)據(jù)。

?

read_eeprom函數(shù)允許我們從EEPROM中讀入數(shù)據(jù),首先設(shè)置SLAVESELECT為低來enable設(shè)備。接下來送入一個(gè)讀指定,接下來送入要讀的16位地址,最高有效位有限。接下來我們發(fā)送一個(gè)假數(shù)據(jù)到EEPROM中以將數(shù)據(jù)傳出。最后我們?cè)谧x入一個(gè)字節(jié)后,再次設(shè)置SLAVESELECT線為高來釋放設(shè)備,并返回?cái)?shù)據(jù),如果我們想要一次讀入多個(gè)數(shù)據(jù),那么當(dāng)我們重復(fù)data=spi_transfer(0XFF)時(shí),需要將SLAVESELECT一直設(shè)置為低,這樣來回128次后讀出整個(gè)頁的數(shù)據(jù):

?

?

為了方便大家CTRL+c、 ?CTRL+v,下面是整個(gè)手冊(cè)的源碼:

?

#define DATAOUT 11//MOSI #define DATAIN 12//MISO #define SPICLOCK 13//sck #define SLAVESELECT 10//ss //opcodes #define WREN 6 #define WRDI 4 #define RDSR 5 #define WRSR 1 #define READ 3 #define WRITE 2 byte eeprom_output_data; byte eeprom_input_data=0; byte clr; int address=0; //data buffer char buffer [128]; void fill_buffer() { for (int I=0;I<128;I++) { buffer[I]=I; } } char spi_transfer(volatile char data) { SPDR = data; // Start the transmission while (!(SPSR & (1<<SPIF))) // Wait the end of the transmission { }; return SPDR; // return the received byte } void setup() { Serial.begin(9600); pinMode(DATAOUT, OUTPUT); pinMode(DATAIN, INPUT); pinMode(SPICLOCK,OUTPUT); pinMode(SLAVESELECT,OUTPUT); digitalWrite(SLAVESELECT,HIGH); //disable device // SPCR = 01010000 //interrupt disabled,spi enabled,msb 1st,master,clk low when idle, //sample on leading edge of clk,system clock/4 rate (fastest) SPCR = (1<<SPE)|(1<<MSTR); clr=SPSR; clr=SPDR; delay(10); //fill buffer with data fill_buffer(); //fill eeprom w/ buffer digitalWrite(SLAVESELECT,LOW); spi_transfer(WREN); //write enable digitalWrite(SLAVESELECT,HIGH); delay(10); digitalWrite(SLAVESELECT,LOW); spi_transfer(WRITE); //write instruction address=0; spi_transfer((char)(address>>8)); //send MSByte address first spi_transfer((char)(address)); //send LSByte address //write 128 bytes for (int I=0;I<128;I++) { spi_transfer(buffer[I]); //write data byte } digitalWrite(SLAVESELECT,HIGH); //release chip //wait for eeprom to finish writing delay(3000); Serial.print('h',BYTE); Serial.print('i',BYTE); Serial.print('\n',BYTE);//debug delay(1000); } byte read_eeprom(int EEPROM_address) { //READ EEPROM int data; digitalWrite(SLAVESELECT,LOW); spi_transfer(READ); //transmit read opcode spi_transfer((char)(EEPROM_address>>8)); //send MSByte address first spi_transfer((char)(EEPROM_address)); //send LSByte address data = spi_transfer(0xFF); //get data byte digitalWrite(SLAVESELECT,HIGH); //release chip, signal end transfer return data; } void loop() { eeprom_output_data = read_eeprom(address); Serial.print(eeprom_output_data,DEC); Serial.print('\n',BYTE); address++; if (address == 128) address = 0; delay(500); //pause for readability }

?總結(jié):

1.這里主要以內(nèi)存器EEPROM為主, 而且個(gè)人感覺這里的SPI控制進(jìn)入到Arduino的開發(fā)版, 大體的方向?qū)芏郃rduino——SPI控制實(shí)用,但畢竟只是一個(gè)例子,下面一節(jié)將講述SPI最底層的東西。

2.如果只是簡(jiǎn)單的讀寫,Arduino 中是有SPI.h頭文件和cpp 也是大家可以研究的一個(gè)方向,現(xiàn)在記憶留心還是spi.transfer用法。

?

二. SPI 深層理解

SPI,是英語Serial Peripheral Interface的縮寫,顧名思義就是串行外圍設(shè)備接口。SPI,是一種高速的,全雙工,同步的通信總線,并且在芯片的管腳上只占用四根線,節(jié)約了芯片的管腳,同時(shí)為PCB的布局上節(jié)省空間,提供方便,正是出于這種簡(jiǎn)單易用的特性,現(xiàn)在越來越多的芯片集成了這種通信協(xié)議。 SPI是一個(gè)環(huán)形總線結(jié)構(gòu),由ss(cs)、sck、sdi、sdo構(gòu)成,其時(shí)序其實(shí)很簡(jiǎn)單,主要是在sck的控制下,兩個(gè)雙向移位寄存器進(jìn)行數(shù)據(jù)交換。

上升沿發(fā)送、下降沿接收、高位先發(fā)送。 上升沿到來的時(shí)候,sdo上的電平將被發(fā)送到從設(shè)備的寄存器中。 下降沿到來的時(shí)候,sdi上的電平將被接收到主設(shè)備的寄存器中。
假設(shè)主機(jī)和從機(jī)初始化就緒:并且主機(jī)的sbuff=0xaa (10101010),從機(jī)的sbuff=0x55 (01010101),下面將分步對(duì)spi的8個(gè)時(shí)鐘周期的數(shù)據(jù)情況演示一遍(假設(shè)上升沿發(fā)送數(shù)據(jù))。
--------------------------------------------------- 脈沖 ? ? ?主機(jī)sbuff 從機(jī)sbuff sdi sdo --------------------------------------------------- 0 00-0 ??10101010?01010101 0 0 --------------------------------------------------- 1 0--1 ??0101010x 10101011?0?1 1 1--0 ? 01010100?10101011?0?1 --------------------------------------------------- 2 0--1 ??1010100x 01010110?1?0 2 1--0 ? 10101001?01010110?1?0 --------------------------------------------------- 3 0--1 ??0101001x 10101101?0?1 3 1--0 ? 01010010?10101101?0?1 --------------------------------------------------- 4 0--1 ??1010010x 01011010?1?0 4 1--0 ? 10100101?01011010?1?0 --------------------------------------------------- 5 0--1 ??0100101x 10110101?0?1 5 1--0 ? 01001010?10110101?0?1 --------------------------------------------------- 6 0--1 ??1001010x 01101010?1?0 6 1--0 ? 10010101?01101010?1?0 --------------------------------------------------- 7 0--1 ??0010101x 11010101?0?1 7 1--0 ? 00101010?11010101?0?1 --------------------------------------------------- 8 0--1 ? 0101010x 10101010?1?0 8 1--0 ? 01010101?10101010?1?0 ---------------------------------------------------
這樣就完成了兩個(gè)寄存器8位的交換,上面的0--1表示上升沿、1--0表示下降沿,sdi、 sdo相對(duì)于主機(jī)而言的。根據(jù)以上分析,一個(gè)完整的傳送周期是16位,即兩個(gè)字節(jié),因?yàn)?#xff0c;首先主機(jī)要發(fā)送命令過去,然后從機(jī)根據(jù)主機(jī)的名準(zhǔn)備數(shù)據(jù),主機(jī)在下一個(gè)8位時(shí)鐘周期才把數(shù)據(jù)讀回來。? SPI總線是Motorola公司推出的三線同步接口,同步串行3線方式進(jìn)行通信:一條時(shí)鐘線SCK,一條數(shù)據(jù)輸入線MOSI,一條數(shù)據(jù)輸出線MISO;用于 CPU與各種外圍器件進(jìn)行全雙工、同步串行通訊。
SPI主要特點(diǎn)有:可以同時(shí)發(fā)出和接收串行數(shù)據(jù);可以當(dāng)作主機(jī)或從機(jī)工作;提供頻率可編程時(shí)鐘;發(fā)送結(jié)束中斷標(biāo)志;寫沖突保護(hù);總線競(jìng)爭(zhēng)保護(hù)等。 SPI總線有四種工作方式(SP0, SP1, SP2, SP3),其中使用的最為廣泛的是SPI0和SPI3方式。 SPI模塊為了和外設(shè)進(jìn)行數(shù)據(jù)交換,根據(jù)外設(shè)工作要求,其輸出串行同步時(shí)鐘極性和相位可以進(jìn)行配置,時(shí)鐘極性(CPOL)對(duì)傳輸協(xié)議沒有重大的影響。如果CPOL=0,串行同步時(shí)鐘的空閑狀態(tài)為低電平;如果CPOL=1,串行同步時(shí)鐘的空閑狀態(tài)為高電平。時(shí)鐘相位(CPHA)能夠配置用于選擇兩種不同的傳輸協(xié)議之一進(jìn)行數(shù)據(jù)傳輸。如果 CPHA=0,在串行同步時(shí)鐘的第一個(gè)跳變沿(上升或下降)數(shù)據(jù)被采樣;如果CPHA=1,在串行同步時(shí)鐘的第二個(gè)跳變沿(上升或下降)數(shù)據(jù)被采樣。 SPI主模塊和與之通信的外設(shè)音時(shí)鐘相位和極性應(yīng)該一致。

?

?

SPI時(shí)序圖詳解-SPI接口在模式0下輸出第一位數(shù)據(jù)的時(shí)刻

SPI接口在模式0下輸出第一位數(shù)據(jù)的時(shí)刻
SPI接口有四種不同的數(shù)據(jù)傳輸時(shí)序,取決于CPOL和CPHL這兩位的組合。圖1中表現(xiàn)了這四種時(shí)序, 時(shí)序與CPOL、CPHL的關(guān)系也可以從圖中看出。

CPOL(時(shí)鐘極性)和CPHA(時(shí)鐘相位)意義

CPOL=0,表示當(dāng)SCLK=0時(shí)處于空閑態(tài),所以有效狀態(tài)就是SCLK處于高電平時(shí)

CPOL=1,表示當(dāng)SCLK=1時(shí)處于空閑態(tài),所以有效狀態(tài)就是SCLK處于低電平時(shí)

CPHA=0,表示數(shù)據(jù)采樣是在第1個(gè)邊沿,數(shù)據(jù)發(fā)送在第2個(gè)邊沿 ?

CPHA=1,表示數(shù)據(jù)采樣是在第2個(gè)邊沿,數(shù)據(jù)發(fā)送在第1個(gè)邊沿

通過CPOL和CPHA來控制我們主設(shè)備的通信模式
發(fā)送和接收設(shè)備需要根據(jù)實(shí)際情況分析 (發(fā)送設(shè)備 ≠ 主設(shè)備
Mode0:CPOL=0,CPHA=0
SCLK(0)空閑;
當(dāng)SCLK由低到高跳變(上升沿),(接收設(shè)備)進(jìn)行數(shù)據(jù)的讀取;
當(dāng)SCLK由高到低跳變(下降沿),(發(fā)送設(shè)備)進(jìn)行數(shù)據(jù)的發(fā)送;
Mode1:CPOL=0,CPHA=1
SCLK(0)空閑;
當(dāng)SCLK由高到低跳變(下降沿),(接收設(shè)備)進(jìn)行數(shù)據(jù)的讀取;
當(dāng)SCLK由低到高跳變(上升沿),(發(fā)送設(shè)備)進(jìn)行數(shù)據(jù)的發(fā)送;
Mode2:CPOL=1,CPHA=0
SCLK(1)空閑;
當(dāng)SCLK由高到低跳變(下降沿),(接收設(shè)備)進(jìn)行數(shù)據(jù)的讀取;
當(dāng)SCLK由低到高跳變(上升沿),(發(fā)送設(shè)備)進(jìn)行數(shù)據(jù)的發(fā)送;
Mode3:CPOL=1,CPHA=1
SCLK(1)空閑;
當(dāng)SCLK由低到高跳變(上升沿),(接收設(shè)備)進(jìn)行數(shù)據(jù)的讀取;
當(dāng)SCLK由高到低跳變(下降沿),(發(fā)送設(shè)備)進(jìn)行數(shù)據(jù)的發(fā)送;
---------------------

?

?

圖1

?

?

CPOL是用來決定SCK時(shí)鐘信號(hào)空閑時(shí)的電平,CPOL=0,空閑電平為低電平,CPOL=1時(shí),

空閑電平為高電平。CPHA是用來決定采樣時(shí)刻的,CPHA=0,在每個(gè)周期的第一個(gè)時(shí)鐘沿采樣,

CPHA=1,在每個(gè)周期的第二個(gè)時(shí)鐘沿采樣。

?

由于我使用的器件工作在模式0這種時(shí)序(CPOL=0,CPHA=0),所以將圖1簡(jiǎn)化為圖2, 只關(guān)注模式0的時(shí)序。 圖2 我們來關(guān)注SCK的第一個(gè)時(shí)鐘周期,在時(shí)鐘的前沿采樣數(shù)據(jù)(上升沿,第一個(gè)時(shí)鐘沿), 在時(shí)鐘的后沿輸出數(shù)據(jù)(下降沿,第二個(gè)時(shí)鐘沿)。首先來看主器件,主器件的輸出口(MOSI)輸出的數(shù)據(jù)bit1, 在時(shí)鐘的前沿被從器件采樣,那主器件是在何時(shí)刻輸出bit1的呢?bit1的輸出時(shí)刻實(shí)際上在SCK信號(hào)有效以前, 比?SCK的上升沿還要早半個(gè)時(shí)鐘周期。bit1的輸出時(shí)刻與SSEL信號(hào)沒有關(guān)系。再來看從器件, 主器件的輸入口MISO同樣是在時(shí)鐘的前沿采樣從器件輸出的bit1的,那從器件又是在何時(shí)刻輸出bit1的呢。 從器件是在SSEL信號(hào)有效后,立即輸出bit1,盡管此時(shí)SCK信號(hào)還沒有起效。關(guān)于上面的主器件 和從器件輸出bit1位的時(shí)刻,可以從圖3、4中得到驗(yàn)證。 圖3 注意圖3中,CS信號(hào)有效后(低電平有效,注意CS下降沿后發(fā)生的情況),故意用延時(shí)程序 延時(shí)了一段時(shí)間,之后再向數(shù)據(jù)寄存器寫入了要發(fā)送的數(shù)據(jù),來觀察主器件輸出bit1的情況(MOSI)。 可以看出,bit1(值為1)是在SCK信號(hào)有效之前的半個(gè)時(shí)鐘周期的時(shí)刻開始輸出的(與CS信號(hào)無關(guān)), 到了SCK的第一個(gè)時(shí)鐘周期的上升沿正好被從器件采樣。 圖4

圖4中,注意看CS和MISO信號(hào)。我們可以看出,CS信號(hào)有效后,從器件立刻輸出了bit1(值為1)。

?

通常我們進(jìn)行的spi操作都是16位的。圖5記錄了第一個(gè)字節(jié)和第二個(gè)字節(jié)間的相互銜接的過程。 第一個(gè)字節(jié)的最后一位在SCK的上升沿被采樣,隨后的SCK下降沿,從器件就輸出了第二個(gè)字節(jié)的第一位。

?

?

?

?

SPI總線協(xié)議介紹(接口定義,傳輸時(shí)序)

?

一、技術(shù)性能 SPI接口是Motorola 首先提出的全雙工三線同步串行外圍接口,采用主從模式(Master Slave)架構(gòu);支持多slave模式應(yīng)用,一般僅支持單Master。 時(shí)鐘由Master控制,在時(shí)鐘移位脈沖下,數(shù)據(jù)按位傳輸,高位在前,低位在后(MSB first);SPI接口有2根單向數(shù)據(jù)線,為全雙工通信,目前應(yīng)用中的數(shù)據(jù)速率可達(dá)幾Mbps的水平。
------------------------------------------------------- 二、接口定義 SPI接口共有4根信號(hào)線,分別是:設(shè)備選擇線、時(shí)鐘線、串行輸出數(shù)據(jù)線、串行輸入數(shù)據(jù)線。

?

(1)MOSI:主器件數(shù)據(jù)輸出,從器件數(shù)據(jù)輸入 (2)MISO:主器件數(shù)據(jù)輸入,從器件數(shù)據(jù)輸出 (3)SCLK :時(shí)鐘信號(hào),由主器件產(chǎn)生 (4)/SS:從器件使能信號(hào),由主器件控制
------------------------------------------------------- 三、內(nèi)部結(jié)構(gòu) ?四、傳輸時(shí)序 SPI接口在內(nèi)部硬件實(shí)際上是兩個(gè)簡(jiǎn)單的移位寄存器,傳輸?shù)臄?shù)據(jù)為8位,在主器件產(chǎn)生的從器件使能信號(hào)和移位脈沖下,按位傳輸,高位在前,低位在后。如下圖所示,在SCLK的下降沿上數(shù)據(jù)改變,上升沿一位數(shù)據(jù)被存入移位寄存器。 SPI接口沒有指定的流控制,沒有應(yīng)答機(jī)制確認(rèn)是否接收到數(shù)據(jù)。 謝謝!

?

?

?

轉(zhuǎn)載于:https://www.cnblogs.com/MCSFX/p/10805878.html

總結(jié)

以上是生活随笔為你收集整理的Arduino 与 SPI 结合使用 以及SPI 深层理解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。